diff --git a/.clang-format b/.clang-format index 10fcbb62..c2b5fa23 100644 --- a/.clang-format +++ b/.clang-format @@ -17,7 +17,7 @@ AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: true +AlwaysBreakTemplateDeclarations: Yes BinPackArguments: true BinPackParameters: true BraceWrapping: @@ -39,6 +39,7 @@ BraceWrapping: BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon @@ -81,6 +82,7 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None +ObjCBinPackProtocolList: Never ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: false @@ -89,12 +91,37 @@ PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left RawStringFormats: - - Delimiter: pb - Language: TextProto + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' BasedOnStyle: google ReflowComments: true SortIncludes: true @@ -102,7 +129,11 @@ SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..15228e3d --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,52 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,google-*' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +User: brenden +CheckOptions: + - key: google-build-namespaces.HeaderFileExtensions + value: ',h,hh,hpp,hxx' + - key: google-global-names-in-headers.HeaderFileExtensions + value: ',h,hh,hpp,hxx' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.BranchThreshold + value: '4294967295' + - key: google-readability-function-size.LineThreshold + value: '4294967295' + - key: google-readability-function-size.NestingThreshold + value: '4294967295' + - key: google-readability-function-size.ParameterThreshold + value: '4294967295' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-function-size.VariableThreshold + value: '4294967295' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: google-runtime-int.SignedTypePrefix + value: int + - key: google-runtime-int.TypeSuffix + value: '' + - key: google-runtime-int.UnsignedTypePrefix + value: uint + - key: google-runtime-references.WhiteListTypes + value: '' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: 'NULL' +... + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4dd6c80f..ae328d0c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,27 +1,65 @@ stages: + - dependencies - build - test - lint -image: brndnmtthws/conky-builder:latest variables: CC: clang-7 CXX: clang++-7 + DOCKER_DRIVER: overlay2 + DOCKER_HOST: tcp://localhost:2375/ + +docker_builder: + stage: dependencies + image: docker:stable + only: + changes: + - Dockerfile.builder + services: + - docker:dind + before_script: + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY + script: + - docker pull $CI_REGISTRY_IMAGE/builder:latest || true + - docker build -f Dockerfile.builder --cache-from $CI_REGISTRY_IMAGE/builder:latest --tag $CI_REGISTRY_IMAGE/builder:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE/builder:latest . + - docker push ${CI_REGISTRY_IMAGE}/builder:$CI_COMMIT_SHA + - docker push ${CI_REGISTRY_IMAGE}/builder:latest build: + image: $CI_REGISTRY_IMAGE/builder:latest + stage: build script: - mkdir build - cd build - - cmake .. + - cmake -DMAINTAINER_MODE=ON .. - make -j4 + artifacts: + expire_in: 1 day + paths: + - build/ test: + image: $CI_REGISTRY_IMAGE/builder:latest + stage: test script: - cd build - - make test + - cmake -DCMAKE_SOURCE_DIR=$(dirname `pwd`) -DCMAKE_BINARY_DIR=`pwd` -DMAINTAINER_MODE=ON -DBUILD_TESTS=ON .. + - make -j4 + - make -j4 test -lint: +check-clang-tidy: + image: $CI_REGISTRY_IMAGE/builder:latest + stage: test script: - cd build - - cmake -DCHECK_CODE_QUALITY=ON .. - - make check + - cmake -DCMAKE_SOURCE_DIR=$(dirname `pwd`) -DCMAKE_BINARY_DIR=`pwd` -DMAINTAINER_MODE=ON -DCHECK_CODE_QUALITY=ON .. + - make -j4 check-clang-tidy + +check-clang-format: + image: $CI_REGISTRY_IMAGE/builder:latest + stage: test + script: + - cd build + - cmake -DCMAKE_SOURCE_DIR=$(dirname `pwd`) -DCMAKE_BINARY_DIR=`pwd` -DMAINTAINER_MODE=ON -DCHECK_CODE_QUALITY=ON .. + - make -j4 check-clang-format diff --git a/CMakeLists.txt b/CMakeLists.txt index 291bf0d2..d4aeeeb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,12 +101,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") if(CHECK_CODE_QUALITY) - # Set up clang-tidy - set(CLANG_TIDY_BIN_NAME - clang-tidy - clang-tidy-5.0 - clang-tidy-6.0 - clang-tidy-7.0) - set(CLANG_TIDY_EXCLUDE_PATTERNS "build/" ${CMAKE_BINARY_DIR}) find_package(ClangTidy) + find_package(ClangFormat) endif(CHECK_CODE_QUALITY) diff --git a/Dockerfile.builder b/Dockerfile.builder index 08ba21f7..7579bd7a 100644 --- a/Dockerfile.builder +++ b/Dockerfile.builder @@ -1,16 +1,11 @@ FROM ubuntu:bionic + RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive \ apt-get install -qy --no-install-recommends \ software-properties-common \ wget \ gpg-agent \ - && wget -q https://apt.llvm.org/llvm-snapshot.gpg.key \ - && apt-key add llvm-snapshot.gpg.key \ - && add-apt-repository 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main' \ - && DEBIAN_FRONTEND=noninteractive \ - apt-get install -qy --no-install-recommends \ - software-properties-common \ cmake \ git \ audacious-dev \ @@ -35,6 +30,16 @@ RUN apt-get update \ libxmmsclient-dev \ libxnvctrl-dev \ ncurses-dev \ + lcov \ + docbook2x \ + man \ + less + +RUN wget -q https://apt.llvm.org/llvm-snapshot.gpg.key \ + && apt-key add llvm-snapshot.gpg.key \ + && add-apt-repository 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main' \ + && DEBIAN_FRONTEND=noninteractive \ + apt-get install -qy --no-install-recommends \ clang-7 \ lldb-7 \ lld-7 \ diff --git a/bin/run-clang-format.py b/bin/run-clang-format.py new file mode 100755 index 00000000..ab628601 --- /dev/null +++ b/bin/run-clang-format.py @@ -0,0 +1,326 @@ +#!/usr/bin/env python +"""A wrapper script around clang-format, suitable for linting multiple files +and to use for continuous integration. + +This is an alternative API for the clang-format command line. +It runs over multiple files and directories in parallel. +A diff output is produced and a sensible exit code is returned. + +Source: https://raw.githubusercontent.com/Sarcasm/run-clang-format/master/run-clang-format.py +""" + +from __future__ import print_function, unicode_literals + +import argparse +import codecs +import difflib +import fnmatch +import io +import multiprocessing +import os +import signal +import subprocess +import sys +import traceback + +from functools import partial + +DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx' + + +class ExitStatus: + SUCCESS = 0 + DIFF = 1 + TROUBLE = 2 + + +def list_files(files, recursive=False, extensions=None, exclude=None): + if extensions is None: + extensions = [] + if exclude is None: + exclude = [] + + out = [] + for file in files: + if recursive and os.path.isdir(file): + for dirpath, dnames, fnames in os.walk(file): + fpaths = [os.path.join(dirpath, fname) for fname in fnames] + for pattern in exclude: + # os.walk() supports trimming down the dnames list + # by modifying it in-place, + # to avoid unnecessary directory listings. + dnames[:] = [ + x for x in dnames + if + not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) + ] + fpaths = [ + x for x in fpaths if not fnmatch.fnmatch(x, pattern) + ] + for f in fpaths: + ext = os.path.splitext(f)[1][1:] + if ext in extensions: + out.append(f) + else: + out.append(file) + return out + + +def make_diff(file, original, reformatted): + return list( + difflib.unified_diff( + original, + reformatted, + fromfile='{}\t(original)'.format(file), + tofile='{}\t(reformatted)'.format(file), + n=3)) + + +class DiffError(Exception): + def __init__(self, message, errs=None): + super(DiffError, self).__init__(message) + self.errs = errs or [] + + +class UnexpectedError(Exception): + def __init__(self, message, exc=None): + super(UnexpectedError, self).__init__(message) + self.formatted_traceback = traceback.format_exc() + self.exc = exc + + +def run_clang_format_diff_wrapper(args, file): + try: + ret = run_clang_format_diff(args, file) + return ret + except DiffError: + raise + except Exception as e: + raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, + e), e) + + +def run_clang_format_diff(args, file): + try: + with io.open(file, 'r', encoding='utf-8') as f: + original = f.readlines() + except IOError as exc: + raise DiffError(str(exc)) + invocation = [args.clang_format_executable, file] + + # Use of utf-8 to decode the process output. + # + # Hopefully, this is the correct thing to do. + # + # It's done due to the following assumptions (which may be incorrect): + # - clang-format will returns the bytes read from the files as-is, + # without conversion, and it is already assumed that the files use utf-8. + # - if the diagnostics were internationalized, they would use utf-8: + # > Adding Translations to Clang + # > + # > Not possible yet! + # > Diagnostic strings should be written in UTF-8, + # > the client can translate to the relevant code page if needed. + # > Each translation completely replaces the format string + # > for the diagnostic. + # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation + # + # It's not pretty, due to Python 2 & 3 compatibility. + encoding_py3 = {} + if sys.version_info[0] >= 3: + encoding_py3['encoding'] = 'utf-8' + + try: + proc = subprocess.Popen( + invocation, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + **encoding_py3) + except OSError as exc: + raise DiffError(str(exc)) + proc_stdout = proc.stdout + proc_stderr = proc.stderr + if sys.version_info[0] < 3: + # make the pipes compatible with Python 3, + # reading lines should output unicode + encoding = 'utf-8' + proc_stdout = codecs.getreader(encoding)(proc_stdout) + proc_stderr = codecs.getreader(encoding)(proc_stderr) + # hopefully the stderr pipe won't get full and block the process + outs = list(proc_stdout.readlines()) + errs = list(proc_stderr.readlines()) + proc.wait() + if proc.returncode: + raise DiffError("clang-format exited with status {}: '{}'".format( + proc.returncode, file), errs) + return make_diff(file, original, outs), errs + + +def bold_red(s): + return '\x1b[1m\x1b[31m' + s + '\x1b[0m' + + +def colorize(diff_lines): + def bold(s): + return '\x1b[1m' + s + '\x1b[0m' + + def cyan(s): + return '\x1b[36m' + s + '\x1b[0m' + + def green(s): + return '\x1b[32m' + s + '\x1b[0m' + + def red(s): + return '\x1b[31m' + s + '\x1b[0m' + + for line in diff_lines: + if line[:4] in ['--- ', '+++ ']: + yield bold(line) + elif line.startswith('@@ '): + yield cyan(line) + elif line.startswith('+'): + yield green(line) + elif line.startswith('-'): + yield red(line) + else: + yield line + + +def print_diff(diff_lines, use_color): + if use_color: + diff_lines = colorize(diff_lines) + if sys.version_info[0] < 3: + sys.stdout.writelines((l.encode('utf-8') for l in diff_lines)) + else: + sys.stdout.writelines(diff_lines) + + +def print_trouble(prog, message, use_colors): + error_text = 'error:' + if use_colors: + error_text = bold_red(error_text) + print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--clang-format-executable', + metavar='EXECUTABLE', + help='path to the clang-format executable', + default='clang-format') + parser.add_argument( + '--extensions', + help='comma separated list of file extensions (default: {})'.format( + DEFAULT_EXTENSIONS), + default=DEFAULT_EXTENSIONS) + parser.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + parser.add_argument('files', metavar='file', nargs='+') + parser.add_argument( + '-q', + '--quiet', + action='store_true') + parser.add_argument( + '-j', + metavar='N', + type=int, + default=0, + help='run N clang-format jobs in parallel' + ' (default number of cpus + 1)') + parser.add_argument( + '--color', + default='auto', + choices=['auto', 'always', 'never'], + help='show colored diff (default: auto)') + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=[], + help='exclude paths matching the given glob-like pattern(s)' + ' from recursive search') + + args = parser.parse_args() + + # use default signal handling, like diff return SIGINT value on ^C + # https://bugs.python.org/issue14229#msg156446 + signal.signal(signal.SIGINT, signal.SIG_DFL) + try: + signal.SIGPIPE + except AttributeError: + # compatibility, SIGPIPE does not exist on Windows + pass + else: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + colored_stdout = False + colored_stderr = False + if args.color == 'always': + colored_stdout = True + colored_stderr = True + elif args.color == 'auto': + colored_stdout = sys.stdout.isatty() + colored_stderr = sys.stderr.isatty() + + retcode = ExitStatus.SUCCESS + files = list_files( + args.files, + recursive=args.recursive, + exclude=args.exclude, + extensions=args.extensions.split(',')) + + if not files: + return + + njobs = args.j + if njobs == 0: + njobs = multiprocessing.cpu_count() + 1 + njobs = min(len(files), njobs) + + if njobs == 1: + # execute directly instead of in a pool, + # less overhead, simpler stacktraces + it = (run_clang_format_diff_wrapper(args, file) for file in files) + pool = None + else: + pool = multiprocessing.Pool(njobs) + it = pool.imap_unordered( + partial(run_clang_format_diff_wrapper, args), files) + while True: + try: + outs, errs = next(it) + except StopIteration: + break + except DiffError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + retcode = ExitStatus.TROUBLE + sys.stderr.writelines(e.errs) + except UnexpectedError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + sys.stderr.write(e.formatted_traceback) + retcode = ExitStatus.TROUBLE + # stop at the first unexpected error, + # something could be very wrong, + # don't process all files unnecessarily + if pool: + pool.terminate() + break + else: + sys.stderr.writelines(errs) + if outs == []: + continue + if not args.quiet: + print_diff(outs, use_color=colored_stdout) + if retcode == ExitStatus.SUCCESS: + retcode = ExitStatus.DIFF + return retcode + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/cmake/FindClangFormat.cmake b/cmake/FindClangFormat.cmake new file mode 100644 index 00000000..02f2fb86 --- /dev/null +++ b/cmake/FindClangFormat.cmake @@ -0,0 +1,23 @@ +# Find Clang format +# + +set(CLANG_FORMAT_BIN_NAME + clang-format + clang-format-5.0 + clang-format-6.0 + clang-format-7) + +find_program(CLANG_FORMAT_BIN NAMES ${CLANG_FORMAT_BIN_NAME}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CLANG_FORMAT DEFAULT_MSG CLANG_FORMAT_BIN) + +mark_as_advanced(CLANG_FORMAT_BIN) + +if(CLANG_FORMAT_FOUND) + # A CMake script to find all source files and setup clang-format targets for + # them + include(clang-format) +else() + message("clang-format not found. Not setting up format targets") +endif() diff --git a/cmake/FindClangTidy.cmake b/cmake/FindClangTidy.cmake index 0e9adffb..699bd8f6 100644 --- a/cmake/FindClangTidy.cmake +++ b/cmake/FindClangTidy.cmake @@ -1,17 +1,7 @@ # Find Clang tidy # -if(NOT CLANG_TIDY_BIN_NAME) - set(CLANG_TIDY_BIN_NAME clang-tidy) -endif() - -# if custom path check there first -if(CLANG_TIDY_ROOT_DIR) - find_program(CLANG_TIDY_BIN - NAMES ${CLANG_TIDY_BIN_NAME} - PATHS "${CLANG_TIDY_ROOT_DIR}" - NO_DEFAULT_PATH) -endif() +set(CLANG_TIDY_BIN_NAME clang-tidy clang-tidy-5.0 clang-tidy-6.0 clang-tidy-7) find_program(CLANG_TIDY_BIN NAMES ${CLANG_TIDY_BIN_NAME}) diff --git a/cmake/clang-format.cmake b/cmake/clang-format.cmake new file mode 100644 index 00000000..7fc6b1e8 --- /dev/null +++ b/cmake/clang-format.cmake @@ -0,0 +1,27 @@ +set(CLANG_FORMAT_CXX_FILE_EXTENSIONS + ${CLANG_FORMAT_CXX_FILE_EXTENSIONS} + *.cpp + *.h + *.cxx + *.hxx + *.hpp + *.cc + *.hh + *.ipp) + +foreach(PATTERN ${CLANG_FORMAT_CXX_FILE_EXTENSIONS}) + list(APPEND CLANG_FORMAT_CXX_PATTERN ${CMAKE_SOURCE_DIR}/src/${PATTERN}) + list(APPEND CLANG_FORMAT_CXX_PATTERN ${CMAKE_SOURCE_DIR}/tests/${PATTERN}) + list(APPEND CLANG_FORMAT_CXX_PATTERN ${CMAKE_SOURCE_DIR}/lua/${PATTERN}) +endforeach() + +file(GLOB_RECURSE CLANG_FORMAT_SRCS ${CLANG_FORMAT_CXX_PATTERN}) + +add_custom_target(clang-format + COMMAND ${CLANG_FORMAT_BIN} -style=file -i + ${CLANG_FORMAT_SRCS}) +add_custom_target(check-clang-format + COMMAND ${CMAKE_SOURCE_DIR}/bin/run-clang-format.py + --color always + --clang-format-executable ${CLANG_FORMAT_BIN} + ${CLANG_FORMAT_SRCS}) diff --git a/cmake/clang-tidy.cmake b/cmake/clang-tidy.cmake index 940775f4..bb94ba54 100644 --- a/cmake/clang-tidy.cmake +++ b/cmake/clang-tidy.cmake @@ -1,15 +1,27 @@ -# Run clang-tidy +get_target_property(CLANG_TIDY_SRCS_TMP conky SOURCES) +get_target_property(conky_SRC_DIR conky SOURCE_DIR) -set(DO_CLANG_TIDY - "${CLANG_TIDY_BIN}" - -format-style='{BasedOnStyle: - google, - IndentWidth: - 2}' - -checks=*,-clang-analyzer-alpha.* - -fix - -fix-errors) - -if(CLANG_TIDY_BIN) - set_target_properties(conky PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") +if(BUILD_TESTS) + get_target_property(CLANG_TIDY_SRCS_TMP_CORE conky_core SOURCES) + list(APPEND CLANG_TIDY_SRCS_TMP ${CLANG_TIDY_SRCS_TMP_CORE}) endif() + +foreach(TMP_SRC ${CLANG_TIDY_SRCS_TMP}) + if("${TMP_SRC}" MATCHES ".*\.cc|.*\.hh|.*\.[chi]pp|.*\.[chi]xx|.*\.ii") + list(APPEND CLANG_TIDY_SRCS ${conky_SRC_DIR}/${TMP_SRC}) + endif() +endforeach(TMP_SRC) + +get_target_property(CLANG_INCLUDES_tmp conky INCLUDE_DIRECTORIES) +foreach(TMP_INCLUDE ${CLANG_INCLUDES_tmp}) + list(APPEND CLANG_INCLUDES -I${TMP_INCLUDE}) +endforeach(TMP_INCLUDE) + +add_custom_target(clang-tidy + COMMAND ${CLANG_TIDY_BIN} -config='' -fix -format-style=file + ${CLANG_TIDY_SRCS} + -- -std=c++17 -I${CMAKE_BINARY_DIR} ${CLANG_INCLUDES}) +add_custom_target(check-clang-tidy + COMMAND ${CLANG_TIDY_BIN} -config='' -format-style=file + ${CLANG_TIDY_SRCS} + -- -std=c++17 -I${CMAKE_BINARY_DIR} ${CLANG_INCLUDES}) diff --git a/lua/libcairo-helper.h b/lua/libcairo-helper.h index 6612d9f0..3a524655 100644 --- a/lua/libcairo-helper.h +++ b/lua/libcairo-helper.h @@ -47,9 +47,6 @@ void destroy_cairo_font_extents_t(cairo_font_extents_t *pointer) { free(pointer); } -void destroy_cairo_matrix_t(cairo_matrix_t *pointer) { - free(pointer); -} - +void destroy_cairo_matrix_t(cairo_matrix_t *pointer) { free(pointer); } #endif /* _LIBCAIRO_HELPER_H_ */ diff --git a/src/audacious.h b/src/audacious.h index 1bc40e40..43f2ccdc 100644 --- a/src/audacious.h +++ b/src/audacious.h @@ -29,13 +29,16 @@ void print_audacious_title(struct text_object *, char *, unsigned int); void print_audacious_length(struct text_object *, char *, unsigned int); void print_audacious_length_seconds(struct text_object *, char *, unsigned int); void print_audacious_position(struct text_object *, char *, unsigned int); -void print_audacious_position_seconds(struct text_object *, char *, unsigned int); +void print_audacious_position_seconds(struct text_object *, char *, + unsigned int); void print_audacious_bitrate(struct text_object *, char *, unsigned int); void print_audacious_frequency(struct text_object *, char *, unsigned int); void print_audacious_channels(struct text_object *, char *, unsigned int); void print_audacious_filename(struct text_object *, char *, unsigned int); -void print_audacious_playlist_length(struct text_object *, char *, unsigned int); -void print_audacious_playlist_position(struct text_object *, char *, unsigned int); +void print_audacious_playlist_length(struct text_object *, char *, + unsigned int); +void print_audacious_playlist_position(struct text_object *, char *, + unsigned int); void print_audacious_main_volume(struct text_object *, char *, unsigned int); double audacious_barval(struct text_object *); diff --git a/src/bsdapm.cc b/src/bsdapm.cc index 194a5925..204dfa10 100644 --- a/src/bsdapm.cc +++ b/src/bsdapm.cc @@ -61,7 +61,8 @@ static int apm_getinfo(int fd, apm_info_t aip) { return 0; } -void print_apm_adapter(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_apm_adapter(struct text_object *obj, char *p, + unsigned int p_max_size) { int fd; const char *out; #ifdef __OpenBSD__ @@ -109,7 +110,8 @@ void print_apm_adapter(struct text_object *obj, char *p, unsigned int p_max_size snprintf(p, p_max_size, "%s", out); } -void print_apm_battery_life(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_apm_battery_life(struct text_object *obj, char *p, + unsigned int p_max_size) { int fd; u_int batt_life; const char *out; @@ -150,7 +152,8 @@ void print_apm_battery_life(struct text_object *obj, char *p, unsigned int p_max snprintf(p, p_max_size, "%s", out); } -void print_apm_battery_time(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_apm_battery_time(struct text_object *obj, char *p, + unsigned int p_max_size) { int fd; int batt_time; #ifdef __OpenBSD__ diff --git a/src/c++wrap.cc b/src/c++wrap.cc index eb46b147..5d1683f4 100644 --- a/src/c++wrap.cc +++ b/src/c++wrap.cc @@ -24,8 +24,8 @@ #include "c++wrap.hh" -#include #include +#include /* force use of POSIX strerror_r instead of non-portable GNU specific */ #ifdef _GNU_SOURCE @@ -42,9 +42,7 @@ namespace { int pipe2_emulate(int pipefd[2], int flags) { - if (pipe(pipefd) == -1) { - return -1; - } + if (pipe(pipefd) == -1) { return -1; } if ((flags & O_CLOEXEC) != 0) { // we emulate O_CLOEXEC if the system does not have it @@ -52,13 +50,9 @@ int pipe2_emulate(int pipefd[2], int flags) { for (int i = 0; i < 2; ++i) { int r = fcntl(pipefd[i], F_GETFD); - if (r == -1) { - return -1; - } + if (r == -1) { return -1; } - if (fcntl(pipefd[i], F_SETFD, r | FD_CLOEXEC) == -1) { - return -1; - } + if (fcntl(pipefd[i], F_SETFD, r | FD_CLOEXEC) == -1) { return -1; } } } @@ -81,8 +75,6 @@ std::string strerror_r(int errnum) { std::pair pipe2(int flags) { int fd[2]; - if (pipe2_ptr(fd, flags) == -1) { - throw errno_error("pipe2"); - } + if (pipe2_ptr(fd, flags) == -1) { throw errno_error("pipe2"); } { return std::pair(fd[0], fd[1]); } } diff --git a/src/cmus.cc b/src/cmus.cc index 7b4daedf..8ed11b91 100644 --- a/src/cmus.cc +++ b/src/cmus.cc @@ -138,7 +138,7 @@ void cmus_cb::work() { #define CMUS_PRINT_GENERATOR(type, alt) \ void print_cmus_##type(struct text_object *obj, char *p, \ - unsigned int p_max_size) { \ + unsigned int p_max_size) { \ (void)obj; \ uint32_t period = std::max( \ lround(music_player_interval.get(*state) / active_update_interval()), \ @@ -179,7 +179,8 @@ double cmus_progress(struct text_object *obj) { return (double)cmus.progress; } -void print_cmus_totaltime(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_cmus_totaltime(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state) / active_update_interval()), 1l); @@ -188,7 +189,8 @@ void print_cmus_totaltime(struct text_object *obj, char *p, unsigned int p_max_s format_seconds_short(p, p_max_size, atol(cmus.totaltime.c_str())); } -void print_cmus_timeleft(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_cmus_timeleft(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state) / active_update_interval()), 1l); @@ -198,7 +200,8 @@ void print_cmus_timeleft(struct text_object *obj, char *p, unsigned int p_max_si format_seconds_short(p, p_max_size, (long)cmus.timeleft); } -void print_cmus_curtime(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_cmus_curtime(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; uint32_t period = std::max( lround(music_player_interval.get(*state) / active_update_interval()), 1l); diff --git a/src/colours.cc b/src/colours.cc index c04fb99e..efd14086 100644 --- a/src/colours.cc +++ b/src/colours.cc @@ -63,9 +63,7 @@ static void set_up_gradient() { greenmask |= 1 << i; bluemask |= 1 << i; } - if (colour_depth % 3 == 1) { - greenmask |= 1 << (colour_depth / 3); - } + if (colour_depth % 3 == 1) { greenmask |= 1 << (colour_depth / 3); } redmask = redmask << (2 * colour_depth / 3 + colour_depth % 3); greenmask = greenmask << (colour_depth / 3); } @@ -74,9 +72,7 @@ static void set_up_gradient() { unsigned int adjust_colours(unsigned int colour) { double r, g, b; - if (colour_depth == 0) { - set_up_gradient(); - } + if (colour_depth == 0) { set_up_gradient(); } if (colour_depth == 16) { r = (colour & 0xff0000) >> 16; g = (colour & 0xff00) >> 8; @@ -100,9 +96,7 @@ unsigned long *do_gradient(int width, unsigned long first_colour, static_cast(malloc(width * sizeof(unsigned long))); int i; - if (colour_depth == 0) { - set_up_gradient(); - } + if (colour_depth == 0) { set_up_gradient(); } red1 = (first_colour & redmask) >> redshift; green1 = (first_colour & greenmask) >> greenshift; blue1 = first_colour & bluemask; @@ -139,24 +133,12 @@ unsigned long *do_gradient(int width, unsigned long first_colour, red3 += red1; green3 += green1; blue3 += blue1; - if (red3 < 0) { - red3 = 0; - } - if (green3 < 0) { - green3 = 0; - } - if (blue3 < 0) { - blue3 = 0; - } - if (red3 > bluemask) { - red3 = bluemask; - } - if (green3 > bluemask) { - green3 = bluemask; - } - if (blue3 > bluemask) { - blue3 = bluemask; - } + if (red3 < 0) { red3 = 0; } + if (green3 < 0) { green3 = 0; } + if (blue3 < 0) { blue3 = 0; } + if (red3 > bluemask) { red3 = bluemask; } + if (green3 > bluemask) { green3 = bluemask; } + if (blue3 > bluemask) { blue3 = bluemask; } colours[i] = (red3 << redshift) | (green3 << greenshift) | blue3; } return colours; diff --git a/src/darwin.h b/src/darwin.h index d25ccbda..b21a7d7b 100644 --- a/src/darwin.h +++ b/src/darwin.h @@ -54,7 +54,8 @@ int get_entropy_poolsize(const unsigned int *); /* System Integrity Protection */ int get_sip_status(void); -void print_sip_status(struct text_object *obj, char *p, unsigned int p_max_size); +void print_sip_status(struct text_object *obj, char *p, + unsigned int p_max_size); void deallocate_cpu_sample(struct text_object *obj); diff --git a/src/diskio.cc b/src/diskio.cc index 3acb7a04..1b4e564b 100644 --- a/src/diskio.cc +++ b/src/diskio.cc @@ -62,9 +62,7 @@ struct diskio_stat *prepare_diskio_stat(const char *s) { char *rpbuf; char rpbuf2[256]; - if (s == nullptr) { - return &stats; - } + if (s == nullptr) { return &stats; } if (strncmp(s, "label:", 6) == 0) { snprintf(&(device_name[0]), text_buffer_size.get(*state), @@ -101,13 +99,13 @@ struct diskio_stat *prepare_diskio_stat(const char *s) { if (strncmp(s, "label:", 6) == 0) { snprintf(&(stat_name[0]), text_buffer_size.get(*state), "/dev/%s", - &(device_name[0])); + &(device_name[0])); if ((stat(&(stat_name[0]), &sb) != 0) || !S_ISBLK(sb.st_mode)) { NORM_ERR("diskio device '%s' does not exist", &device_s[0]); } } else if ((0 == (strncmp(s, "partuuid:", 9))) && - ((stat(rpbuf2, &sb) != 0) || !S_ISBLK(sb.st_mode))) { - NORM_ERR("diskio device '%s' does not exist", &device_s[0]); + ((stat(rpbuf2, &sb) != 0) || !S_ISBLK(sb.st_mode))) { + NORM_ERR("diskio device '%s' does not exist", &device_s[0]); } #endif @@ -115,9 +113,7 @@ struct diskio_stat *prepare_diskio_stat(const char *s) { /* lookup existing */ while (cur->next != nullptr) { cur = cur->next; - if (strcmp(cur->dev, &(device_name[0])) == 0) { - return cur; - } + if (strcmp(cur->dev, &(device_name[0])) == 0) { return cur; } } /* no existing found, make a new one */ @@ -145,9 +141,7 @@ static void print_diskio_dir(struct text_object *obj, int dir, char *p, auto *diskio = static_cast(obj->data.opaque); double val; - if (diskio == nullptr) { - return; - } + if (diskio == nullptr) { return; } if (dir < 0) { val = diskio->current_read; @@ -166,11 +160,13 @@ void print_diskio(struct text_object *obj, char *p, unsigned int p_max_size) { print_diskio_dir(obj, 0, p, p_max_size); } -void print_diskio_read(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_diskio_read(struct text_object *obj, char *p, + unsigned int p_max_size) { print_diskio_dir(obj, -1, p, p_max_size); } -void print_diskio_write(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_diskio_write(struct text_object *obj, char *p, + unsigned int p_max_size) { print_diskio_dir(obj, 1, p, p_max_size); } diff --git a/src/dragonfly.cc b/src/dragonfly.cc index 06fc207d..d02971d6 100644 --- a/src/dragonfly.cc +++ b/src/dragonfly.cc @@ -347,7 +347,8 @@ int update_cpu_usage(void) { return 0; } -void free_cpu(struct text_object *) { /* no-op */ } +void free_cpu(struct text_object *) { /* no-op */ +} int update_load_average(void) { double v[3]; diff --git a/src/entropy.cc b/src/entropy.cc index 08988fd8..b509376c 100644 --- a/src/entropy.cc +++ b/src/entropy.cc @@ -27,11 +27,11 @@ * */ +#include +#include #include "config.h" #include "conky.h" #include "text_object.h" -#include -#include /* check for OS and include appropriate headers */ #if defined(__linux__) @@ -64,7 +64,8 @@ int update_entropy() { return 0; } -void print_entropy_avail(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_entropy_avail(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; snprintf(p, p_max_size, "%u", entropy.avail); } @@ -75,7 +76,8 @@ uint8_t entropy_percentage(struct text_object *obj) { static_cast(entropy.poolsize)); } -void print_entropy_poolsize(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_entropy_poolsize(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; snprintf(p, p_max_size, "%u", entropy.poolsize); } @@ -88,18 +90,16 @@ double entropy_barval(struct text_object *obj) { void print_password(struct text_object *obj, char *p, unsigned int p_max_size) { time_t t; - static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_"; + static const char letters[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*(" + ")_"; static const int len = (int)sizeof(letters) - 1; uintmax_t x = strtoumax(obj->data.s, (char **)NULL, 10); uintmax_t z = 0; - if (-1 == (t = time(NULL))) { - return; - } + if (-1 == (t = time(NULL))) { return; } srandom((unsigned int)t); - for (; z < x && p_max_size-1 > z; z++) { - *p++ = letters[random() % len]; - } + for (; z < x && p_max_size - 1 > z; z++) { *p++ = letters[random() % len]; } *p = '\0'; } diff --git a/src/exec.cc b/src/exec.cc index b998f657..db9da68a 100644 --- a/src/exec.cc +++ b/src/exec.cc @@ -27,6 +27,7 @@ * */ +#include "exec.h" #include #include #include @@ -36,7 +37,6 @@ #include #include "conky.h" #include "core.h" -#include "exec.h" #include "logging.h" #include "specials.h" #include "text_object.h" @@ -68,7 +68,7 @@ static char *remove_excess_quotes(const char *command) { } for (; *command_ptr; command_ptr++) { - if ('\0' == *(command_ptr+1) && 1 == skip && + if ('\0' == *(command_ptr + 1) && 1 == skip && (*command_ptr == '"' || *command_ptr == '\'')) { continue; } @@ -122,7 +122,8 @@ static FILE *pid_popen(const char *command, const char *mode, pid_t *child) { if (fcntl(childend, F_DUPFD, 0) == -1) { perror("fcntl()"); } close(childend); - execl("/bin/sh", "sh", "-c", remove_excess_quotes(command), (char *)nullptr); + execl("/bin/sh", "sh", "-c", remove_excess_quotes(command), + (char *)nullptr); _exit(EXIT_FAILURE); // child should die here, (normally execl will take // care of this but it can fail) } diff --git a/src/i8k.cc b/src/i8k.cc index 8b08c0b1..d4ca6c24 100644 --- a/src/i8k.cc +++ b/src/i8k.cc @@ -56,13 +56,11 @@ static char *i8k_procbuf = nullptr; int update_i8k(void) { FILE *fp; - if (!i8k_procbuf) { - i8k_procbuf = (char *)malloc(128 * sizeof(char)); - } + if (!i8k_procbuf) { i8k_procbuf = (char *)malloc(128 * sizeof(char)); } if ((fp = fopen(PROC_I8K, "r")) == nullptr) { free_and_zero(i8k_procbuf); - /*THREAD_CRIT_ERR(nullptr, NULL, "/proc/i8k doesn't exist! use insmod to make - sure the kernel " "driver is loaded...");*/ + /*THREAD_CRIT_ERR(nullptr, NULL, "/proc/i8k doesn't exist! use insmod to + make sure the kernel " "driver is loaded...");*/ NORM_ERR( "/proc/i8k doesn't exist! use insmod to make sure the kernel driver is " "loaded..."); @@ -107,7 +105,8 @@ void print_i8k_left_fan_status(struct text_object *obj, char *p, print_i8k_fan_status(p, p_max_size, i8k.left_fan_status); } -void print_i8k_cpu_temp(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_i8k_cpu_temp(struct text_object *obj, char *p, + unsigned int p_max_size) { int cpu_temp; (void)obj; @@ -122,7 +121,8 @@ void print_i8k_right_fan_status(struct text_object *obj, char *p, print_i8k_fan_status(p, p_max_size, i8k.right_fan_status); } -void print_i8k_ac_status(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_i8k_ac_status(struct text_object *obj, char *p, + unsigned int p_max_size) { int ac_status; (void)obj; @@ -131,19 +131,15 @@ void print_i8k_ac_status(struct text_object *obj, char *p, unsigned int p_max_si if (ac_status == -1) { snprintf(p, p_max_size, "%s", "disabled (read i8k docs)"); } - if (ac_status == 0) { - snprintf(p, p_max_size, "%s", "off"); - } - if (ac_status == 1) { - snprintf(p, p_max_size, "%s", "on"); - } + if (ac_status == 0) { snprintf(p, p_max_size, "%s", "off"); } + if (ac_status == 1) { snprintf(p, p_max_size, "%s", "on"); } } -#define I8K_PRINT_GENERATOR(name) \ - void print_i8k_##name(struct text_object *obj, char *p, \ - unsigned int p_max_size) { \ - (void)obj; \ - snprintf(p, p_max_size, "%s", i8k.name); \ +#define I8K_PRINT_GENERATOR(name) \ + void print_i8k_##name(struct text_object *obj, char *p, \ + unsigned int p_max_size) { \ + (void)obj; \ + snprintf(p, p_max_size, "%s", i8k.name); \ } I8K_PRINT_GENERATOR(version) diff --git a/src/ibm.cc b/src/ibm.cc index 31b2afaa..13f0ca4e 100644 --- a/src/ibm.cc +++ b/src/ibm.cc @@ -72,16 +72,15 @@ speed: 2944 commands: enable, disable * Peter Tarjan (ptarjan@citromail.hu) */ -void get_ibm_acpi_fan(struct text_object *obj, char *p, unsigned int p_max_size) { +void get_ibm_acpi_fan(struct text_object *obj, char *p, + unsigned int p_max_size) { FILE *fp; unsigned int speed = 0; char fan[128]; (void)obj; - if (!p || p_max_size <= 0) { - return; - } + if (!p || p_max_size <= 0) { return; } snprintf(fan, 127, "%s/fan", IBM_ACPI_DIR); @@ -90,12 +89,8 @@ void get_ibm_acpi_fan(struct text_object *obj, char *p, unsigned int p_max_size) while (!feof(fp)) { char line[256]; - if (fgets(line, 255, fp) == nullptr) { - break; - } - if (sscanf(line, "speed: %u", &speed)) { - break; - } + if (fgets(line, 255, fp) == nullptr) { break; } + if (sscanf(line, "speed: %u", &speed)) { break; } } } else { CRIT_ERR(nullptr, NULL, @@ -140,9 +135,7 @@ int get_ibm_acpi_temps(void) { while (!feof(fp)) { char line[256]; - if (fgets(line, 255, fp) == nullptr) { - break; - } + if (fgets(line, 255, fp) == nullptr) { break; } if (sscanf(line, "temperatures: %d %d %d %d %d %d %d %d", &ibm_acpi_temps[0], &ibm_acpi_temps[1], &ibm_acpi_temps[2], &ibm_acpi_temps[3], &ibm_acpi_temps[4], &ibm_acpi_temps[5], @@ -171,7 +164,8 @@ commands: up, down, mute commands: level ( is 0-15) * Peter Tarjan (ptarjan@citromail.hu) */ -void get_ibm_acpi_volume(struct text_object *obj, char *p, unsigned int p_max_size) { +void get_ibm_acpi_volume(struct text_object *obj, char *p, + unsigned int p_max_size) { FILE *fp; char volume[128]; unsigned int vol = -1; @@ -179,9 +173,7 @@ void get_ibm_acpi_volume(struct text_object *obj, char *p, unsigned int p_max_si (void)obj; - if (!p || p_max_size <= 0) { - return; - } + if (!p || p_max_size <= 0) { return; } snprintf(volume, 127, "%s/volume", IBM_ACPI_DIR); @@ -191,16 +183,12 @@ void get_ibm_acpi_volume(struct text_object *obj, char *p, unsigned int p_max_si char line[256]; unsigned int read_vol = -1; - if (fgets(line, 255, fp) == nullptr) { - break; - } + if (fgets(line, 255, fp) == nullptr) { break; } if (sscanf(line, "level: %u", &read_vol)) { vol = read_vol; continue; } - if (sscanf(line, "mute: %s", mute)) { - break; - } + if (sscanf(line, "mute: %s", mute)) { break; } } } else { CRIT_ERR(nullptr, NULL, @@ -226,16 +214,15 @@ commands: up, down commands: level ( is 0-7) * Peter Tarjan (ptarjan@citromail.hu) */ -void get_ibm_acpi_brightness(struct text_object *obj, char *p, unsigned int p_max_size) { +void get_ibm_acpi_brightness(struct text_object *obj, char *p, + unsigned int p_max_size) { FILE *fp; unsigned int brightness = 0; char filename[128]; (void)obj; - if (!p || p_max_size <= 0) { - return; - } + if (!p || p_max_size <= 0) { return; } snprintf(filename, 127, "%s/brightness", IBM_ACPI_DIR); @@ -244,12 +231,8 @@ void get_ibm_acpi_brightness(struct text_object *obj, char *p, unsigned int p_ma while (!feof(fp)) { char line[256]; - if (fgets(line, 255, fp) == nullptr) { - break; - } - if (sscanf(line, "level: %u", &brightness)) { - break; - } + if (fgets(line, 255, fp) == nullptr) { break; } + if (sscanf(line, "level: %u", &brightness)) { break; } } } else { CRIT_ERR(nullptr, NULL, @@ -271,16 +254,15 @@ commands: on, off * get "unknown" for a few models that do not make the status available. * Lluis Esquerda (eskerda@gmail.com) */ -void get_ibm_acpi_thinklight(struct text_object *obj, char *p, unsigned int p_max_size) { +void get_ibm_acpi_thinklight(struct text_object *obj, char *p, + unsigned int p_max_size) { FILE *fp; char thinklight[8]; char filename[128]; (void)obj; - if (!p || p_max_size <= 0) { - return; - } + if (!p || p_max_size <= 0) { return; } snprintf(filename, 127, "%s/light", IBM_ACPI_DIR); @@ -289,12 +271,8 @@ void get_ibm_acpi_thinklight(struct text_object *obj, char *p, unsigned int p_ma while (!feof(fp)) { char line[256]; - if (fgets(line, 255, fp) == nullptr) { - break; - } - if (sscanf(line, "status: %s", thinklight)) { - break; - } + if (fgets(line, 255, fp) == nullptr) { break; } + if (sscanf(line, "status: %s", thinklight)) { break; } } } else { CRIT_ERR(nullptr, NULL, @@ -317,6 +295,7 @@ void parse_ibm_temps_arg(struct text_object *obj, const char *arg) { obj->data.l = atoi(arg); } -void print_ibm_temps(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_ibm_temps(struct text_object *obj, char *p, + unsigned int p_max_size) { temp_print(p, p_max_size, ibm_acpi_temps[obj->data.l], TEMP_CELSIUS, 1); } diff --git a/src/iconv_tools.cc b/src/iconv_tools.cc index 9ba2a96b..c4ad0e01 100644 --- a/src/iconv_tools.cc +++ b/src/iconv_tools.cc @@ -44,13 +44,9 @@ static iconv_t **iconv_cd = 0; int register_iconv(iconv_t *new_iconv) { iconv_cd = (void ***)realloc(iconv_cd, sizeof(iconv_t *) * (iconv_count + 1)); - if (!iconv_cd) { - CRIT_ERR(nullptr, NULL, "Out of memory"); - } + if (!iconv_cd) { CRIT_ERR(nullptr, NULL, "Out of memory"); } iconv_cd[iconv_count] = (void **)malloc(sizeof(iconv_t)); - if (!iconv_cd[iconv_count]) { - CRIT_ERR(nullptr, NULL, "Out of memory"); - } + if (!iconv_cd[iconv_count]) { CRIT_ERR(nullptr, NULL, "Out of memory"); } memcpy(iconv_cd[iconv_count], new_iconv, sizeof(iconv_t)); iconv_count++; return iconv_count; @@ -135,7 +131,8 @@ void init_iconv_start(struct text_object *obj, void *free_at_crash, void init_iconv_stop(void) { iconv_converting = 0; } -void print_iconv_start(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_iconv_start(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)p; (void)p_max_size; @@ -143,7 +140,8 @@ void print_iconv_start(struct text_object *obj, char *p, unsigned int p_max_size iconv_selected = obj->data.i; } -void print_iconv_stop(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_iconv_stop(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; (void)p; (void)p_max_size; diff --git a/src/imlib2.cc b/src/imlib2.cc index 70faade7..955ff8ef 100644 --- a/src/imlib2.cc +++ b/src/imlib2.cc @@ -62,8 +62,7 @@ conky::range_config_setting imlib_cache_flush_interval( unsigned int cimlib_cache_flush_last = 0; -conky::simple_config_setting draw_blended( - "draw_blended", true, true); +conky::simple_config_setting draw_blended("draw_blended", true, true); } // namespace void imlib_cache_size_setting::lua_setter(lua::state &l, bool init) { @@ -123,7 +122,7 @@ void cimlib_add_image(const char *args) { "Invalid args for $image. Format is: ' (-p" "x,y) (-s WxH) (-n) (-f interval)' (got '%s')", args); - delete [] cur; + delete[] cur; return; } strncpy(cur->name, to_real_path(cur->name).c_str(), 1024); @@ -138,22 +137,16 @@ void cimlib_add_image(const char *args) { tmp = strstr(args, "-s "); if (tmp != nullptr) { tmp += 3; - if (sscanf(tmp, "%ix%i", &cur->w, &cur->h) != 0) { - cur->wh_set = 1; - } + if (sscanf(tmp, "%ix%i", &cur->w, &cur->h) != 0) { cur->wh_set = 1; } } tmp = strstr(args, "-n"); - if (tmp != nullptr) { - cur->no_cache = 1; - } + if (tmp != nullptr) { cur->no_cache = 1; } tmp = strstr(args, "-f "); if (tmp != nullptr) { tmp += 3; - if (sscanf(tmp, "%d", &cur->flush_interval) != 0) { - cur->no_cache = 0; - } + if (sscanf(tmp, "%d", &cur->flush_interval) != 0) { cur->no_cache = 0; } } if (cur->flush_interval < 0) { NORM_ERR("Imlib2: flush interval should be >= 0"); @@ -180,9 +173,7 @@ static void cimlib_draw_image(struct image_list_s *cur, int *clip_x, image = imlib_load_image(cur->name); if (image == nullptr) { - if (rep == 0) { - NORM_ERR("Unable to load image '%s'", cur->name); - } + if (rep == 0) { NORM_ERR("Unable to load image '%s'", cur->name); } rep = 1; return; } @@ -213,18 +204,10 @@ static void cimlib_draw_image(struct image_list_s *cur, int *clip_x, } else { imlib_free_image(); } - if (cur->x < *clip_x) { - *clip_x = cur->x; - } - if (cur->y < *clip_y) { - *clip_y = cur->y; - } - if (cur->x + cur->w > *clip_x2) { - *clip_x2 = cur->x + cur->w; - } - if (cur->y + cur->h > *clip_y2) { - *clip_y2 = cur->y + cur->h; - } + if (cur->x < *clip_x) { *clip_x = cur->x; } + if (cur->y < *clip_y) { *clip_y = cur->y; } + if (cur->x + cur->w > *clip_x2) { *clip_x2 = cur->x + cur->w; } + if (cur->y + cur->h > *clip_y2) { *clip_y2 = cur->y + cur->h; } } static void cimlib_draw_all(int *clip_x, int *clip_y, int *clip_x2, @@ -280,12 +263,8 @@ void cimlib_render(int x, int y, int width, int height) { imlib_context_set_image(buffer); /* setup our clip rect */ - if (clip_x == INT_MAX) { - clip_x = 0; - } - if (clip_y == INT_MAX) { - clip_y = 0; - } + if (clip_x == INT_MAX) { clip_x = 0; } + if (clip_y == INT_MAX) { clip_y = 0; } /* render the image at 0, 0 */ imlib_render_image_part_on_drawable_at_size( @@ -295,7 +274,6 @@ void cimlib_render(int x, int y, int width, int height) { imlib_free_image(); } -void print_image_callback(struct text_object *obj, char *, - unsigned int) { +void print_image_callback(struct text_object *obj, char *, unsigned int) { cimlib_add_image(obj->data.s); } diff --git a/src/libtcp-portmon.cc b/src/libtcp-portmon.cc index e40fcb7a..caf3bd34 100644 --- a/src/libtcp-portmon.cc +++ b/src/libtcp-portmon.cc @@ -114,7 +114,8 @@ struct _tcp_port_monitor_t { _tcp_port_monitor_t(int max_connections) : hash(), - p_peek(max_connections, static_cast(nullptr)) {} + p_peek(max_connections, + static_cast(nullptr)) {} _tcp_port_monitor_t(const _tcp_port_monitor_t &other) : hash(other.hash), @@ -202,9 +203,7 @@ void show_connection_to_tcp_port_monitor(monitor_hash_t::value_type &monitor, tcp_connection_t *p_connection; - if (!p_void) { - return; - } + if (!p_void) { return; } /* This p_connection is on caller's stack and not the heap. * If we are interested, we will create a copy of the connection @@ -242,9 +241,7 @@ void show_connection_to_tcp_port_monitor(monitor_hash_t::value_type &monitor, void for_each_tcp_port_monitor_in_collection( tcp_port_monitor_collection_t *p_collection, tcp_port_monitor_function_ptr_t p_function, void *p_function_args) { - if (!p_collection || !p_function) { - return; - } + if (!p_collection || !p_function) { return; } /* for each monitor in the collection */ for (monitor_hash_t::iterator i = p_collection->hash.begin(); @@ -318,9 +315,7 @@ void process_file(tcp_port_monitor_collection_t *p_collection, tcp_connection_t conn; unsigned long inode, uid, state; - if ((fp = std::fopen(file, "r")) == nullptr) { - return; - } + if ((fp = std::fopen(file, "r")) == nullptr) { return; } /* ignore field name line */ if (std::fgets(buf, 255, fp) == nullptr) { @@ -340,9 +335,7 @@ void process_file(tcp_port_monitor_collection_t *p_collection, } /** TCP_ESTABLISHED equals 1, but is not (always??) included **/ // if ((inode == 0) || (state != TCP_ESTABLISHED)) { - if ((inode == 0) || (state != 1)) { - continue; - } + if ((inode == 0) || (state != 1)) { continue; } string_to_addr(&conn.local_addr, local_addr); string_to_addr(&conn.remote_addr, remote_addr); @@ -375,9 +368,7 @@ int peek_tcp_port_monitor(const tcp_port_monitor_t *p_monitor, int item, size_t buffer_size) { struct sockaddr_in sa; - if (!p_monitor || !p_buffer || connection_index < 0) { - return -1; - } + if (!p_monitor || !p_buffer || connection_index < 0) { return -1; } std::memset(p_buffer, 0, buffer_size); std::memset(&sa, 0, sizeof(sa)); @@ -419,8 +410,8 @@ int peek_tcp_port_monitor(const tcp_port_monitor_t *p_monitor, int item, case REMOTESERVICE: sa.sin_port = htons(p_monitor->p_peek[connection_index]->remote_port); - getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), nullptr, 0, - p_buffer, buffer_size, NI_NUMERICHOST); + getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), nullptr, + 0, p_buffer, buffer_size, NI_NUMERICHOST); break; case LOCALIP: @@ -444,8 +435,8 @@ int peek_tcp_port_monitor(const tcp_port_monitor_t *p_monitor, int item, case LOCALSERVICE: sa.sin_port = htons(p_monitor->p_peek[connection_index]->local_port); - getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), nullptr, 0, - p_buffer, buffer_size, NI_NUMERICHOST); + getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), nullptr, + 0, p_buffer, buffer_size, NI_NUMERICHOST); break; default: @@ -474,9 +465,7 @@ void destroy_tcp_port_monitor_collection( /* Updates the tcp statistics for all monitors within a collection */ void update_tcp_port_monitor_collection( tcp_port_monitor_collection_t *p_collection) { - if (!p_collection) { - return; - } + if (!p_collection) { return; } process_file(p_collection, "/proc/net/tcp"); process_file(p_collection, "/proc/net/tcp6"); @@ -495,9 +484,7 @@ void update_tcp_port_monitor_collection( int insert_new_tcp_port_monitor_into_collection( tcp_port_monitor_collection_t *p_collection, in_port_t port_range_begin, in_port_t port_range_end, tcp_port_monitor_args_t *p_creation_args) { - if (!p_collection) { - return -1; - } + if (!p_collection) { return -1; } p_collection->hash.insert(monitor_hash_t::value_type( port_range_t(port_range_begin, port_range_end), @@ -510,9 +497,7 @@ int insert_new_tcp_port_monitor_into_collection( tcp_port_monitor_t *find_tcp_port_monitor( tcp_port_monitor_collection_t *p_collection, in_port_t port_range_begin, in_port_t port_range_end) { - if (!p_collection) { - return nullptr; - } + if (!p_collection) { return nullptr; } /* is monitor in hash? */ monitor_hash_t::iterator i = diff --git a/src/linux.cc b/src/linux.cc index 51aaec72..14fe9107 100644 --- a/src/linux.cc +++ b/src/linux.cc @@ -1126,8 +1126,7 @@ static int get_first_file_in_a_directory(const char *dir, char *s, int *rep) { /* * Convert @dev "0" (hwmon number) or "k10temp" (hwmon name) to "hwmon2/device" */ -static void get_dev_path(const char *dir, const char *dev, char *out_buf) -{ +static void get_dev_path(const char *dir, const char *dev, char *out_buf) { struct dirent **namelist; char path[256] = {'\0'}; char name[256] = {'\0'}; @@ -1151,18 +1150,15 @@ static void get_dev_path(const char *dir, const char *dev, char *out_buf) NORM_ERR("scandir for %s: %s", dir, strerror(errno)); goto not_found; } - if (n == 0) - goto not_found; + if (n == 0) goto not_found; /* Search each hwmon%s/name */ for (i = 0; i < n; i++) { - if (found) - continue; + if (found) continue; snprintf(path, 256, "%s%s/name", dir, namelist[i]->d_name); name_fd = open(path, O_RDONLY); - if (name_fd < 0) - continue; + if (name_fd < 0) continue; size = read(name_fd, name, strlen(dev)); if (size < strlen(dev)) { close(name_fd); @@ -1177,11 +1173,9 @@ static void get_dev_path(const char *dir, const char *dev, char *out_buf) } /* cleanup */ - for (i = 0; i < n; i++) - free(namelist[i]); + for (i = 0; i < n; i++) free(namelist[i]); free(namelist); - if (found) - return; + if (found) return; not_found: out_buf[0] = '\0'; diff --git a/src/luamm.cc b/src/luamm.cc index 346261d5..03bbc644 100644 --- a/src/luamm.cc +++ b/src/luamm.cc @@ -49,14 +49,12 @@ const char this_cpp_object[] = "lua::this_cpp_object"; // converts C++ exceptions to strings, so lua can do something with them int exception_to_string(lua_State *l) { - auto *ptr = static_cast(lua_touserdata(l, -1)); - assert(ptr); - try { - std::rethrow_exception(*ptr); - } catch (std::exception &e) { - lua_pushstring(l, e.what()); - } catch (...) { - lua_pushstring(l, typeid(*ptr).name()); + auto *ptr = static_cast(lua_touserdata(l, -1)); + assert(ptr); + try { + std::rethrow_exception(*ptr); + } catch (std::exception &e) { lua_pushstring(l, e.what()); } catch (...) { + lua_pushstring(l, typeid(*ptr).name()); } return 1; } @@ -68,12 +66,9 @@ int absindex(lua_State *l, int index) { // Just like getfield(), only without calling metamethods (or throwing random // exceptions) -inline void rawgetfield(lua_State *l, int index, - const char *k) { +inline void rawgetfield(lua_State *l, int index, const char *k) { index = absindex(l, index); - if (lua_checkstack(l, 1) == 0) { - throw std::bad_alloc(); - } + if (lua_checkstack(l, 1) == 0) { throw std::bad_alloc(); } lua_pushstring(l, k); lua_rawget(l, index); @@ -81,12 +76,9 @@ inline void rawgetfield(lua_State *l, int index, // Just like setfield(), only without calling metamethods (or throwing random // exceptions) -inline void rawsetfield(lua_State *l, int index, - const char *k) { +inline void rawsetfield(lua_State *l, int index, const char *k) { index = absindex(l, index); - if (lua_checkstack(l, 2) == 0) { - throw std::bad_alloc(); - } + if (lua_checkstack(l, 2) == 0) { throw std::bad_alloc(); } lua_pushstring(l, k); lua_insert(l, -2); @@ -130,9 +122,7 @@ int closure_trampoline(lua_State *l) { * execute everything in protected mode). */ int panic_throw(lua_State *l) { - if (lua_checkstack(l, 1) == 0) { - throw std::bad_alloc(); - } + if (lua_checkstack(l, 1) == 0) { throw std::bad_alloc(); } rawgetfield(l, REGISTRYINDEX, this_cpp_object); assert(lua_islightuserdata(l, -1)); @@ -191,9 +181,7 @@ std::string exception::get_error_msg(state *L) { try { return L->tostring(-1); - } catch (not_string_error &e) { - return default_msg; - } + } catch (not_string_error &e) { return default_msg; } } exception::exception(state *l) : std::runtime_error(get_error_msg(l)), L(l) { @@ -206,9 +194,7 @@ exception::exception(state *l) : std::runtime_error(get_error_msg(l)), L(l) { } exception::~exception() { - if (L == nullptr) { - return; - } + if (L == nullptr) { return; } L->checkstack(1); L->rawgetfield(REGISTRYINDEX, lua_exception_namespace); @@ -272,9 +258,7 @@ state::state() { void state::call(int nargs, int nresults, int errfunc) { int r = lua_pcall(cobj.get(), nargs, nresults, errfunc); - if (r == 0) { - return; - } + if (r == 0) { return; } if (r == LUA_ERRMEM) { // memory allocation error, cross your fingers @@ -301,16 +285,12 @@ void state::call(int nargs, int nresults, int errfunc) { pop(2); } // it's a lua exception, wrap it - if (r == LUA_ERRERR) { - throw lua::errfunc_error(this); - } + if (r == LUA_ERRERR) { throw lua::errfunc_error(this); } { throw lua::exception(this); } } void state::checkstack(int extra) { - if (lua_checkstack(cobj.get(), extra) == 0) { - throw std::bad_alloc(); - } + if (lua_checkstack(cobj.get(), extra) == 0) { throw std::bad_alloc(); } } void state::concat(int n) { @@ -323,9 +303,7 @@ void state::concat(int n) { bool state::equal(int index1, int index2) { // avoid pcall overhead in trivial cases - if (rawequal(index1, index2)) { - return true; - } + if (rawequal(index1, index2)) { return true; } return safe_compare(&safe_compare_trampoline, index1, index2); } @@ -438,9 +416,7 @@ void state::rawsetfield(int index, const char *k) { bool state::safe_compare(lua_CFunction trampoline, int index1, int index2) { // if one of the indexes is invalid, return false - if (isnone(index1) || isnone(index2)) { - return false; - } + if (isnone(index1) || isnone(index2)) { return false; } // convert relative indexes into absolute index1 = absindex(index1); @@ -491,9 +467,7 @@ void state::settable(int index) { std::string state::tostring(int index) { size_t len; const char *str = lua_tolstring(cobj.get(), index, &len); - if (str == nullptr) { - throw not_string_error(); - } + if (str == nullptr) { throw not_string_error(); } return std::string(str, len); } } // namespace lua diff --git a/src/luamm.hh b/src/luamm.hh index 2d62a1ec..78e083dd 100644 --- a/src/luamm.hh +++ b/src/luamm.hh @@ -152,8 +152,7 @@ class state : private std::mutex { // throwing exceptions in destructors is a bad idea // but we catch (and ignore) them, just in case ptr->~T(); - } catch (...) { - } + } catch (...) {} return 0; } @@ -305,9 +304,9 @@ class state : private std::mutex { void setfield(int index, const char *k); void setglobal(const char *name); void settable(int index); - // lua_tostring uses nullptr to indicate conversion error, since there is no such - // thing as a nullptr std::string, we throw an exception. Returned value may - // contain '\0' + // lua_tostring uses nullptr to indicate conversion error, since there is no + // such thing as a nullptr std::string, we throw an exception. Returned value + // may contain '\0' std::string tostring(int index); // allocate a new lua userdata of appropriate size, and create a object in it // pushes the userdata on stack and returns the pointer @@ -343,8 +342,7 @@ class stack_sentry { const stack_sentry &operator=(const stack_sentry &) = delete; public: - explicit stack_sentry(state &l, int n_ = 0) - : L(&l), n(l.gettop() + n_) { + explicit stack_sentry(state &l, int n_ = 0) : L(&l), n(l.gettop() + n_) { assert(n >= 0); } diff --git a/src/main.cc b/src/main.cc index 0e7e45a4..64433c9c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -181,8 +181,8 @@ static void print_version() { << _(" * Own window\n") #endif #endif /* BUILD_X11 */ -#if defined BUILD_AUDACIOUS || defined BUILD_CMUS || \ - defined BUILD_MPD || defined BUILD_MOC || defined BUILD_XMMS2 +#if defined BUILD_AUDACIOUS || defined BUILD_CMUS || defined BUILD_MPD || \ + defined BUILD_MOC || defined BUILD_XMMS2 << _("\n Music detection:\n") #endif #ifdef BUILD_AUDACIOUS diff --git a/src/mboxscan.cc b/src/mboxscan.cc index 4293c074..693bb241 100644 --- a/src/mboxscan.cc +++ b/src/mboxscan.cc @@ -86,9 +86,7 @@ static void mbox_scan(char *args, char *output, size_t max_len) { } else { print_num_mails = PRINT_MAILS; } - if (print_num_mails < 1) { - print_num_mails = 1; - } + if (print_num_mails < 1) { print_num_mails = 1; } substr = strstr(args, "-t"); if (substr != nullptr) { @@ -131,9 +129,7 @@ static void mbox_scan(char *args, char *output, size_t max_len) { while (tmp != nullptr) { tmp = strtok(nullptr, " "); - if (tmp != nullptr) { - start = tmp; - } + if (tmp != nullptr) { start = tmp; } } strncpy(mbox_mail_spool, start, DEFAULT_TEXT_BUFFER_SIZE); free(copy_args); @@ -189,9 +185,7 @@ static void mbox_scan(char *args, char *output, size_t max_len) { curr->from[0] = '\0'; curr->subject[0] = '\0'; - if (i == 0) { - startlist = curr; - } + if (i == 0) { startlist = curr; } if (i > 0) { curr->previous = prev; prev->next = curr; @@ -199,34 +193,26 @@ static void mbox_scan(char *args, char *output, size_t max_len) { prev = curr; } - if (startlist == nullptr) { - return; - } + if (startlist == nullptr) { return; } /* connect end to start for an endless loop-ring */ startlist->previous = curr; curr->next = startlist; /* mbox */ fp = fopen(mbox_mail_spool, "re"); - if (fp == nullptr) { - return; - } + if (fp == nullptr) { return; } /* first find a "From " to set it to 0 for header-sarchings */ flag = 1; while (feof(fp) == 0) { - if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { - break; - } + if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { break; } if (strncmp(buf, "From ", 5) == 0) { curr = curr->next; /* skip until \n */ while (strchr(buf, '\n') == nullptr && (feof(fp) == 0)) { - if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { - break; - } + if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { break; } } flag = 0; /* in the headers now */ @@ -242,9 +228,7 @@ static void mbox_scan(char *args, char *output, size_t max_len) { /* then search for new mail ("From ") */ while (strchr(buf, '\n') == nullptr && (feof(fp) == 0)) { - if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { - break; - } + if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { break; } } flag = 1; /* in the body now */ continue; @@ -260,9 +244,7 @@ static void mbox_scan(char *args, char *output, size_t max_len) { curr = curr->previous; /* Skip until \n */ while (strchr(buf, '\n') == nullptr && (feof(fp) == 0)) { - if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { - break; - } + if (fgets(buf, text_buffer_size.get(*state), fp) == nullptr) { break; } } continue; } @@ -398,9 +380,7 @@ void parse_mboxscan_arg(struct text_object *obj, const char *arg) { void print_mboxscan(struct text_object *obj, char *p, unsigned int p_max_size) { auto *msd = static_cast(obj->data.opaque); - if (msd == nullptr) { - return; - } + if (msd == nullptr) { return; } mbox_scan(msd->args, msd->output, text_buffer_size.get(*state)); snprintf(p, p_max_size, "%s", msd->output); @@ -409,9 +389,7 @@ void print_mboxscan(struct text_object *obj, char *p, unsigned int p_max_size) { void free_mboxscan(struct text_object *obj) { auto *msd = static_cast(obj->data.opaque); - if (msd == nullptr) { - return; - } + if (msd == nullptr) { return; } free_and_zero(msd->args); free_and_zero(msd->output); free_and_zero(obj->data.opaque); diff --git a/src/mixer.cc b/src/mixer.cc index a707794a..19605ec8 100644 --- a/src/mixer.cc +++ b/src/mixer.cc @@ -59,9 +59,7 @@ static const char *devs[] = SOUND_DEVICE_NAMES; int mixer_init(const char *name) { unsigned int i; - if (name == 0 || name[0] == '\0') { - name = "vol"; - } + if (name == 0 || name[0] == '\0') { name = "vol"; } /* open mixer */ if (mixer_fd <= 0) { @@ -73,9 +71,7 @@ int mixer_init(const char *name) { } for (i = 0; i < sizeof(devs) / sizeof(const char *); i++) { - if (strcasecmp(devs[i], name) == 0) { - return i; - } + if (strcasecmp(devs[i], name) == 0) { return i; } } return -1; @@ -86,9 +82,7 @@ static int mixer_get(int i) { int val = -1; if (ioctl(mixer_fd, MIXER_READ(i), &val) == -1) { - if (!rep) { - NORM_ERR("mixer ioctl: %s", strerror(errno)); - } + if (!rep) { NORM_ERR("mixer ioctl: %s", strerror(errno)); } rep = 1; return 0; } diff --git a/src/moc.cc b/src/moc.cc index 5d4779fd..1804bb24 100644 --- a/src/moc.cc +++ b/src/moc.cc @@ -70,12 +70,8 @@ void moc_cb::work() { char *p; /* Read a line from the pipe and strip the possible '\n'. */ - if (fgets(line, 100, fp) == nullptr) { - break; - } - if ((p = strrchr(line, '\n')) != nullptr) { - *p = '\0'; - } + if (fgets(line, 100, fp) == nullptr) { break; } + if ((p = strrchr(line, '\n')) != nullptr) { *p = '\0'; } /* Parse infos. */ if (strncmp(line, "State:", 6) == 0) { @@ -113,7 +109,7 @@ void moc_cb::work() { #define MOC_PRINT_GENERATOR(type, alt) \ void print_moc_##type(struct text_object *obj, char *p, \ - unsigned int p_max_size) { \ + unsigned int p_max_size) { \ (void)obj; \ uint32_t period = std::max( \ lround(music_player_interval.get(*state) / active_update_interval()), \ diff --git a/src/mpd.cc b/src/mpd.cc index 1647c7db..3509e40d 100644 --- a/src/mpd.cc +++ b/src/mpd.cc @@ -27,13 +27,13 @@ */ #include "mpd.h" +#include +#include #include "conky.h" #include "libmpdclient.h" #include "logging.h" #include "timeinfo.h" #include "update-cb.hh" -#include -#include namespace { @@ -61,9 +61,7 @@ void mpd_host_setting::lua_setter(lua::state &l, bool init) { l.checkstack(1); const char *h = strchr(t, '@'); if (h != nullptr) { - if (h[1] != 0) { - l.pushstring(h + 1); - } + if (h[1] != 0) { l.pushstring(h + 1); } } else { l.pushstring(t); } @@ -147,9 +145,7 @@ class mpd_cb : public conky::callback { : Base(period, false, Tuple()), conn(nullptr) {} ~mpd_cb() override { - if (conn != nullptr) { - mpd_closeConnection(conn); - } + if (conn != nullptr) { mpd_closeConnection(conn); } } }; @@ -234,9 +230,9 @@ void mpd_cb::work() { mpd_info.is_playing = 1; mpd_info.bitrate = status->bitRate; mpd_info.progress = - ((0 != status->totalTime) ? - static_cast(status->elapsedTime) / status->totalTime - : 0.0); + ((0 != status->totalTime) + ? static_cast(status->elapsedTime) / status->totalTime + : 0.0); mpd_info.elapsed = status->elapsedTime; mpd_info.length = status->totalTime; } else { @@ -335,12 +331,14 @@ static inline void format_media_player_time(char *buf, const int size, } } -void print_mpd_elapsed(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_mpd_elapsed(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; format_media_player_time(p, p_max_size, get_mpd().elapsed); } -void print_mpd_length(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_mpd_length(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; format_media_player_time(p, p_max_size, get_mpd().length); } @@ -355,12 +353,11 @@ double mpd_barval(struct text_object *obj) { return get_mpd().progress; } -void print_mpd_smart(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_mpd_smart(struct text_object *obj, char *p, + unsigned int p_max_size) { const mpd_result &mpd_info = get_mpd(); int len = obj->data.i; - if (len == 0 || (unsigned int) len > p_max_size) { - len = p_max_size; - } + if (len == 0 || (unsigned int)len > p_max_size) { len = p_max_size; } memset(p, 0, p_max_size); if ((static_cast(!mpd_info.artist.empty()) != 0u) && @@ -383,11 +380,12 @@ int check_mpd_playing(struct text_object *obj) { return get_mpd().is_playing; } -#define MPD_PRINT_GENERATOR(name, fmt, acc) \ - void print_mpd_##name(struct text_object *obj, char *p, \ - unsigned int p_max_size) { \ - if (obj->data.i && (unsigned int) obj->data.i < p_max_size) p_max_size = obj->data.i; \ - snprintf(p, p_max_size, fmt, get_mpd().name acc); \ +#define MPD_PRINT_GENERATOR(name, fmt, acc) \ + void print_mpd_##name(struct text_object *obj, char *p, \ + unsigned int p_max_size) { \ + if (obj->data.i && (unsigned int)obj->data.i < p_max_size) \ + p_max_size = obj->data.i; \ + snprintf(p, p_max_size, fmt, get_mpd().name acc); \ } MPD_PRINT_GENERATOR(title, "%s", .c_str()) diff --git a/src/mysql.cc b/src/mysql.cc index bf94dac5..9e3562e2 100644 --- a/src/mysql.cc +++ b/src/mysql.cc @@ -26,9 +26,9 @@ * */ +#include "mysql.h" #include "conky.h" #include "logging.h" -#include "mysql.h" #include diff --git a/src/nc.cc b/src/nc.cc index 513eb7fc..96318fde 100644 --- a/src/nc.cc +++ b/src/nc.cc @@ -52,9 +52,7 @@ void out_to_ncurses_setting::lua_setter(lua::state &l, bool init) { void out_to_ncurses_setting::cleanup(lua::state &l) { lua::stack_sentry s(l, -1); - if (do_convert(l, -1).first) { - endwin(); - } + if (do_convert(l, -1).first) { endwin(); } l.pop(); } diff --git a/src/nvidia.h b/src/nvidia.h index 957ecbde..d9f29b49 100644 --- a/src/nvidia.h +++ b/src/nvidia.h @@ -31,7 +31,7 @@ #define NVIDIA_CONKY_H int set_nvidia_query(struct text_object *, const char *, unsigned int); -void print_nvidia_value(struct text_object *, char *,unsigned int); +void print_nvidia_value(struct text_object *, char *, unsigned int); double get_nvidia_barval(struct text_object *); void free_nvidia(struct text_object *); diff --git a/src/prioqueue.cc b/src/prioqueue.cc index e0295893..a1780e63 100644 --- a/src/prioqueue.cc +++ b/src/prioqueue.cc @@ -84,21 +84,15 @@ struct prio_queue *init_prio_queue() { void pq_set_compare(struct prio_queue *queue, int (*pqcompare)(void *a, void *b)) { - if (pqcompare != nullptr) { - queue->compare = pqcompare; - } + if (pqcompare != nullptr) { queue->compare = pqcompare; } } void pq_set_free(struct prio_queue *queue, void (*pqfree)(void *a)) { - if (pqfree != nullptr) { - queue->free = pqfree; - } + if (pqfree != nullptr) { queue->free = pqfree; } } void pq_set_max_size(struct prio_queue *queue, int max_size) { - if (max_size >= 0) { - queue->max_size = max_size; - } + if (max_size >= 0) { queue->max_size = max_size; } } int pq_get_cur_size(struct prio_queue *queue) { return queue->cur_size; } @@ -117,9 +111,7 @@ void insert_prio_elem(struct prio_queue *queue, void *data) { struct prio_elem *cur; /* queue->compare is a must-have */ - if (queue->compare == nullptr) { - return; - } + if (queue->compare == nullptr) { return; } /* empty queue, insert the first item */ if (queue->cur_size == 0) { @@ -176,9 +168,7 @@ void *pop_prio_elem(struct prio_queue *queue) { struct prio_elem *tmp; void *data; - if (queue->cur_size <= 0) { - return nullptr; - } + if (queue->cur_size <= 0) { return nullptr; } tmp = queue->head; data = tmp->data; @@ -197,8 +187,6 @@ void *pop_prio_elem(struct prio_queue *queue) { void free_prio_queue(struct prio_queue *queue) { void *data; - while ((data = pop_prio_elem(queue)) != nullptr) { - (*queue->free)(data); - } + while ((data = pop_prio_elem(queue)) != nullptr) { (*queue->free)(data); } free(queue); } diff --git a/src/proc.cc b/src/proc.cc index 4df31f8e..d8117694 100644 --- a/src/proc.cc +++ b/src/proc.cc @@ -32,10 +32,10 @@ #include #include #include +#include #include "conky.h" #include "core.h" #include "logging.h" -#include char *readfile(const char *filename, int *total_read, char showerror) { FILE *file; @@ -79,18 +79,14 @@ struct ll_string *addnode(struct ll_string *end, char *string) { static_cast(malloc(sizeof(struct ll_string))); current->string = strdup(string); current->next = nullptr; - if (end != nullptr) { - end->next = current; - } + if (end != nullptr) { end->next = current; } return current; } void freelist(struct ll_string *front) { if (front != nullptr) { free(front->string); - if (front->next != nullptr) { - freelist(front->next); - } + if (front->next != nullptr) { freelist(front->next); } free(front); } } @@ -99,23 +95,23 @@ int inlist(struct ll_string *front, char *string) { struct ll_string *current; for (current = front; current != nullptr; current = current->next) { - if (strcmp(current->string, string) == 0) { - return 1; - } + if (strcmp(current->string, string) == 0) { return 1; } } return 0; } -void print_pid_chroot(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_chroot(struct text_object *obj, char *p, + unsigned int p_max_size) { std::ostringstream pathstream; std::unique_ptr buf(new char[max_user_text.get(*state)]); generate_text_internal(buf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << buf.get() << "/root"; + pathstream << PROCDIR "/" << buf.get() << "/root"; pid_readlink(pathstream.str().c_str(), p, p_max_size); } -void print_pid_cmdline(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_cmdline(struct text_object *obj, char *p, + unsigned int p_max_size) { char *buf; int i, bytes_read; std::ostringstream pathstream; @@ -124,13 +120,11 @@ void print_pid_cmdline(struct text_object *obj, char *p, unsigned int p_max_size generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if (*(objbuf.get()) != 0) { - pathstream << PROCDIR "/" << objbuf.get() << "/cmdline"; + pathstream << PROCDIR "/" << objbuf.get() << "/cmdline"; buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { for (i = 0; i < bytes_read - 1; i++) { - if (buf[i] == 0) { - buf[i] = ' '; - } + if (buf[i] == 0) { buf[i] = ' '; } } snprintf(p, p_max_size, "%s", buf); free(buf); @@ -147,7 +141,7 @@ void print_pid_cwd(struct text_object *obj, char *p, unsigned int p_max_size) { std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/cwd"; + pathstream << PROCDIR "/" << objbuf.get() << "/cwd"; bytes_read = readlink(pathstream.str().c_str(), buf.get(), p_max_size); if (bytes_read != -1) { buf[bytes_read] = 0; @@ -157,7 +151,8 @@ void print_pid_cwd(struct text_object *obj, char *p, unsigned int p_max_size) { } } -void print_pid_environ(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_environ(struct text_object *obj, char *p, + unsigned int p_max_size) { int i, total_read; pid_t pid; std::ostringstream pathstream; @@ -167,10 +162,8 @@ void print_pid_environ(struct text_object *obj, char *p, unsigned int p_max_size generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if (sscanf(objbuf.get(), "%d %s", &pid, var) == 2) { - for (i = 0; var[i] != 0; i++) { - var[i] = toupper((unsigned char)var[i]); - } - pathstream << PROCDIR "/" << pid << "/cwd"; + for (i = 0; var[i] != 0; i++) { var[i] = toupper((unsigned char)var[i]); } + pathstream << PROCDIR "/" << pid << "/cwd"; buf = readfile(pathstream.str().c_str(), &total_read, 1); if (buf != nullptr) { for (i = 0; i < total_read; i += strlen(buf + i) + 1) { @@ -189,7 +182,8 @@ void print_pid_environ(struct text_object *obj, char *p, unsigned int p_max_size free(var); } -void print_pid_environ_list(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_environ_list(struct text_object *obj, char *p, + unsigned int p_max_size) { char *buf = nullptr; char *buf2; int bytes_read, total_read; @@ -198,7 +192,7 @@ void print_pid_environ_list(struct text_object *obj, char *p, unsigned int p_max std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/environ"; + pathstream << PROCDIR "/" << objbuf.get() << "/environ"; buf = readfile(pathstream.str().c_str(), &total_read, 1); if (buf != nullptr) { @@ -220,7 +214,7 @@ void print_pid_exe(struct text_object *obj, char *p, unsigned int p_max_size) { std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/exe"; + pathstream << PROCDIR "/" << objbuf.get() << "/exe"; pid_readlink(pathstream.str().c_str(), p, p_max_size); } @@ -234,7 +228,7 @@ void print_pid_nice(struct text_object *obj, char *p, unsigned int p_max_size) { generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if (!obj->data.s) { - pathstream << PROCDIR "/" << objbuf.get() << "/stat"; + pathstream << PROCDIR "/" << objbuf.get() << "/stat"; buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { sscanf(buf, @@ -249,7 +243,8 @@ void print_pid_nice(struct text_object *obj, char *p, unsigned int p_max_size) { } } -void print_pid_openfiles(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_openfiles(struct text_object *obj, char *p, + unsigned int p_max_size) { DIR *dir; struct dirent *entry; std::unique_ptr buf(new char[p_max_size]); @@ -273,9 +268,7 @@ void print_pid_openfiles(struct text_object *obj, char *p, unsigned int p_max_si buf.get()); totallength += length + strlen("; "); } - if (files_front == nullptr) { - files_front = files_back; - } + if (files_front == nullptr) { files_front = files_back; } } } closedir(dir); @@ -286,7 +279,8 @@ void print_pid_openfiles(struct text_object *obj, char *p, unsigned int p_max_si } } -void print_pid_parent(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_parent(struct text_object *obj, char *p, + unsigned int p_max_size) { #define PARENT_ENTRY "PPid:\t" #define PARENTNOTFOUND "Can't find the process parent in '%s'" char *begin, *end, *buf = nullptr; @@ -295,7 +289,7 @@ void print_pid_parent(struct text_object *obj, char *p, unsigned int p_max_size) std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/status"; + pathstream << PROCDIR "/" << objbuf.get() << "/status"; buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { @@ -303,9 +297,7 @@ void print_pid_parent(struct text_object *obj, char *p, unsigned int p_max_size) if (begin != nullptr) { begin += strlen(PARENT_ENTRY); end = strchr(begin, '\n'); - if (end != nullptr) { - *(end) = 0; - } + if (end != nullptr) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(PARENTNOTFOUND, pathstream.str().c_str()); @@ -314,7 +306,8 @@ void print_pid_parent(struct text_object *obj, char *p, unsigned int p_max_size) } } -void print_pid_priority(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_priority(struct text_object *obj, char *p, + unsigned int p_max_size) { char *buf = nullptr; int bytes_read; long int priority; @@ -324,7 +317,7 @@ void print_pid_priority(struct text_object *obj, char *p, unsigned int p_max_siz generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); if (*(objbuf.get()) != 0) { - pathstream << PROCDIR "/" << objbuf.get() << "/stat"; + pathstream << PROCDIR "/" << objbuf.get() << "/stat"; buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { sscanf(buf, @@ -339,7 +332,8 @@ void print_pid_priority(struct text_object *obj, char *p, unsigned int p_max_siz } } -void print_pid_state(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_state(struct text_object *obj, char *p, + unsigned int p_max_size) { #define STATE_ENTRY "State:\t" #define STATENOTFOUND "Can't find the process state in '%s'" char *begin, *end, *buf = nullptr; @@ -348,7 +342,7 @@ void print_pid_state(struct text_object *obj, char *p, unsigned int p_max_size) std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/status"; + pathstream << PROCDIR "/" << objbuf.get() << "/status"; buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { @@ -369,7 +363,8 @@ void print_pid_state(struct text_object *obj, char *p, unsigned int p_max_size) } } -void print_pid_state_short(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_state_short(struct text_object *obj, char *p, + unsigned int p_max_size) { char *begin, *buf = nullptr; int bytes_read; std::ostringstream pathstream; @@ -377,7 +372,7 @@ void print_pid_state_short(struct text_object *obj, char *p, unsigned int p_max_ generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/status"; + pathstream << PROCDIR "/" << objbuf.get() << "/status"; buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { @@ -391,27 +386,30 @@ void print_pid_state_short(struct text_object *obj, char *p, unsigned int p_max_ } } -void print_pid_stderr(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_stderr(struct text_object *obj, char *p, + unsigned int p_max_size) { std::ostringstream pathstream; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/fd/2"; + pathstream << PROCDIR "/" << objbuf.get() << "/fd/2"; pid_readlink(pathstream.str().c_str(), p, p_max_size); } -void print_pid_stdin(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_stdin(struct text_object *obj, char *p, + unsigned int p_max_size) { std::unique_ptr objbuf(new char[max_user_text.get(*state)]); std::ostringstream pathstream; generate_text_internal(objbuf.get(), max_user_text.get(*state), *obj->sub); - pathstream << PROCDIR "/" << objbuf.get() << "/fd/0"; + pathstream << PROCDIR "/" << objbuf.get() << "/fd/0"; pid_readlink(pathstream.str().c_str(), p, p_max_size); } -void print_pid_stdout(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_stdout(struct text_object *obj, char *p, + unsigned int p_max_size) { std::ostringstream pathstream; std::unique_ptr objbuf(new char[max_user_text.get(*state)]); @@ -437,15 +435,14 @@ void scan_cmdline_to_pid_arg(struct text_object *obj, const char *arg, strlen(obj->data.s + i + 1) + 1); } } - if (obj->data.s[i - 1] == ' ') { - obj->data.s[i - 1] = 0; - } + if (obj->data.s[i - 1] == ' ') { obj->data.s[i - 1] = 0; } } else { CRIT_ERR(obj, free_at_crash, "${cmdline_to_pid commandline}"); } } -void print_cmdline_to_pid(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_cmdline_to_pid(struct text_object *obj, char *p, + unsigned int p_max_size) { DIR *dir; struct dirent *entry; char *buf; @@ -460,9 +457,7 @@ void print_cmdline_to_pid(struct text_object *obj, char *p, unsigned int p_max_s buf = readfile(pathstream.str().c_str(), &bytes_read, 0); if (buf != nullptr) { for (i = 0; i < bytes_read - 1; i++) { - if (buf[i] == 0) { - buf[i] = ' '; - } + if (buf[i] == 0) { buf[i] = ' '; } } if (strstr(buf, obj->data.s) != nullptr) { snprintf(p, p_max_size, "%s", entry->d_name); @@ -479,7 +474,8 @@ void print_cmdline_to_pid(struct text_object *obj, char *p, unsigned int p_max_s } } -void print_pid_threads(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_threads(struct text_object *obj, char *p, + unsigned int p_max_size) { #define THREADS_ENTRY "Threads:\t" #define THREADSNOTFOUND \ "Can't find the number of the threads of the process in '%s'" @@ -497,9 +493,7 @@ void print_pid_threads(struct text_object *obj, char *p, unsigned int p_max_size if (begin != nullptr) { begin += strlen(THREADS_ENTRY); end = strchr(begin, '\n'); - if (end != nullptr) { - *(end) = 0; - } + if (end != nullptr) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(THREADSNOTFOUND, pathstream.str().c_str()); @@ -508,7 +502,8 @@ void print_pid_threads(struct text_object *obj, char *p, unsigned int p_max_size } } -void print_pid_thread_list(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_thread_list(struct text_object *obj, char *p, + unsigned int p_max_size) { DIR *dir; struct dirent *entry; int totallength = 0; @@ -528,9 +523,7 @@ void print_pid_thread_list(struct text_object *obj, char *p, unsigned int p_max_ } } closedir(dir); - if (p[totallength - 1] == ',') { - p[totallength - 1] = 0; - } + if (p[totallength - 1] == ',') { p[totallength - 1] = 0; } } else { p[0] = 0; } @@ -560,7 +553,8 @@ void print_pid_time_kernelmode(struct text_object *obj, char *p, } } -void print_pid_time_usermode(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_time_usermode(struct text_object *obj, char *p, + unsigned int p_max_size) { char *buf = nullptr; int bytes_read; unsigned long int kmtime; @@ -607,9 +601,10 @@ void print_pid_time(struct text_object *obj, char *p, unsigned int p_max_size) { } } -enum idtype {egid, euid, fsgid, fsuid, gid, sgid, suid, uid}; +enum idtype { egid, euid, fsgid, fsuid, gid, sgid, suid, uid }; -void print_pid_Xid(struct text_object *obj, char *p, int p_max_size, idtype type) { +void print_pid_Xid(struct text_object *obj, char *p, int p_max_size, + idtype type) { char *begin, *end, *buf = nullptr; int bytes_read; std::ostringstream pathstream; @@ -621,106 +616,107 @@ void print_pid_Xid(struct text_object *obj, char *p, int p_max_size, idtype type buf = readfile(pathstream.str().c_str(), &bytes_read, 1); if (buf != nullptr) { - switch(type) { - case egid: - begin = strstr(buf, "Gid:\t"); - break; - case euid: - begin = strstr(buf, "Uid:\t"); - break; - case fsgid: - begin = strstr(buf, "Gid:\t"); - break; - case fsuid: - begin = strstr(buf, "Uid:\t"); - break; - case gid: - begin = strstr(buf, "Gid:\t"); - break; - case sgid: - begin = strstr(buf, "Gid:\t"); - break; - case suid: - begin = strstr(buf, "Uid:\t"); - break; - case uid: - begin = strstr(buf, "Uid:\t"); - break; - default: - break; - } - if (begin != nullptr) { - switch(type) { - case gid: - begin += strlen("Gid:\t"); - break; - case uid: - begin += strlen("Uid:\t"); - break; + switch (type) { case egid: - case euid: - begin = strchr(begin, '\t'); - begin++; - begin = strchr(begin, '\t'); - begin++; + begin = strstr(buf, "Gid:\t"); break; - case sgid: - case suid: - begin = strchr(begin, '\t'); - begin++; - begin = strchr(begin, '\t'); - begin++; - begin = strchr(begin, '\t'); - begin++; + case euid: + begin = strstr(buf, "Uid:\t"); break; case fsgid: + begin = strstr(buf, "Gid:\t"); + break; case fsuid: - begin = strchr(begin, '\t'); - begin++; - begin = strchr(begin, '\t'); - begin++; - begin = strchr(begin, '\t'); - begin++; - begin = strchr(begin, '\t'); - begin++; - break; + begin = strstr(buf, "Uid:\t"); + break; + case gid: + begin = strstr(buf, "Gid:\t"); + break; + case sgid: + begin = strstr(buf, "Gid:\t"); + break; + case suid: + begin = strstr(buf, "Uid:\t"); + break; + case uid: + begin = strstr(buf, "Uid:\t"); + break; default: break; + } + if (begin != nullptr) { + switch (type) { + case gid: + begin += strlen("Gid:\t"); + break; + case uid: + begin += strlen("Uid:\t"); + break; + case egid: + case euid: + begin = strchr(begin, '\t'); + begin++; + begin = strchr(begin, '\t'); + begin++; + break; + case sgid: + case suid: + begin = strchr(begin, '\t'); + begin++; + begin = strchr(begin, '\t'); + begin++; + begin = strchr(begin, '\t'); + begin++; + break; + case fsgid: + case fsuid: + begin = strchr(begin, '\t'); + begin++; + begin = strchr(begin, '\t'); + begin++; + begin = strchr(begin, '\t'); + begin++; + begin = strchr(begin, '\t'); + begin++; + break; + default: + break; } - if(type == fsgid || type == fsuid) end = strchr(begin, '\n'); else end = strchr(begin, '\t'); - if (end != nullptr) { - *(end) = 0; - } + if (type == fsgid || type == fsuid) + end = strchr(begin, '\n'); + else + end = strchr(begin, '\t'); + if (end != nullptr) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { errorstring = "Can't find the process "; - switch(type) { - case egid: - errorstring.append("effective gid"); - break; - case euid: - errorstring.append("effective uid"); - break; - case fsgid: - errorstring.append("process file system gid"); - break; - case fsuid: - errorstring.append("process file system uid"); - break; - case gid: - errorstring.append("real gid"); - break; - case sgid: - errorstring.append("saved set gid"); - break; - case suid: - errorstring.append("saved set uid"); - break; - case uid: - errorstring.append("real uid"); - break; - default: - break; + switch (type) { + case egid: + errorstring.append("effective gid"); + break; + case euid: + errorstring.append("effective uid"); + break; + case fsgid: + errorstring.append("process file system gid"); + break; + case fsuid: + errorstring.append("process file system uid"); + break; + case gid: + errorstring.append("real gid"); + break; + case sgid: + errorstring.append("saved set gid"); + break; + case suid: + errorstring.append("saved set uid"); + break; + case uid: + errorstring.append("real uid"); + break; + default: + break; } errorstring.append(" in '%s'"); NORM_ERR(errorstring.c_str(), pathstream.str().c_str()); @@ -730,23 +726,25 @@ void print_pid_Xid(struct text_object *obj, char *p, int p_max_size, idtype type } void print_pid_egid(struct text_object *obj, char *p, unsigned int p_max_size) { - print_pid_Xid(obj, p, p_max_size, egid); + print_pid_Xid(obj, p, p_max_size, egid); } void print_pid_euid(struct text_object *obj, char *p, unsigned int p_max_size) { print_pid_Xid(obj, p, p_max_size, euid); } -void print_pid_fsgid(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_fsgid(struct text_object *obj, char *p, + unsigned int p_max_size) { print_pid_Xid(obj, p, p_max_size, fsgid); } -void print_pid_fsuid(struct text_object *obj, char *p, unsigned int p_max_size) { - print_pid_Xid(obj, p, p_max_size, fsuid); +void print_pid_fsuid(struct text_object *obj, char *p, + unsigned int p_max_size) { + print_pid_Xid(obj, p, p_max_size, fsuid); } void print_pid_gid(struct text_object *obj, char *p, unsigned int p_max_size) { - print_pid_Xid(obj, p, p_max_size, gid); + print_pid_Xid(obj, p, p_max_size, gid); } void print_pid_sgid(struct text_object *obj, char *p, unsigned int p_max_size) { @@ -754,7 +752,7 @@ void print_pid_sgid(struct text_object *obj, char *p, unsigned int p_max_size) { } void print_pid_suid(struct text_object *obj, char *p, unsigned int p_max_size) { - print_pid_Xid(obj, p, p_max_size, suid); + print_pid_Xid(obj, p, p_max_size, suid); } void print_pid_uid(struct text_object *obj, char *p, unsigned int p_max_size) { @@ -776,13 +774,9 @@ void internal_print_pid_vm(struct text_object *obj, char *p, int p_max_size, begin = strstr(buf, entry); if (begin != nullptr) { begin += strlen(entry); - while (*begin == '\t' || *begin == ' ') { - begin++; - } + while (*begin == '\t' || *begin == ' ') { begin++; } end = strchr(begin, '\n'); - if (end != nullptr) { - *(end) = 0; - } + if (end != nullptr) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(errorstring, pathstream.str().c_str()); @@ -791,55 +785,65 @@ void internal_print_pid_vm(struct text_object *obj, char *p, int p_max_size, } } -void print_pid_vmpeak(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmpeak(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm( obj, p, p_max_size, "VmPeak:\t", "Can't find the process peak virtual memory size in '%s'"); } -void print_pid_vmsize(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmsize(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmSize:\t", "Can't find the process virtual memory size in '%s'"); } -void print_pid_vmlck(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmlck(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmLck:\t", "Can't find the process locked memory size in '%s'"); } -void print_pid_vmhwm(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmhwm(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm( obj, p, p_max_size, "VmHWM:\t", "Can't find the process peak resident set size in '%s'"); } -void print_pid_vmrss(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmrss(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmHWM:\t", "Can't find the process resident set size in '%s'"); } -void print_pid_vmdata(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmdata(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmData:\t", "Can't find the process data segment size in '%s'"); } -void print_pid_vmstk(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmstk(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmData:\t", "Can't find the process stack segment size in '%s'"); } -void print_pid_vmexe(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmexe(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm(obj, p, p_max_size, "VmData:\t", "Can't find the process text segment size in '%s'"); } -void print_pid_vmlib(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmlib(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm( obj, p, p_max_size, "VmLib:\t", "Can't find the process shared library code size in '%s'"); } -void print_pid_vmpte(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_vmpte(struct text_object *obj, char *p, + unsigned int p_max_size) { internal_print_pid_vm( obj, p, p_max_size, "VmPTE:\t", "Can't find the process page table entries size in '%s'"); @@ -861,9 +865,7 @@ void print_pid_read(struct text_object *obj, char *p, unsigned int p_max_size) { begin = strstr(buf, READ_ENTRY); if (begin != nullptr) { end = strchr(begin, '\n'); - if (end != nullptr) { - *(end) = 0; - } + if (end != nullptr) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(READNOTFOUND, pathstream.str().c_str()); @@ -874,7 +876,8 @@ void print_pid_read(struct text_object *obj, char *p, unsigned int p_max_size) { #define WRITE_ENTRY "write_bytes: " #define WRITENOTFOUND "Can't find the amount of bytes written in '%s'" -void print_pid_write(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_pid_write(struct text_object *obj, char *p, + unsigned int p_max_size) { char *begin, *end, *buf = nullptr; int bytes_read; std::ostringstream pathstream; @@ -888,9 +891,7 @@ void print_pid_write(struct text_object *obj, char *p, unsigned int p_max_size) begin = strstr(buf, WRITE_ENTRY); if (begin != nullptr) { end = strchr(begin, '\n'); - if (end != nullptr) { - *(end) = 0; - } + if (end != nullptr) { *(end) = 0; } snprintf(p, p_max_size, "%s", begin); } else { NORM_ERR(WRITENOTFOUND, pathstream.str().c_str()); diff --git a/src/proc.h b/src/proc.h index 6c2579a2..f019d5f8 100644 --- a/src/proc.h +++ b/src/proc.h @@ -34,26 +34,39 @@ #define READERR "Can't read '%s'" #define READSIZE 128 -void print_pid_chroot(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_cmdline(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_chroot(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_cmdline(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_cwd(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_environ(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_environ_list(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_environ(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_environ_list(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_exe(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_nice(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_openfiles(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_parent(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_priority(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_openfiles(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_parent(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_priority(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_state(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_state_short(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_stderr(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_state_short(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_stderr(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_stdin(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_stdout(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_threads(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_thread_list(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_stdout(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_threads(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_thread_list(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_time_kernelmode(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_time_usermode(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_time_usermode(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_time(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_uid(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_euid(struct text_object *obj, char *p, unsigned int p_max_size); @@ -64,12 +77,15 @@ void print_pid_egid(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_sgid(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_fsgid(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_read(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_vmpeak(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_vmsize(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_vmpeak(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_pid_vmsize(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_vmlck(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_vmhwm(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_vmrss(struct text_object *obj, char *p, unsigned int p_max_size); -void print_pid_vmdata(struct text_object *obj, char *p, unsigned int p_max_size); +void print_pid_vmdata(struct text_object *obj, char *p, + unsigned int p_max_size); void print_pid_vmstk(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_vmexe(struct text_object *obj, char *p, unsigned int p_max_size); void print_pid_vmlib(struct text_object *obj, char *p, unsigned int p_max_size); @@ -78,6 +94,7 @@ void print_pid_write(struct text_object *obj, char *p, unsigned int p_max_size); void scan_cmdline_to_pid_arg(struct text_object *obj, const char *arg, void *free_at_crash); -void print_cmdline_to_pid(struct text_object *obj, char *p, unsigned int p_max_size); +void print_cmdline_to_pid(struct text_object *obj, char *p, + unsigned int p_max_size); #endif /* CONKY_PROC_H */ diff --git a/src/prss.cc b/src/prss.cc index 33787fd9..0f069d9f 100644 --- a/src/prss.cc +++ b/src/prss.cc @@ -101,14 +101,10 @@ static inline void read_item(PRSS_Item *res, xmlNodePtr data) { for (; data; data = data->next) { xmlNodePtr child; - if (data->type != XML_ELEMENT_NODE) { - continue; - } + if (data->type != XML_ELEMENT_NODE) { continue; } child = data->children; - if (!child) { - continue; - } + if (!child) { continue; } #define ASSIGN(a) \ if (strcasecmp((const char *)data->name, #a) == EQUAL) { \ @@ -128,14 +124,10 @@ static inline void read_item(PRSS_Item *res, xmlNodePtr data) { static inline void read_element(PRSS *res, xmlNodePtr n) { xmlNodePtr child; - if (n->type != XML_ELEMENT_NODE) { - return; - } + if (n->type != XML_ELEMENT_NODE) { return; } child = n->children; - if (!child) { - return; - } + if (!child) { return; } #define ASSIGN(a) \ if (strcasecmp((const char *)n->name, #a) == EQUAL) { \ @@ -172,9 +164,7 @@ static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root) { strcmp((const char *)channel->name, "channel"))) { channel = channel->next; } - if (!channel) { - return 0; - } + if (!channel) { return 0; } for (n = channel->children; n; n = n->next) { if (n->type == XML_ELEMENT_NODE && !strcmp((const char *)n->name, "item")) { @@ -188,9 +178,7 @@ static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root) { res->items = (PRSS_Item *)malloc(items * sizeof(PRSS_Item)); res->item_count = 0; - for (n = channel->children; n; n = n->next) { - read_element(res, n); - } + for (n = channel->children; n; n = n->next) { read_element(res, n); } return 1; } @@ -207,9 +195,7 @@ static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root) { } else if (!strcmp((const char *)n->name, "channel")) { xmlNodePtr i; - for (i = n->children; i; i = i->next) { - read_element(res, i); - } + for (i = n->children; i; i = i->next) { read_element(res, i); } } } } diff --git a/src/pulseaudio.h b/src/pulseaudio.h index fcae4fc0..ad128bdc 100644 --- a/src/pulseaudio.h +++ b/src/pulseaudio.h @@ -36,11 +36,16 @@ void init_pulseaudio(struct text_object *obj); void free_pulseaudio(struct text_object *obj); uint8_t puau_vol(struct text_object *); // preserve pa_* for libpulse -void print_puau_sink_description(struct text_object *obj, char *p, unsigned int p_max_size); -void print_puau_sink_active_port_name(struct text_object *obj, char *p, unsigned int p_max_size); -void print_puau_sink_active_port_description(struct text_object *obj, char *p, unsigned int p_max_size); -void print_puau_card_name(struct text_object *obj, char *p, unsigned int p_max_size); -void print_puau_card_active_profile(struct text_object *obj, char *p, unsigned int p_max_size); +void print_puau_sink_description(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_puau_sink_active_port_name(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_puau_sink_active_port_description(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_puau_card_name(struct text_object *obj, char *p, + unsigned int p_max_size); +void print_puau_card_active_profile(struct text_object *obj, char *p, + unsigned int p_max_size); double puau_volumebarval(struct text_object *obj); int puau_muted(struct text_object *obj); diff --git a/src/rss.cc b/src/rss.cc index 266bbc4a..b15ac93f 100644 --- a/src/rss.cc +++ b/src/rss.cc @@ -52,9 +52,7 @@ class rss_cb : public curl_callback> { std::unique_lock lock(Base::result_mutex); Base::result = tmp; - } catch (std::runtime_error &e) { - NORM_ERR("%s", e.what()); - } + } catch (std::runtime_error &e) { NORM_ERR("%s", e.what()); } } public: @@ -87,9 +85,7 @@ static void rss_process_info(char *p, int p_max_size, const std::string &uri, str = data->title; if (str && strlen(str) > 0) { // remove trailing new line if one exists - if (str[strlen(str) - 1] == '\n') { - str[strlen(str) - 1] = 0; - } + if (str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } snprintf(p, p_max_size, "%s", str); } } else if (strcmp(action, "item_title") == EQUAL) { @@ -97,9 +93,7 @@ static void rss_process_info(char *p, int p_max_size, const std::string &uri, str = data->items[act_par].title; // remove trailing new line if one exists if (str && strlen(str) > 0) { - if (str[strlen(str) - 1] == '\n') { - str[strlen(str) - 1] = 0; - } + if (str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } snprintf(p, p_max_size, "%s", str); } } @@ -108,9 +102,7 @@ static void rss_process_info(char *p, int p_max_size, const std::string &uri, str = data->items[act_par].description; // remove trailing new line if one exists if (str && strlen(str) > 0) { - if (str[strlen(str) - 1] == '\n') { - str[strlen(str) - 1] = 0; - } + if (str[strlen(str) - 1] == '\n') { str[strlen(str) - 1] = 0; } snprintf(p, p_max_size, "%s", str); } } @@ -135,9 +127,7 @@ static void rss_process_info(char *p, int p_max_size, const std::string &uri, str = item->title; if (str) { // don't add new line before first item - if (itmp > 0) { - strncat(p, "\n", p_max_size); - } + if (itmp > 0) { strncat(p, "\n", p_max_size); } /* remove trailing new line if one exists, * we have our own */ if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') { diff --git a/src/setting.cc b/src/setting.cc index 2a9648be..fdfe54ff 100644 --- a/src/setting.cc +++ b/src/setting.cc @@ -71,9 +71,7 @@ settings_vector make_settings_vector() { settings_vector ret; ret.reserve(settings->size()); - for (auto &setting : *settings) { - ret.push_back(setting.second); - } + for (auto &setting : *settings) { ret.push_back(setting.second); } sort(ret.begin(), ret.end(), &priv::config_setting_base::seq_compare); return ret; @@ -131,9 +129,7 @@ void config_setting_base::process_setting(lua::state &l, bool init) { lua::stack_sentry s(l, -3); config_setting_base *ptr = get_setting(l, -3); - if (ptr == nullptr) { - return; - } + if (ptr == nullptr) { return; } ptr->lua_setter(l, init); l.pushvalue(-2); diff --git a/src/smapi.cc b/src/smapi.cc index e37e8bbe..bc86c076 100644 --- a/src/smapi.cc +++ b/src/smapi.cc @@ -132,7 +132,8 @@ uint8_t smapi_bat_percentage(struct text_object *obj) { return val; } -void print_smapi_bat_temp(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_smapi_bat_temp(struct text_object *obj, char *p, + unsigned int p_max_size) { int idx, val; if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { val = smapi_bat_installed_internal(idx) @@ -144,7 +145,8 @@ void print_smapi_bat_temp(struct text_object *obj, char *p, unsigned int p_max_s NORM_ERR("argument to smapi_bat_temp must be an integer"); } -void print_smapi_bat_power(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_smapi_bat_power(struct text_object *obj, char *p, + unsigned int p_max_size) { int idx, val; if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { val = smapi_bat_installed_internal(idx) @@ -165,9 +167,7 @@ double smapi_bat_barval(struct text_object *obj) { int smapi_bat_installed(struct text_object *obj) { int idx; if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { - if (!smapi_bat_installed_internal(idx)) { - return 0; - } + if (!smapi_bat_installed_internal(idx)) { return 0; } } else NORM_ERR("argument to if_smapi_bat_installed must be an integer"); return 1; diff --git a/src/sony.cc b/src/sony.cc index 2e2735b1..7da18968 100644 --- a/src/sony.cc +++ b/src/sony.cc @@ -51,9 +51,7 @@ void get_sony_fanspeed(struct text_object *obj, char *p_client_buffer, (void)obj; - if (!p_client_buffer || client_buffer_size <= 0) { - return; - } + if (!p_client_buffer || client_buffer_size <= 0) { return; } snprintf(fan, 127, "%s/fanspeed", SONY_LAPTOP_DIR); @@ -62,12 +60,8 @@ void get_sony_fanspeed(struct text_object *obj, char *p_client_buffer, while (!feof(fp)) { char line[256]; - if (fgets(line, 255, fp) == nullptr) { - break; - } - if (sscanf(line, "%u", &speed)) { - break; - } + if (fgets(line, 255, fp) == nullptr) { break; } + if (sscanf(line, "%u", &speed)) { break; } } } else { CRIT_ERR(nullptr, NULL, diff --git a/src/tailhead.cc b/src/tailhead.cc index 56e63b9e..a4e18864 100644 --- a/src/tailhead.cc +++ b/src/tailhead.cc @@ -65,13 +65,9 @@ static void tailstring(char *string, int endofstring, int wantedlines) { string[endofstring - 1] = 0; } for (i = endofstring - 1; i >= 0 && linescounted < wantedlines; i--) { - if (string[i] == '\n') { - linescounted++; - } - } - if (i > 0) { - strfold(string, i + 2); + if (string[i] == '\n') { linescounted++; } } + if (i > 0) { strfold(string, i + 2); } } } @@ -124,9 +120,7 @@ static void print_tailhead(const char *type, struct text_object *obj, char *p, struct stat st {}; auto *ht = static_cast(obj->data.opaque); - if (ht == nullptr) { - return; - } + if (ht == nullptr) { return; } // empty the buffer and reset the counter if we used it the max number of // times @@ -145,12 +139,8 @@ static void print_tailhead(const char *type, struct text_object *obj, char *p, if (fd != -1) { if (strcmp(type, "head") == 0) { for (i = 0; linescounted < ht->wantedlines; i++) { - if (read(fd, p + i, 1) <= 0) { - break; - } - if (p[i] == '\n') { - linescounted++; - } + if (read(fd, p + i, 1) <= 0) { break; } + if (p[i] == '\n') { linescounted++; } } p[i] = 0; } else if (strcmp(type, "tail") == 0) { @@ -175,7 +165,7 @@ static void print_tailhead(const char *type, struct text_object *obj, char *p, endofstring = strlen(p); } } else if (strcmp(type, "tail") == 0) { - fseek(fp, - (long) p_max_size, SEEK_END); + fseek(fp, -(long)p_max_size, SEEK_END); i = fread(p, 1, p_max_size - 1, fp); tailstring(p, i, ht->wantedlines); } else { @@ -219,9 +209,7 @@ void print_lines(struct text_object *obj, char *p, unsigned int p_max_size) { lines = 0; while (fgets(buf, BUFSZ, fp) != nullptr) { for (j = 0; buf[j] != 0; j++) { - if (buf[j] == '\n') { - lines++; - } + if (buf[j] == '\n') { lines++; } } } snprintf(p, p_max_size, "%d", lines); diff --git a/src/tcp-portmon.cc b/src/tcp-portmon.cc index 15ad6ba0..9a266bd9 100644 --- a/src/tcp-portmon.cc +++ b/src/tcp-portmon.cc @@ -17,10 +17,10 @@ * along with this program. If not, see . * */ +#include "tcp-portmon.h" #include "conky.h" #include "libtcp-portmon.h" #include "logging.h" -#include "tcp-portmon.h" #include "text_object.h" static tcp_port_monitor_collection_t *pmc = nullptr; @@ -122,7 +122,8 @@ int tcp_portmon_init(struct text_object *obj, const char *arg) { return 0; } -void tcp_portmon_action(struct text_object *obj, char *p, unsigned int p_max_size) { +void tcp_portmon_action(struct text_object *obj, char *p, + unsigned int p_max_size) { struct tcp_port_monitor_data *pmd = (tcp_port_monitor_data *)obj->data.opaque; tcp_port_monitor_t *p_monitor; diff --git a/src/temphelper.cc b/src/temphelper.cc index 11b58de9..45cb474c 100644 --- a/src/temphelper.cc +++ b/src/temphelper.cc @@ -41,9 +41,7 @@ static double fahrenheit_to_celsius(double n) { return ((n - 32) * 5 / 9); } static double celsius_to_fahrenheit(double n) { return ((n * 9 / 5) + 32); } static double convert_temp_output(double n, enum TEMP_UNIT input_unit) { - if (input_unit == output_unit.get(*state)) { - return n; - } + if (input_unit == output_unit.get(*state)) { return n; } switch (output_unit.get(*state)) { case TEMP_CELSIUS: @@ -55,8 +53,8 @@ static double convert_temp_output(double n, enum TEMP_UNIT input_unit) { return 0.0; } -int temp_print(char *p, size_t p_max_size, double n, - enum TEMP_UNIT input_unit, int to_int) { +int temp_print(char *p, size_t p_max_size, double n, enum TEMP_UNIT input_unit, + int to_int) { int i_out = 0; float f_out = 0.0; size_t plen = 0; diff --git a/src/template.cc b/src/template.cc index 84f9a9cd..e53e8688 100644 --- a/src/template.cc +++ b/src/template.cc @@ -184,7 +184,10 @@ char *find_and_replace_templates(const char *inbuf) { if (*(p + 1) == '{') { p += 2; templ = p; - while ((*p != 0) && (isspace((unsigned char)*p) == 0) && *p != '{' && *p != '}') { p++; } + while ((*p != 0) && (isspace((unsigned char)*p) == 0) && *p != '{' && + *p != '}') { + p++; + } if (*p == '}') { args = nullptr; } else { diff --git a/src/timeinfo.h b/src/timeinfo.h index 10321706..1b3c0181 100644 --- a/src/timeinfo.h +++ b/src/timeinfo.h @@ -44,7 +44,8 @@ void scan_tztime(struct text_object *, const char *); void print_time(struct text_object *, char *, unsigned int); void print_utime(struct text_object *, char *, unsigned int); void print_tztime(struct text_object *, char *, unsigned int); -void print_format_time(struct text_object *obj, char *p, unsigned int p_max_size); +void print_format_time(struct text_object *obj, char *p, + unsigned int p_max_size); /* free object data */ void free_time(struct text_object *); diff --git a/src/weather.cc b/src/weather.cc index 7abafdde..01f41057 100644 --- a/src/weather.cc +++ b/src/weather.cc @@ -22,6 +22,7 @@ * */ +#include "weather.h" #include #include #include @@ -34,9 +35,8 @@ #include "logging.h" #include "temphelper.h" #include "text_object.h" -#include "weather.h" void print_weather(struct text_object *obj, char *p, unsigned int p_max_size) { - (void) obj; - strncpy(p ,"TODO...", p_max_size); + (void)obj; + strncpy(p, "TODO...", p_max_size); } diff --git a/src/xmms2.cc b/src/xmms2.cc index f37e71a9..4e8d3b2e 100644 --- a/src/xmms2.cc +++ b/src/xmms2.cc @@ -289,9 +289,7 @@ int update_xmms2(void) { /* initialize connection */ if (current_info->xmms2.conn_state == CONN_INIT) { - if (xmms2_conn == nullptr) { - xmms2_conn = xmmsc_init(PACKAGE_NAME); - } + if (xmms2_conn == nullptr) { xmms2_conn = xmmsc_init(PACKAGE_NAME); } /* did init fail? */ if (xmms2_conn == nullptr) { @@ -351,20 +349,23 @@ int update_xmms2(void) { return 0; } -void print_xmms2_tracknr(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_xmms2_tracknr(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; if (info.xmms2.tracknr != -1) { snprintf(p, p_max_size, "%i", info.xmms2.tracknr); } } -void print_xmms2_elapsed(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_xmms2_elapsed(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; snprintf(p, p_max_size, "%02d:%02d", info.xmms2.elapsed / 60000, (info.xmms2.elapsed / 1000) % 60); } -void print_xmms2_duration(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_xmms2_duration(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; snprintf(p, p_max_size, "%02d:%02d", info.xmms2.duration / 60000, (info.xmms2.duration / 1000) % 60); @@ -376,7 +377,8 @@ double xmms2_barval(struct text_object *obj) { return info.xmms2.progress; } -void print_xmms2_smart(struct text_object *obj, char *p, unsigned int p_max_size) { +void print_xmms2_smart(struct text_object *obj, char *p, + unsigned int p_max_size) { (void)obj; int artist_len = strlen(info.xmms2.artist); int title_len = strlen(info.xmms2.title); @@ -389,11 +391,11 @@ void print_xmms2_smart(struct text_object *obj, char *p, unsigned int p_max_size } } -#define XMMS2_PRINT_GENERATOR(name, fmt) \ - void print_xmms2_##name(struct text_object *obj, char *p, \ - unsigned int p_max_size) { \ - (void)obj; \ - snprintf(p, p_max_size, fmt, info.xmms2.name); \ +#define XMMS2_PRINT_GENERATOR(name, fmt) \ + void print_xmms2_##name(struct text_object *obj, char *p, \ + unsigned int p_max_size) { \ + (void)obj; \ + snprintf(p, p_max_size, fmt, info.xmms2.name); \ } XMMS2_PRINT_GENERATOR(artist, "%s") diff --git a/tests/catch2/catch.hpp b/tests/catch2/catch.hpp index 4d991eee..e67283e9 100644 --- a/tests/catch2/catch.hpp +++ b/tests/catch2/catch.hpp @@ -2,8 +2,8 @@ * Catch v2.5.0 * Generated: 2018-11-26 20:46:12.165372 * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. + * This file has been merged from multiple headers. Please don't edit it + * directly Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,87 +12,87 @@ #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED // start catch.hpp - #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 5 #define CATCH_VERSION_PATCH 0 #ifdef __clang__ -# pragma clang system_header +#pragma clang system_header #elif defined __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif // start catch_suppress_warnings.h #ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif +#ifdef __ICC // icpc defines the __clang__ macro +#pragma warning(push) +#pragma warning(disable : 161 1682) +#else // __ICC +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#endif #elif defined __GNUC__ - // GCC likes to warn on REQUIREs, and we cannot suppress them - // locally because g++'s support for _Pragma is lacking in older, - // still supported, versions -# pragma GCC diagnostic ignored "-Wparentheses" -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" +// GCC likes to warn on REQUIREs, and we cannot suppress them +// locally because g++'s support for _Pragma is lacking in older, +// still supported, versions +#pragma GCC diagnostic ignored "-Wparentheses" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wpadded" #endif // end catch_suppress_warnings.h #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS +#define CATCH_IMPL +#define CATCH_CONFIG_ALL_PARTS #endif // In the impl file, we want to have access to all parts of the headers // Can also be used to sanely support PCHs #if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif +#define CATCH_CONFIG_EXTERNAL_INTERFACES +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#undef CATCH_CONFIG_DISABLE_MATCHERS +#endif +#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif #endif #if !defined(CATCH_CONFIG_IMPL_ONLY) // start catch_platform.h #ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif +#include +#if TARGET_OS_OSX == 1 +#define CATCH_PLATFORM_MAC +#elif TARGET_OS_IPHONE == 1 +#define CATCH_PLATFORM_IPHONE +#endif #elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX +#define CATCH_PLATFORM_LINUX -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || \ + defined(_MSC_VER) || defined(__MINGW32__) +#define CATCH_PLATFORM_WINDOWS #endif // end catch_platform.h #ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif +#ifndef CLARA_CONFIG_MAIN +#define CLARA_CONFIG_MAIN_NOT_DEFINED +#define CLARA_CONFIG_MAIN +#endif #endif // start catch_user_interfaces.h namespace Catch { - unsigned int rngSeed(); +unsigned int rngSeed(); } // end catch_user_interfaces.h @@ -121,13 +121,13 @@ namespace Catch { #ifdef __cplusplus -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif +#if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +#define CATCH_CPP14_OR_GREATER +#endif -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif +#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define CATCH_CPP17_OR_GREATER +#endif /* Disable C++17 on older GCC versions. */ #if defined(__GNUC__) && !defined(_GLIBCXX_RELEASE) @@ -137,65 +137,66 @@ namespace Catch { #endif #if defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif #ifdef __clang__ -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") +#define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + _Pragma("clang diagnostic pop") -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wparentheses\"") +#define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + _Pragma("clang diagnostic pop") -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunused-variable\"") +#define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ + _Pragma("clang diagnostic pop") -#endif // __clang__ +#endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // Assume that non-Windows platforms support posix signals by default #if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS #endif //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || \ + defined(__DJGPP__) +#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS #endif #ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE +#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#define CATCH_CONFIG_COLOUR_NONE #endif //////////////////////////////////////////////////////////////////////////////// // Android somehow still does not support std::to_string #if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING #endif //////////////////////////////////////////////////////////////////////////////// // Not all Windows environments support SEH properly #if defined(__MINGW32__) -# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH #endif //////////////////////////////////////////////////////////////////////////////// // PS4 #if defined(__ORBIS__) -# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE #endif //////////////////////////////////////////////////////////////////////////////// @@ -203,59 +204,63 @@ namespace Catch { #ifdef __CYGWIN__ // Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 -# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) +// see: +// http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +#define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd +// check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html +// line 2812-2813 +#if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) && \ + !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# endif -#endif // __CYGWIN__ +#endif +#endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif +#if _MSC_VER >= 1900 // Visual Studio 2015 or newer +#define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif // Universal Windows platform does not support SEH // Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define CATCH_CONFIG_COLOUR_NONE +#else +#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +#endif // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif +#if !defined(_MSVC_TRADITIONAL) || \ + (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +#define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif -#endif // _MSC_VER +#endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // Check if we are compiled with -fno-exceptions or equivalent #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED #endif //////////////////////////////////////////////////////////////////////////////// // DJGPP #ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ +#define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ //////////////////////////////////////////////////////////////////////////////// // Embarcadero C++Build #if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN #endif //////////////////////////////////////////////////////////////////////////////// @@ -265,8 +270,8 @@ namespace Catch { // handled by it. // Otherwise all supported compilers support COUNTER macro, // but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER +#if (!defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L) +#define CATCH_INTERNAL_CONFIG_COUNTER #endif //////////////////////////////////////////////////////////////////////////////// @@ -274,85 +279,111 @@ namespace Catch { // The check is split apart to work around v140 (VS2015) preprocessor issue... #if defined(__has_include) #if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW +#define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW #endif #endif //////////////////////////////////////////////////////////////////////////////// // Check if variant is available and usable #if defined(__has_include) -# if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 -# include -# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# define CATCH_CONFIG_NO_CPP17_VARIANT -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# endif // defined(__clang__) && (__clang_major__ < 8) -# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#if defined(__clang__) && (__clang_major__ < 8) +// work around clang bug with libstdc++ +// https://bugs.llvm.org/show_bug.cgi?id=31852 fix should be in clang 8, +// workaround in libstdc++ 8.2 +#include +#if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) +#define CATCH_CONFIG_NO_CPP17_VARIANT +#else +#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +#endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && + // (_GLIBCXX_RELEASE < 9) +#endif // defined(__clang__) && (__clang_major__ < 8) +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // __has_include -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && \ + !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +#define CATCH_CONFIG_COUNTER #endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && \ + !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && \ + !defined(CATCH_CONFIG_WINDOWS_SEH) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +#define CATCH_CONFIG_WINDOWS_SEH #endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS +// This is set by default, because we assume that unix compilers are +// posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && \ + !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && \ + !defined(CATCH_CONFIG_POSIX_SIGNALS) +#define CATCH_CONFIG_POSIX_SIGNALS #endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR +// This is set by default, because we assume that compilers with no wchar_t +// support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && \ + !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +#define CATCH_CONFIG_WCHAR #endif -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && \ + !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && \ + !defined(CATCH_CONFIG_CPP11_TO_STRING) +#define CATCH_CONFIG_CPP11_TO_STRING #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && \ + !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && \ + !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +#define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && \ + !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && \ + !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +#define CATCH_CONFIG_CPP17_STRING_VIEW #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && \ + !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && \ + !defined(CATCH_CONFIG_CPP17_VARIANT) +#define CATCH_CONFIG_CPP17_VARIANT #endif #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) -# define CATCH_CONFIG_NEW_CAPTURE +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && \ + !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && \ + !defined(CATCH_CONFIG_NEW_CAPTURE) +#define CATCH_CONFIG_NEW_CAPTURE #endif -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && \ + !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_CONFIG_DISABLE_EXCEPTIONS #endif -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) -# define CATCH_CONFIG_POLYFILL_ISNAN +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && \ + !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && \ + !defined(CATCH_CONFIG_POLYFILL_ISNAN) +#define CATCH_CONFIG_POLYFILL_ISNAN #endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) @@ -365,311 +396,316 @@ namespace Catch { #define CATCH_CATCH_ANON(type) catch (type) #endif -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && \ + !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && \ + !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #endif // end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE(name, line) \ + INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) #ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#define INTERNAL_CATCH_UNIQUE_NAME(name) \ + INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __COUNTER__) #else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#define INTERNAL_CATCH_UNIQUE_NAME(name) \ + INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__) #endif +#include #include #include -#include -// We need a dummy global operator<< so we can bring it into Catch namespace later +// We need a dummy global operator<< so we can bring it into Catch namespace +// later struct Catch_global_namespace_dummy {}; std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); namespace Catch { - struct CaseSensitive { enum Choice { - Yes, - No - }; }; +struct CaseSensitive { + enum Choice { Yes, No }; +}; - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; +class NonCopyable { + NonCopyable(NonCopyable const&) = delete; + NonCopyable(NonCopyable&&) = delete; + NonCopyable& operator=(NonCopyable const&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; + protected: + NonCopyable(); + virtual ~NonCopyable(); +}; - struct SourceLineInfo { +struct SourceLineInfo { + SourceLineInfo() = delete; + SourceLineInfo(char const* _file, std::size_t _line) noexcept + : file(_file), line(_line) {} - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} + SourceLineInfo(SourceLineInfo const& other) = default; + SourceLineInfo(SourceLineInfo&&) = default; + SourceLineInfo& operator=(SourceLineInfo const&) = default; + SourceLineInfo& operator=(SourceLineInfo&&) = default; - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; + bool empty() const noexcept; + bool operator==(SourceLineInfo const& other) const noexcept; + bool operator<(SourceLineInfo const& other) const noexcept; - bool empty() const noexcept; - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; + char const* file; + std::size_t line; +}; - char const* file; - std::size_t line; - }; +std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info); - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); +// Bring in operator<< from global namespace into Catch namespace +// This is necessary because the overload of operator<< above makes +// lookup stop at namespace Catch +using ::operator<<; - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } +// Use this in variadic streaming macros to allow +// >> +StreamEndStop +// as well as +// >> stuff +StreamEndStop +struct StreamEndStop { + std::string operator+() const; +}; +template +T const& operator+(T const& value, StreamEndStop) { + return value; } +} // namespace Catch #define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + ::Catch::SourceLineInfo(__FILE__, static_cast(__LINE__)) // end catch_common.h namespace Catch { - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; +struct RegistrarForTagAliases { + RegistrarForTagAliases(char const* alias, char const* tag, + SourceLineInfo const& lineInfo); +}; -} // end namespace Catch +} // end namespace Catch -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#define CATCH_REGISTER_TAG_ALIAS(alias, spec) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( \ + AutoRegisterTagAlias)(alias, spec, CATCH_INTERNAL_LINEINFO); \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h // start catch_interfaces_testcase.h -#include #include +#include namespace Catch { - class TestSpec; +class TestSpec; - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; +struct ITestInvoker { + virtual void invoke() const = 0; + virtual ~ITestInvoker(); +}; - using ITestCasePtr = std::shared_ptr; +using ITestCasePtr = std::shared_ptr; - class TestCase; - struct IConfig; +class TestCase; +struct IConfig; - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; +struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( + IConfig const& config) const = 0; +}; - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); +bool matchTest(TestCase const& testCase, TestSpec const& testSpec, + IConfig const& config); +std::vector filterTests(std::vector const& testCases, + TestSpec const& testSpec, + IConfig const& config); +std::vector const& getAllTestCasesSorted(IConfig const& config); -} +} // namespace Catch // end catch_interfaces_testcase.h // start catch_stringref.h #include -#include #include +#include namespace Catch { - class StringData; +class StringData; - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. - class StringRef { - public: - using size_type = std::size_t; +/// A non-owning string class (similar to the forthcoming std::string_view) +/// Note that, because a StringRef may be a substring of another string, +/// it may not be null terminated. c_str() must return a null terminated +/// string, however, and so the StringRef will internally take ownership +/// (taking a copy), if necessary. In theory this ownership is not externally +/// visible - but it does mean (substring) StringRefs should not be shared +/// between threads. +class StringRef { + public: + using size_type = std::size_t; - private: - friend struct StringRefTestAccess; + private: + friend struct StringRefTestAccess; - char const* m_start; - size_type m_size; + char const* m_start; + size_type m_size; - char* m_data = nullptr; + char* m_data = nullptr; - void takeOwnership(); + void takeOwnership(); - static constexpr char const* const s_empty = ""; + static constexpr char const* const s_empty = ""; - public: // construction/ assignment - StringRef() noexcept - : StringRef( s_empty, 0 ) - {} + public: // construction/ assignment + StringRef() noexcept : StringRef(s_empty, 0) {} - StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} + StringRef(StringRef const& other) noexcept + : m_start(other.m_start), m_size(other.m_size) {} - StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } + StringRef(StringRef&& other) noexcept + : m_start(other.m_start), m_size(other.m_size), m_data(other.m_data) { + other.m_data = nullptr; + } - StringRef( char const* rawChars ) noexcept; + StringRef(char const* rawChars) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - {} + StringRef(char const* rawChars, size_type size) noexcept + : m_start(rawChars), m_size(size) {} - StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} + StringRef(std::string const& stdString) noexcept + : m_start(stdString.c_str()), m_size(stdString.size()) {} - ~StringRef() noexcept { - delete[] m_data; - } + ~StringRef() noexcept { delete[] m_data; } - auto operator = ( StringRef const &other ) noexcept -> StringRef& { - delete[] m_data; - m_data = nullptr; - m_start = other.m_start; - m_size = other.m_size; - return *this; - } + auto operator=(StringRef const& other) noexcept -> StringRef& { + delete[] m_data; + m_data = nullptr; + m_start = other.m_start; + m_size = other.m_size; + return *this; + } - operator std::string() const; + operator std::string() const; - void swap( StringRef& other ) noexcept; + void swap(StringRef& other) noexcept; - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; + public: // operators + auto operator==(StringRef const& other) const noexcept -> bool; + auto operator!=(StringRef const& other) const noexcept -> bool; - auto operator[] ( size_type index ) const noexcept -> char; + auto operator[](size_type index) const noexcept -> char; - public: // named queries - auto empty() const noexcept -> bool { - return m_size == 0; - } - auto size() const noexcept -> size_type { - return m_size; - } + public: // named queries + auto empty() const noexcept -> bool { return m_size == 0; } + auto size() const noexcept -> size_type { return m_size; } - auto numberOfCharacters() const noexcept -> size_type; - auto c_str() const -> char const*; + auto numberOfCharacters() const noexcept -> size_type; + auto c_str() const -> char const*; - public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; + public: // substrings and searches + auto substr(size_type start, size_type size) const noexcept -> StringRef; - // Returns the current start pointer. - // Note that the pointer can change when if the StringRef is a substring - auto currentData() const noexcept -> char const*; + // Returns the current start pointer. + // Note that the pointer can change when if the StringRef is a substring + auto currentData() const noexcept -> char const*; - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - }; + private: // ownership queries - may not be consistent between calls + auto isOwned() const noexcept -> bool; + auto isSubstring() const noexcept -> bool; +}; - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; +auto operator+(StringRef const& lhs, StringRef const& rhs) -> std::string; +auto operator+(StringRef const& lhs, char const* rhs) -> std::string; +auto operator+(char const* lhs, StringRef const& rhs) -> std::string; - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; +auto operator+=(std::string& lhs, StringRef const& sr) -> std::string&; +auto operator<<(std::ostream& os, StringRef const& sr) -> std::ostream&; - inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); - } +inline auto operator"" _sr(char const* rawChars, std::size_t size) noexcept + -> StringRef { + return StringRef(rawChars, size); +} -} // namespace Catch +} // namespace Catch -inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); +inline auto operator"" _catch_sr(char const* rawChars, + std::size_t size) noexcept + -> Catch::StringRef { + return Catch::StringRef(rawChars, size); } // end catch_stringref.h // start catch_type_traits.hpp - -namespace Catch{ +namespace Catch { #ifdef CATCH_CPP17_OR_GREATER - template - inline constexpr auto is_unique = std::true_type{}; +template +inline constexpr auto is_unique = std::true_type{}; - template - inline constexpr auto is_unique = std::bool_constant< - (!std::is_same_v && ...) && is_unique - >{}; +template +inline constexpr auto is_unique = + std::bool_constant<(!std::is_same_v && ...) && + is_unique>{}; #else template -struct is_unique : std::true_type{}; +struct is_unique : std::true_type {}; template -struct is_unique : std::integral_constant -::value - && is_unique::value - && is_unique::value ->{}; +struct is_unique + : std::integral_constant::value && + is_unique::value && + is_unique::value> {}; #endif -} +} // namespace Catch // end catch_type_traits.hpp // start catch_preprocessor.hpp - #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL1(...) \ + CATCH_RECURSION_LEVEL0( \ + CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) \ + CATCH_RECURSION_LEVEL1( \ + CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) \ + CATCH_RECURSION_LEVEL2( \ + CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) \ + CATCH_RECURSION_LEVEL3( \ + CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) \ + CATCH_RECURSION_LEVEL4( \ + CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ // MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#define CATCH_RECURSION_LEVEL6(...) \ + CATCH_RECURSION_LEVEL5( \ + CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) \ + CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) #else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) #endif #define CATCH_REC_END(...) @@ -682,206 +718,291 @@ struct is_unique : std::integral_constant #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER(CATCH_REC_NEXT0)(test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST0(f, x, peek, ...) \ + , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, \ + __VA_ARGS__) +#define CATCH_REC_LIST1(f, x, peek, ...) \ + , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0))(f, peek, \ + __VA_ARGS__) +#define CATCH_REC_LIST2(f, x, peek, ...) \ + f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, __VA_ARGS__) -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) \ + , f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))( \ + f, userdata, peek, __VA_ARGS__) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) \ + , f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD))( \ + f, userdata, peek, __VA_ARGS__) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) \ + f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))( \ + f, userdata, peek, __VA_ARGS__) -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) +// Applies the function macro `f` to each of the remaining parameters, inserts +// commas between the results, and passes userdata as the first parameter to +// each invocation, e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), +// f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) \ + CATCH_RECURSE( \ + CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) +#define CATCH_REC_LIST(f, ...) \ + CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO##__VA_ARGS__ #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) +#define INTERNAL_CATCH_REMOVE_PARENS(...) \ + INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) -#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__) +#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) \ + INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__ -#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, ...) Name " - " #__VA_ARGS__ +#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) \ + INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2( \ + Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) #else // MSVC is adding extra space and needs more calls to properly remove () -#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__ -#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__) -#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, ...) Name " -" #__VA_ARGS__ +#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) \ + INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__) +#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) \ + INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1( \ + Name, \ + INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) #endif // end catch_preprocessor.hpp namespace Catch { -template +template class TestInvokerAsMethod : public ITestInvoker { - void (C::*m_testAsMethod)(); -public: - TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} + void (C::*m_testAsMethod)(); - void invoke() const override { - C obj; - (obj.*m_testAsMethod)(); - } + public: + TestInvokerAsMethod(void (C::*testAsMethod)()) noexcept + : m_testAsMethod(testAsMethod) {} + + void invoke() const override { + C obj; + (obj.*m_testAsMethod)(); + } }; -auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; +auto makeTestInvoker(void (*testAsFunction)()) noexcept -> ITestInvoker*; -template -auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { - return new(std::nothrow) TestInvokerAsMethod( testAsMethod ); +template +auto makeTestInvoker(void (C::*testAsMethod)()) noexcept -> ITestInvoker* { + return new (std::nothrow) TestInvokerAsMethod(testAsMethod); } struct NameAndTags { - NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; - StringRef name; - StringRef tags; + NameAndTags(StringRef const& name_ = StringRef(), + StringRef const& tags_ = StringRef()) noexcept; + StringRef name; + StringRef tags; }; struct AutoReg : NonCopyable { - AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; - ~AutoReg(); + AutoReg(ITestInvoker* invoker, SourceLineInfo const& lineInfo, + StringRef const& classOrMethod, + NameAndTags const& nameAndTags) noexcept; + ~AutoReg(); }; -} // end namespace Catch +} // end namespace Catch #if defined(CATCH_CONFIG_DISABLE) - #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ - namespace{ \ - struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ - void test(); \ - }; \ - } \ - void TestName::test() - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... ) \ - template \ - static void TestName() - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ - namespace{ \ - template \ - struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \ - void test(); \ - }; \ - } \ - template \ - void TestName::test() +#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(TestName, ...) \ + static void TestName() +#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(TestName, ClassName, \ + ...) \ + namespace { \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + } \ + void TestName::test() +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(TestName, ...) \ + template \ + static void TestName() +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ + TestName, ClassName, ...) \ + namespace { \ + template \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + } \ + template \ + void TestName::test() #endif - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( ... ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TESTCASE2(TestName, ...) \ + static void TestName(); \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)( \ + Catch::makeTestInvoker(&TestName), CATCH_INTERNAL_LINEINFO, \ + Catch::StringRef(), Catch::NameAndTags{__VA_ARGS__}); \ + } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + static void TestName() +#define INTERNAL_CATCH_TESTCASE(...) \ + INTERNAL_CATCH_TESTCASE2( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), __VA_ARGS__) - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_METHOD_AS_TEST_CASE(QualifiedMethod, ...) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)( \ + Catch::makeTestInvoker(&QualifiedMethod), CATCH_INTERNAL_LINEINFO, \ + "&" #QualifiedMethod, Catch::NameAndTags{__VA_ARGS__}); \ + } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ \ - struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - void TestName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST_CASE_METHOD2(TestName, ClassName, ...) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)( \ + Catch::makeTestInvoker(&TestName::test), CATCH_INTERNAL_LINEINFO, \ + #ClassName, Catch::NameAndTags{__VA_ARGS__}); /* NOLINT */ \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + void TestName::test() +#define INTERNAL_CATCH_TEST_CASE_METHOD(ClassName, ...) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), ClassName, \ + __VA_ARGS__) - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_REGISTER_TESTCASE(Function, ...) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)( \ + Catch::makeTestInvoker(Function), CATCH_INTERNAL_LINEINFO, \ + Catch::StringRef(), Catch::NameAndTags{__VA_ARGS__}); /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - template \ - static void TestFunc();\ - namespace {\ - template \ - struct TestName{\ - template \ - TestName(Ts...names){\ - CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ - using expander = int[];\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \ - }\ - };\ - INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \ - }\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - template \ - static void TestFunc() +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, \ + ...) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + template \ + static void TestFunc(); \ + namespace { \ + template \ + struct TestName { \ + template \ + TestName(Ts... names) { \ + CATCH_INTERNAL_CHECK_UNIQUE_TYPES( \ + CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ + using expander = int[]; \ + (void)expander{ \ + (Catch::AutoReg(Catch::makeTestInvoker(&TestFunc), \ + CATCH_INTERNAL_LINEINFO, Catch::StringRef(), \ + Catch::NameAndTags{names, Tags}), \ + 0)...}; /* NOLINT */ \ + } \ + }; \ + INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + template \ + static void TestFunc() #if defined(CATCH_CPP17_OR_GREATER) -#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case"); +#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) \ + static_assert( \ + Catch::is_unique<__VA_ARGS__>, \ + "Duplicate type detected in declaration of template test case"); #else -#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case"); +#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) \ + static_assert( \ + Catch::is_unique<__VA_ARGS__>::value, \ + "Duplicate type detected in declaration of template test case"); #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____), \ + Name, Tags, __VA_ARGS__) #else - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) ) +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ + INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____), \ + Name, Tags, __VA_ARGS__)) #endif - #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\ - static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ - TestName(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\ - return 0;\ - }(); +#define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...) \ + static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ + TestName( \ + CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME, Name, \ + __VA_ARGS__)); \ + return 0; \ + }(); - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ \ - template \ - struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \ - void test();\ - };\ - template \ - struct TestNameClass{\ - template \ - TestNameClass(Ts...names){\ - CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ - using expander = int[];\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \ - }\ - };\ - INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\ - }\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\ - template \ - void TestName::test() +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2(TestNameClass, TestName, \ + ClassName, Name, Tags, ...) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + template \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + template \ + struct TestNameClass { \ + template \ + TestNameClass(Ts... names) { \ + CATCH_INTERNAL_CHECK_UNIQUE_TYPES( \ + CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ + using expander = int[]; \ + (void)expander{ \ + (Catch::AutoReg(Catch::makeTestInvoker(&TestName::test), \ + CATCH_INTERNAL_LINEINFO, #ClassName, \ + Catch::NameAndTags{names, Tags}), \ + 0)...}; /* NOLINT */ \ + } \ + }; \ + INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__) \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + template \ + void TestName::test() #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(ClassName, Name, Tags, ...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____), \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + ClassName, Name, Tags, __VA_ARGS__) #else - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) ) +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(ClassName, Name, Tags, ...) \ + INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____), \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + ClassName, Name, Tags, __VA_ARGS__)) #endif // end catch_test_registry.h @@ -895,111 +1016,118 @@ struct AutoReg : NonCopyable { namespace Catch { - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, +// ResultWas::OfType enum +struct ResultWas { + enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, - FailureBit = 0x10, + FailureBit = 0x10, - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, - Exception = 0x100 | FailureBit, + Exception = 0x100 | FailureBit, - ThrewException = Exception | 1, - DidntThrowException = Exception | 2, + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, - FatalErrorCondition = 0x200 | FailureBit + FatalErrorCondition = 0x200 | FailureBit - }; }; + }; +}; - bool isOk( ResultWas::OfType resultType ); - bool isJustInfo( int flags ); +bool isOk(ResultWas::OfType resultType); +bool isJustInfo(int flags); - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x01, +// ResultDisposition::Flags enum +struct ResultDisposition { + enum Flags { + Normal = 0x01, - ContinueOnFailure = 0x02, // Failures fail test, but execution continues - FalseTest = 0x04, // Prefix expression with ! - SuppressFail = 0x08 // Failures are reported but do not fail the test - }; }; + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; +}; - ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); +ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, + ResultDisposition::Flags rhs); - bool shouldContinueOnFailure( int flags ); - inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } - bool shouldSuppressFailure( int flags ); +bool shouldContinueOnFailure(int flags); +inline bool isFalseTest(int flags) { + return (flags & ResultDisposition::FalseTest) != 0; +} +bool shouldSuppressFailure(int flags); -} // end namespace Catch +} // end namespace Catch // end catch_result_type.h namespace Catch { - struct AssertionInfo - { - StringRef macroName; - SourceLineInfo lineInfo; - StringRef capturedExpression; - ResultDisposition::Flags resultDisposition; +struct AssertionInfo { + StringRef macroName; + SourceLineInfo lineInfo; + StringRef capturedExpression; + ResultDisposition::Flags resultDisposition; - // We want to delete this constructor but a compiler bug in 4.8 means - // the struct is then treated as non-aggregate - //AssertionInfo() = delete; - }; + // We want to delete this constructor but a compiler bug in 4.8 means + // the struct is then treated as non-aggregate + // AssertionInfo() = delete; +}; -} // end namespace Catch +} // end namespace Catch // end catch_assertioninfo.h // start catch_decomposer.h // start catch_tostring.h -#include #include -#include #include +#include +#include // start catch_stream.h -#include #include +#include #include namespace Catch { - std::ostream& cout(); - std::ostream& cerr(); - std::ostream& clog(); +std::ostream& cout(); +std::ostream& cerr(); +std::ostream& clog(); - class StringRef; +class StringRef; - struct IStream { - virtual ~IStream(); - virtual std::ostream& stream() const = 0; - }; +struct IStream { + virtual ~IStream(); + virtual std::ostream& stream() const = 0; +}; - auto makeStream( StringRef const &filename ) -> IStream const*; +auto makeStream(StringRef const& filename) -> IStream const*; - class ReusableStringStream { - std::size_t m_index; - std::ostream* m_oss; - public: - ReusableStringStream(); - ~ReusableStringStream(); +class ReusableStringStream { + std::size_t m_index; + std::ostream* m_oss; - auto str() const -> std::string; + public: + ReusableStringStream(); + ~ReusableStringStream(); - template - auto operator << ( T const& value ) -> ReusableStringStream& { - *m_oss << value; - return *this; - } - auto get() -> std::ostream& { return *m_oss; } - }; -} + auto str() const -> std::string; + + template + auto operator<<(T const& value) -> ReusableStringStream& { + *m_oss << value; + return *this; + } + auto get() -> std::ostream& { return *m_oss; } +}; +} // namespace Catch // end catch_stream.h @@ -1018,33 +1146,29 @@ namespace Catch { #define CATCH_ARC_ENABLED 0 #endif -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); +void arcSafeRelease(NSObject* obj); +id performOptionalSelector(id obj, SEL sel); #if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; +inline void arcSafeRelease(NSObject* obj) { [obj release]; } +inline id performOptionalSelector(id obj, SEL sel) { + if ([obj respondsToSelector:sel]) return [obj performSelector:sel]; + return nil; } #define CATCH_UNSAFE_UNRETAINED #define CATCH_ARC_STRONG #else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { +inline void arcSafeRelease(NSObject*) {} +inline id performOptionalSelector(id obj, SEL sel) { #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" #endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; + if ([obj respondsToSelector:sel]) return [obj performSelector:sel]; #ifdef __clang__ #pragma clang diagnostic pop #endif - return nil; + return nil; } #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained #define CATCH_ARC_STRONG __strong @@ -1055,594 +1179,596 @@ inline id performOptionalSelector( id obj, SEL sel ) { #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless +#pragma warning( \ + disable : 4180) // We attempt to stream a function (address) by const&, + // which MSVC complains about but is harmless #endif namespace Catch { - namespace Detail { +namespace Detail { - extern const std::string unprintableString; +extern const std::string unprintableString; - std::string rawMemoryToString( const void *object, std::size_t size ); +std::string rawMemoryToString(const void* object, std::size_t size); - template - std::string rawMemoryToString( const T& object ) { - return rawMemoryToString( &object, sizeof(object) ); - } +template +std::string rawMemoryToString(const T& object) { + return rawMemoryToString(&object, sizeof(object)); +} - template - class IsStreamInsertable { - template - static auto test(int) - -> decltype(std::declval() << std::declval(), std::true_type()); +template +class IsStreamInsertable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); - template - static auto test(...)->std::false_type; + template + static auto test(...) -> std::false_type; - public: - static const bool value = decltype(test(0))::value; - }; + public: + static const bool value = decltype(test(0))::value; +}; - template - std::string convertUnknownEnumToString( E e ); +template +std::string convertUnknownEnumToString(E e); - template - typename std::enable_if< - !std::is_enum::value && !std::is_base_of::value, - std::string>::type convertUnstreamable( T const& ) { - return Detail::unprintableString; - } - template - typename std::enable_if< - !std::is_enum::value && std::is_base_of::value, - std::string>::type convertUnstreamable(T const& ex) { - return ex.what(); - } +template +typename std::enable_if::value && + !std::is_base_of::value, + std::string>::type +convertUnstreamable(T const&) { + return Detail::unprintableString; +} +template +typename std::enable_if::value && + std::is_base_of::value, + std::string>::type +convertUnstreamable(T const& ex) { + return ex.what(); +} - template - typename std::enable_if< - std::is_enum::value - , std::string>::type convertUnstreamable( T const& value ) { - return convertUnknownEnumToString( value ); - } +template +typename std::enable_if::value, std::string>::type +convertUnstreamable(T const& value) { + return convertUnknownEnumToString(value); +} #if defined(_MANAGED) - //! Convert a CLR string to a utf8 std::string - template - std::string clrReferenceToString( T^ ref ) { - if (ref == nullptr) - return std::string("null"); - auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); - cli::pin_ptr p = &bytes[0]; - return std::string(reinterpret_cast(p), bytes->Length); - } +//! Convert a CLR string to a utf8 std::string +template +std::string clrReferenceToString(T ^ ref) { + if (ref == nullptr) return std::string("null"); + auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); + cli::pin_ptr p = &bytes[0]; + return std::string(reinterpret_cast(p), bytes->Length); +} #endif - } // namespace Detail +} // namespace Detail - // If we decide for C++14, change these to enable_if_ts - template - struct StringMaker { - template - static - typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type - convert(const Fake& value) { - ReusableStringStream rss; - // NB: call using the function-like syntax to avoid ambiguity with - // user-defined templated operator<< under clang. - rss.operator<<(value); - return rss.str(); - } +// If we decide for C++14, change these to enable_if_ts +template +struct StringMaker { + template + static + typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, + std::string>::type + convert(const Fake& value) { + ReusableStringStream rss; + // NB: call using the function-like syntax to avoid ambiguity with + // user-defined templated operator<< under clang. + rss.operator<<(value); + return rss.str(); + } - template - static - typename std::enable_if::value, std::string>::type - convert( const Fake& value ) { + template + static + typename std::enable_if::value, + std::string>::type + convert(const Fake& value) { #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) - return Detail::convertUnstreamable(value); + return Detail::convertUnstreamable(value); #else - return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); + return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); #endif - } - }; + } +}; - namespace Detail { +namespace Detail { - // This function dispatches all stringification requests inside of Catch. - // Should be preferably called fully qualified, like ::Catch::Detail::stringify - template - std::string stringify(const T& e) { - return ::Catch::StringMaker::type>::type>::convert(e); - } +// This function dispatches all stringification requests inside of Catch. +// Should be preferably called fully qualified, like ::Catch::Detail::stringify +template +std::string stringify(const T& e) { + return ::Catch::StringMaker::type>::type>::convert(e); +} - template - std::string convertUnknownEnumToString( E e ) { - return ::Catch::Detail::stringify(static_cast::type>(e)); - } +template +std::string convertUnknownEnumToString(E e) { + return ::Catch::Detail::stringify( + static_cast::type>(e)); +} #if defined(_MANAGED) - template - std::string stringify( T^ e ) { - return ::Catch::StringMaker::convert(e); - } +template +std::string stringify(T ^ e) { + return ::Catch::StringMaker::convert(e); +} #endif - } // namespace Detail +} // namespace Detail - // Some predefined specializations +// Some predefined specializations - template<> - struct StringMaker { - static std::string convert(const std::string& str); - }; +template <> +struct StringMaker { + static std::string convert(const std::string& str); +}; #ifdef CATCH_CONFIG_CPP17_STRING_VIEW - template<> - struct StringMaker { - static std::string convert(std::string_view str); - }; +template <> +struct StringMaker { + static std::string convert(std::string_view str); +}; #endif - template<> - struct StringMaker { - static std::string convert(char const * str); - }; - template<> - struct StringMaker { - static std::string convert(char * str); - }; +template <> +struct StringMaker { + static std::string convert(char const* str); +}; +template <> +struct StringMaker { + static std::string convert(char* str); +}; #ifdef CATCH_CONFIG_WCHAR - template<> - struct StringMaker { - static std::string convert(const std::wstring& wstr); - }; +template <> +struct StringMaker { + static std::string convert(const std::wstring& wstr); +}; -# ifdef CATCH_CONFIG_CPP17_STRING_VIEW - template<> - struct StringMaker { - static std::string convert(std::wstring_view str); - }; -# endif - - template<> - struct StringMaker { - static std::string convert(wchar_t const * str); - }; - template<> - struct StringMaker { - static std::string convert(wchar_t * str); - }; +#ifdef CATCH_CONFIG_CPP17_STRING_VIEW +template <> +struct StringMaker { + static std::string convert(std::wstring_view str); +}; #endif - // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, - // while keeping string semantics? - template - struct StringMaker { - static std::string convert(char const* str) { - return ::Catch::Detail::stringify(std::string{ str }); - } - }; - template - struct StringMaker { - static std::string convert(signed char const* str) { - return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) }); - } - }; - template - struct StringMaker { - static std::string convert(unsigned char const* str) { - return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) }); - } - }; +template <> +struct StringMaker { + static std::string convert(wchar_t const* str); +}; +template <> +struct StringMaker { + static std::string convert(wchar_t* str); +}; +#endif - template<> - struct StringMaker { - static std::string convert(int value); - }; - template<> - struct StringMaker { - static std::string convert(long value); - }; - template<> - struct StringMaker { - static std::string convert(long long value); - }; - template<> - struct StringMaker { - static std::string convert(unsigned int value); - }; - template<> - struct StringMaker { - static std::string convert(unsigned long value); - }; - template<> - struct StringMaker { - static std::string convert(unsigned long long value); - }; +// TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, +// while keeping string semantics? +template +struct StringMaker { + static std::string convert(char const* str) { + return ::Catch::Detail::stringify(std::string{str}); + } +}; +template +struct StringMaker { + static std::string convert(signed char const* str) { + return ::Catch::Detail::stringify( + std::string{reinterpret_cast(str)}); + } +}; +template +struct StringMaker { + static std::string convert(unsigned char const* str) { + return ::Catch::Detail::stringify( + std::string{reinterpret_cast(str)}); + } +}; - template<> - struct StringMaker { - static std::string convert(bool b); - }; +template <> +struct StringMaker { + static std::string convert(int value); +}; +template <> +struct StringMaker { + static std::string convert(long value); +}; +template <> +struct StringMaker { + static std::string convert(long long value); +}; +template <> +struct StringMaker { + static std::string convert(unsigned int value); +}; +template <> +struct StringMaker { + static std::string convert(unsigned long value); +}; +template <> +struct StringMaker { + static std::string convert(unsigned long long value); +}; - template<> - struct StringMaker { - static std::string convert(char c); - }; - template<> - struct StringMaker { - static std::string convert(signed char c); - }; - template<> - struct StringMaker { - static std::string convert(unsigned char c); - }; +template <> +struct StringMaker { + static std::string convert(bool b); +}; - template<> - struct StringMaker { - static std::string convert(std::nullptr_t); - }; +template <> +struct StringMaker { + static std::string convert(char c); +}; +template <> +struct StringMaker { + static std::string convert(signed char c); +}; +template <> +struct StringMaker { + static std::string convert(unsigned char c); +}; - template<> - struct StringMaker { - static std::string convert(float value); - }; - template<> - struct StringMaker { - static std::string convert(double value); - }; +template <> +struct StringMaker { + static std::string convert(std::nullptr_t); +}; - template - struct StringMaker { - template - static std::string convert(U* p) { - if (p) { - return ::Catch::Detail::rawMemoryToString(p); - } else { - return "nullptr"; - } - } - }; +template <> +struct StringMaker { + static std::string convert(float value); +}; +template <> +struct StringMaker { + static std::string convert(double value); +}; - template - struct StringMaker { - static std::string convert(R C::* p) { - if (p) { - return ::Catch::Detail::rawMemoryToString(p); - } else { - return "nullptr"; - } - } - }; +template +struct StringMaker { + template + static std::string convert(U* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } +}; + +template +struct StringMaker { + static std::string convert(R C::*p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } +}; #if defined(_MANAGED) - template - struct StringMaker { - static std::string convert( T^ ref ) { - return ::Catch::Detail::clrReferenceToString(ref); - } - }; +template +struct StringMaker { + static std::string convert(T ^ ref) { + return ::Catch::Detail::clrReferenceToString(ref); + } +}; #endif - namespace Detail { - template - std::string rangeToString(InputIterator first, InputIterator last) { - ReusableStringStream rss; - rss << "{ "; - if (first != last) { - rss << ::Catch::Detail::stringify(*first); - for (++first; first != last; ++first) - rss << ", " << ::Catch::Detail::stringify(*first); - } - rss << " }"; - return rss.str(); - } - } +namespace Detail { +template +std::string rangeToString(InputIterator first, InputIterator last) { + ReusableStringStream rss; + rss << "{ "; + if (first != last) { + rss << ::Catch::Detail::stringify(*first); + for (++first; first != last; ++first) + rss << ", " << ::Catch::Detail::stringify(*first); + } + rss << " }"; + return rss.str(); +} +} // namespace Detail #ifdef __OBJC__ - template<> - struct StringMaker { - static std::string convert(NSString * nsstring) { - if (!nsstring) - return "nil"; - return std::string("@") + [nsstring UTF8String]; - } - }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); - } +template <> +struct StringMaker { + static std::string convert(NSString* nsstring) { + if (!nsstring) return "nil"; + return std::string("@") + [nsstring UTF8String]; + } +}; +template <> +struct StringMaker { + static std::string convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); + } +}; +namespace Detail { +inline std::string stringify(NSString* nsstring) { + return StringMaker::convert(nsstring); +} - }; - namespace Detail { - inline std::string stringify( NSString* nsstring ) { - return StringMaker::convert( nsstring ); - } +} // namespace Detail +#endif // __OBJC__ - } // namespace Detail -#endif // __OBJC__ - -} // namespace Catch +} // namespace Catch ////////////////////////////////////////////////////// // Separate std-lib types stringification, so it can be selectively enabled // This means that we do not bring in #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) -# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER -# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER -# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +#define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +#define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER #endif // Separate std::pair specialization #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) #include namespace Catch { - template - struct StringMaker > { - static std::string convert(const std::pair& pair) { - ReusableStringStream rss; - rss << "{ " - << ::Catch::Detail::stringify(pair.first) - << ", " - << ::Catch::Detail::stringify(pair.second) - << " }"; - return rss.str(); - } - }; -} -#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +template +struct StringMaker> { + static std::string convert(const std::pair& pair) { + ReusableStringStream rss; + rss << "{ " << ::Catch::Detail::stringify(pair.first) << ", " + << ::Catch::Detail::stringify(pair.second) << " }"; + return rss.str(); + } +}; +} // namespace Catch +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER // Separate std::tuple specialization #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) #include namespace Catch { - namespace Detail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct TupleElementPrinter { - static void print(const Tuple& tuple, std::ostream& os) { - os << (N ? ", " : " ") - << ::Catch::Detail::stringify(std::get(tuple)); - TupleElementPrinter::print(tuple, os); - } - }; +namespace Detail { +template ::value)> +struct TupleElementPrinter { + static void print(const Tuple& tuple, std::ostream& os) { + os << (N ? ", " : " ") << ::Catch::Detail::stringify(std::get(tuple)); + TupleElementPrinter::print(tuple, os); + } +}; - template< - typename Tuple, - std::size_t N - > - struct TupleElementPrinter { - static void print(const Tuple&, std::ostream&) {} - }; +template +struct TupleElementPrinter { + static void print(const Tuple&, std::ostream&) {} +}; - } +} // namespace Detail - template - struct StringMaker> { - static std::string convert(const std::tuple& tuple) { - ReusableStringStream rss; - rss << '{'; - Detail::TupleElementPrinter>::print(tuple, rss.get()); - rss << " }"; - return rss.str(); - } - }; -} -#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +template +struct StringMaker> { + static std::string convert(const std::tuple& tuple) { + ReusableStringStream rss; + rss << '{'; + Detail::TupleElementPrinter>::print(tuple, rss.get()); + rss << " }"; + return rss.str(); + } +}; +} // namespace Catch +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER -#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) +#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && \ + defined(CATCH_CONFIG_CPP17_VARIANT) #include namespace Catch { - template<> - struct StringMaker { - static std::string convert(const std::monostate&) { - return "{ }"; - } - }; +template <> +struct StringMaker { + static std::string convert(const std::monostate&) { return "{ }"; } +}; - template - struct StringMaker> { - static std::string convert(const std::variant& variant) { - if (variant.valueless_by_exception()) { - return "{valueless variant}"; - } else { - return std::visit( - [](const auto& value) { - return ::Catch::Detail::stringify(value); - }, - variant - ); - } - } - }; -} -#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER +template +struct StringMaker> { + static std::string convert(const std::variant& variant) { + if (variant.valueless_by_exception()) { + return "{valueless variant}"; + } else { + return std::visit( + [](const auto& value) { return ::Catch::Detail::stringify(value); }, + variant); + } + } +}; +} // namespace Catch +#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER namespace Catch { - struct not_this_one {}; // Tag type for detecting which begin/ end are being selected +struct not_this_one { +}; // Tag type for detecting which begin/ end are being selected - // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace - using std::begin; - using std::end; +// Import begin/ end from std here so they are considered alongside the fallback +// (...) overloads in this namespace +using std::begin; +using std::end; - not_this_one begin( ... ); - not_this_one end( ... ); +not_this_one begin(...); +not_this_one end(...); - template - struct is_range { - static const bool value = - !std::is_same())), not_this_one>::value && - !std::is_same())), not_this_one>::value; - }; +template +struct is_range { + static const bool value = + !std::is_same())), not_this_one>::value && + !std::is_same())), not_this_one>::value; +}; -#if defined(_MANAGED) // Managed types are never ranges - template - struct is_range { - static const bool value = false; - }; +#if defined(_MANAGED) // Managed types are never ranges +template +struct is_range { + static const bool value = false; +}; #endif - template - std::string rangeToString( Range const& range ) { - return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); - } +template +std::string rangeToString(Range const& range) { + return ::Catch::Detail::rangeToString(begin(range), end(range)); +} - // Handle vector specially - template - std::string rangeToString( std::vector const& v ) { - ReusableStringStream rss; - rss << "{ "; - bool first = true; - for( bool b : v ) { - if( first ) - first = false; - else - rss << ", "; - rss << ::Catch::Detail::stringify( b ); - } - rss << " }"; - return rss.str(); - } +// Handle vector specially +template +std::string rangeToString(std::vector const& v) { + ReusableStringStream rss; + rss << "{ "; + bool first = true; + for (bool b : v) { + if (first) + first = false; + else + rss << ", "; + rss << ::Catch::Detail::stringify(b); + } + rss << " }"; + return rss.str(); +} - template - struct StringMaker::value && !::Catch::Detail::IsStreamInsertable::value>::type> { - static std::string convert( R const& range ) { - return rangeToString( range ); - } - }; +template +struct StringMaker::value && + !::Catch::Detail::IsStreamInsertable::value>::type> { + static std::string convert(R const& range) { return rangeToString(range); } +}; - template - struct StringMaker { - static std::string convert(T const(&arr)[SZ]) { - return rangeToString(arr); - } - }; +template +struct StringMaker { + static std::string convert(T const (&arr)[SZ]) { return rangeToString(arr); } +}; -} // namespace Catch +} // namespace Catch // Separate std::chrono::duration specialization #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#include #include #include -#include namespace Catch { template struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; template std::string ratio_string::symbol() { - Catch::ReusableStringStream rss; - rss << '[' << Ratio::num << '/' - << Ratio::den << ']'; - return rss.str(); + Catch::ReusableStringStream rss; + rss << '[' << Ratio::num << '/' << Ratio::den << ']'; + return rss.str(); } template <> struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; template <> struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; template <> struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; template <> struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; template <> struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; template <> struct ratio_string { - static std::string symbol(); + static std::string symbol(); }; - //////////// - // std::chrono::duration specializations - template - struct StringMaker> { - static std::string convert(std::chrono::duration const& duration) { - ReusableStringStream rss; - rss << duration.count() << ' ' << ratio_string::symbol() << 's'; - return rss.str(); - } - }; - template - struct StringMaker>> { - static std::string convert(std::chrono::duration> const& duration) { - ReusableStringStream rss; - rss << duration.count() << " s"; - return rss.str(); - } - }; - template - struct StringMaker>> { - static std::string convert(std::chrono::duration> const& duration) { - ReusableStringStream rss; - rss << duration.count() << " m"; - return rss.str(); - } - }; - template - struct StringMaker>> { - static std::string convert(std::chrono::duration> const& duration) { - ReusableStringStream rss; - rss << duration.count() << " h"; - return rss.str(); - } - }; +//////////// +// std::chrono::duration specializations +template +struct StringMaker> { + static std::string convert( + std::chrono::duration const& duration) { + ReusableStringStream rss; + rss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return rss.str(); + } +}; +template +struct StringMaker>> { + static std::string convert( + std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " s"; + return rss.str(); + } +}; +template +struct StringMaker>> { + static std::string convert( + std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " m"; + return rss.str(); + } +}; +template +struct StringMaker>> { + static std::string convert( + std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " h"; + return rss.str(); + } +}; - //////////// - // std::chrono::time_point specialization - // Generic time_point cannot be specialized, only std::chrono::time_point - template - struct StringMaker> { - static std::string convert(std::chrono::time_point const& time_point) { - return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; - } - }; - // std::chrono::time_point specialization - template - struct StringMaker> { - static std::string convert(std::chrono::time_point const& time_point) { - auto converted = std::chrono::system_clock::to_time_t(time_point); +//////////// +// std::chrono::time_point specialization +// Generic time_point cannot be specialized, only +// std::chrono::time_point +template +struct StringMaker> { + static std::string convert( + std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + + " since epoch"; + } +}; +// std::chrono::time_point specialization +template +struct StringMaker< + std::chrono::time_point> { + static std::string convert( + std::chrono::time_point const& + time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); #ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &converted); + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); #else - std::tm* timeInfo = std::gmtime(&converted); + std::tm* timeInfo = std::gmtime(&converted); #endif - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; #ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); #else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); #endif - return std::string(timeStamp); - } - }; -} -#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER + return std::string(timeStamp); + } +}; +} // namespace Catch +#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER #ifdef _MSC_VER #pragma warning(pop) @@ -1653,156 +1779,173 @@ struct ratio_string { #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#pragma warning(disable:4018) // more "signed/unsigned mismatch" -#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) -#pragma warning(disable:4180) // qualifier applied to function type has no meaning +#pragma warning(disable : 4389) // '==' : signed/unsigned mismatch +#pragma warning(disable : 4018) // more "signed/unsigned mismatch" +#pragma warning(disable : 4312) // Converting int to T* using reinterpret_cast + // (issue on x64 platform) +#pragma warning( \ + disable : 4180) // qualifier applied to function type has no meaning #endif namespace Catch { - struct ITransientExpression { - auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } - auto getResult() const -> bool { return m_result; } - virtual void streamReconstructedExpression( std::ostream &os ) const = 0; +struct ITransientExpression { + auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } + auto getResult() const -> bool { return m_result; } + virtual void streamReconstructedExpression(std::ostream& os) const = 0; - ITransientExpression( bool isBinaryExpression, bool result ) - : m_isBinaryExpression( isBinaryExpression ), - m_result( result ) - {} + ITransientExpression(bool isBinaryExpression, bool result) + : m_isBinaryExpression(isBinaryExpression), m_result(result) {} - // We don't actually need a virtual destructor, but many static analysers - // complain if it's not here :-( - virtual ~ITransientExpression(); + // We don't actually need a virtual destructor, but many static analysers + // complain if it's not here :-( + virtual ~ITransientExpression(); - bool m_isBinaryExpression; - bool m_result; + bool m_isBinaryExpression; + bool m_result; +}; - }; +void formatReconstructedExpression(std::ostream& os, std::string const& lhs, + StringRef op, std::string const& rhs); - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); +template +class BinaryExpr : public ITransientExpression { + LhsT m_lhs; + StringRef m_op; + RhsT m_rhs; - template - class BinaryExpr : public ITransientExpression { - LhsT m_lhs; - StringRef m_op; - RhsT m_rhs; + void streamReconstructedExpression(std::ostream& os) const override { + formatReconstructedExpression(os, Catch::Detail::stringify(m_lhs), m_op, + Catch::Detail::stringify(m_rhs)); + } - void streamReconstructedExpression( std::ostream &os ) const override { - formatReconstructedExpression - ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); - } + public: + BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs) + : ITransientExpression{true, comparisonResult}, + m_lhs(lhs), + m_op(op), + m_rhs(rhs) {} +}; - public: - BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) - : ITransientExpression{ true, comparisonResult }, - m_lhs( lhs ), - m_op( op ), - m_rhs( rhs ) - {} - }; +template +class UnaryExpr : public ITransientExpression { + LhsT m_lhs; - template - class UnaryExpr : public ITransientExpression { - LhsT m_lhs; + void streamReconstructedExpression(std::ostream& os) const override { + os << Catch::Detail::stringify(m_lhs); + } - void streamReconstructedExpression( std::ostream &os ) const override { - os << Catch::Detail::stringify( m_lhs ); - } + public: + explicit UnaryExpr(LhsT lhs) + : ITransientExpression{false, lhs ? true : false}, m_lhs(lhs) {} +}; - public: - explicit UnaryExpr( LhsT lhs ) - : ITransientExpression{ false, lhs ? true : false }, - m_lhs( lhs ) - {} - }; +// Specialised comparison functions to handle equality comparisons between ints +// and pointers (NULL deduces as an int) +template +auto compareEqual(LhsT const& lhs, RhsT const& rhs) -> bool { + return static_cast(lhs == rhs); +} +template +auto compareEqual(T* const& lhs, int rhs) -> bool { + return lhs == reinterpret_cast(rhs); +} +template +auto compareEqual(T* const& lhs, long rhs) -> bool { + return lhs == reinterpret_cast(rhs); +} +template +auto compareEqual(int lhs, T* const& rhs) -> bool { + return reinterpret_cast(lhs) == rhs; +} +template +auto compareEqual(long lhs, T* const& rhs) -> bool { + return reinterpret_cast(lhs) == rhs; +} - // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) - template - auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast(lhs == rhs); } - template - auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } - template - auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } - template - auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } - template - auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } +template +auto compareNotEqual(LhsT const& lhs, RhsT&& rhs) -> bool { + return static_cast(lhs != rhs); +} +template +auto compareNotEqual(T* const& lhs, int rhs) -> bool { + return lhs != reinterpret_cast(rhs); +} +template +auto compareNotEqual(T* const& lhs, long rhs) -> bool { + return lhs != reinterpret_cast(rhs); +} +template +auto compareNotEqual(int lhs, T* const& rhs) -> bool { + return reinterpret_cast(lhs) != rhs; +} +template +auto compareNotEqual(long lhs, T* const& rhs) -> bool { + return reinterpret_cast(lhs) != rhs; +} - template - auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast(lhs != rhs); } - template - auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } - template - auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } - template - auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } - template - auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } +template +class ExprLhs { + LhsT m_lhs; - template - class ExprLhs { - LhsT m_lhs; - public: - explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} + public: + explicit ExprLhs(LhsT lhs) : m_lhs(lhs) {} - template - auto operator == ( RhsT const& rhs ) -> BinaryExpr const { - return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; - } - auto operator == ( bool rhs ) -> BinaryExpr const { - return { m_lhs == rhs, m_lhs, "==", rhs }; - } + template + auto operator==(RhsT const& rhs) -> BinaryExpr const { + return {compareEqual(m_lhs, rhs), m_lhs, "==", rhs}; + } + auto operator==(bool rhs) -> BinaryExpr const { + return {m_lhs == rhs, m_lhs, "==", rhs}; + } - template - auto operator != ( RhsT const& rhs ) -> BinaryExpr const { - return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; - } - auto operator != ( bool rhs ) -> BinaryExpr const { - return { m_lhs != rhs, m_lhs, "!=", rhs }; - } + template + auto operator!=(RhsT const& rhs) -> BinaryExpr const { + return {compareNotEqual(m_lhs, rhs), m_lhs, "!=", rhs}; + } + auto operator!=(bool rhs) -> BinaryExpr const { + return {m_lhs != rhs, m_lhs, "!=", rhs}; + } - template - auto operator > ( RhsT const& rhs ) -> BinaryExpr const { - return { static_cast(m_lhs > rhs), m_lhs, ">", rhs }; - } - template - auto operator < ( RhsT const& rhs ) -> BinaryExpr const { - return { static_cast(m_lhs < rhs), m_lhs, "<", rhs }; - } - template - auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { - return { static_cast(m_lhs >= rhs), m_lhs, ">=", rhs }; - } - template - auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { - return { static_cast(m_lhs <= rhs), m_lhs, "<=", rhs }; - } + template + auto operator>(RhsT const& rhs) -> BinaryExpr const { + return {static_cast(m_lhs > rhs), m_lhs, ">", rhs}; + } + template + auto operator<(RhsT const& rhs) -> BinaryExpr const { + return {static_cast(m_lhs < rhs), m_lhs, "<", rhs}; + } + template + auto operator>=(RhsT const& rhs) -> BinaryExpr const { + return {static_cast(m_lhs >= rhs), m_lhs, ">=", rhs}; + } + template + auto operator<=(RhsT const& rhs) -> BinaryExpr const { + return {static_cast(m_lhs <= rhs), m_lhs, "<=", rhs}; + } - auto makeUnaryExpr() const -> UnaryExpr { - return UnaryExpr{ m_lhs }; - } - }; + auto makeUnaryExpr() const -> UnaryExpr { + return UnaryExpr{m_lhs}; + } +}; - void handleExpression( ITransientExpression const& expr ); +void handleExpression(ITransientExpression const& expr); - template - void handleExpression( ExprLhs const& expr ) { - handleExpression( expr.makeUnaryExpr() ); - } +template +void handleExpression(ExprLhs const& expr) { + handleExpression(expr.makeUnaryExpr()); +} - struct Decomposer { - template - auto operator <= ( T const& lhs ) -> ExprLhs { - return ExprLhs{ lhs }; - } +struct Decomposer { + template + auto operator<=(T const& lhs) -> ExprLhs { + return ExprLhs{lhs}; + } - auto operator <=( bool value ) -> ExprLhs { - return ExprLhs{ value }; - } - }; + auto operator<=(bool value) -> ExprLhs { return ExprLhs{value}; } +}; -} // end namespace Catch +} // end namespace Catch #ifdef _MSC_VER #pragma warning(pop) @@ -1815,146 +1958,139 @@ namespace Catch { namespace Catch { - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - struct Counts; - struct BenchmarkInfo; - struct BenchmarkStats; - struct AssertionReaction; - struct SourceLineInfo; +class AssertionResult; +struct AssertionInfo; +struct SectionInfo; +struct SectionEndInfo; +struct MessageInfo; +struct Counts; +struct BenchmarkInfo; +struct BenchmarkStats; +struct AssertionReaction; +struct SourceLineInfo; - struct ITransientExpression; - struct IGeneratorTracker; +struct ITransientExpression; +struct IGeneratorTracker; - struct IResultCapture { +struct IResultCapture { + virtual ~IResultCapture(); - virtual ~IResultCapture(); + virtual bool sectionStarted(SectionInfo const& sectionInfo, + Counts& assertions) = 0; + virtual void sectionEnded(SectionEndInfo const& endInfo) = 0; + virtual void sectionEndedEarly(SectionEndInfo const& endInfo) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual auto acquireGeneratorTracker(SourceLineInfo const& lineInfo) + -> IGeneratorTracker& = 0; - virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; + virtual void benchmarkStarting(BenchmarkInfo const& info) = 0; + virtual void benchmarkEnded(BenchmarkStats const& stats) = 0; - virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; - virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; + virtual void pushScopedMessage(MessageInfo const& message) = 0; + virtual void popScopedMessage(MessageInfo const& message) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; + virtual void handleFatalErrorCondition(StringRef message) = 0; - virtual void handleFatalErrorCondition( StringRef message ) = 0; + virtual void handleExpr(AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction) = 0; + virtual void handleMessage(AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef const& message, + AssertionReaction& reaction) = 0; + virtual void handleUnexpectedExceptionNotThrown( + AssertionInfo const& info, AssertionReaction& reaction) = 0; + virtual void handleUnexpectedInflightException( + AssertionInfo const& info, std::string const& message, + AssertionReaction& reaction) = 0; + virtual void handleIncomplete(AssertionInfo const& info) = 0; + virtual void handleNonExpr(AssertionInfo const& info, + ResultWas::OfType resultType, + AssertionReaction& reaction) = 0; - virtual void handleExpr - ( AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction ) = 0; - virtual void handleMessage - ( AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef const& message, - AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedExceptionNotThrown - ( AssertionInfo const& info, - AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedInflightException - ( AssertionInfo const& info, - std::string const& message, - AssertionReaction& reaction ) = 0; - virtual void handleIncomplete - ( AssertionInfo const& info ) = 0; - virtual void handleNonExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - AssertionReaction &reaction ) = 0; + virtual bool lastAssertionPassed() = 0; + virtual void assertionPassed() = 0; - virtual bool lastAssertionPassed() = 0; - virtual void assertionPassed() = 0; + // Deprecated, do not use: + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + virtual void exceptionEarlyReported() = 0; +}; - // Deprecated, do not use: - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - virtual void exceptionEarlyReported() = 0; - }; - - IResultCapture& getResultCapture(); -} +IResultCapture& getResultCapture(); +} // namespace Catch // end catch_interfaces_capture.h namespace Catch { - struct TestFailureException{}; - struct AssertionResultData; - struct IResultCapture; - class RunContext; +struct TestFailureException {}; +struct AssertionResultData; +struct IResultCapture; +class RunContext; - class LazyExpression { - friend class AssertionHandler; - friend struct AssertionStats; - friend class RunContext; +class LazyExpression { + friend class AssertionHandler; + friend struct AssertionStats; + friend class RunContext; - ITransientExpression const* m_transientExpression = nullptr; - bool m_isNegated; - public: - LazyExpression( bool isNegated ); - LazyExpression( LazyExpression const& other ); - LazyExpression& operator = ( LazyExpression const& ) = delete; + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; - explicit operator bool() const; + public: + LazyExpression(bool isNegated); + LazyExpression(LazyExpression const& other); + LazyExpression& operator=(LazyExpression const&) = delete; - friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; - }; + explicit operator bool() const; - struct AssertionReaction { - bool shouldDebugBreak = false; - bool shouldThrow = false; - }; + friend auto operator<<(std::ostream& os, LazyExpression const& lazyExpr) + -> std::ostream&; +}; - class AssertionHandler { - AssertionInfo m_assertionInfo; - AssertionReaction m_reaction; - bool m_completed = false; - IResultCapture& m_resultCapture; +struct AssertionReaction { + bool shouldDebugBreak = false; + bool shouldThrow = false; +}; - public: - AssertionHandler - ( StringRef const& macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition ); - ~AssertionHandler() { - if ( !m_completed ) { - m_resultCapture.handleIncomplete( m_assertionInfo ); - } - } +class AssertionHandler { + AssertionInfo m_assertionInfo; + AssertionReaction m_reaction; + bool m_completed = false; + IResultCapture& m_resultCapture; - template - void handleExpr( ExprLhs const& expr ) { - handleExpr( expr.makeUnaryExpr() ); - } - void handleExpr( ITransientExpression const& expr ); + public: + AssertionHandler(StringRef const& macroName, SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition); + ~AssertionHandler() { + if (!m_completed) { m_resultCapture.handleIncomplete(m_assertionInfo); } + } - void handleMessage(ResultWas::OfType resultType, StringRef const& message); + template + void handleExpr(ExprLhs const& expr) { + handleExpr(expr.makeUnaryExpr()); + } + void handleExpr(ITransientExpression const& expr); - void handleExceptionThrownAsExpected(); - void handleUnexpectedExceptionNotThrown(); - void handleExceptionNotThrownAsExpected(); - void handleThrowingCallSkipped(); - void handleUnexpectedInflightException(); + void handleMessage(ResultWas::OfType resultType, StringRef const& message); - void complete(); - void setCompleted(); + void handleExceptionThrownAsExpected(); + void handleUnexpectedExceptionNotThrown(); + void handleExceptionNotThrownAsExpected(); + void handleThrowingCallSkipped(); + void handleUnexpectedInflightException(); - // query - auto allowThrows() const -> bool; - }; + void complete(); + void setCompleted(); - void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); + // query + auto allowThrows() const -> bool; +}; -} // namespace Catch +void handleExceptionMatchExpr(AssertionHandler& handler, std::string const& str, + StringRef const& matcherString); + +} // namespace Catch // end catch_assertionhandler.h // start catch_message.h @@ -1964,216 +2100,245 @@ namespace Catch { namespace Catch { - struct MessageInfo { - MessageInfo( StringRef const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); +struct MessageInfo { + MessageInfo(StringRef const& _macroName, SourceLineInfo const& _lineInfo, + ResultWas::OfType _type); - StringRef macroName; - std::string message; - SourceLineInfo lineInfo; - ResultWas::OfType type; - unsigned int sequence; + StringRef macroName; + std::string message; + SourceLineInfo lineInfo; + ResultWas::OfType type; + unsigned int sequence; - bool operator == ( MessageInfo const& other ) const; - bool operator < ( MessageInfo const& other ) const; - private: - static unsigned int globalCount; - }; + bool operator==(MessageInfo const& other) const; + bool operator<(MessageInfo const& other) const; - struct MessageStream { + private: + static unsigned int globalCount; +}; - template - MessageStream& operator << ( T const& value ) { - m_stream << value; - return *this; - } +struct MessageStream { + template + MessageStream& operator<<(T const& value) { + m_stream << value; + return *this; + } - ReusableStringStream m_stream; - }; + ReusableStringStream m_stream; +}; - struct MessageBuilder : MessageStream { - MessageBuilder( StringRef const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ); +struct MessageBuilder : MessageStream { + MessageBuilder(StringRef const& macroName, SourceLineInfo const& lineInfo, + ResultWas::OfType type); - template - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } + template + MessageBuilder& operator<<(T const& value) { + m_stream << value; + return *this; + } - MessageInfo m_info; - }; + MessageInfo m_info; +}; - class ScopedMessage { - public: - explicit ScopedMessage( MessageBuilder const& builder ); - ~ScopedMessage(); +class ScopedMessage { + public: + explicit ScopedMessage(MessageBuilder const& builder); + ~ScopedMessage(); - MessageInfo m_info; - }; + MessageInfo m_info; +}; - class Capturer { - std::vector m_messages; - IResultCapture& m_resultCapture = getResultCapture(); - size_t m_captured = 0; - public: - Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); - ~Capturer(); +class Capturer { + std::vector m_messages; + IResultCapture& m_resultCapture = getResultCapture(); + size_t m_captured = 0; - void captureValue( size_t index, std::string const& value ); + public: + Capturer(StringRef macroName, SourceLineInfo const& lineInfo, + ResultWas::OfType resultType, StringRef names); + ~Capturer(); - template - void captureValues( size_t index, T const& value ) { - captureValue( index, Catch::Detail::stringify( value ) ); - } + void captureValue(size_t index, std::string const& value); - template - void captureValues( size_t index, T const& value, Ts const&... values ) { - captureValue( index, Catch::Detail::stringify(value) ); - captureValues( index+1, values... ); - } - }; + template + void captureValues(size_t index, T const& value) { + captureValue(index, Catch::Detail::stringify(value)); + } -} // end namespace Catch + template + void captureValues(size_t index, T const& value, Ts const&... values) { + captureValue(index, Catch::Detail::stringify(value)); + captureValues(index + 1, values...); + } +}; + +} // end namespace Catch // end catch_message.h #if !defined(CATCH_CONFIG_DISABLE) #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) - #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ +#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ #else - #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" +#define CATCH_INTERNAL_STRINGIFY(...) \ + "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" #endif -#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#if defined(CATCH_CONFIG_FAST_COMPILE) || \ + defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* // macros. #define INTERNAL_CATCH_TRY -#define INTERNAL_CATCH_CATCH( capturer ) +#define INTERNAL_CATCH_CATCH(capturer) -#else // CATCH_CONFIG_FAST_COMPILE +#else // CATCH_CONFIG_FAST_COMPILE #define INTERNAL_CATCH_TRY try -#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } +#define INTERNAL_CATCH_CATCH(handler) \ + catch (...) { \ + handler.handleUnexpectedInflightException(); \ + } #endif -#define INTERNAL_CATCH_REACT( handler ) handler.complete(); +#define INTERNAL_CATCH_REACT(handler) handler.complete(); /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ - INTERNAL_CATCH_TRY { \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( (void)0, false && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look - // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. +#define INTERNAL_CATCH_TEST(macroName, resultDisposition, ...) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + INTERNAL_CATCH_TRY { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + catchAssertionHandler.handleExpr(Catch::Decomposer() <= __VA_ARGS__); \ + CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + } \ + INTERNAL_CATCH_CATCH(catchAssertionHandler) \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while ((void)0, \ + false && static_cast( \ + !!(__VA_ARGS__))) // the expression here is never + // evaluated at runtime but it forces + // the compiler to give it a look + // The double negation silences MSVC's C4800 warning, the static_cast forces + // short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ - if( Catch::getResultCapture().lastAssertionPassed() ) +#define INTERNAL_CATCH_IF(macroName, resultDisposition, ...) \ + INTERNAL_CATCH_TEST(macroName, resultDisposition, __VA_ARGS__); \ + if (Catch::getResultCapture().lastAssertionPassed()) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ - if( !Catch::getResultCapture().lastAssertionPassed() ) +#define INTERNAL_CATCH_ELSE(macroName, resultDisposition, ...) \ + INTERNAL_CATCH_TEST(macroName, resultDisposition, __VA_ARGS__); \ + if (!Catch::getResultCapture().lastAssertionPassed()) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ - } \ - catch( ... ) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CATCH_NO_THROW(macroName, resultDisposition, ...) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ + } catch (...) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( ... ) { \ - catchAssertionHandler.handleExceptionThrownAsExpected(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CATCH_THROWS(macroName, resultDisposition, ...) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + if (catchAssertionHandler.allowThrows()) try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } catch (...) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(expr); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( exceptionType const& ) { \ - catchAssertionHandler.handleExceptionThrownAsExpected(); \ - } \ - catch( ... ) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CATCH_THROWS_AS(macroName, exceptionType, resultDisposition, \ + expr) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY( \ + exceptionType), \ + resultDisposition); \ + if (catchAssertionHandler.allowThrows()) try { \ + static_cast(expr); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } catch (exceptionType const&) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } catch (...) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ - catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CATCH_MSG(macroName, messageType, resultDisposition, ...) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), \ + resultDisposition); \ + catchAssertionHandler.handleMessage( \ + messageType, \ + (Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop()) \ + .m_stream.str()); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ - auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ - varName.captureValues( 0, __VA_ARGS__ ) +#define INTERNAL_CATCH_CAPTURE(varName, macroName, ...) \ + auto varName = Catch::Capturer(macroName, CATCH_INTERNAL_LINEINFO, \ + Catch::ResultWas::Info, #__VA_ARGS__); \ + varName.captureValues(0, __VA_ARGS__) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( macroName, log ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); +#define INTERNAL_CATCH_INFO(macroName, log) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME(scopedMessage)( \ + Catch::MessageBuilder(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + Catch::ResultWas::Info) \ + << log); /////////////////////////////////////////////////////////////////////////////// // Although this is matcher-based, it can be used with just a string -#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( ... ) { \ - Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CATCH_THROWS_STR_MATCHES(macroName, resultDisposition, \ + matcher, ...) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY( \ + matcher), \ + resultDisposition); \ + if (catchAssertionHandler.allowThrows()) try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } catch (...) { \ + Catch::handleExceptionMatchExpr(catchAssertionHandler, matcher, \ + #matcher##_catch_sr); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) -#endif // CATCH_CONFIG_DISABLE +#endif // CATCH_CONFIG_DISABLE // end catch_capture.hpp // start catch_section.h @@ -2186,60 +2351,56 @@ namespace Catch { namespace Catch { - struct Counts { - Counts operator - ( Counts const& other ) const; - Counts& operator += ( Counts const& other ); +struct Counts { + Counts operator-(Counts const& other) const; + Counts& operator+=(Counts const& other); - std::size_t total() const; - bool allPassed() const; - bool allOk() const; + std::size_t total() const; + bool allPassed() const; + bool allOk() const; - std::size_t passed = 0; - std::size_t failed = 0; - std::size_t failedButOk = 0; - }; + std::size_t passed = 0; + std::size_t failed = 0; + std::size_t failedButOk = 0; +}; - struct Totals { +struct Totals { + Totals operator-(Totals const& other) const; + Totals& operator+=(Totals const& other); - Totals operator - ( Totals const& other ) const; - Totals& operator += ( Totals const& other ); + Totals delta(Totals const& prevTotals) const; - Totals delta( Totals const& prevTotals ) const; - - int error = 0; - Counts assertions; - Counts testCases; - }; -} + int error = 0; + Counts assertions; + Counts testCases; +}; +} // namespace Catch // end catch_totals.h #include namespace Catch { - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name ); +struct SectionInfo { + SectionInfo(SourceLineInfo const& _lineInfo, std::string const& _name); - // Deprecated - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& ) : SectionInfo( _lineInfo, _name ) {} + // Deprecated + SectionInfo(SourceLineInfo const& _lineInfo, std::string const& _name, + std::string const&) + : SectionInfo(_lineInfo, _name) {} - std::string name; - std::string description; // !Deprecated: this will always be empty - SourceLineInfo lineInfo; - }; + std::string name; + std::string description; // !Deprecated: this will always be empty + SourceLineInfo lineInfo; +}; - struct SectionEndInfo { - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; - }; +struct SectionEndInfo { + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; +}; -} // end namespace Catch +} // end namespace Catch // end catch_section_info.h // start catch_timer.h @@ -2248,54 +2409,61 @@ namespace Catch { namespace Catch { - auto getCurrentNanosecondsSinceEpoch() -> uint64_t; - auto getEstimatedClockResolution() -> uint64_t; +auto getCurrentNanosecondsSinceEpoch() -> uint64_t; +auto getEstimatedClockResolution() -> uint64_t; - class Timer { - uint64_t m_nanoseconds = 0; - public: - void start(); - auto getElapsedNanoseconds() const -> uint64_t; - auto getElapsedMicroseconds() const -> uint64_t; - auto getElapsedMilliseconds() const -> unsigned int; - auto getElapsedSeconds() const -> double; - }; +class Timer { + uint64_t m_nanoseconds = 0; -} // namespace Catch + public: + void start(); + auto getElapsedNanoseconds() const -> uint64_t; + auto getElapsedMicroseconds() const -> uint64_t; + auto getElapsedMilliseconds() const -> unsigned int; + auto getElapsedSeconds() const -> double; +}; + +} // namespace Catch // end catch_timer.h #include namespace Catch { - class Section : NonCopyable { - public: - Section( SectionInfo const& info ); - ~Section(); +class Section : NonCopyable { + public: + Section(SectionInfo const& info); + ~Section(); - // This indicates whether the section should be executed or not - explicit operator bool() const; + // This indicates whether the section should be executed or not + explicit operator bool() const; - private: - SectionInfo m_info; + private: + SectionInfo m_info; - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; +}; -} // end namespace Catch +} // end namespace Catch -#define INTERNAL_CATCH_SECTION( ... ) \ - CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ - CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS +#define INTERNAL_CATCH_SECTION(...) \ + CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_Section) = \ + Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, __VA_ARGS__)) \ + CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS -#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ - CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ - CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS +#define INTERNAL_CATCH_DYNAMIC_SECTION(...) \ + CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_Section) = \ + Catch::SectionInfo( \ + CATCH_INTERNAL_LINEINFO, \ + (Catch::ReusableStringStream() << __VA_ARGS__).str())) \ + CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS // end catch_section.h // start catch_benchmark.h @@ -2305,98 +2473,98 @@ namespace Catch { namespace Catch { - class BenchmarkLooper { +class BenchmarkLooper { + std::string m_name; + std::size_t m_count = 0; + std::size_t m_iterationsToRun = 1; + uint64_t m_resolution; + Timer m_timer; - std::string m_name; - std::size_t m_count = 0; - std::size_t m_iterationsToRun = 1; - uint64_t m_resolution; - Timer m_timer; + static auto getResolution() -> uint64_t; - static auto getResolution() -> uint64_t; - public: - // Keep most of this inline as it's on the code path that is being timed - BenchmarkLooper( StringRef name ) - : m_name( name ), - m_resolution( getResolution() ) - { - reportStart(); - m_timer.start(); - } + public: + // Keep most of this inline as it's on the code path that is being timed + BenchmarkLooper(StringRef name) + : m_name(name), m_resolution(getResolution()) { + reportStart(); + m_timer.start(); + } - explicit operator bool() { - if( m_count < m_iterationsToRun ) - return true; - return needsMoreIterations(); - } + explicit operator bool() { + if (m_count < m_iterationsToRun) return true; + return needsMoreIterations(); + } - void increment() { - ++m_count; - } + void increment() { ++m_count; } - void reportStart(); - auto needsMoreIterations() -> bool; - }; + void reportStart(); + auto needsMoreIterations() -> bool; +}; -} // end namespace Catch +} // end namespace Catch -#define BENCHMARK( name ) \ - for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) +#define BENCHMARK(name) \ + for (Catch::BenchmarkLooper looper(name); looper; looper.increment()) // end catch_benchmark.h // start catch_interfaces_exception.h // start catch_interfaces_registry_hub.h -#include #include +#include namespace Catch { - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - struct ITagAliasRegistry; - class StartupExceptionRegistry; +class TestCase; +struct ITestCaseRegistry; +struct IExceptionTranslatorRegistry; +struct IExceptionTranslator; +struct IReporterRegistry; +struct IReporterFactory; +struct ITagAliasRegistry; +class StartupExceptionRegistry; - using IReporterFactoryPtr = std::shared_ptr; +using IReporterFactoryPtr = std::shared_ptr; - struct IRegistryHub { - virtual ~IRegistryHub(); +struct IRegistryHub { + virtual ~IRegistryHub(); - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; - virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; + virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() + const = 0; - virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; - }; + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() + const = 0; +}; - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; - virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - virtual void registerStartupException() noexcept = 0; - }; +struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter(std::string const& name, + IReporterFactoryPtr const& factory) = 0; + virtual void registerListener(IReporterFactoryPtr const& factory) = 0; + virtual void registerTest(TestCase const& testInfo) = 0; + virtual void registerTranslator(const IExceptionTranslator* translator) = 0; + virtual void registerTagAlias(std::string const& alias, + std::string const& tag, + SourceLineInfo const& lineInfo) = 0; + virtual void registerStartupException() noexcept = 0; +}; - IRegistryHub const& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); +IRegistryHub const& getRegistryHub(); +IMutableRegistryHub& getMutableRegistryHub(); +void cleanUp(); +std::string translateActiveException(); -} +} // namespace Catch // end catch_interfaces_registry_hub.h #if defined(CATCH_CONFIG_DISABLE) - #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ - static std::string translatorName( signature ) +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG(translatorName, signature) \ + static std::string translatorName(signature) #endif #include @@ -2404,65 +2572,71 @@ namespace Catch { #include namespace Catch { - using exceptionTranslateFunction = std::string(*)(); +using exceptionTranslateFunction = std::string (*)(); - struct IExceptionTranslator; - using ExceptionTranslators = std::vector>; +struct IExceptionTranslator; +using ExceptionTranslators = + std::vector>; - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; - }; +struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( + ExceptionTranslators::const_iterator it, + ExceptionTranslators::const_iterator itEnd) const = 0; +}; - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); +struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); - virtual std::string translateActiveException() const = 0; - }; + virtual std::string translateActiveException() const = 0; +}; - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: +class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + ExceptionTranslator(std::string (*translateFunction)(T&)) + : m_translateFunction(translateFunction) {} - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} + std::string translate( + ExceptionTranslators::const_iterator it, + ExceptionTranslators::const_iterator itEnd) const override { + try { + if (it == itEnd) + std::rethrow_exception(std::current_exception()); + else + return (*it)->translate(it + 1, itEnd); + } catch (T& ex) { return m_translateFunction(ex); } + } - std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { - try { - if( it == itEnd ) - std::rethrow_exception(std::current_exception()); - else - return (*it)->translate( it+1, itEnd ); - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } + protected: + std::string (*m_translateFunction)(T&); + }; - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} + public: + template + ExceptionTranslatorRegistrar(std::string (*translateFunction)(T&)) { + getMutableRegistryHub().registerTranslator( + new ExceptionTranslator(translateFunction)); + } +}; +} // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ - static std::string translatorName( signature ); \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - static std::string translatorName( signature ) +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2(translatorName, signature) \ + static std::string translatorName(signature); \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_ExceptionRegistrar)(&translatorName); \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + static std::string translatorName(signature) -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature) \ + INTERNAL_CATCH_TRANSLATE_EXCEPTION2( \ + INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator), \ + signature) // end catch_interfaces_exception.h // start catch_approx.h @@ -2472,146 +2646,160 @@ namespace Catch { namespace Catch { namespace Detail { - class Approx { - private: - bool equalityComparisonImpl(double other) const; - // Validates the new margin (margin >= 0) - // out-of-line to avoid including stdexcept in the header - void setMargin(double margin); - // Validates the new epsilon (0 < epsilon < 1) - // out-of-line to avoid including stdexcept in the header - void setEpsilon(double epsilon); +class Approx { + private: + bool equalityComparisonImpl(double other) const; + // Validates the new margin (margin >= 0) + // out-of-line to avoid including stdexcept in the header + void setMargin(double margin); + // Validates the new epsilon (0 < epsilon < 1) + // out-of-line to avoid including stdexcept in the header + void setEpsilon(double epsilon); - public: - explicit Approx ( double value ); + public: + explicit Approx(double value); - static Approx custom(); + static Approx custom(); - Approx operator-() const; + Approx operator-() const; - template ::value>::type> - Approx operator()( T const& value ) { - Approx approx( static_cast(value) ); - approx.m_epsilon = m_epsilon; - approx.m_margin = m_margin; - approx.m_scale = m_scale; - return approx; - } + template ::value>::type> + Approx operator()(T const& value) { + Approx approx(static_cast(value)); + approx.m_epsilon = m_epsilon; + approx.m_margin = m_margin; + approx.m_scale = m_scale; + return approx; + } - template ::value>::type> - explicit Approx( T const& value ): Approx(static_cast(value)) - {} + template ::value>::type> + explicit Approx(T const& value) : Approx(static_cast(value)) {} - template ::value>::type> - friend bool operator == ( const T& lhs, Approx const& rhs ) { - auto lhs_v = static_cast(lhs); - return rhs.equalityComparisonImpl(lhs_v); - } + template ::value>::type> + friend bool operator==(const T& lhs, Approx const& rhs) { + auto lhs_v = static_cast(lhs); + return rhs.equalityComparisonImpl(lhs_v); + } - template ::value>::type> - friend bool operator == ( Approx const& lhs, const T& rhs ) { - return operator==( rhs, lhs ); - } + template ::value>::type> + friend bool operator==(Approx const& lhs, const T& rhs) { + return operator==(rhs, lhs); + } - template ::value>::type> - friend bool operator != ( T const& lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } + template ::value>::type> + friend bool operator!=(T const& lhs, Approx const& rhs) { + return !operator==(lhs, rhs); + } - template ::value>::type> - friend bool operator != ( Approx const& lhs, T const& rhs ) { - return !operator==( rhs, lhs ); - } + template ::value>::type> + friend bool operator!=(Approx const& lhs, T const& rhs) { + return !operator==(rhs, lhs); + } - template ::value>::type> - friend bool operator <= ( T const& lhs, Approx const& rhs ) { - return static_cast(lhs) < rhs.m_value || lhs == rhs; - } + template ::value>::type> + friend bool operator<=(T const& lhs, Approx const& rhs) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; + } - template ::value>::type> - friend bool operator <= ( Approx const& lhs, T const& rhs ) { - return lhs.m_value < static_cast(rhs) || lhs == rhs; - } + template ::value>::type> + friend bool operator<=(Approx const& lhs, T const& rhs) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; + } - template ::value>::type> - friend bool operator >= ( T const& lhs, Approx const& rhs ) { - return static_cast(lhs) > rhs.m_value || lhs == rhs; - } + template ::value>::type> + friend bool operator>=(T const& lhs, Approx const& rhs) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; + } - template ::value>::type> - friend bool operator >= ( Approx const& lhs, T const& rhs ) { - return lhs.m_value > static_cast(rhs) || lhs == rhs; - } + template ::value>::type> + friend bool operator>=(Approx const& lhs, T const& rhs) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; + } - template ::value>::type> - Approx& epsilon( T const& newEpsilon ) { - double epsilonAsDouble = static_cast(newEpsilon); - setEpsilon(epsilonAsDouble); - return *this; - } + template ::value>::type> + Approx& epsilon(T const& newEpsilon) { + double epsilonAsDouble = static_cast(newEpsilon); + setEpsilon(epsilonAsDouble); + return *this; + } - template ::value>::type> - Approx& margin( T const& newMargin ) { - double marginAsDouble = static_cast(newMargin); - setMargin(marginAsDouble); - return *this; - } + template ::value>::type> + Approx& margin(T const& newMargin) { + double marginAsDouble = static_cast(newMargin); + setMargin(marginAsDouble); + return *this; + } - template ::value>::type> - Approx& scale( T const& newScale ) { - m_scale = static_cast(newScale); - return *this; - } + template ::value>::type> + Approx& scale(T const& newScale) { + m_scale = static_cast(newScale); + return *this; + } - std::string toString() const; + std::string toString() const; - private: - double m_epsilon; - double m_margin; - double m_scale; - double m_value; - }; -} // end namespace Detail + private: + double m_epsilon; + double m_margin; + double m_scale; + double m_value; +}; +} // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); -} // end namespace literals +Detail::Approx operator"" _a(long double val); +Detail::Approx operator"" _a(unsigned long long val); +} // end namespace literals -template<> +template <> struct StringMaker { - static std::string convert(Catch::Detail::Approx const& value); + static std::string convert(Catch::Detail::Approx const& value); }; -} // end namespace Catch +} // end namespace Catch // end catch_approx.h // start catch_string_manip.h -#include #include +#include namespace Catch { - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); +bool startsWith(std::string const& s, std::string const& prefix); +bool startsWith(std::string const& s, char prefix); +bool endsWith(std::string const& s, std::string const& suffix); +bool endsWith(std::string const& s, char suffix); +bool contains(std::string const& s, std::string const& infix); +void toLowerInPlace(std::string& s); +std::string toLower(std::string const& s); +std::string trim(std::string const& str); +bool replaceInPlace(std::string& str, std::string const& replaceThis, + std::string const& withThis); - struct pluralise { - pluralise( std::size_t count, std::string const& label ); +struct pluralise { + pluralise(std::size_t count, std::string const& label); - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + friend std::ostream& operator<<(std::ostream& os, + pluralise const& pluraliser); - std::size_t m_count; - std::string m_label; - }; -} + std::size_t m_count; + std::string m_label; +}; +} // namespace Catch // end catch_string_manip.h #ifndef CATCH_CONFIG_DISABLE_MATCHERS @@ -2624,192 +2812,193 @@ namespace Catch { namespace Catch { namespace Matchers { - namespace Impl { +namespace Impl { - template struct MatchAllOf; - template struct MatchAnyOf; - template struct MatchNotOf; +template +struct MatchAllOf; +template +struct MatchAnyOf; +template +struct MatchNotOf; - class MatcherUntypedBase { - public: - MatcherUntypedBase() = default; - MatcherUntypedBase ( MatcherUntypedBase const& ) = default; - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; - std::string toString() const; +class MatcherUntypedBase { + public: + MatcherUntypedBase() = default; + MatcherUntypedBase(MatcherUntypedBase const&) = default; + MatcherUntypedBase& operator=(MatcherUntypedBase const&) = delete; + std::string toString() const; - protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; - mutable std::string m_cachedToString; - }; + protected: + virtual ~MatcherUntypedBase(); + virtual std::string describe() const = 0; + mutable std::string m_cachedToString; +}; #ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wnon-virtual-dtor" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnon-virtual-dtor" #endif - template - struct MatcherMethod { - virtual bool match( ObjectT const& arg ) const = 0; - }; +template +struct MatcherMethod { + virtual bool match(ObjectT const& arg) const = 0; +}; #ifdef __clang__ -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif - template - struct MatcherBase : MatcherUntypedBase, MatcherMethod { +template +struct MatcherBase : MatcherUntypedBase, MatcherMethod { + MatchAllOf operator&&(MatcherBase const& other) const; + MatchAnyOf operator||(MatcherBase const& other) const; + MatchNotOf operator!() const; +}; - MatchAllOf operator && ( MatcherBase const& other ) const; - MatchAnyOf operator || ( MatcherBase const& other ) const; - MatchNotOf operator ! () const; - }; +template +struct MatchAllOf : MatcherBase { + bool match(ArgT const& arg) const override { + for (auto matcher : m_matchers) { + if (!matcher->match(arg)) return false; + } + return true; + } + std::string describe() const override { + std::string description; + description.reserve(4 + m_matchers.size() * 32); + description += "( "; + bool first = true; + for (auto matcher : m_matchers) { + if (first) + first = false; + else + description += " and "; + description += matcher->toString(); + } + description += " )"; + return description; + } - template - struct MatchAllOf : MatcherBase { - bool match( ArgT const& arg ) const override { - for( auto matcher : m_matchers ) { - if (!matcher->match(arg)) - return false; - } - return true; - } - std::string describe() const override { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - bool first = true; - for( auto matcher : m_matchers ) { - if( first ) - first = false; - else - description += " and "; - description += matcher->toString(); - } - description += " )"; - return description; - } + MatchAllOf& operator&&(MatcherBase const& other) { + m_matchers.push_back(&other); + return *this; + } - MatchAllOf& operator && ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } + std::vector const*> m_matchers; +}; +template +struct MatchAnyOf : MatcherBase { + bool match(ArgT const& arg) const override { + for (auto matcher : m_matchers) { + if (matcher->match(arg)) return true; + } + return false; + } + std::string describe() const override { + std::string description; + description.reserve(4 + m_matchers.size() * 32); + description += "( "; + bool first = true; + for (auto matcher : m_matchers) { + if (first) + first = false; + else + description += " or "; + description += matcher->toString(); + } + description += " )"; + return description; + } - std::vector const*> m_matchers; - }; - template - struct MatchAnyOf : MatcherBase { + MatchAnyOf& operator||(MatcherBase const& other) { + m_matchers.push_back(&other); + return *this; + } - bool match( ArgT const& arg ) const override { - for( auto matcher : m_matchers ) { - if (matcher->match(arg)) - return true; - } - return false; - } - std::string describe() const override { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - bool first = true; - for( auto matcher : m_matchers ) { - if( first ) - first = false; - else - description += " or "; - description += matcher->toString(); - } - description += " )"; - return description; - } + std::vector const*> m_matchers; +}; - MatchAnyOf& operator || ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } +template +struct MatchNotOf : MatcherBase { + MatchNotOf(MatcherBase const& underlyingMatcher) + : m_underlyingMatcher(underlyingMatcher) {} - std::vector const*> m_matchers; - }; + bool match(ArgT const& arg) const override { + return !m_underlyingMatcher.match(arg); + } - template - struct MatchNotOf : MatcherBase { + std::string describe() const override { + return "not " + m_underlyingMatcher.toString(); + } + MatcherBase const& m_underlyingMatcher; +}; - MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} +template +MatchAllOf MatcherBase::operator&&(MatcherBase const& other) const { + return MatchAllOf() && *this && other; +} +template +MatchAnyOf MatcherBase::operator||(MatcherBase const& other) const { + return MatchAnyOf() || *this || other; +} +template +MatchNotOf MatcherBase::operator!() const { + return MatchNotOf(*this); +} - bool match( ArgT const& arg ) const override { - return !m_underlyingMatcher.match( arg ); - } +} // namespace Impl - std::string describe() const override { - return "not " + m_underlyingMatcher.toString(); - } - MatcherBase const& m_underlyingMatcher; - }; - - template - MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { - return MatchAllOf() && *this && other; - } - template - MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { - return MatchAnyOf() || *this || other; - } - template - MatchNotOf MatcherBase::operator ! () const { - return MatchNotOf( *this ); - } - - } // namespace Impl - -} // namespace Matchers +} // namespace Matchers using namespace Matchers; using Matchers::Impl::MatcherBase; -} // namespace Catch +} // namespace Catch // end catch_matchers.h // start catch_matchers_floating.h -#include #include +#include namespace Catch { namespace Matchers { - namespace Floating { +namespace Floating { - enum class FloatingPointKind : uint8_t; +enum class FloatingPointKind : uint8_t; - struct WithinAbsMatcher : MatcherBase { - WithinAbsMatcher(double target, double margin); - bool match(double const& matchee) const override; - std::string describe() const override; - private: - double m_target; - double m_margin; - }; +struct WithinAbsMatcher : MatcherBase { + WithinAbsMatcher(double target, double margin); + bool match(double const& matchee) const override; + std::string describe() const override; - struct WithinUlpsMatcher : MatcherBase { - WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); - bool match(double const& matchee) const override; - std::string describe() const override; - private: - double m_target; - int m_ulps; - FloatingPointKind m_type; - }; + private: + double m_target; + double m_margin; +}; - } // namespace Floating +struct WithinUlpsMatcher : MatcherBase { + WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); + bool match(double const& matchee) const override; + std::string describe() const override; - // The following functions create the actual matcher objects. - // This allows the types to be inferred - Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff); - Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff); - Floating::WithinAbsMatcher WithinAbs(double target, double margin); + private: + double m_target; + int m_ulps; + FloatingPointKind m_type; +}; -} // namespace Matchers -} // namespace Catch +} // namespace Floating + +// The following functions create the actual matcher objects. +// This allows the types to be inferred +Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff); +Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff); +Floating::WithinAbsMatcher WithinAbs(double target, double margin); + +} // namespace Matchers +} // namespace Catch // end catch_matchers_floating.h // start catch_matchers_generic.hpp @@ -2822,42 +3011,40 @@ namespace Matchers { namespace Generic { namespace Detail { - std::string finalizeDescription(const std::string& desc); +std::string finalizeDescription(const std::string& desc); } template class PredicateMatcher : public MatcherBase { - std::function m_predicate; - std::string m_description; -public: + std::function m_predicate; + std::string m_description; - PredicateMatcher(std::function const& elem, std::string const& descr) - :m_predicate(std::move(elem)), - m_description(Detail::finalizeDescription(descr)) - {} + public: + PredicateMatcher(std::function const& elem, + std::string const& descr) + : m_predicate(std::move(elem)), + m_description(Detail::finalizeDescription(descr)) {} - bool match( T const& item ) const override { - return m_predicate(item); - } + bool match(T const& item) const override { return m_predicate(item); } - std::string describe() const override { - return m_description; - } + std::string describe() const override { return m_description; } }; -} // namespace Generic +} // namespace Generic - // The following functions create the actual matcher objects. - // The user has to explicitly specify type to the function, because - // infering std::function is hard (but possible) and - // requires a lot of TMP. - template - Generic::PredicateMatcher Predicate(std::function const& predicate, std::string const& description = "") { - return Generic::PredicateMatcher(predicate, description); - } +// The following functions create the actual matcher objects. +// The user has to explicitly specify type to the function, because +// infering std::function is hard (but possible) and +// requires a lot of TMP. +template +Generic::PredicateMatcher Predicate( + std::function const& predicate, + std::string const& description = "") { + return Generic::PredicateMatcher(predicate, description); +} -} // namespace Matchers -} // namespace Catch +} // namespace Matchers +} // namespace Catch // end catch_matchers_generic.hpp // start catch_matchers_string.h @@ -2867,66 +3054,76 @@ public: namespace Catch { namespace Matchers { - namespace StdString { +namespace StdString { - struct CasedString - { - CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); - std::string adjustString( std::string const& str ) const; - std::string caseSensitivitySuffix() const; +struct CasedString { + CasedString(std::string const& str, CaseSensitive::Choice caseSensitivity); + std::string adjustString(std::string const& str) const; + std::string caseSensitivitySuffix() const; - CaseSensitive::Choice m_caseSensitivity; - std::string m_str; - }; + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; +}; - struct StringMatcherBase : MatcherBase { - StringMatcherBase( std::string const& operation, CasedString const& comparator ); - std::string describe() const override; +struct StringMatcherBase : MatcherBase { + StringMatcherBase(std::string const& operation, + CasedString const& comparator); + std::string describe() const override; - CasedString m_comparator; - std::string m_operation; - }; + CasedString m_comparator; + std::string m_operation; +}; - struct EqualsMatcher : StringMatcherBase { - EqualsMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; - }; - struct ContainsMatcher : StringMatcherBase { - ContainsMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; - }; - struct StartsWithMatcher : StringMatcherBase { - StartsWithMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; - }; - struct EndsWithMatcher : StringMatcherBase { - EndsWithMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; - }; +struct EqualsMatcher : StringMatcherBase { + EqualsMatcher(CasedString const& comparator); + bool match(std::string const& source) const override; +}; +struct ContainsMatcher : StringMatcherBase { + ContainsMatcher(CasedString const& comparator); + bool match(std::string const& source) const override; +}; +struct StartsWithMatcher : StringMatcherBase { + StartsWithMatcher(CasedString const& comparator); + bool match(std::string const& source) const override; +}; +struct EndsWithMatcher : StringMatcherBase { + EndsWithMatcher(CasedString const& comparator); + bool match(std::string const& source) const override; +}; - struct RegexMatcher : MatcherBase { - RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); - bool match( std::string const& matchee ) const override; - std::string describe() const override; +struct RegexMatcher : MatcherBase { + RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity); + bool match(std::string const& matchee) const override; + std::string describe() const override; - private: - std::string m_regex; - CaseSensitive::Choice m_caseSensitivity; - }; + private: + std::string m_regex; + CaseSensitive::Choice m_caseSensitivity; +}; - } // namespace StdString +} // namespace StdString - // The following functions create the actual matcher objects. - // This allows the types to be inferred +// The following functions create the actual matcher objects. +// This allows the types to be inferred - StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); +StdString::EqualsMatcher Equals( + std::string const& str, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); +StdString::ContainsMatcher Contains( + std::string const& str, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); +StdString::EndsWithMatcher EndsWith( + std::string const& str, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); +StdString::StartsWithMatcher StartsWith( + std::string const& str, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); +StdString::RegexMatcher Matches( + std::string const& regex, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); -} // namespace Matchers -} // namespace Catch +} // namespace Matchers +} // namespace Catch // end catch_matchers_string.h // start catch_matchers_vector.h @@ -2936,237 +3133,234 @@ namespace Matchers { namespace Catch { namespace Matchers { - namespace Vector { - namespace Detail { - template - size_t count(InputIterator first, InputIterator last, T const& item) { - size_t cnt = 0; - for (; first != last; ++first) { - if (*first == item) { - ++cnt; - } - } - return cnt; - } - template - bool contains(InputIterator first, InputIterator last, T const& item) { - for (; first != last; ++first) { - if (*first == item) { - return true; - } - } - return false; - } +namespace Vector { +namespace Detail { +template +size_t count(InputIterator first, InputIterator last, T const& item) { + size_t cnt = 0; + for (; first != last; ++first) { + if (*first == item) { ++cnt; } + } + return cnt; +} +template +bool contains(InputIterator first, InputIterator last, T const& item) { + for (; first != last; ++first) { + if (*first == item) { return true; } + } + return false; +} +} // namespace Detail + +template +struct ContainsElementMatcher : MatcherBase> { + ContainsElementMatcher(T const& comparator) : m_comparator(comparator) {} + + bool match(std::vector const& v) const override { + for (auto const& el : v) { + if (el == m_comparator) { return true; } + } + return false; + } + + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify(m_comparator); + } + + T const& m_comparator; +}; + +template +struct ContainsMatcher : MatcherBase> { + ContainsMatcher(std::vector const& comparator) + : m_comparator(comparator) {} + + bool match(std::vector const& v) const override { + // !TBD: see note in EqualsMatcher + if (m_comparator.size() > v.size()) return false; + for (auto const& comparator : m_comparator) { + auto present = false; + for (const auto& el : v) { + if (el == comparator) { + present = true; + break; } + } + if (!present) { return false; } + } + return true; + } + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify(m_comparator); + } - template - struct ContainsElementMatcher : MatcherBase> { + std::vector const& m_comparator; +}; - ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} +template +struct EqualsMatcher : MatcherBase> { + EqualsMatcher(std::vector const& comparator) : m_comparator(comparator) {} - bool match(std::vector const &v) const override { - for (auto const& el : v) { - if (el == m_comparator) { - return true; - } - } - return false; - } + bool match(std::vector const& v) const override { + // !TBD: This currently works if all elements can be compared using != + // - a more general approach would be via a compare template that defaults + // to using !=. but could be specialised for, e.g. std::vector etc + // - then just call that directly + if (m_comparator.size() != v.size()) return false; + for (std::size_t i = 0; i < v.size(); ++i) + if (m_comparator[i] != v[i]) return false; + return true; + } + std::string describe() const override { + return "Equals: " + ::Catch::Detail::stringify(m_comparator); + } + std::vector const& m_comparator; +}; - std::string describe() const override { - return "Contains: " + ::Catch::Detail::stringify( m_comparator ); - } +template +struct UnorderedEqualsMatcher : MatcherBase> { + UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {} + bool match(std::vector const& vec) const override { + // Note: This is a reimplementation of std::is_permutation, + // because I don't want to include inside the common path + if (m_target.size() != vec.size()) { return false; } + auto lfirst = m_target.begin(), llast = m_target.end(); + auto rfirst = vec.begin(), rlast = vec.end(); + // Cut common prefix to optimize checking of permuted parts + while (lfirst != llast && *lfirst == *rfirst) { + ++lfirst; + ++rfirst; + } + if (lfirst == llast) { return true; } - T const& m_comparator; - }; - - template - struct ContainsMatcher : MatcherBase> { - - ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - - bool match(std::vector const &v) const override { - // !TBD: see note in EqualsMatcher - if (m_comparator.size() > v.size()) - return false; - for (auto const& comparator : m_comparator) { - auto present = false; - for (const auto& el : v) { - if (el == comparator) { - present = true; - break; - } - } - if (!present) { - return false; - } - } - return true; - } - std::string describe() const override { - return "Contains: " + ::Catch::Detail::stringify( m_comparator ); - } - - std::vector const& m_comparator; - }; - - template - struct EqualsMatcher : MatcherBase> { - - EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - - bool match(std::vector const &v) const override { - // !TBD: This currently works if all elements can be compared using != - // - a more general approach would be via a compare template that defaults - // to using !=. but could be specialised for, e.g. std::vector etc - // - then just call that directly - if (m_comparator.size() != v.size()) - return false; - for (std::size_t i = 0; i < v.size(); ++i) - if (m_comparator[i] != v[i]) - return false; - return true; - } - std::string describe() const override { - return "Equals: " + ::Catch::Detail::stringify( m_comparator ); - } - std::vector const& m_comparator; - }; - - template - struct UnorderedEqualsMatcher : MatcherBase> { - UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {} - bool match(std::vector const& vec) const override { - // Note: This is a reimplementation of std::is_permutation, - // because I don't want to include inside the common path - if (m_target.size() != vec.size()) { - return false; - } - auto lfirst = m_target.begin(), llast = m_target.end(); - auto rfirst = vec.begin(), rlast = vec.end(); - // Cut common prefix to optimize checking of permuted parts - while (lfirst != llast && *lfirst == *rfirst) { - ++lfirst; ++rfirst; - } - if (lfirst == llast) { - return true; - } - - for (auto mid = lfirst; mid != llast; ++mid) { - // Skip already counted items - if (Detail::contains(lfirst, mid, *mid)) { - continue; - } - size_t num_vec = Detail::count(rfirst, rlast, *mid); - if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) { - return false; - } - } - - return true; - } - - std::string describe() const override { - return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); - } - private: - std::vector const& m_target; - }; - - } // namespace Vector - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - - template - Vector::ContainsMatcher Contains( std::vector const& comparator ) { - return Vector::ContainsMatcher( comparator ); + for (auto mid = lfirst; mid != llast; ++mid) { + // Skip already counted items + if (Detail::contains(lfirst, mid, *mid)) { continue; } + size_t num_vec = Detail::count(rfirst, rlast, *mid); + if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) { + return false; + } } - template - Vector::ContainsElementMatcher VectorContains( T const& comparator ) { - return Vector::ContainsElementMatcher( comparator ); - } + return true; + } - template - Vector::EqualsMatcher Equals( std::vector const& comparator ) { - return Vector::EqualsMatcher( comparator ); - } + std::string describe() const override { + return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); + } - template - Vector::UnorderedEqualsMatcher UnorderedEquals(std::vector const& target) { - return Vector::UnorderedEqualsMatcher(target); - } + private: + std::vector const& m_target; +}; -} // namespace Matchers -} // namespace Catch +} // namespace Vector + +// The following functions create the actual matcher objects. +// This allows the types to be inferred + +template +Vector::ContainsMatcher Contains(std::vector const& comparator) { + return Vector::ContainsMatcher(comparator); +} + +template +Vector::ContainsElementMatcher VectorContains(T const& comparator) { + return Vector::ContainsElementMatcher(comparator); +} + +template +Vector::EqualsMatcher Equals(std::vector const& comparator) { + return Vector::EqualsMatcher(comparator); +} + +template +Vector::UnorderedEqualsMatcher UnorderedEquals( + std::vector const& target) { + return Vector::UnorderedEqualsMatcher(target); +} + +} // namespace Matchers +} // namespace Catch // end catch_matchers_vector.h namespace Catch { - template - class MatchExpr : public ITransientExpression { - ArgT const& m_arg; - MatcherT m_matcher; - StringRef m_matcherString; - public: - MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) - : ITransientExpression{ true, matcher.match( arg ) }, - m_arg( arg ), - m_matcher( matcher ), - m_matcherString( matcherString ) - {} +template +class MatchExpr : public ITransientExpression { + ArgT const& m_arg; + MatcherT m_matcher; + StringRef m_matcherString; - void streamReconstructedExpression( std::ostream &os ) const override { - auto matcherAsString = m_matcher.toString(); - os << Catch::Detail::stringify( m_arg ) << ' '; - if( matcherAsString == Detail::unprintableString ) - os << m_matcherString; - else - os << matcherAsString; - } - }; + public: + MatchExpr(ArgT const& arg, MatcherT const& matcher, + StringRef const& matcherString) + : ITransientExpression{true, matcher.match(arg)}, + m_arg(arg), + m_matcher(matcher), + m_matcherString(matcherString) {} - using StringMatcher = Matchers::Impl::MatcherBase; + void streamReconstructedExpression(std::ostream& os) const override { + auto matcherAsString = m_matcher.toString(); + os << Catch::Detail::stringify(m_arg) << ' '; + if (matcherAsString == Detail::unprintableString) + os << m_matcherString; + else + os << matcherAsString; + } +}; - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); +using StringMatcher = Matchers::Impl::MatcherBase; - template - auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr { - return MatchExpr( arg, matcher, matcherString ); - } +void handleExceptionMatchExpr(AssertionHandler& handler, + StringMatcher const& matcher, + StringRef const& matcherString); -} // namespace Catch +template +auto makeMatchExpr(ArgT const& arg, MatcherT const& matcher, + StringRef const& matcherString) + -> MatchExpr { + return MatchExpr(arg, matcher, matcherString); +} + +} // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ - INTERNAL_CATCH_TRY { \ - catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ - } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CHECK_THAT(macroName, matcher, resultDisposition, arg) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), \ + resultDisposition); \ + INTERNAL_CATCH_TRY { \ + catchAssertionHandler.handleExpr( \ + Catch::makeMatchExpr(arg, matcher, #matcher##_catch_sr)); \ + } \ + INTERNAL_CATCH_CATCH(catchAssertionHandler) \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(__VA_ARGS__ ); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( exceptionType const& ex ) { \ - catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ - } \ - catch( ... ) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#define INTERNAL_CATCH_THROWS_MATCHES(macroName, exceptionType, \ + resultDisposition, matcher, ...) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( \ + macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY( \ + exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), \ + resultDisposition); \ + if (catchAssertionHandler.allowThrows()) try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } catch (exceptionType const& ex) { \ + catchAssertionHandler.handleExpr( \ + Catch::makeMatchExpr(ex, matcher, #matcher##_catch_sr)); \ + } catch (...) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) // end catch_capture_matchers.h #endif @@ -3174,34 +3368,33 @@ namespace Catch { // start catch_interfaces_generatortracker.h - #include namespace Catch { - namespace Generators { - class GeneratorBase { - protected: - size_t m_size = 0; +namespace Generators { +class GeneratorBase { + protected: + size_t m_size = 0; - public: - GeneratorBase( size_t size ) : m_size( size ) {} - virtual ~GeneratorBase(); - auto size() const -> size_t { return m_size; } - }; - using GeneratorBasePtr = std::unique_ptr; + public: + GeneratorBase(size_t size) : m_size(size) {} + virtual ~GeneratorBase(); + auto size() const -> size_t { return m_size; } +}; +using GeneratorBasePtr = std::unique_ptr; - } // namespace Generators +} // namespace Generators - struct IGeneratorTracker { - virtual ~IGeneratorTracker(); - virtual auto hasGenerator() const -> bool = 0; - virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; - virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; - virtual auto getIndex() const -> std::size_t = 0; - }; +struct IGeneratorTracker { + virtual ~IGeneratorTracker(); + virtual auto hasGenerator() const -> bool = 0; + virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; + virtual void setGenerator(Generators::GeneratorBasePtr&& generator) = 0; + virtual auto getIndex() const -> std::size_t = 0; +}; -} // namespace Catch +} // namespace Catch // end catch_interfaces_generatortracker.h // start catch_enforce.h @@ -3210,262 +3403,278 @@ namespace Catch { namespace Catch { #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - template - [[noreturn]] - void throw_exception(Ex const& e) { - throw e; - } -#else // ^^ Exceptions are enabled // Exceptions are disabled vv - [[noreturn]] - void throw_exception(std::exception const& e); +template +[[noreturn]] void throw_exception(Ex const& e) { + throw e; +} +#else // ^^ Exceptions are enabled // Exceptions are disabled vv +[[noreturn]] void throw_exception(std::exception const& e); #endif -} // namespace Catch; +} // namespace Catch -#define CATCH_PREPARE_EXCEPTION( type, msg ) \ - type( ( Catch::ReusableStringStream() << msg ).str() ) -#define CATCH_INTERNAL_ERROR( msg ) \ - Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg)) -#define CATCH_ERROR( msg ) \ - Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg )) -#define CATCH_RUNTIME_ERROR( msg ) \ - Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg )) -#define CATCH_ENFORCE( condition, msg ) \ - do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) +#define CATCH_PREPARE_EXCEPTION(type, msg) \ + type((Catch::ReusableStringStream() << msg).str()) +#define CATCH_INTERNAL_ERROR(msg) \ + Catch::throw_exception(CATCH_PREPARE_EXCEPTION( \ + std::logic_error, \ + CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg)) +#define CATCH_ERROR(msg) \ + Catch::throw_exception(CATCH_PREPARE_EXCEPTION(std::domain_error, msg)) +#define CATCH_RUNTIME_ERROR(msg) \ + Catch::throw_exception(CATCH_PREPARE_EXCEPTION(std::runtime_error, msg)) +#define CATCH_ENFORCE(condition, msg) \ + do { \ + if (!(condition)) CATCH_ERROR(msg); \ + } while (false) // end catch_enforce.h +#include #include #include -#include #include namespace Catch { namespace Generators { - // !TBD move this into its own location? - namespace pf{ - template - std::unique_ptr make_unique( Args&&... args ) { - return std::unique_ptr(new T(std::forward(args)...)); - } +// !TBD move this into its own location? +namespace pf { +template +std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} +} // namespace pf + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual auto get(size_t index) const -> T = 0; +}; + +template +class SingleValueGenerator : public IGenerator { + T m_value; + + public: + SingleValueGenerator(T const& value) : m_value(value) {} + + auto get(size_t) const -> T override { return m_value; } +}; + +template +class FixedValuesGenerator : public IGenerator { + std::vector m_values; + + public: + FixedValuesGenerator(std::initializer_list values) : m_values(values) {} + + auto get(size_t index) const -> T override { return m_values[index]; } +}; + +template +class RangeGenerator : public IGenerator { + T const m_first; + T const m_last; + + public: + RangeGenerator(T const& first, T const& last) : m_first(first), m_last(last) { + assert(m_last > m_first); + } + + auto get(size_t index) const -> T override { + // ToDo:: introduce a safe cast to catch potential overflows + return static_cast(m_first + index); + } +}; + +template +struct NullGenerator : IGenerator { + auto get(size_t) const -> T override { + CATCH_INTERNAL_ERROR("A Null Generator is always empty"); + } +}; + +template +class Generator { + std::unique_ptr> m_generator; + size_t m_size; + + public: + Generator(size_t size, std::unique_ptr> generator) + : m_generator(std::move(generator)), m_size(size) {} + + auto size() const -> size_t { return m_size; } + auto operator[](size_t index) const -> T { + assert(index < m_size); + return m_generator->get(index); + } +}; + +std::vector randomiseIndices(size_t selectionSize, size_t sourceSize); + +template +class GeneratorRandomiser : public IGenerator { + Generator m_baseGenerator; + + std::vector m_indices; + + public: + GeneratorRandomiser(Generator&& baseGenerator, size_t numberOfItems) + : m_baseGenerator(std::move(baseGenerator)), + m_indices(randomiseIndices(numberOfItems, m_baseGenerator.size())) {} + + auto get(size_t index) const -> T override { + return m_baseGenerator[m_indices[index]]; + } +}; + +template +struct RequiresASpecialisationFor; + +template +auto all() -> Generator { + return RequiresASpecialisationFor(); +} + +template <> +auto all() -> Generator; + +template +auto range(T const& first, T const& last) -> Generator { + return Generator((last - first), + pf::make_unique>(first, last)); +} + +template +auto random(T const& first, T const& last) -> Generator { + auto gen = range(first, last); + auto size = gen.size(); + + return Generator( + size, pf::make_unique>(std::move(gen), size)); +} +template +auto random(size_t size) -> Generator { + return Generator(size, + pf::make_unique>(all(), size)); +} + +template +auto values(std::initializer_list values) -> Generator { + return Generator(values.size(), + pf::make_unique>(values)); +} +template +auto value(T const& val) -> Generator { + return Generator(1, pf::make_unique>(val)); +} + +template +auto as() -> Generator { + return Generator(0, pf::make_unique>()); +} + +template +auto table(std::initializer_list>&& tuples) + -> Generator> { + return values>( + std::forward>>(tuples)); +} + +template +struct Generators : GeneratorBase { + std::vector> m_generators; + + using type = T; + + Generators() : GeneratorBase(0) {} + + void populate(T&& val) { + m_size += 1; + m_generators.emplace_back(value(std::move(val))); + } + template + void populate(U&& val) { + populate(T(std::move(val))); + } + void populate(Generator&& generator) { + m_size += generator.size(); + m_generators.emplace_back(std::move(generator)); + } + + template + void populate(U&& valueOrGenerator, Gs... moreGenerators) { + populate(std::forward(valueOrGenerator)); + populate(std::forward(moreGenerators)...); + } + + auto operator[](size_t index) const -> T { + size_t sizes = 0; + for (auto const& gen : m_generators) { + auto localIndex = index - sizes; + sizes += gen.size(); + if (index < sizes) return gen[localIndex]; } + CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes + << ')'); + } +}; - template - struct IGenerator { - virtual ~IGenerator() {} - virtual auto get( size_t index ) const -> T = 0; - }; +template +auto makeGenerators(Generator&& generator, Gs... moreGenerators) + -> Generators { + Generators generators; + generators.m_generators.reserve(1 + sizeof...(Gs)); + generators.populate(std::move(generator), + std::forward(moreGenerators)...); + return generators; +} +template +auto makeGenerators(Generator&& generator) -> Generators { + Generators generators; + generators.populate(std::move(generator)); + return generators; +} +template +auto makeGenerators(T&& val, Gs... moreGenerators) -> Generators { + return makeGenerators(value(std::forward(val)), + std::forward(moreGenerators)...); +} +template +auto makeGenerators(U&& val, Gs... moreGenerators) -> Generators { + return makeGenerators(value(T(std::forward(val))), + std::forward(moreGenerators)...); +} - template - class SingleValueGenerator : public IGenerator { - T m_value; - public: - SingleValueGenerator( T const& value ) : m_value( value ) {} +auto acquireGeneratorTracker(SourceLineInfo const& lineInfo) + -> IGeneratorTracker&; - auto get( size_t ) const -> T override { - return m_value; - } - }; +template +// Note: The type after -> is weird, because VS2015 cannot parse +// the expression used in the typedef inside, when it is in +// return type. Yeah, ¯\_(ツ)_/¯ +auto generate(SourceLineInfo const& lineInfo, L const& generatorExpression) + -> decltype(std::declval()[0]) { + using UnderlyingType = typename decltype(generatorExpression())::type; - template - class FixedValuesGenerator : public IGenerator { - std::vector m_values; + IGeneratorTracker& tracker = acquireGeneratorTracker(lineInfo); + if (!tracker.hasGenerator()) + tracker.setGenerator( + pf::make_unique>(generatorExpression())); - public: - FixedValuesGenerator( std::initializer_list values ) : m_values( values ) {} + auto const& generator = + static_cast const&>(*tracker.getGenerator()); + return generator[tracker.getIndex()]; +} - auto get( size_t index ) const -> T override { - return m_values[index]; - } - }; +} // namespace Generators +} // namespace Catch - template - class RangeGenerator : public IGenerator { - T const m_first; - T const m_last; - - public: - RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) { - assert( m_last > m_first ); - } - - auto get( size_t index ) const -> T override { - // ToDo:: introduce a safe cast to catch potential overflows - return static_cast(m_first+index); - } - }; - - template - struct NullGenerator : IGenerator { - auto get( size_t ) const -> T override { - CATCH_INTERNAL_ERROR("A Null Generator is always empty"); - } - }; - - template - class Generator { - std::unique_ptr> m_generator; - size_t m_size; - - public: - Generator( size_t size, std::unique_ptr> generator ) - : m_generator( std::move( generator ) ), - m_size( size ) - {} - - auto size() const -> size_t { return m_size; } - auto operator[]( size_t index ) const -> T { - assert( index < m_size ); - return m_generator->get( index ); - } - }; - - std::vector randomiseIndices( size_t selectionSize, size_t sourceSize ); - - template - class GeneratorRandomiser : public IGenerator { - Generator m_baseGenerator; - - std::vector m_indices; - public: - GeneratorRandomiser( Generator&& baseGenerator, size_t numberOfItems ) - : m_baseGenerator( std::move( baseGenerator ) ), - m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) ) - {} - - auto get( size_t index ) const -> T override { - return m_baseGenerator[m_indices[index]]; - } - }; - - template - struct RequiresASpecialisationFor; - - template - auto all() -> Generator { return RequiresASpecialisationFor(); } - - template<> - auto all() -> Generator; - - template - auto range( T const& first, T const& last ) -> Generator { - return Generator( (last-first), pf::make_unique>( first, last ) ); - } - - template - auto random( T const& first, T const& last ) -> Generator { - auto gen = range( first, last ); - auto size = gen.size(); - - return Generator( size, pf::make_unique>( std::move( gen ), size ) ); - } - template - auto random( size_t size ) -> Generator { - return Generator( size, pf::make_unique>( all(), size ) ); - } - - template - auto values( std::initializer_list values ) -> Generator { - return Generator( values.size(), pf::make_unique>( values ) ); - } - template - auto value( T const& val ) -> Generator { - return Generator( 1, pf::make_unique>( val ) ); - } - - template - auto as() -> Generator { - return Generator( 0, pf::make_unique>() ); - } - - template - auto table( std::initializer_list>&& tuples ) -> Generator> { - return values>( std::forward>>( tuples ) ); - } - - template - struct Generators : GeneratorBase { - std::vector> m_generators; - - using type = T; - - Generators() : GeneratorBase( 0 ) {} - - void populate( T&& val ) { - m_size += 1; - m_generators.emplace_back( value( std::move( val ) ) ); - } - template - void populate( U&& val ) { - populate( T( std::move( val ) ) ); - } - void populate( Generator&& generator ) { - m_size += generator.size(); - m_generators.emplace_back( std::move( generator ) ); - } - - template - void populate( U&& valueOrGenerator, Gs... moreGenerators ) { - populate( std::forward( valueOrGenerator ) ); - populate( std::forward( moreGenerators )... ); - } - - auto operator[]( size_t index ) const -> T { - size_t sizes = 0; - for( auto const& gen : m_generators ) { - auto localIndex = index-sizes; - sizes += gen.size(); - if( index < sizes ) - return gen[localIndex]; - } - CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')'); - } - }; - - template - auto makeGenerators( Generator&& generator, Gs... moreGenerators ) -> Generators { - Generators generators; - generators.m_generators.reserve( 1+sizeof...(Gs) ); - generators.populate( std::move( generator ), std::forward( moreGenerators )... ); - return generators; - } - template - auto makeGenerators( Generator&& generator ) -> Generators { - Generators generators; - generators.populate( std::move( generator ) ); - return generators; - } - template - auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators { - return makeGenerators( value( std::forward( val ) ), std::forward( moreGenerators )... ); - } - template - auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators { - return makeGenerators( value( T( std::forward( val ) ) ), std::forward( moreGenerators )... ); - } - - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; - - template - // Note: The type after -> is weird, because VS2015 cannot parse - // the expression used in the typedef inside, when it is in - // return type. Yeah, ¯\_(ツ)_/¯ - auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval()[0]) { - using UnderlyingType = typename decltype(generatorExpression())::type; - - IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); - if( !tracker.hasGenerator() ) - tracker.setGenerator( pf::make_unique>( generatorExpression() ) ); - - auto const& generator = static_cast const&>( *tracker.getGenerator() ); - return generator[tracker.getIndex()]; - } - -} // namespace Generators -} // namespace Catch - -#define GENERATE( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) +#define GENERATE(...) \ + Catch::Generators::generate(CATCH_INTERNAL_LINEINFO, [] { \ + using namespace Catch::Generators; \ + return makeGenerators(__VA_ARGS__); \ + }) // end catch_generators.hpp @@ -3473,9 +3682,9 @@ namespace Generators { // in the conditionally compiled sections // start catch_test_case_info.h +#include #include #include -#include #ifdef __clang__ #pragma clang diagnostic push @@ -3484,66 +3693,64 @@ namespace Generators { namespace Catch { - struct ITestInvoker; +struct ITestInvoker; - struct TestCaseInfo { - enum SpecialProperties{ - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4, - NonPortable = 1 << 5, - Benchmark = 1 << 6 - }; +struct TestCaseInfo { + enum SpecialProperties { + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4, + NonPortable = 1 << 5, + Benchmark = 1 << 6 + }; - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::vector const& _tags, - SourceLineInfo const& _lineInfo ); + TestCaseInfo(std::string const& _name, std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo); - friend void setTags( TestCaseInfo& testCaseInfo, std::vector tags ); + friend void setTags(TestCaseInfo& testCaseInfo, + std::vector tags); - bool isHidden() const; - bool throws() const; - bool okToFail() const; - bool expectedToFail() const; + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; - std::string tagsAsString() const; + std::string tagsAsString() const; - std::string name; - std::string className; - std::string description; - std::vector tags; - std::vector lcaseTags; - SourceLineInfo lineInfo; - SpecialProperties properties; - }; + std::string name; + std::string className; + std::string description; + std::vector tags; + std::vector lcaseTags; + SourceLineInfo lineInfo; + SpecialProperties properties; +}; - class TestCase : public TestCaseInfo { - public: +class TestCase : public TestCaseInfo { + public: + TestCase(ITestInvoker* testCase, TestCaseInfo&& info); - TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); + TestCase withName(std::string const& _newName) const; - TestCase withName( std::string const& _newName ) const; + void invoke() const; - void invoke() const; + TestCaseInfo const& getTestCaseInfo() const; - TestCaseInfo const& getTestCaseInfo() const; + bool operator==(TestCase const& other) const; + bool operator<(TestCase const& other) const; - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; + private: + std::shared_ptr test; +}; - private: - std::shared_ptr test; - }; - - TestCase makeTestCase( ITestInvoker* testCase, - std::string const& className, - NameAndTags const& nameAndTags, - SourceLineInfo const& lineInfo ); -} +TestCase makeTestCase(ITestInvoker* testCase, std::string const& className, + NameAndTags const& nameAndTags, + SourceLineInfo const& lineInfo); +} // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop @@ -3554,11 +3761,11 @@ namespace Catch { namespace Catch { - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} +struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; +}; +} // namespace Catch // end catch_interfaces_runner.h @@ -3580,188 +3787,190 @@ namespace Catch { @optional --(void) setUp; --(void) tearDown; +- (void)setUp; +- (void)tearDown; @end namespace Catch { - class OcMethod : public ITestInvoker { +class OcMethod : public ITestInvoker { + public: + OcMethod(Class cls, SEL sel) : m_cls(cls), m_sel(sel) {} - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + virtual void invoke() const { + id obj = [[m_cls alloc] init]; - virtual void invoke() const { - id obj = [[m_cls alloc] init]; + performOptionalSelector(obj, @selector(setUp)); + performOptionalSelector(obj, m_sel); + performOptionalSelector(obj, @selector(tearDown)); - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); + arcSafeRelease(obj); + } - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; +}; + +namespace Detail { + +inline std::string getAnnotation(Class cls, std::string const& annotationName, + std::string const& testCaseName) { + NSString* selStr = + [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), + testCaseName.c_str()]; + SEL sel = NSSelectorFromString(selStr); + arcSafeRelease(selStr); + id value = performOptionalSelector(cls, sel); + if (value) return [(NSString*)value UTF8String]; + return ""; +} +} // namespace Detail + +inline std::size_t registerTestMethods() { + std::size_t noTestMethods = 0; + int noClasses = objc_getClassList(nullptr, 0); + + Class* classes = + (CATCH_UNSAFE_UNRETAINED Class*)malloc(sizeof(Class) * noClasses); + objc_getClassList(classes, noClasses); + + for (int c = 0; c < noClasses; c++) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList(cls, &count); + for (u_int m = 0; m < count; m++) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if (startsWith(methodName, "Catch_TestCase_")) { + std::string testCaseName = methodName.substr(15); + std::string name = Detail::getAnnotation(cls, "Name", testCaseName); + std::string desc = + Detail::getAnnotation(cls, "Description", testCaseName); + const char* className = class_getName(cls); + + getMutableRegistryHub().registerTest(makeTestCase( + new OcMethod(cls, selector), className, + NameAndTags(name.c_str(), desc.c_str()), SourceLineInfo("", 0))); + noTestMethods++; } + } + free(methods); } - - inline std::size_t registerTestMethods() { - std::size_t noTestMethods = 0; - int noClasses = objc_getClassList( nullptr, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } + } + return noTestMethods; +} #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { +namespace Matchers { +namespace Impl { +namespace NSStringMatchers { - struct StringHolder : MatcherBase{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } +struct StringHolder : MatcherBase { + StringHolder(NSString* substr) : m_substr([substr copy]) {} + StringHolder(StringHolder const& other) : m_substr([other.m_substr copy]) {} + StringHolder() { arcSafeRelease(m_substr); } - bool match( NSString* arg ) const override { - return false; - } + bool match(NSString* arg) const override { return false; } - NSString* CATCH_ARC_STRONG m_substr; - }; + NSString* CATCH_ARC_STRONG m_substr; +}; - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} +struct Equals : StringHolder { + Equals(NSString* substr) : StringHolder(substr) {} - bool match( NSString* str ) const override { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } + bool match(NSString* str) const override { + return (str != nil || m_substr == nil) && [str isEqualToString:m_substr]; + } - std::string describe() const override { - return "equals string: " + Catch::Detail::stringify( m_substr ); - } - }; + std::string describe() const override { + return "equals string: " + Catch::Detail::stringify(m_substr); + } +}; - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} +struct Contains : StringHolder { + Contains(NSString* substr) : StringHolder(substr) {} - bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } + bool match(NSString* str) const { + return (str != nil || m_substr == nil) && + [str rangeOfString:m_substr].location != NSNotFound; + } - std::string describe() const override { - return "contains string: " + Catch::Detail::stringify( m_substr ); - } - }; + std::string describe() const override { + return "contains string: " + Catch::Detail::stringify(m_substr); + } +}; - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} +struct StartsWith : StringHolder { + StartsWith(NSString* substr) : StringHolder(substr) {} - bool match( NSString* str ) const override { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } + bool match(NSString* str) const override { + return (str != nil || m_substr == nil) && + [str rangeOfString:m_substr].location == 0; + } - std::string describe() const override { - return "starts with: " + Catch::Detail::stringify( m_substr ); - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} + std::string describe() const override { + return "starts with: " + Catch::Detail::stringify(m_substr); + } +}; +struct EndsWith : StringHolder { + EndsWith(NSString* substr) : StringHolder(substr) {} - bool match( NSString* str ) const override { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } + bool match(NSString* str) const override { + return (str != nil || m_substr == nil) && + [str rangeOfString:m_substr].location == + [str length] - [m_substr length]; + } - std::string describe() const override { - return "ends with: " + Catch::Detail::stringify( m_substr ); - } - }; + std::string describe() const override { + return "ends with: " + Catch::Detail::stringify(m_substr); + } +}; - } // namespace NSStringMatchers - } // namespace Impl +} // namespace NSStringMatchers +} // namespace Impl - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } +inline Impl::NSStringMatchers::Equals Equals(NSString* substr) { + return Impl::NSStringMatchers::Equals(substr); +} - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } +inline Impl::NSStringMatchers::Contains Contains(NSString* substr) { + return Impl::NSStringMatchers::Contains(substr); +} - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } +inline Impl::NSStringMatchers::StartsWith StartsWith(NSString* substr) { + return Impl::NSStringMatchers::StartsWith(substr); +} - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } +inline Impl::NSStringMatchers::EndsWith EndsWith(NSString* substr) { + return Impl::NSStringMatchers::EndsWith(substr); +} - } // namespace Matchers +} // namespace Matchers - using namespace Matchers; +using namespace Matchers; -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#endif // CATCH_CONFIG_DISABLE_MATCHERS -} // namespace Catch +} // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix -#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ -+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ -{ \ -return @ name; \ -} \ -+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ -{ \ -return @ desc; \ -} \ --(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) +#define OC_MAKE_UNIQUE_NAME(root, uniqueSuffix) root##uniqueSuffix +#define OC_TEST_CASE2(name, desc, uniqueSuffix) \ + +(NSString*)OC_MAKE_UNIQUE_NAME(Catch_Name_test_, uniqueSuffix) { \ + return @name; \ + } \ + +(NSString*)OC_MAKE_UNIQUE_NAME(Catch_Description_test_, uniqueSuffix) { \ + return @desc; \ + } \ + -(void)OC_MAKE_UNIQUE_NAME(Catch_TestCase_test_, uniqueSuffix) -#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) +#define OC_TEST_CASE(name, desc) OC_TEST_CASE2(name, desc, __LINE__) // end catch_objc.hpp #endif @@ -3791,87 +4000,89 @@ return @ desc; \ // start catch_wildcard_pattern.h -namespace Catch -{ - class WildcardPattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; +namespace Catch { +class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; - public: + public: + WildcardPattern(std::string const& pattern, + CaseSensitive::Choice caseSensitivity); + virtual ~WildcardPattern() = default; + virtual bool matches(std::string const& str) const; - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); - virtual ~WildcardPattern() = default; - virtual bool matches( std::string const& str ) const; - - private: - std::string adjustCase( std::string const& str ) const; - CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard = NoWildcard; - std::string m_pattern; - }; -} + private: + std::string adjustCase(std::string const& str) const; + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard = NoWildcard; + std::string m_pattern; +}; +} // namespace Catch // end catch_wildcard_pattern.h +#include #include #include -#include namespace Catch { - class TestSpec { - struct Pattern { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - using PatternPtr = std::shared_ptr; +class TestSpec { + struct Pattern { + virtual ~Pattern(); + virtual bool matches(TestCaseInfo const& testCase) const = 0; + }; + using PatternPtr = std::shared_ptr; - class NamePattern : public Pattern { - public: - NamePattern( std::string const& name ); - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; - private: - WildcardPattern m_wildcardPattern; - }; + class NamePattern : public Pattern { + public: + NamePattern(std::string const& name); + virtual ~NamePattern(); + virtual bool matches(TestCaseInfo const& testCase) const override; - class TagPattern : public Pattern { - public: - TagPattern( std::string const& tag ); - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; - private: - std::string m_tag; - }; + private: + WildcardPattern m_wildcardPattern; + }; - class ExcludedPattern : public Pattern { - public: - ExcludedPattern( PatternPtr const& underlyingPattern ); - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; - private: - PatternPtr m_underlyingPattern; - }; + class TagPattern : public Pattern { + public: + TagPattern(std::string const& tag); + virtual ~TagPattern(); + virtual bool matches(TestCaseInfo const& testCase) const override; - struct Filter { - std::vector m_patterns; + private: + std::string m_tag; + }; - bool matches( TestCaseInfo const& testCase ) const; - }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern(PatternPtr const& underlyingPattern); + virtual ~ExcludedPattern(); + virtual bool matches(TestCaseInfo const& testCase) const override; - public: - bool hasFilters() const; - bool matches( TestCaseInfo const& testCase ) const; + private: + PatternPtr m_underlyingPattern; + }; - private: - std::vector m_filters; + struct Filter { + std::vector m_patterns; - friend class TestSpecParser; - }; -} + bool matches(TestCaseInfo const& testCase) const; + }; + + public: + bool hasFilters() const; + bool matches(TestCaseInfo const& testCase) const; + + private: + std::vector m_filters; + + friend class TestSpecParser; +}; +} // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop @@ -3884,70 +4095,72 @@ namespace Catch { namespace Catch { - struct TagAlias; +struct TagAlias; - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - // Nullptr if not present - virtual TagAlias const* find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; +struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + // Nullptr if not present + virtual TagAlias const* find(std::string const& alias) const = 0; + virtual std::string expandAliases( + std::string const& unexpandedTestSpec) const = 0; - static ITagAliasRegistry const& get(); - }; + static ITagAliasRegistry const& get(); +}; -} // end namespace Catch +} // end namespace Catch // end catch_interfaces_tag_alias_registry.h namespace Catch { - class TestSpecParser { - enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode = None; - bool m_exclusion = false; - std::size_t m_start = std::string::npos, m_pos = 0; - std::string m_arg; - std::vector m_escapeChars; - TestSpec::Filter m_currentFilter; - TestSpec m_testSpec; - ITagAliasRegistry const* m_tagAliases = nullptr; +class TestSpecParser { + enum Mode { None, Name, QuotedName, Tag, EscapedName }; + Mode m_mode = None; + bool m_exclusion = false; + std::size_t m_start = std::string::npos, m_pos = 0; + std::string m_arg; + std::vector m_escapeChars; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases = nullptr; - public: - TestSpecParser( ITagAliasRegistry const& tagAliases ); + public: + TestSpecParser(ITagAliasRegistry const& tagAliases); - TestSpecParser& parse( std::string const& arg ); - TestSpec testSpec(); + TestSpecParser& parse(std::string const& arg); + TestSpec testSpec(); - private: - void visitChar( char c ); - void startNewMode( Mode mode, std::size_t start ); - void escape(); - std::string subString() const; + private: + void visitChar(char c); + void startNewMode(Mode mode, std::size_t start); + void escape(); + std::string subString() const; - template - void addPattern() { - std::string token = subString(); - for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) - token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); - m_escapeChars.clear(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - TestSpec::PatternPtr pattern = std::make_shared( token ); - if( m_exclusion ) - pattern = std::make_shared( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; - } + template + void addPattern() { + std::string token = subString(); + for (std::size_t i = 0; i < m_escapeChars.size(); ++i) + token = token.substr(0, m_escapeChars[i] - m_start - i) + + token.substr(m_escapeChars[i] - m_start - i + 1); + m_escapeChars.clear(); + if (startsWith(token, "exclude:")) { + m_exclusion = true; + token = token.substr(8); + } + if (!token.empty()) { + TestSpec::PatternPtr pattern = std::make_shared(token); + if (m_exclusion) + pattern = std::make_shared(pattern); + m_currentFilter.m_patterns.push_back(pattern); + } + m_exclusion = false; + m_mode = None; + } - void addFilter(); - }; - TestSpec parseTestSpec( std::string const& arg ); + void addFilter(); +}; +TestSpec parseTestSpec(std::string const& arg); -} // namespace Catch +} // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop @@ -3957,81 +4170,74 @@ namespace Catch { // start catch_interfaces_config.h #include +#include #include #include -#include namespace Catch { - enum class Verbosity { - Quiet = 0, - Normal, - High - }; +enum class Verbosity { Quiet = 0, Normal, High }; - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01, - NoTests = 0x02 - }; }; +struct WarnAbout { + enum What { Nothing = 0x00, NoAssertions = 0x01, NoTests = 0x02 }; +}; - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - struct RunTests { enum InWhatOrder { - InDeclarationOrder, - InLexicographicalOrder, - InRandomOrder - }; }; - struct UseColour { enum YesOrNo { - Auto, - Yes, - No - }; }; - struct WaitForKeypress { enum When { - Never, - BeforeStart = 1, - BeforeExit = 2, - BeforeStartAndExit = BeforeStart | BeforeExit - }; }; +struct ShowDurations { + enum OrNot { DefaultForReporter, Always, Never }; +}; +struct RunTests { + enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; +}; +struct UseColour { + enum YesOrNo { Auto, Yes, No }; +}; +struct WaitForKeypress { + enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; +}; - class TestSpec; +class TestSpec; - struct IConfig : NonCopyable { +struct IConfig : NonCopyable { + virtual ~IConfig(); - virtual ~IConfig(); + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual bool warnAboutNoTests() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual bool hasTestFilters() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual int benchmarkResolutionMultiple() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + virtual Verbosity verbosity() const = 0; +}; - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual bool warnAboutNoTests() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual TestSpec const& testSpec() const = 0; - virtual bool hasTestFilters() const = 0; - virtual RunTests::InWhatOrder runOrder() const = 0; - virtual unsigned int rngSeed() const = 0; - virtual int benchmarkResolutionMultiple() const = 0; - virtual UseColour::YesOrNo useColour() const = 0; - virtual std::vector const& getSectionsToRun() const = 0; - virtual Verbosity verbosity() const = 0; - }; - - using IConfigPtr = std::shared_ptr; -} +using IConfigPtr = std::shared_ptr; +} // namespace Catch // end catch_interfaces_config.h // Libstdc++ doesn't like incomplete classes for unique_ptr #include -#include #include +#include #ifndef CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CONFIG_CONSOLE_WIDTH 80 @@ -4039,99 +4245,97 @@ namespace Catch { namespace Catch { - struct IStream; +struct IStream; - struct ConfigData { - bool listTests = false; - bool listTags = false; - bool listReporters = false; - bool listTestNamesOnly = false; +struct ConfigData { + bool listTests = false; + bool listTags = false; + bool listReporters = false; + bool listTestNamesOnly = false; - bool showSuccessfulTests = false; - bool shouldDebugBreak = false; - bool noThrow = false; - bool showHelp = false; - bool showInvisibles = false; - bool filenamesAsTags = false; - bool libIdentify = false; + bool showSuccessfulTests = false; + bool shouldDebugBreak = false; + bool noThrow = false; + bool showHelp = false; + bool showInvisibles = false; + bool filenamesAsTags = false; + bool libIdentify = false; - int abortAfter = -1; - unsigned int rngSeed = 0; - int benchmarkResolutionMultiple = 100; + int abortAfter = -1; + unsigned int rngSeed = 0; + int benchmarkResolutionMultiple = 100; - Verbosity verbosity = Verbosity::Normal; - WarnAbout::What warnings = WarnAbout::Nothing; - ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; - RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; - UseColour::YesOrNo useColour = UseColour::Auto; - WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; + Verbosity verbosity = Verbosity::Normal; + WarnAbout::What warnings = WarnAbout::Nothing; + ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; + UseColour::YesOrNo useColour = UseColour::Auto; + WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; - std::string outputFilename; - std::string name; - std::string processName; + std::string outputFilename; + std::string name; + std::string processName; #ifndef CATCH_CONFIG_DEFAULT_REPORTER #define CATCH_CONFIG_DEFAULT_REPORTER "console" #endif - std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; + std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; #undef CATCH_CONFIG_DEFAULT_REPORTER - std::vector testsOrTags; - std::vector sectionsToRun; - }; + std::vector testsOrTags; + std::vector sectionsToRun; +}; - class Config : public IConfig { - public: +class Config : public IConfig { + public: + Config() = default; + Config(ConfigData const& data); + virtual ~Config() = default; - Config() = default; - Config( ConfigData const& data ); - virtual ~Config() = default; + std::string const& getFilename() const; - std::string const& getFilename() const; + bool listTests() const; + bool listTestNamesOnly() const; + bool listTags() const; + bool listReporters() const; - bool listTests() const; - bool listTestNamesOnly() const; - bool listTags() const; - bool listReporters() const; + std::string getProcessName() const; + std::string const& getReporterName() const; - std::string getProcessName() const; - std::string const& getReporterName() const; + std::vector const& getTestsOrTags() const; + std::vector const& getSectionsToRun() const override; - std::vector const& getTestsOrTags() const; - std::vector const& getSectionsToRun() const override; + virtual TestSpec const& testSpec() const override; + bool hasTestFilters() const override; - virtual TestSpec const& testSpec() const override; - bool hasTestFilters() const override; + bool showHelp() const; - bool showHelp() const; + // IConfig interface + bool allowThrows() const override; + std::ostream& stream() const override; + std::string name() const override; + bool includeSuccessfulResults() const override; + bool warnAboutMissingAssertions() const override; + bool warnAboutNoTests() const override; + ShowDurations::OrNot showDurations() const override; + RunTests::InWhatOrder runOrder() const override; + unsigned int rngSeed() const override; + int benchmarkResolutionMultiple() const override; + UseColour::YesOrNo useColour() const override; + bool shouldDebugBreak() const override; + int abortAfter() const override; + bool showInvisibles() const override; + Verbosity verbosity() const override; - // IConfig interface - bool allowThrows() const override; - std::ostream& stream() const override; - std::string name() const override; - bool includeSuccessfulResults() const override; - bool warnAboutMissingAssertions() const override; - bool warnAboutNoTests() const override; - ShowDurations::OrNot showDurations() const override; - RunTests::InWhatOrder runOrder() const override; - unsigned int rngSeed() const override; - int benchmarkResolutionMultiple() const override; - UseColour::YesOrNo useColour() const override; - bool shouldDebugBreak() const override; - int abortAfter() const override; - bool showInvisibles() const override; - Verbosity verbosity() const override; + private: + IStream const* openStream(); + ConfigData m_data; - private: + std::unique_ptr m_stream; + TestSpec m_testSpec; + bool m_hasTestFilters = false; +}; - IStream const* openStream(); - ConfigData m_data; - - std::unique_ptr m_stream; - TestSpec m_testSpec; - bool m_hasTestFilters = false; - }; - -} // end namespace Catch +} // end namespace Catch // end catch_config.hpp // start catch_assertionresult.h @@ -4140,707 +4344,688 @@ namespace Catch { namespace Catch { - struct AssertionResultData - { - AssertionResultData() = delete; +struct AssertionResultData { + AssertionResultData() = delete; - AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); + AssertionResultData(ResultWas::OfType _resultType, + LazyExpression const& _lazyExpression); - std::string message; - mutable std::string reconstructedExpression; - LazyExpression lazyExpression; - ResultWas::OfType resultType; + std::string message; + mutable std::string reconstructedExpression; + LazyExpression lazyExpression; + ResultWas::OfType resultType; - std::string reconstructExpression() const; - }; + std::string reconstructExpression() const; +}; - class AssertionResult { - public: - AssertionResult() = delete; - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); +class AssertionResult { + public: + AssertionResult() = delete; + AssertionResult(AssertionInfo const& info, AssertionResultData const& data); - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - StringRef getTestMacroName() const; + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + StringRef getTestMacroName() const; - //protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; + // protected: + AssertionInfo m_info; + AssertionResultData m_resultData; +}; -} // end namespace Catch +} // end namespace Catch // end catch_assertionresult.h // start catch_option.hpp namespace Catch { - // An optional type - template - class Option { - public: - Option() : nullableValue( nullptr ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) - {} +// An optional type +template +class Option { + public: + Option() : nullableValue(nullptr) {} + Option(T const& _value) : nullableValue(new (storage) T(_value)) {} + Option(Option const& _other) + : nullableValue(_other ? new (storage) T(*_other) : nullptr) {} - ~Option() { - reset(); - } + ~Option() { reset(); } - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } + Option& operator=(Option const& _other) { + if (&_other != this) { + reset(); + if (_other) nullableValue = new (storage) T(*_other); + } + return *this; + } + Option& operator=(T const& _value) { + reset(); + nullableValue = new (storage) T(_value); + return *this; + } - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = nullptr; - } + void reset() { + if (nullableValue) nullableValue->~T(); + nullableValue = nullptr; + } - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } + T valueOr(T const& defaultValue) const { + return nullableValue ? *nullableValue : defaultValue; + } - bool some() const { return nullableValue != nullptr; } - bool none() const { return nullableValue == nullptr; } + bool some() const { return nullableValue != nullptr; } + bool none() const { return nullableValue == nullptr; } - bool operator !() const { return nullableValue == nullptr; } - explicit operator bool() const { - return some(); - } + bool operator!() const { return nullableValue == nullptr; } + explicit operator bool() const { return some(); } - private: - T *nullableValue; - alignas(alignof(T)) char storage[sizeof(T)]; - }; + private: + T* nullableValue; + alignas(alignof(T)) char storage[sizeof(T)]; +}; -} // end namespace Catch +} // end namespace Catch // end catch_option.hpp -#include #include #include -#include #include +#include +#include namespace Catch { - struct ReporterConfig { - explicit ReporterConfig( IConfigPtr const& _fullConfig ); +struct ReporterConfig { + explicit ReporterConfig(IConfigPtr const& _fullConfig); - ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); + ReporterConfig(IConfigPtr const& _fullConfig, std::ostream& _stream); - std::ostream& stream() const; - IConfigPtr fullConfig() const; + std::ostream& stream() const; + IConfigPtr fullConfig() const; - private: - std::ostream* m_stream; - IConfigPtr m_fullConfig; - }; + private: + std::ostream* m_stream; + IConfigPtr m_fullConfig; +}; - struct ReporterPreferences { - bool shouldRedirectStdOut = false; - bool shouldReportAllAssertions = false; - }; +struct ReporterPreferences { + bool shouldRedirectStdOut = false; + bool shouldReportAllAssertions = false; +}; - template - struct LazyStat : Option { - LazyStat& operator=( T const& _value ) { - Option::operator=( _value ); - used = false; - return *this; - } - void reset() { - Option::reset(); - used = false; - } - bool used = false; - }; +template +struct LazyStat : Option { + LazyStat& operator=(T const& _value) { + Option::operator=(_value); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used = false; +}; - struct TestRunInfo { - TestRunInfo( std::string const& _name ); - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ); +struct TestRunInfo { + TestRunInfo(std::string const& _name); + std::string name; +}; +struct GroupInfo { + GroupInfo(std::string const& _name, std::size_t _groupIndex, + std::size_t _groupsCount); - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; +}; - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ); +struct AssertionStats { + AssertionStats(AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals); - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = default; - AssertionStats& operator = ( AssertionStats && ) = default; - virtual ~AssertionStats(); + AssertionStats(AssertionStats const&) = default; + AssertionStats(AssertionStats&&) = default; + AssertionStats& operator=(AssertionStats const&) = default; + AssertionStats& operator=(AssertionStats&&) = default; + virtual ~AssertionStats(); - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; +}; - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ); - SectionStats( SectionStats const& ) = default; - SectionStats( SectionStats && ) = default; - SectionStats& operator = ( SectionStats const& ) = default; - SectionStats& operator = ( SectionStats && ) = default; - virtual ~SectionStats(); +struct SectionStats { + SectionStats(SectionInfo const& _sectionInfo, Counts const& _assertions, + double _durationInSeconds, bool _missingAssertions); + SectionStats(SectionStats const&) = default; + SectionStats(SectionStats&&) = default; + SectionStats& operator=(SectionStats const&) = default; + SectionStats& operator=(SectionStats&&) = default; + virtual ~SectionStats(); - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; +}; - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ); +struct TestCaseStats { + TestCaseStats(TestCaseInfo const& _testInfo, Totals const& _totals, + std::string const& _stdOut, std::string const& _stdErr, + bool _aborting); - TestCaseStats( TestCaseStats const& ) = default; - TestCaseStats( TestCaseStats && ) = default; - TestCaseStats& operator = ( TestCaseStats const& ) = default; - TestCaseStats& operator = ( TestCaseStats && ) = default; - virtual ~TestCaseStats(); + TestCaseStats(TestCaseStats const&) = default; + TestCaseStats(TestCaseStats&&) = default; + TestCaseStats& operator=(TestCaseStats const&) = default; + TestCaseStats& operator=(TestCaseStats&&) = default; + virtual ~TestCaseStats(); - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; +}; - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ); - TestGroupStats( GroupInfo const& _groupInfo ); +struct TestGroupStats { + TestGroupStats(GroupInfo const& _groupInfo, Totals const& _totals, + bool _aborting); + TestGroupStats(GroupInfo const& _groupInfo); - TestGroupStats( TestGroupStats const& ) = default; - TestGroupStats( TestGroupStats && ) = default; - TestGroupStats& operator = ( TestGroupStats const& ) = default; - TestGroupStats& operator = ( TestGroupStats && ) = default; - virtual ~TestGroupStats(); + TestGroupStats(TestGroupStats const&) = default; + TestGroupStats(TestGroupStats&&) = default; + TestGroupStats& operator=(TestGroupStats const&) = default; + TestGroupStats& operator=(TestGroupStats&&) = default; + virtual ~TestGroupStats(); - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; + GroupInfo groupInfo; + Totals totals; + bool aborting; +}; - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ); +struct TestRunStats { + TestRunStats(TestRunInfo const& _runInfo, Totals const& _totals, + bool _aborting); - TestRunStats( TestRunStats const& ) = default; - TestRunStats( TestRunStats && ) = default; - TestRunStats& operator = ( TestRunStats const& ) = default; - TestRunStats& operator = ( TestRunStats && ) = default; - virtual ~TestRunStats(); + TestRunStats(TestRunStats const&) = default; + TestRunStats(TestRunStats&&) = default; + TestRunStats& operator=(TestRunStats const&) = default; + TestRunStats& operator=(TestRunStats&&) = default; + virtual ~TestRunStats(); - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; + TestRunInfo runInfo; + Totals totals; + bool aborting; +}; - struct BenchmarkInfo { - std::string name; - }; - struct BenchmarkStats { - BenchmarkInfo info; - std::size_t iterations; - uint64_t elapsedTimeInNanoseconds; - }; +struct BenchmarkInfo { + std::string name; +}; +struct BenchmarkStats { + BenchmarkInfo info; + std::size_t iterations; + uint64_t elapsedTimeInNanoseconds; +}; - struct IStreamingReporter { - virtual ~IStreamingReporter() = default; +struct IStreamingReporter { + virtual ~IStreamingReporter() = default; - // Implementing class must also provide the following static methods: - // static std::string getDescription(); - // static std::set getSupportedVerbosities() + // Implementing class must also provide the following static methods: + // static std::string getDescription(); + // static std::set getSupportedVerbosities() - virtual ReporterPreferences getPreferences() const = 0; + virtual ReporterPreferences getPreferences() const = 0; - virtual void noMatchingTestCases( std::string const& spec ) = 0; + virtual void noMatchingTestCases(std::string const& spec) = 0; - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + virtual void testRunStarting(TestRunInfo const& testRunInfo) = 0; + virtual void testGroupStarting(GroupInfo const& groupInfo) = 0; - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + virtual void testCaseStarting(TestCaseInfo const& testInfo) = 0; + virtual void sectionStarting(SectionInfo const& sectionInfo) = 0; - // *** experimental *** - virtual void benchmarkStarting( BenchmarkInfo const& ) {} + // *** experimental *** + virtual void benchmarkStarting(BenchmarkInfo const&) {} - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + virtual void assertionStarting(AssertionInfo const& assertionInfo) = 0; - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded(AssertionStats const& assertionStats) = 0; - // *** experimental *** - virtual void benchmarkEnded( BenchmarkStats const& ) {} + // *** experimental *** + virtual void benchmarkEnded(BenchmarkStats const&) {} - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + virtual void sectionEnded(SectionStats const& sectionStats) = 0; + virtual void testCaseEnded(TestCaseStats const& testCaseStats) = 0; + virtual void testGroupEnded(TestGroupStats const& testGroupStats) = 0; + virtual void testRunEnded(TestRunStats const& testRunStats) = 0; - virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + virtual void skipTest(TestCaseInfo const& testInfo) = 0; - // Default empty implementation provided - virtual void fatalErrorEncountered( StringRef name ); + // Default empty implementation provided + virtual void fatalErrorEncountered(StringRef name); - virtual bool isMulti() const; - }; - using IStreamingReporterPtr = std::unique_ptr; + virtual bool isMulti() const; +}; +using IStreamingReporterPtr = std::unique_ptr; - struct IReporterFactory { - virtual ~IReporterFactory(); - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - using IReporterFactoryPtr = std::shared_ptr; +struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporterPtr create(ReporterConfig const& config) const = 0; + virtual std::string getDescription() const = 0; +}; +using IReporterFactoryPtr = std::shared_ptr; - struct IReporterRegistry { - using FactoryMap = std::map; - using Listeners = std::vector; +struct IReporterRegistry { + using FactoryMap = std::map; + using Listeners = std::vector; - virtual ~IReporterRegistry(); - virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - virtual Listeners const& getListeners() const = 0; - }; + virtual ~IReporterRegistry(); + virtual IStreamingReporterPtr create(std::string const& name, + IConfigPtr const& config) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; +}; -} // end namespace Catch +} // end namespace Catch // end catch_interfaces_reporter.h #include -#include +#include #include #include -#include +#include #include #include namespace Catch { - void prepareExpandedExpression(AssertionResult& result); +void prepareExpandedExpression(AssertionResult& result); - // Returns double formatted as %.3f (format expected on output) - std::string getFormattedDuration( double duration ); +// Returns double formatted as %.3f (format expected on output) +std::string getFormattedDuration(double duration); - template - struct StreamingReporterBase : IStreamingReporter { +template +struct StreamingReporterBase : IStreamingReporter { + StreamingReporterBase(ReporterConfig const& _config) + : m_config(_config.fullConfig()), stream(_config.stream()) { + m_reporterPrefs.shouldRedirectStdOut = false; + if (!DerivedT::getSupportedVerbosities().count(m_config->verbosity())) + CATCH_ERROR("Verbosity level not supported by this reporter"); + } - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) - CATCH_ERROR( "Verbosity level not supported by this reporter" ); - } + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } - ReporterPreferences getPreferences() const override { - return m_reporterPrefs; - } + static std::set getSupportedVerbosities() { + return {Verbosity::Normal}; + } - static std::set getSupportedVerbosities() { - return { Verbosity::Normal }; - } + ~StreamingReporterBase() override = default; - ~StreamingReporterBase() override = default; + void noMatchingTestCases(std::string const&) override {} - void noMatchingTestCases(std::string const&) override {} + void testRunStarting(TestRunInfo const& _testRunInfo) override { + currentTestRunInfo = _testRunInfo; + } + void testGroupStarting(GroupInfo const& _groupInfo) override { + currentGroupInfo = _groupInfo; + } - void testRunStarting(TestRunInfo const& _testRunInfo) override { - currentTestRunInfo = _testRunInfo; - } - void testGroupStarting(GroupInfo const& _groupInfo) override { - currentGroupInfo = _groupInfo; - } + void testCaseStarting(TestCaseInfo const& _testInfo) override { + currentTestCaseInfo = _testInfo; + } + void sectionStarting(SectionInfo const& _sectionInfo) override { + m_sectionStack.push_back(_sectionInfo); + } - void testCaseStarting(TestCaseInfo const& _testInfo) override { - currentTestCaseInfo = _testInfo; - } - void sectionStarting(SectionInfo const& _sectionInfo) override { - m_sectionStack.push_back(_sectionInfo); - } + void sectionEnded(SectionStats const& /* _sectionStats */) override { + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { + currentTestCaseInfo.reset(); + } + void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { + currentGroupInfo.reset(); + } + void testRunEnded(TestRunStats const& /* _testRunStats */) override { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } - void sectionEnded(SectionStats const& /* _sectionStats */) override { - m_sectionStack.pop_back(); - } - void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { - currentTestCaseInfo.reset(); - } - void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { - currentGroupInfo.reset(); - } - void testRunEnded(TestRunStats const& /* _testRunStats */) override { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } + void skipTest(TestCaseInfo const&) override { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } - void skipTest(TestCaseInfo const&) override { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } + IConfigPtr m_config; + std::ostream& stream; - IConfigPtr m_config; - std::ostream& stream; + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; +}; - std::vector m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; +template +struct CumulativeReporterBase : IStreamingReporter { + template + struct Node { + explicit Node(T const& _value) : value(_value) {} + virtual ~Node() {} - template - struct CumulativeReporterBase : IStreamingReporter { - template - struct Node { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} + using ChildNodes = std::vector>; + T value; + ChildNodes children; + }; + struct SectionNode { + explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} + virtual ~SectionNode() = default; - using ChildNodes = std::vector>; - T value; - ChildNodes children; - }; - struct SectionNode { - explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} - virtual ~SectionNode() = default; - - bool operator == (SectionNode const& other) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == (std::shared_ptr const& other) const { - return operator==(*other); - } - - SectionStats stats; - using ChildSections = std::vector>; - using Assertions = std::vector; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() (std::shared_ptr const& node) const { - return ((node->stats.sectionInfo.name == m_other.name) && - (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); - } - void operator=(BySectionInfo const&) = delete; - - private: - SectionInfo const& m_other; - }; - - using TestCaseNode = Node; - using TestGroupNode = Node; - using TestRunNode = Node; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) - CATCH_ERROR( "Verbosity level not supported by this reporter" ); - } - ~CumulativeReporterBase() override = default; - - ReporterPreferences getPreferences() const override { - return m_reporterPrefs; - } - - static std::set getSupportedVerbosities() { - return { Verbosity::Normal }; - } - - void testRunStarting( TestRunInfo const& ) override {} - void testGroupStarting( GroupInfo const& ) override {} - - void testCaseStarting( TestCaseInfo const& ) override {} - - void sectionStarting( SectionInfo const& sectionInfo ) override { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - std::shared_ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = std::make_shared( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - auto it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = std::make_shared( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = std::move(node); - } - - void assertionStarting(AssertionInfo const&) override {} - - bool assertionEnded(AssertionStats const& assertionStats) override { - assert(!m_sectionStack.empty()); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression(const_cast( assertionStats.assertionResult ) ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back(assertionStats); - return true; - } - void sectionEnded(SectionStats const& sectionStats) override { - assert(!m_sectionStack.empty()); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - void testCaseEnded(TestCaseStats const& testCaseStats) override { - auto node = std::make_shared(testCaseStats); - assert(m_sectionStack.size() == 0); - node->children.push_back(m_rootSection); - m_testCases.push_back(node); - m_rootSection.reset(); - - assert(m_deepestSection); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - void testGroupEnded(TestGroupStats const& testGroupStats) override { - auto node = std::make_shared(testGroupStats); - node->children.swap(m_testCases); - m_testGroups.push_back(node); - } - void testRunEnded(TestRunStats const& testRunStats) override { - auto node = std::make_shared(testRunStats); - node->children.swap(m_testGroups); - m_testRuns.push_back(node); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - void skipTest(TestCaseInfo const&) override {} - - IConfigPtr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector>> m_sections; - std::vector> m_testCases; - std::vector> m_testGroups; - - std::vector> m_testRuns; - - std::shared_ptr m_rootSection; - std::shared_ptr m_deepestSection; - std::vector> m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; - - template - char const* getLineOfChars() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; + bool operator==(SectionNode const& other) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator==(std::shared_ptr const& other) const { + return operator==(*other); } - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ); + SectionStats stats; + using ChildSections = std::vector>; + using Assertions = std::vector; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; - static std::set getSupportedVerbosities(); + struct BySectionInfo { + BySectionInfo(SectionInfo const& other) : m_other(other) {} + BySectionInfo(BySectionInfo const& other) : m_other(other.m_other) {} + bool operator()(std::shared_ptr const& node) const { + return ((node->stats.sectionInfo.name == m_other.name) && + (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); + } + void operator=(BySectionInfo const&) = delete; - void assertionStarting(AssertionInfo const&) override; - bool assertionEnded(AssertionStats const&) override; - }; + private: + SectionInfo const& m_other; + }; -} // end namespace Catch + using TestCaseNode = Node; + using TestGroupNode = Node; + using TestRunNode = Node; + + CumulativeReporterBase(ReporterConfig const& _config) + : m_config(_config.fullConfig()), stream(_config.stream()) { + m_reporterPrefs.shouldRedirectStdOut = false; + if (!DerivedT::getSupportedVerbosities().count(m_config->verbosity())) + CATCH_ERROR("Verbosity level not supported by this reporter"); + } + ~CumulativeReporterBase() override = default; + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return {Verbosity::Normal}; + } + + void testRunStarting(TestRunInfo const&) override {} + void testGroupStarting(GroupInfo const&) override {} + + void testCaseStarting(TestCaseInfo const&) override {} + + void sectionStarting(SectionInfo const& sectionInfo) override { + SectionStats incompleteStats(sectionInfo, Counts(), 0, false); + std::shared_ptr node; + if (m_sectionStack.empty()) { + if (!m_rootSection) + m_rootSection = std::make_shared(incompleteStats); + node = m_rootSection; + } else { + SectionNode& parentNode = *m_sectionStack.back(); + auto it = std::find_if(parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo(sectionInfo)); + if (it == parentNode.childSections.end()) { + node = std::make_shared(incompleteStats); + parentNode.childSections.push_back(node); + } else + node = *it; + } + m_sectionStack.push_back(node); + m_deepestSection = std::move(node); + } + + void assertionStarting(AssertionInfo const&) override {} + + bool assertionEnded(AssertionStats const& assertionStats) override { + assert(!m_sectionStack.empty()); + // AssertionResult holds a pointer to a temporary DecomposedExpression, + // which getExpandedExpression() calls to build the expression string. + // Our section stack copy of the assertionResult will likely outlive the + // temporary, so it must be expanded or discarded now to avoid calling + // a destroyed object later. + prepareExpandedExpression( + const_cast(assertionStats.assertionResult)); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back(assertionStats); + return true; + } + void sectionEnded(SectionStats const& sectionStats) override { + assert(!m_sectionStack.empty()); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& testCaseStats) override { + auto node = std::make_shared(testCaseStats); + assert(m_sectionStack.size() == 0); + node->children.push_back(m_rootSection); + m_testCases.push_back(node); + m_rootSection.reset(); + + assert(m_deepestSection); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + void testGroupEnded(TestGroupStats const& testGroupStats) override { + auto node = std::make_shared(testGroupStats); + node->children.swap(m_testCases); + m_testGroups.push_back(node); + } + void testRunEnded(TestRunStats const& testRunStats) override { + auto node = std::make_shared(testRunStats); + node->children.swap(m_testGroups); + m_testRuns.push_back(node); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + void skipTest(TestCaseInfo const&) override {} + + IConfigPtr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector>> m_sections; + std::vector> m_testCases; + std::vector> m_testGroups; + + std::vector> m_testRuns; + + std::shared_ptr m_rootSection; + std::shared_ptr m_deepestSection; + std::vector> m_sectionStack; + ReporterPreferences m_reporterPrefs; +}; + +template +char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if (!*line) { + std::memset(line, C, CATCH_CONFIG_CONSOLE_WIDTH - 1); + line[CATCH_CONFIG_CONSOLE_WIDTH - 1] = 0; + } + return line; +} + +struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase(ReporterConfig const& _config); + + static std::set getSupportedVerbosities(); + + void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const&) override; +}; + +} // end namespace Catch // end catch_reporter_bases.hpp // start catch_console_colour.h namespace Catch { - struct Colour { - enum Code { - None = 0, +struct Colour { + enum Code { + None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, - Bright = 0x10, + Bright = 0x10, - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - BrightYellow = Bright | Yellow, + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + BrightYellow = Bright | Yellow, - // By intention - FileName = LightGrey, - Warning = BrightYellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, + // By intention + FileName = LightGrey, + Warning = BrightYellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, - Error = BrightRed, - Success = Green, + Error = BrightRed, + Success = Green, - OriginalExpression = Cyan, - ReconstructedExpression = BrightYellow, + OriginalExpression = Cyan, + ReconstructedExpression = BrightYellow, - SecondaryText = LightGrey, - Headers = White - }; + SecondaryText = LightGrey, + Headers = White + }; - // Use constructed object for RAII guard - Colour( Code _colourCode ); - Colour( Colour&& other ) noexcept; - Colour& operator=( Colour&& other ) noexcept; - ~Colour(); + // Use constructed object for RAII guard + Colour(Code _colourCode); + Colour(Colour&& other) noexcept; + Colour& operator=(Colour&& other) noexcept; + ~Colour(); - // Use static method for one-shot changes - static void use( Code _colourCode ); + // Use static method for one-shot changes + static void use(Code _colourCode); - private: - bool m_moved = false; - }; + private: + bool m_moved = false; +}; - std::ostream& operator << ( std::ostream& os, Colour const& ); +std::ostream& operator<<(std::ostream& os, Colour const&); -} // end namespace Catch +} // end namespace Catch // end catch_console_colour.h // start catch_reporter_registrars.hpp - namespace Catch { - template - class ReporterRegistrar { +template +class ReporterRegistrar { + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporterPtr create( + ReporterConfig const& config) const override { + return std::unique_ptr(new T(config)); + } - class ReporterFactory : public IReporterFactory { + virtual std::string getDescription() const override { + return T::getDescription(); + } + }; - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { - return std::unique_ptr( new T( config ) ); - } + public: + explicit ReporterRegistrar(std::string const& name) { + getMutableRegistryHub().registerReporter( + name, std::make_shared()); + } +}; - virtual std::string getDescription() const override { - return T::getDescription(); - } - }; +template +class ListenerRegistrar { + class ListenerFactory : public IReporterFactory { + virtual IStreamingReporterPtr create( + ReporterConfig const& config) const override { + return std::unique_ptr(new T(config)); + } + virtual std::string getDescription() const override { + return std::string(); + } + }; - public: - - explicit ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, std::make_shared() ); - } - }; - - template - class ListenerRegistrar { - - class ListenerFactory : public IReporterFactory { - - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { - return std::unique_ptr( new T( config ) ); - } - virtual std::string getDescription() const override { - return std::string(); - } - }; - - public: - - ListenerRegistrar() { - getMutableRegistryHub().registerListener( std::make_shared() ); - } - }; -} + public: + ListenerRegistrar() { + getMutableRegistryHub().registerListener( + std::make_shared()); + } +}; +} // namespace Catch #if !defined(CATCH_CONFIG_DISABLE) -#define CATCH_REGISTER_REPORTER( name, reporterType ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#define CATCH_REGISTER_REPORTER(name, reporterType) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::ReporterRegistrar \ + catch_internal_RegistrarFor##reporterType(name); \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS -#define CATCH_REGISTER_LISTENER( listenerType ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#else // CATCH_CONFIG_DISABLE +#define CATCH_REGISTER_LISTENER(listenerType) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::ListenerRegistrar \ + catch_internal_RegistrarFor##listenerType; \ + } \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#else // CATCH_CONFIG_DISABLE #define CATCH_REGISTER_REPORTER(name, reporterType) #define CATCH_REGISTER_LISTENER(listenerType) -#endif // CATCH_CONFIG_DISABLE +#endif // CATCH_CONFIG_DISABLE // end catch_reporter_registrars.hpp // Allow users to base their work off existing reporters @@ -4848,95 +5033,93 @@ namespace Catch { namespace Catch { - struct CompactReporter : StreamingReporterBase { +struct CompactReporter : StreamingReporterBase { + using StreamingReporterBase::StreamingReporterBase; - using StreamingReporterBase::StreamingReporterBase; + ~CompactReporter() override; - ~CompactReporter() override; + static std::string getDescription(); - static std::string getDescription(); + ReporterPreferences getPreferences() const override; - ReporterPreferences getPreferences() const override; + void noMatchingTestCases(std::string const& spec) override; - void noMatchingTestCases(std::string const& spec) override; + void assertionStarting(AssertionInfo const&) override; - void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const& _assertionStats) override; - bool assertionEnded(AssertionStats const& _assertionStats) override; + void sectionEnded(SectionStats const& _sectionStats) override; - void sectionEnded(SectionStats const& _sectionStats) override; + void testRunEnded(TestRunStats const& _testRunStats) override; +}; - void testRunEnded(TestRunStats const& _testRunStats) override; - - }; - -} // end namespace Catch +} // end namespace Catch // end catch_reporter_compact.h // start catch_reporter_console.h #if defined(_MSC_VER) #pragma warning(push) -#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch - // Note that 4062 (not all labels are handled - // and default is missing) is enabled +#pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in + // switch Note that 4062 (not all labels are + // handled and default is missing) is enabled #endif namespace Catch { - // Fwd decls - struct SummaryColumn; - class TablePrinter; +// Fwd decls +struct SummaryColumn; +class TablePrinter; - struct ConsoleReporter : StreamingReporterBase { - std::unique_ptr m_tablePrinter; +struct ConsoleReporter : StreamingReporterBase { + std::unique_ptr m_tablePrinter; - ConsoleReporter(ReporterConfig const& config); - ~ConsoleReporter() override; - static std::string getDescription(); + ConsoleReporter(ReporterConfig const& config); + ~ConsoleReporter() override; + static std::string getDescription(); - void noMatchingTestCases(std::string const& spec) override; + void noMatchingTestCases(std::string const& spec) override; - void assertionStarting(AssertionInfo const&) override; + void assertionStarting(AssertionInfo const&) override; - bool assertionEnded(AssertionStats const& _assertionStats) override; + bool assertionEnded(AssertionStats const& _assertionStats) override; - void sectionStarting(SectionInfo const& _sectionInfo) override; - void sectionEnded(SectionStats const& _sectionStats) override; + void sectionStarting(SectionInfo const& _sectionInfo) override; + void sectionEnded(SectionStats const& _sectionStats) override; - void benchmarkStarting(BenchmarkInfo const& info) override; - void benchmarkEnded(BenchmarkStats const& stats) override; + void benchmarkStarting(BenchmarkInfo const& info) override; + void benchmarkEnded(BenchmarkStats const& stats) override; - void testCaseEnded(TestCaseStats const& _testCaseStats) override; - void testGroupEnded(TestGroupStats const& _testGroupStats) override; - void testRunEnded(TestRunStats const& _testRunStats) override; + void testCaseEnded(TestCaseStats const& _testCaseStats) override; + void testGroupEnded(TestGroupStats const& _testGroupStats) override; + void testRunEnded(TestRunStats const& _testRunStats) override; - private: + private: + void lazyPrint(); - void lazyPrint(); + void lazyPrintWithoutClosingBenchmarkTable(); + void lazyPrintRunInfo(); + void lazyPrintGroupInfo(); + void printTestCaseAndSectionHeader(); - void lazyPrintWithoutClosingBenchmarkTable(); - void lazyPrintRunInfo(); - void lazyPrintGroupInfo(); - void printTestCaseAndSectionHeader(); + void printClosedHeader(std::string const& _name); + void printOpenHeader(std::string const& _name); - void printClosedHeader(std::string const& _name); - void printOpenHeader(std::string const& _name); + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString(std::string const& _string, std::size_t indent = 0); - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString(std::string const& _string, std::size_t indent = 0); + void printTotals(Totals const& totals); + void printSummaryRow(std::string const& label, + std::vector const& cols, std::size_t row); - void printTotals(Totals const& totals); - void printSummaryRow(std::string const& label, std::vector const& cols, std::size_t row); + void printTotalsDivider(Totals const& totals); + void printSummaryDivider(); - void printTotalsDivider(Totals const& totals); - void printSummaryDivider(); + private: + bool m_headerPrinted = false; +}; - private: - bool m_headerPrinted = false; - }; - -} // end namespace Catch +} // end namespace Catch #if defined(_MSC_VER) #pragma warning(pop) @@ -4951,194 +5134,191 @@ namespace Catch { namespace Catch { - class XmlEncode { - public: - enum ForWhat { ForTextNodes, ForAttributes }; +class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); + XmlEncode(std::string const& str, ForWhat forWhat = ForTextNodes); - void encodeTo( std::ostream& os ) const; + void encodeTo(std::ostream& os) const; - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); + friend std::ostream& operator<<(std::ostream& os, XmlEncode const& xmlEncode); - private: - std::string m_str; - ForWhat m_forWhat; - }; + private: + std::string m_str; + ForWhat m_forWhat; +}; - class XmlWriter { - public: +class XmlWriter { + public: + class ScopedElement { + public: + ScopedElement(XmlWriter* writer); - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ); + ScopedElement(ScopedElement&& other) noexcept; + ScopedElement& operator=(ScopedElement&& other) noexcept; - ScopedElement( ScopedElement&& other ) noexcept; - ScopedElement& operator=( ScopedElement&& other ) noexcept; + ~ScopedElement(); - ~ScopedElement(); + ScopedElement& writeText(std::string const& text, bool indent = true); - ScopedElement& writeText( std::string const& text, bool indent = true ); + template + ScopedElement& writeAttribute(std::string const& name, T const& attribute) { + m_writer->writeAttribute(name, attribute); + return *this; + } - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } + private: + mutable XmlWriter* m_writer = nullptr; + }; - private: - mutable XmlWriter* m_writer = nullptr; - }; + XmlWriter(std::ostream& os = Catch::cout()); + ~XmlWriter(); - XmlWriter( std::ostream& os = Catch::cout() ); - ~XmlWriter(); + XmlWriter(XmlWriter const&) = delete; + XmlWriter& operator=(XmlWriter const&) = delete; - XmlWriter( XmlWriter const& ) = delete; - XmlWriter& operator=( XmlWriter const& ) = delete; + XmlWriter& startElement(std::string const& name); - XmlWriter& startElement( std::string const& name ); + ScopedElement scopedElement(std::string const& name); - ScopedElement scopedElement( std::string const& name ); + XmlWriter& endElement(); - XmlWriter& endElement(); + XmlWriter& writeAttribute(std::string const& name, + std::string const& attribute); - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); + XmlWriter& writeAttribute(std::string const& name, bool attribute); - XmlWriter& writeAttribute( std::string const& name, bool attribute ); + template + XmlWriter& writeAttribute(std::string const& name, T const& attribute) { + ReusableStringStream rss; + rss << attribute; + return writeAttribute(name, rss.str()); + } - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - ReusableStringStream rss; - rss << attribute; - return writeAttribute( name, rss.str() ); - } + XmlWriter& writeText(std::string const& text, bool indent = true); - XmlWriter& writeText( std::string const& text, bool indent = true ); + XmlWriter& writeComment(std::string const& text); - XmlWriter& writeComment( std::string const& text ); + void writeStylesheetRef(std::string const& url); - void writeStylesheetRef( std::string const& url ); + XmlWriter& writeBlankLine(); - XmlWriter& writeBlankLine(); + void ensureTagClosed(); - void ensureTagClosed(); + private: + void writeDeclaration(); - private: + void newlineIfNecessary(); - void writeDeclaration(); + bool m_tagIsOpen = false; + bool m_needsNewline = false; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; +}; - void newlineIfNecessary(); - - bool m_tagIsOpen = false; - bool m_needsNewline = false; - std::vector m_tags; - std::string m_indent; - std::ostream& m_os; - }; - -} +} // namespace Catch // end catch_xmlwriter.h namespace Catch { - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter(ReporterConfig const& _config); +class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter(ReporterConfig const& _config); - ~JunitReporter() override; + ~JunitReporter() override; - static std::string getDescription(); + static std::string getDescription(); - void noMatchingTestCases(std::string const& /*spec*/) override; + void noMatchingTestCases(std::string const& /*spec*/) override; - void testRunStarting(TestRunInfo const& runInfo) override; + void testRunStarting(TestRunInfo const& runInfo) override; - void testGroupStarting(GroupInfo const& groupInfo) override; + void testGroupStarting(GroupInfo const& groupInfo) override; - void testCaseStarting(TestCaseInfo const& testCaseInfo) override; - bool assertionEnded(AssertionStats const& assertionStats) override; + void testCaseStarting(TestCaseInfo const& testCaseInfo) override; + bool assertionEnded(AssertionStats const& assertionStats) override; - void testCaseEnded(TestCaseStats const& testCaseStats) override; + void testCaseEnded(TestCaseStats const& testCaseStats) override; - void testGroupEnded(TestGroupStats const& testGroupStats) override; + void testGroupEnded(TestGroupStats const& testGroupStats) override; - void testRunEndedCumulative() override; + void testRunEndedCumulative() override; - void writeGroup(TestGroupNode const& groupNode, double suiteTime); + void writeGroup(TestGroupNode const& groupNode, double suiteTime); - void writeTestCase(TestCaseNode const& testCaseNode); + void writeTestCase(TestCaseNode const& testCaseNode); - void writeSection(std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode); + void writeSection(std::string const& className, std::string const& rootName, + SectionNode const& sectionNode); - void writeAssertions(SectionNode const& sectionNode); - void writeAssertion(AssertionStats const& stats); + void writeAssertions(SectionNode const& sectionNode); + void writeAssertion(AssertionStats const& stats); - XmlWriter xml; - Timer suiteTimer; - std::string stdOutForSuite; - std::string stdErrForSuite; - unsigned int unexpectedExceptions = 0; - bool m_okToFail = false; - }; + XmlWriter xml; + Timer suiteTimer; + std::string stdOutForSuite; + std::string stdErrForSuite; + unsigned int unexpectedExceptions = 0; + bool m_okToFail = false; +}; -} // end namespace Catch +} // end namespace Catch // end catch_reporter_junit.h // start catch_reporter_xml.h namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter(ReporterConfig const& _config); +class XmlReporter : public StreamingReporterBase { + public: + XmlReporter(ReporterConfig const& _config); - ~XmlReporter() override; + ~XmlReporter() override; - static std::string getDescription(); + static std::string getDescription(); - virtual std::string getStylesheetRef() const; + virtual std::string getStylesheetRef() const; - void writeSourceInfo(SourceLineInfo const& sourceInfo); + void writeSourceInfo(SourceLineInfo const& sourceInfo); - public: // StreamingReporterBase + public: // StreamingReporterBase + void noMatchingTestCases(std::string const& s) override; - void noMatchingTestCases(std::string const& s) override; + void testRunStarting(TestRunInfo const& testInfo) override; - void testRunStarting(TestRunInfo const& testInfo) override; + void testGroupStarting(GroupInfo const& groupInfo) override; - void testGroupStarting(GroupInfo const& groupInfo) override; + void testCaseStarting(TestCaseInfo const& testInfo) override; - void testCaseStarting(TestCaseInfo const& testInfo) override; + void sectionStarting(SectionInfo const& sectionInfo) override; - void sectionStarting(SectionInfo const& sectionInfo) override; + void assertionStarting(AssertionInfo const&) override; - void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const& assertionStats) override; - bool assertionEnded(AssertionStats const& assertionStats) override; + void sectionEnded(SectionStats const& sectionStats) override; - void sectionEnded(SectionStats const& sectionStats) override; + void testCaseEnded(TestCaseStats const& testCaseStats) override; - void testCaseEnded(TestCaseStats const& testCaseStats) override; + void testGroupEnded(TestGroupStats const& testGroupStats) override; - void testGroupEnded(TestGroupStats const& testGroupStats) override; + void testRunEnded(TestRunStats const& testRunStats) override; - void testRunEnded(TestRunStats const& testRunStats) override; + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth = 0; +}; - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth = 0; - }; - -} // end namespace Catch +} // end namespace Catch // end catch_reporter_xml.h // end catch_external_interfaces.h #endif -#endif // ! CATCH_CONFIG_IMPL_ONLY +#endif // ! CATCH_CONFIG_IMPL_ONLY #ifdef CATCH_IMPL // start catch_impl.hpp @@ -5151,166 +5331,168 @@ namespace Catch { // Keep these here for external reporters // start catch_test_case_tracker.h +#include #include #include -#include namespace Catch { namespace TestCaseTracking { - struct NameAndLocation { - std::string name; - SourceLineInfo location; +struct NameAndLocation { + std::string name; + SourceLineInfo location; - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); - }; + NameAndLocation(std::string const& _name, SourceLineInfo const& _location); +}; - struct ITracker; +struct ITracker; - using ITrackerPtr = std::shared_ptr; +using ITrackerPtr = std::shared_ptr; - struct ITracker { - virtual ~ITracker(); +struct ITracker { + virtual ~ITracker(); - // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; + // static queries + virtual NameAndLocation const& nameAndLocation() const = 0; - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; - virtual ITracker& parent() = 0; + virtual ITracker& parent() = 0; - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; - virtual void addChild( ITrackerPtr const& child ) = 0; - virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; - virtual void openChild() = 0; + virtual void addChild(ITrackerPtr const& child) = 0; + virtual ITrackerPtr findChild(NameAndLocation const& nameAndLocation) = 0; + virtual void openChild() = 0; - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isIndexTracker() const = 0; - }; + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; +}; - class TrackerContext { +class TrackerContext { + enum RunState { NotStarted, Executing, CompletedCycle }; - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; + ITrackerPtr m_rootTracker; + ITracker* m_currentTracker = nullptr; + RunState m_runState = NotStarted; - ITrackerPtr m_rootTracker; - ITracker* m_currentTracker = nullptr; - RunState m_runState = NotStarted; + public: + static TrackerContext& instance(); - public: + ITracker& startRun(); + void endRun(); - static TrackerContext& instance(); + void startCycle(); + void completeCycle(); - ITracker& startRun(); - void endRun(); + bool completedCycle() const; + ITracker& currentTracker(); + void setCurrentTracker(ITracker* tracker); +}; - void startCycle(); - void completeCycle(); +class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; - bool completedCycle() const; - ITracker& currentTracker(); - void setCurrentTracker( ITracker* tracker ); - }; + using Children = std::vector; + NameAndLocation m_nameAndLocation; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState = NotStarted; - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; + public: + TrackerBase(NameAndLocation const& nameAndLocation, TrackerContext& ctx, + ITracker* parent); - using Children = std::vector; - NameAndLocation m_nameAndLocation; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState = NotStarted; + NameAndLocation const& nameAndLocation() const override; + bool isComplete() const override; + bool isSuccessfullyCompleted() const override; + bool isOpen() const override; + bool hasChildren() const override; - public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + void addChild(ITrackerPtr const& child) override; - NameAndLocation const& nameAndLocation() const override; - bool isComplete() const override; - bool isSuccessfullyCompleted() const override; - bool isOpen() const override; - bool hasChildren() const override; + ITrackerPtr findChild(NameAndLocation const& nameAndLocation) override; + ITracker& parent() override; - void addChild( ITrackerPtr const& child ) override; + void openChild() override; - ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; - ITracker& parent() override; + bool isSectionTracker() const override; + bool isIndexTracker() const override; - void openChild() override; + void open(); - bool isSectionTracker() const override; - bool isIndexTracker() const override; + void close() override; + void fail() override; + void markAsNeedingAnotherRun() override; - void open(); + private: + void moveToParent(); + void moveToThis(); +}; - void close() override; - void fail() override; - void markAsNeedingAnotherRun() override; +class SectionTracker : public TrackerBase { + std::vector m_filters; - private: - void moveToParent(); - void moveToThis(); - }; + public: + SectionTracker(NameAndLocation const& nameAndLocation, TrackerContext& ctx, + ITracker* parent); - class SectionTracker : public TrackerBase { - std::vector m_filters; - public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + bool isSectionTracker() const override; - bool isSectionTracker() const override; + static SectionTracker& acquire(TrackerContext& ctx, + NameAndLocation const& nameAndLocation); - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); + void tryOpen(); - void tryOpen(); + void addInitialFilters(std::vector const& filters); + void addNextFilters(std::vector const& filters); +}; - void addInitialFilters( std::vector const& filters ); - void addNextFilters( std::vector const& filters ); - }; +class IndexTracker : public TrackerBase { + int m_size; + int m_index = -1; - class IndexTracker : public TrackerBase { - int m_size; - int m_index = -1; - public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); + public: + IndexTracker(NameAndLocation const& nameAndLocation, TrackerContext& ctx, + ITracker* parent, int size); - bool isIndexTracker() const override; - void close() override; + bool isIndexTracker() const override; + void close() override; - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); + static IndexTracker& acquire(TrackerContext& ctx, + NameAndLocation const& nameAndLocation, + int size); - int index() const; + int index() const; - void moveNext(); - }; + void moveNext(); +}; -} // namespace TestCaseTracking +} // namespace TestCaseTracking -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; using TestCaseTracking::IndexTracker; +using TestCaseTracking::ITracker; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::TrackerContext; -} // namespace Catch +} // namespace Catch // end catch_test_case_tracker.h @@ -5318,12 +5500,12 @@ using TestCaseTracking::IndexTracker; namespace Catch { - struct LeakDetector { - LeakDetector(); - ~LeakDetector(); - }; +struct LeakDetector { + LeakDetector(); + ~LeakDetector(); +}; -} +} // namespace Catch // end catch_leak_detector.h // Cpp files will be included in the single-header file here // start catch_approx.cpp @@ -5336,73 +5518,73 @@ namespace { // Performs equivalent check of std::fabs(lhs - rhs) <= margin // But without the subtraction to allow for INFINITY in comparison bool marginComparison(double lhs, double rhs, double margin) { - return (lhs + margin >= rhs) && (rhs + margin >= lhs); + return (lhs + margin >= rhs) && (rhs + margin >= lhs); } -} +} // namespace namespace Catch { namespace Detail { - Approx::Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 0.0 ), - m_value( value ) - {} +Approx::Approx(double value) + : m_epsilon(std::numeric_limits::epsilon() * 100), + m_margin(0.0), + m_scale(0.0), + m_value(value) {} - Approx Approx::custom() { - return Approx( 0 ); - } +Approx Approx::custom() { return Approx(0); } - Approx Approx::operator-() const { - auto temp(*this); - temp.m_value = -temp.m_value; - return temp; - } - - std::string Approx::toString() const { - ReusableStringStream rss; - rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; - return rss.str(); - } - - bool Approx::equalityComparisonImpl(const double other) const { - // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value - // Thanks to Richard Harris for his help refining the scaled margin value - return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); - } - - void Approx::setMargin(double margin) { - CATCH_ENFORCE(margin >= 0, - "Invalid Approx::margin: " << margin << '.' - << " Approx::Margin has to be non-negative."); - m_margin = margin; - } - - void Approx::setEpsilon(double epsilon) { - CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0, - "Invalid Approx::epsilon: " << epsilon << '.' - << " Approx::epsilon has to be in [0, 1]"); - m_epsilon = epsilon; - } - -} // end namespace Detail - -namespace literals { - Detail::Approx operator "" _a(long double val) { - return Detail::Approx(val); - } - Detail::Approx operator "" _a(unsigned long long val) { - return Detail::Approx(val); - } -} // end namespace literals - -std::string StringMaker::convert(Catch::Detail::Approx const& value) { - return value.toString(); +Approx Approx::operator-() const { + auto temp(*this); + temp.m_value = -temp.m_value; + return temp; } -} // end namespace Catch +std::string Approx::toString() const { + ReusableStringStream rss; + rss << "Approx( " << ::Catch::Detail::stringify(m_value) << " )"; + return rss.str(); +} + +bool Approx::equalityComparisonImpl(const double other) const { + // First try with fixed margin, then compute margin based on epsilon, scale + // and Approx's value Thanks to Richard Harris for his help refining the + // scaled margin value + return marginComparison(m_value, other, m_margin) || + marginComparison(m_value, other, + m_epsilon * (m_scale + std::fabs(m_value))); +} + +void Approx::setMargin(double margin) { + CATCH_ENFORCE(margin >= 0, "Invalid Approx::margin: " + << margin << '.' + << " Approx::Margin has to be non-negative."); + m_margin = margin; +} + +void Approx::setEpsilon(double epsilon) { + CATCH_ENFORCE( + epsilon >= 0 && epsilon <= 1.0, + "Invalid Approx::epsilon: " << epsilon << '.' + << " Approx::epsilon has to be in [0, 1]"); + m_epsilon = epsilon; +} + +} // end namespace Detail + +namespace literals { +Detail::Approx operator"" _a(long double val) { return Detail::Approx(val); } +Detail::Approx operator"" _a(unsigned long long val) { + return Detail::Approx(val); +} +} // end namespace literals + +std::string StringMaker::convert( + Catch::Detail::Approx const& value) { + return value.toString(); +} + +} // end namespace Catch // end catch_approx.cpp // start catch_assertionhandler.cpp @@ -5412,87 +5594,81 @@ std::string StringMaker::convert(Catch::Detail::Approx co namespace Catch { - struct IResultCapture; - struct IRunner; - struct IConfig; - struct IMutableContext; +struct IResultCapture; +struct IRunner; +struct IConfig; +struct IMutableContext; - using IConfigPtr = std::shared_ptr; +using IConfigPtr = std::shared_ptr; - struct IContext - { - virtual ~IContext(); +struct IContext { + virtual ~IContext(); - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual IConfigPtr const& getConfig() const = 0; - }; + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual IConfigPtr const& getConfig() const = 0; +}; - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( IConfigPtr const& config ) = 0; +struct IMutableContext : IContext { + virtual ~IMutableContext(); + virtual void setResultCapture(IResultCapture* resultCapture) = 0; + virtual void setRunner(IRunner* runner) = 0; + virtual void setConfig(IConfigPtr const& config) = 0; - private: - static IMutableContext *currentContext; - friend IMutableContext& getCurrentMutableContext(); - friend void cleanUpContext(); - static void createContext(); - }; + private: + static IMutableContext* currentContext; + friend IMutableContext& getCurrentMutableContext(); + friend void cleanUpContext(); + static void createContext(); +}; - inline IMutableContext& getCurrentMutableContext() - { - if( !IMutableContext::currentContext ) - IMutableContext::createContext(); - return *IMutableContext::currentContext; - } - - inline IContext& getCurrentContext() - { - return getCurrentMutableContext(); - } - - void cleanUpContext(); +inline IMutableContext& getCurrentMutableContext() { + if (!IMutableContext::currentContext) IMutableContext::createContext(); + return *IMutableContext::currentContext; } +inline IContext& getCurrentContext() { return getCurrentMutableContext(); } + +void cleanUpContext(); +} // namespace Catch + // end catch_context.h // start catch_debugger.h namespace Catch { - bool isDebuggerActive(); +bool isDebuggerActive(); } #ifdef CATCH_PLATFORM_MAC - #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ +#define CATCH_TRAP() __asm__("int $3\n" : :) /* NOLINT */ #elif defined(CATCH_PLATFORM_LINUX) - // If we can use inline assembler, do it because this allows us to break - // directly at the location of the failing check instead of breaking inside - // raise() called from it, i.e. one stack frame below. - #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) - #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ - #else // Fall back to the generic way. - #include +// If we can use inline assembler, do it because this allows us to break +// directly at the location of the failing check instead of breaking inside +// raise() called from it, i.e. one stack frame below. +#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) +#define CATCH_TRAP() asm volatile("int $3") /* NOLINT */ +#else // Fall back to the generic way. +#include - #define CATCH_TRAP() raise(SIGTRAP) - #endif +#define CATCH_TRAP() raise(SIGTRAP) +#endif #elif defined(_MSC_VER) - #define CATCH_TRAP() __debugbreak() +#define CATCH_TRAP() __debugbreak() #elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_TRAP() DebugBreak() +extern "C" __declspec(dllimport) void __stdcall DebugBreak(); +#define CATCH_TRAP() DebugBreak() #endif #ifdef CATCH_TRAP - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } +#define CATCH_BREAK_INTO_DEBUGGER() \ + if (Catch::isDebuggerActive()) { CATCH_TRAP(); } #else - namespace Catch { - inline void doNothing() {} - } - #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing() +namespace Catch { +inline void doNothing() {} +} // namespace Catch +#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing() #endif // end catch_debugger.h @@ -5502,16 +5678,16 @@ namespace Catch { // start catch_windows_h_proxy.h - #if defined(CATCH_PLATFORM_WINDOWS) #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX +#define CATCH_DEFINED_NOMINMAX +#define NOMINMAX #endif -#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN +#if !defined(WIN32_LEAN_AND_MEAN) && \ + !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +#define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #endif #ifdef __AFXDLL @@ -5521,63 +5697,62 @@ namespace Catch { #endif #ifdef CATCH_DEFINED_NOMINMAX -# undef NOMINMAX +#undef NOMINMAX #endif #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN #endif -#endif // defined(CATCH_PLATFORM_WINDOWS) +#endif // defined(CATCH_PLATFORM_WINDOWS) // end catch_windows_h_proxy.h -#if defined( CATCH_CONFIG_WINDOWS_SEH ) +#if defined(CATCH_CONFIG_WINDOWS_SEH) namespace Catch { - struct FatalConditionHandler { +struct FatalConditionHandler { + static LONG CALLBACK + handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + FatalConditionHandler(); + static void reset(); + ~FatalConditionHandler(); - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); - FatalConditionHandler(); - static void reset(); - ~FatalConditionHandler(); + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; +}; - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; +} // namespace Catch -} // namespace Catch - -#elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) +#elif defined(CATCH_CONFIG_POSIX_SIGNALS) #include namespace Catch { - struct FatalConditionHandler { +struct FatalConditionHandler { + static bool isSet; + static struct sigaction oldSigActions[]; + static stack_t oldSigStack; + static char altStackMem[]; - static bool isSet; - static struct sigaction oldSigActions[]; - static stack_t oldSigStack; - static char altStackMem[]; + static void handleSignal(int sig); - static void handleSignal( int sig ); + FatalConditionHandler(); + ~FatalConditionHandler(); + static void reset(); +}; - FatalConditionHandler(); - ~FatalConditionHandler(); - static void reset(); - }; - -} // namespace Catch +} // namespace Catch #else namespace Catch { - struct FatalConditionHandler { - void reset(); - }; -} +struct FatalConditionHandler { + void reset(); +}; +} // namespace Catch #endif @@ -5586,363 +5761,354 @@ namespace Catch { namespace Catch { - struct IMutableContext; +struct IMutableContext; - /////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// - class RunContext : public IResultCapture, public IRunner { +class RunContext : public IResultCapture, public IRunner { + public: + RunContext(RunContext const&) = delete; + RunContext& operator=(RunContext const&) = delete; - public: - RunContext( RunContext const& ) = delete; - RunContext& operator =( RunContext const& ) = delete; + explicit RunContext(IConfigPtr const& _config, + IStreamingReporterPtr&& reporter); - explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ); + ~RunContext() override; - ~RunContext() override; + void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, + std::size_t groupsCount); + void testGroupEnded(std::string const& testSpec, Totals const& totals, + std::size_t groupIndex, std::size_t groupsCount); - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ); - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ); + Totals runTest(TestCase const& testCase); - Totals runTest(TestCase const& testCase); + IConfigPtr config() const; + IStreamingReporter& reporter() const; - IConfigPtr config() const; - IStreamingReporter& reporter() const; + public: // IResultCapture + // Assertion handlers + void handleExpr(AssertionInfo const& info, ITransientExpression const& expr, + AssertionReaction& reaction) override; + void handleMessage(AssertionInfo const& info, ResultWas::OfType resultType, + StringRef const& message, + AssertionReaction& reaction) override; + void handleUnexpectedExceptionNotThrown(AssertionInfo const& info, + AssertionReaction& reaction) override; + void handleUnexpectedInflightException(AssertionInfo const& info, + std::string const& message, + AssertionReaction& reaction) override; + void handleIncomplete(AssertionInfo const& info) override; + void handleNonExpr(AssertionInfo const& info, ResultWas::OfType resultType, + AssertionReaction& reaction) override; - public: // IResultCapture + bool sectionStarted(SectionInfo const& sectionInfo, + Counts& assertions) override; - // Assertion handlers - void handleExpr - ( AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction ) override; - void handleMessage - ( AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef const& message, - AssertionReaction& reaction ) override; - void handleUnexpectedExceptionNotThrown - ( AssertionInfo const& info, - AssertionReaction& reaction ) override; - void handleUnexpectedInflightException - ( AssertionInfo const& info, - std::string const& message, - AssertionReaction& reaction ) override; - void handleIncomplete - ( AssertionInfo const& info ) override; - void handleNonExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - AssertionReaction &reaction ) override; + void sectionEnded(SectionEndInfo const& endInfo) override; + void sectionEndedEarly(SectionEndInfo const& endInfo) override; - bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; + auto acquireGeneratorTracker(SourceLineInfo const& lineInfo) + -> IGeneratorTracker& override; - void sectionEnded( SectionEndInfo const& endInfo ) override; - void sectionEndedEarly( SectionEndInfo const& endInfo ) override; + void benchmarkStarting(BenchmarkInfo const& info) override; + void benchmarkEnded(BenchmarkStats const& stats) override; - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; + void pushScopedMessage(MessageInfo const& message) override; + void popScopedMessage(MessageInfo const& message) override; - void benchmarkStarting( BenchmarkInfo const& info ) override; - void benchmarkEnded( BenchmarkStats const& stats ) override; + std::string getCurrentTestName() const override; - void pushScopedMessage( MessageInfo const& message ) override; - void popScopedMessage( MessageInfo const& message ) override; + const AssertionResult* getLastResult() const override; - std::string getCurrentTestName() const override; + void exceptionEarlyReported() override; - const AssertionResult* getLastResult() const override; + void handleFatalErrorCondition(StringRef message) override; - void exceptionEarlyReported() override; + bool lastAssertionPassed() override; - void handleFatalErrorCondition( StringRef message ) override; + void assertionPassed() override; - bool lastAssertionPassed() override; + public: + // !TBD We need to do this another way! + bool aborting() const final; - void assertionPassed() override; + private: + void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); + void invokeActiveTestCase(); - public: - // !TBD We need to do this another way! - bool aborting() const final; + void resetAssertionInfo(); + bool testForMissingAssertions(Counts& assertions); - private: + void assertionEnded(AssertionResult const& result); + void reportExpr(AssertionInfo const& info, ResultWas::OfType resultType, + ITransientExpression const* expr, bool negated); - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); - void invokeActiveTestCase(); + void populateReaction(AssertionReaction& reaction); - void resetAssertionInfo(); - bool testForMissingAssertions( Counts& assertions ); + private: + void handleUnfinishedSections(); - void assertionEnded( AssertionResult const& result ); - void reportExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - ITransientExpression const *expr, - bool negated ); + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase = nullptr; + ITracker* m_testCaseTracker; + Option m_lastResult; - void populateReaction( AssertionReaction& reaction ); + IConfigPtr m_config; + Totals m_totals; + IStreamingReporterPtr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + bool m_lastAssertionPassed = false; + bool m_shouldReportUnexpected = true; + bool m_includeSuccessfulResults; +}; - private: - - void handleUnfinishedSections(); - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase = nullptr; - ITracker* m_testCaseTracker; - Option m_lastResult; - - IConfigPtr m_config; - Totals m_totals; - IStreamingReporterPtr m_reporter; - std::vector m_messages; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - bool m_lastAssertionPassed = false; - bool m_shouldReportUnexpected = true; - bool m_includeSuccessfulResults; - }; - -} // end namespace Catch +} // end namespace Catch // end catch_run_context.h namespace Catch { - namespace { - auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { - expr.streamReconstructedExpression( os ); - return os; - } - } +namespace { +auto operator<<(std::ostream& os, ITransientExpression const& expr) + -> std::ostream& { + expr.streamReconstructedExpression(os); + return os; +} +} // namespace - LazyExpression::LazyExpression( bool isNegated ) - : m_isNegated( isNegated ) - {} +LazyExpression::LazyExpression(bool isNegated) : m_isNegated(isNegated) {} - LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} +LazyExpression::LazyExpression(LazyExpression const& other) + : m_isNegated(other.m_isNegated) {} - LazyExpression::operator bool() const { - return m_transientExpression != nullptr; - } +LazyExpression::operator bool() const { + return m_transientExpression != nullptr; +} - auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { - if( lazyExpr.m_isNegated ) - os << "!"; +auto operator<<(std::ostream& os, LazyExpression const& lazyExpr) + -> std::ostream& { + if (lazyExpr.m_isNegated) os << "!"; - if( lazyExpr ) { - if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) - os << "(" << *lazyExpr.m_transientExpression << ")"; - else - os << *lazyExpr.m_transientExpression; - } - else { - os << "{** error - unchecked empty expression requested **}"; - } - return os; - } + if (lazyExpr) { + if (lazyExpr.m_isNegated && + lazyExpr.m_transientExpression->isBinaryExpression()) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; +} - AssertionHandler::AssertionHandler - ( StringRef const& macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, - m_resultCapture( getResultCapture() ) - {} +AssertionHandler::AssertionHandler(StringRef const& macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition) + : m_assertionInfo{macroName, lineInfo, capturedExpression, + resultDisposition}, + m_resultCapture(getResultCapture()) {} - void AssertionHandler::handleExpr( ITransientExpression const& expr ) { - m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); - } - void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) { - m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); - } +void AssertionHandler::handleExpr(ITransientExpression const& expr) { + m_resultCapture.handleExpr(m_assertionInfo, expr, m_reaction); +} +void AssertionHandler::handleMessage(ResultWas::OfType resultType, + StringRef const& message) { + m_resultCapture.handleMessage(m_assertionInfo, resultType, message, + m_reaction); +} - auto AssertionHandler::allowThrows() const -> bool { - return getCurrentContext().getConfig()->allowThrows(); - } +auto AssertionHandler::allowThrows() const -> bool { + return getCurrentContext().getConfig()->allowThrows(); +} - void AssertionHandler::complete() { - setCompleted(); - if( m_reaction.shouldDebugBreak ) { +void AssertionHandler::complete() { + setCompleted(); + if (m_reaction.shouldDebugBreak) { + // If you find your debugger stopping you here then go one level up on the + // call-stack for the code that caused it (typically a failed assertion) - // If you find your debugger stopping you here then go one level up on the - // call-stack for the code that caused it (typically a failed assertion) - - // (To go back to the test and change execution, jump over the throw, next) - CATCH_BREAK_INTO_DEBUGGER(); - } - if (m_reaction.shouldThrow) { + // (To go back to the test and change execution, jump over the throw, next) + CATCH_BREAK_INTO_DEBUGGER(); + } + if (m_reaction.shouldThrow) { #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - throw Catch::TestFailureException(); + throw Catch::TestFailureException(); #else - CATCH_ERROR( "Test failure requires aborting test!" ); + CATCH_ERROR("Test failure requires aborting test!"); #endif - } - } - void AssertionHandler::setCompleted() { - m_completed = true; - } + } +} +void AssertionHandler::setCompleted() { m_completed = true; } - void AssertionHandler::handleUnexpectedInflightException() { - m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction ); - } +void AssertionHandler::handleUnexpectedInflightException() { + m_resultCapture.handleUnexpectedInflightException( + m_assertionInfo, Catch::translateActiveException(), m_reaction); +} - void AssertionHandler::handleExceptionThrownAsExpected() { - m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); - } - void AssertionHandler::handleExceptionNotThrownAsExpected() { - m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); - } +void AssertionHandler::handleExceptionThrownAsExpected() { + m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); +} +void AssertionHandler::handleExceptionNotThrownAsExpected() { + m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); +} - void AssertionHandler::handleUnexpectedExceptionNotThrown() { - m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction ); - } +void AssertionHandler::handleUnexpectedExceptionNotThrown() { + m_resultCapture.handleUnexpectedExceptionNotThrown(m_assertionInfo, + m_reaction); +} - void AssertionHandler::handleThrowingCallSkipped() { - m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); - } +void AssertionHandler::handleThrowingCallSkipped() { + m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); +} - // This is the overload that takes a string and infers the Equals matcher from it - // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp - void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) { - handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); - } +// This is the overload that takes a string and infers the Equals matcher from +// it The more general overload, that takes any string matcher, is in +// catch_capture_matchers.cpp +void handleExceptionMatchExpr(AssertionHandler& handler, std::string const& str, + StringRef const& matcherString) { + handleExceptionMatchExpr(handler, Matchers::Equals(str), matcherString); +} -} // namespace Catch +} // namespace Catch // end catch_assertionhandler.cpp // start catch_assertionresult.cpp namespace Catch { - AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): - lazyExpression(_lazyExpression), - resultType(_resultType) {} +AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, + LazyExpression const& _lazyExpression) + : lazyExpression(_lazyExpression), resultType(_resultType) {} - std::string AssertionResultData::reconstructExpression() const { - - if( reconstructedExpression.empty() ) { - if( lazyExpression ) { - ReusableStringStream rss; - rss << lazyExpression; - reconstructedExpression = rss.str(); - } - } - return reconstructedExpression; +std::string AssertionResultData::reconstructExpression() const { + if (reconstructedExpression.empty()) { + if (lazyExpression) { + ReusableStringStream rss; + rss << lazyExpression; + reconstructedExpression = rss.str(); } + } + return reconstructedExpression; +} - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} +AssertionResult::AssertionResult(AssertionInfo const& info, + AssertionResultData const& data) + : m_info(info), m_resultData(data) {} - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } +// Result was a success +bool AssertionResult::succeeded() const { + return Catch::isOk(m_resultData.resultType); +} - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } +// Result was a success, or failure is suppressed +bool AssertionResult::isOk() const { + return Catch::isOk(m_resultData.resultType) || + shouldSuppressFailure(m_info.resultDisposition); +} - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } +ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; +} - bool AssertionResult::hasExpression() const { - return m_info.capturedExpression[0] != 0; - } +bool AssertionResult::hasExpression() const { + return m_info.capturedExpression[0] != 0; +} - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } +bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); +} - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return "!(" + m_info.capturedExpression + ")"; - else - return m_info.capturedExpression; - } +std::string AssertionResult::getExpression() const { + if (isFalseTest(m_info.resultDisposition)) + return "!(" + m_info.capturedExpression + ")"; + else + return m_info.capturedExpression; +} - std::string AssertionResult::getExpressionInMacro() const { - std::string expr; - if( m_info.macroName[0] == 0 ) - expr = m_info.capturedExpression; - else { - expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); - expr += m_info.macroName; - expr += "( "; - expr += m_info.capturedExpression; - expr += " )"; - } - return expr; - } +std::string AssertionResult::getExpressionInMacro() const { + std::string expr; + if (m_info.macroName[0] == 0) + expr = m_info.capturedExpression; + else { + expr.reserve(m_info.macroName.size() + m_info.capturedExpression.size() + + 4); + expr += m_info.macroName; + expr += "( "; + expr += m_info.capturedExpression; + expr += " )"; + } + return expr; +} - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } +bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); +} - std::string AssertionResult::getExpandedExpression() const { - std::string expr = m_resultData.reconstructExpression(); - return expr.empty() - ? getExpression() - : expr; - } +std::string AssertionResult::getExpandedExpression() const { + std::string expr = m_resultData.reconstructExpression(); + return expr.empty() ? getExpression() : expr; +} - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } +std::string AssertionResult::getMessage() const { return m_resultData.message; } +SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; +} - StringRef AssertionResult::getTestMacroName() const { - return m_info.macroName; - } +StringRef AssertionResult::getTestMacroName() const { return m_info.macroName; } -} // end namespace Catch +} // end namespace Catch // end catch_assertionresult.cpp // start catch_benchmark.cpp namespace Catch { - auto BenchmarkLooper::getResolution() -> uint64_t { - return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); - } +auto BenchmarkLooper::getResolution() -> uint64_t { + return getEstimatedClockResolution() * + getCurrentContext().getConfig()->benchmarkResolutionMultiple(); +} - void BenchmarkLooper::reportStart() { - getResultCapture().benchmarkStarting( { m_name } ); - } - auto BenchmarkLooper::needsMoreIterations() -> bool { - auto elapsed = m_timer.getElapsedNanoseconds(); +void BenchmarkLooper::reportStart() { + getResultCapture().benchmarkStarting({m_name}); +} +auto BenchmarkLooper::needsMoreIterations() -> bool { + auto elapsed = m_timer.getElapsedNanoseconds(); - // Exponentially increasing iterations until we're confident in our timer resolution - if( elapsed < m_resolution ) { - m_iterationsToRun *= 10; - return true; - } + // Exponentially increasing iterations until we're confident in our timer + // resolution + if (elapsed < m_resolution) { + m_iterationsToRun *= 10; + return true; + } - getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); - return false; - } + getResultCapture().benchmarkEnded({{m_name}, m_count, elapsed}); + return false; +} -} // end namespace Catch +} // end namespace Catch // end catch_benchmark.cpp // start catch_capture_matchers.cpp namespace Catch { - using StringMatcher = Matchers::Impl::MatcherBase; +using StringMatcher = Matchers::Impl::MatcherBase; - // This is the general overload that takes a any string matcher - // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers - // the Equals matcher (so the header does not mention matchers) - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { - std::string exceptionMessage = Catch::translateActiveException(); - MatchExpr expr( exceptionMessage, matcher, matcherString ); - handler.handleExpr( expr ); - } +// This is the general overload that takes a any string matcher +// There is another overload, in catch_assertionhandler.h/.cpp, that only takes +// a string and infers the Equals matcher (so the header does not mention +// matchers) +void handleExceptionMatchExpr(AssertionHandler& handler, + StringMatcher const& matcher, + StringRef const& matcherString) { + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr(exceptionMessage, matcher, + matcherString); + handler.handleExpr(expr); +} -} // namespace Catch +} // namespace Catch // end catch_capture_matchers.cpp // start catch_commandline.cpp @@ -5950,12 +6116,14 @@ namespace Catch { // start catch_clara.h -// Use Catch's value for console width (store Clara's off to the side, if present) +// Use Catch's value for console width (store Clara's off to the side, if +// present) #ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH \ + CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH #endif -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - 1 #ifdef __clang__ #pragma clang diagnostic push @@ -5974,13 +6142,13 @@ namespace Catch { // Clara v1.1.5 - #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 #endif #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH \ + CATCH_CLARA_CONFIG_CONSOLE_WIDTH #endif #ifndef CLARA_CONFIG_OPTIONAL_TYPE @@ -6003,7 +6171,6 @@ namespace Catch { // // This project is hosted at https://github.com/philsquared/textflowcpp - #include #include #include @@ -6018,1176 +6185,1180 @@ namespace clara { namespace TextFlow { inline auto isWhitespace(char c) -> bool { - static std::string chars = " \t\n\r"; - return chars.find(c) != std::string::npos; + static std::string chars = " \t\n\r"; + return chars.find(c) != std::string::npos; } inline auto isBreakableBefore(char c) -> bool { - static std::string chars = "[({<|"; - return chars.find(c) != std::string::npos; + static std::string chars = "[({<|"; + return chars.find(c) != std::string::npos; } inline auto isBreakableAfter(char c) -> bool { - static std::string chars = "])}>.,:;*+-=&/\\"; - return chars.find(c) != std::string::npos; + static std::string chars = "])}>.,:;*+-=&/\\"; + return chars.find(c) != std::string::npos; } class Columns; class Column { - std::vector m_strings; - size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; - size_t m_indent = 0; - size_t m_initialIndent = std::string::npos; + std::vector m_strings; + size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t m_indent = 0; + size_t m_initialIndent = std::string::npos; -public: - class iterator { - friend Column; + public: + class iterator { + friend Column; - Column const& m_column; - size_t m_stringIndex = 0; - size_t m_pos = 0; + Column const& m_column; + size_t m_stringIndex = 0; + size_t m_pos = 0; - size_t m_len = 0; - size_t m_end = 0; - bool m_suffix = false; + size_t m_len = 0; + size_t m_end = 0; + bool m_suffix = false; - iterator(Column const& column, size_t stringIndex) - : m_column(column), - m_stringIndex(stringIndex) {} + iterator(Column const& column, size_t stringIndex) + : m_column(column), m_stringIndex(stringIndex) {} - auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } + auto line() const -> std::string const& { + return m_column.m_strings[m_stringIndex]; + } - auto isBoundary(size_t at) const -> bool { - assert(at > 0); - assert(at <= line().size()); + auto isBoundary(size_t at) const -> bool { + assert(at > 0); + assert(at <= line().size()); - return at == line().size() || - (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || - isBreakableBefore(line()[at]) || - isBreakableAfter(line()[at - 1]); - } + return at == line().size() || + (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || + isBreakableBefore(line()[at]) || isBreakableAfter(line()[at - 1]); + } - void calcLength() { - assert(m_stringIndex < m_column.m_strings.size()); + void calcLength() { + assert(m_stringIndex < m_column.m_strings.size()); - m_suffix = false; - auto width = m_column.m_width - indent(); - m_end = m_pos; - while (m_end < line().size() && line()[m_end] != '\n') - ++m_end; + m_suffix = false; + auto width = m_column.m_width - indent(); + m_end = m_pos; + while (m_end < line().size() && line()[m_end] != '\n') ++m_end; - if (m_end < m_pos + width) { - m_len = m_end - m_pos; - } else { - size_t len = width; - while (len > 0 && !isBoundary(m_pos + len)) - --len; - while (len > 0 && isWhitespace(line()[m_pos + len - 1])) - --len; + if (m_end < m_pos + width) { + m_len = m_end - m_pos; + } else { + size_t len = width; + while (len > 0 && !isBoundary(m_pos + len)) --len; + while (len > 0 && isWhitespace(line()[m_pos + len - 1])) --len; - if (len > 0) { - m_len = len; - } else { - m_suffix = true; - m_len = width - 1; - } - } - } + if (len > 0) { + m_len = len; + } else { + m_suffix = true; + m_len = width - 1; + } + } + } - auto indent() const -> size_t { - auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; - return initial == std::string::npos ? m_column.m_indent : initial; - } + auto indent() const -> size_t { + auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent + : std::string::npos; + return initial == std::string::npos ? m_column.m_indent : initial; + } - auto addIndentAndSuffix(std::string const &plain) const -> std::string { - return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); - } + auto addIndentAndSuffix(std::string const& plain) const -> std::string { + return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); + } - public: - using difference_type = std::ptrdiff_t; - using value_type = std::string; - using pointer = value_type * ; - using reference = value_type & ; - using iterator_category = std::forward_iterator_tag; + public: + using difference_type = std::ptrdiff_t; + using value_type = std::string; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::forward_iterator_tag; - explicit iterator(Column const& column) : m_column(column) { - assert(m_column.m_width > m_column.m_indent); - assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent); - calcLength(); - if (m_len == 0) - m_stringIndex++; // Empty string - } + explicit iterator(Column const& column) : m_column(column) { + assert(m_column.m_width > m_column.m_indent); + assert(m_column.m_initialIndent == std::string::npos || + m_column.m_width > m_column.m_initialIndent); + calcLength(); + if (m_len == 0) m_stringIndex++; // Empty string + } - auto operator *() const -> std::string { - assert(m_stringIndex < m_column.m_strings.size()); - assert(m_pos <= m_end); - return addIndentAndSuffix(line().substr(m_pos, m_len)); - } + auto operator*() const -> std::string { + assert(m_stringIndex < m_column.m_strings.size()); + assert(m_pos <= m_end); + return addIndentAndSuffix(line().substr(m_pos, m_len)); + } - auto operator ++() -> iterator& { - m_pos += m_len; - if (m_pos < line().size() && line()[m_pos] == '\n') - m_pos += 1; - else - while (m_pos < line().size() && isWhitespace(line()[m_pos])) - ++m_pos; + auto operator++() -> iterator& { + m_pos += m_len; + if (m_pos < line().size() && line()[m_pos] == '\n') + m_pos += 1; + else + while (m_pos < line().size() && isWhitespace(line()[m_pos])) ++m_pos; - if (m_pos == line().size()) { - m_pos = 0; - ++m_stringIndex; - } - if (m_stringIndex < m_column.m_strings.size()) - calcLength(); - return *this; - } - auto operator ++(int) -> iterator { - iterator prev(*this); - operator++(); - return prev; - } + if (m_pos == line().size()) { + m_pos = 0; + ++m_stringIndex; + } + if (m_stringIndex < m_column.m_strings.size()) calcLength(); + return *this; + } + auto operator++(int) -> iterator { + iterator prev(*this); + operator++(); + return prev; + } - auto operator ==(iterator const& other) const -> bool { - return - m_pos == other.m_pos && - m_stringIndex == other.m_stringIndex && - &m_column == &other.m_column; - } - auto operator !=(iterator const& other) const -> bool { - return !operator==(other); - } - }; - using const_iterator = iterator; + auto operator==(iterator const& other) const -> bool { + return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; + } + auto operator!=(iterator const& other) const -> bool { + return !operator==(other); + } + }; + using const_iterator = iterator; - explicit Column(std::string const& text) { m_strings.push_back(text); } + explicit Column(std::string const& text) { m_strings.push_back(text); } - auto width(size_t newWidth) -> Column& { - assert(newWidth > 0); - m_width = newWidth; - return *this; - } - auto indent(size_t newIndent) -> Column& { - m_indent = newIndent; - return *this; - } - auto initialIndent(size_t newIndent) -> Column& { - m_initialIndent = newIndent; - return *this; - } + auto width(size_t newWidth) -> Column& { + assert(newWidth > 0); + m_width = newWidth; + return *this; + } + auto indent(size_t newIndent) -> Column& { + m_indent = newIndent; + return *this; + } + auto initialIndent(size_t newIndent) -> Column& { + m_initialIndent = newIndent; + return *this; + } - auto width() const -> size_t { return m_width; } - auto begin() const -> iterator { return iterator(*this); } - auto end() const -> iterator { return { *this, m_strings.size() }; } + auto width() const -> size_t { return m_width; } + auto begin() const -> iterator { return iterator(*this); } + auto end() const -> iterator { return {*this, m_strings.size()}; } - inline friend std::ostream& operator << (std::ostream& os, Column const& col) { - bool first = true; - for (auto line : col) { - if (first) - first = false; - else - os << "\n"; - os << line; - } - return os; - } + inline friend std::ostream& operator<<(std::ostream& os, Column const& col) { + bool first = true; + for (auto line : col) { + if (first) + first = false; + else + os << "\n"; + os << line; + } + return os; + } - auto operator + (Column const& other)->Columns; + auto operator+(Column const& other) -> Columns; - auto toString() const -> std::string { - std::ostringstream oss; - oss << *this; - return oss.str(); - } + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } }; class Spacer : public Column { - -public: - explicit Spacer(size_t spaceWidth) : Column("") { - width(spaceWidth); - } + public: + explicit Spacer(size_t spaceWidth) : Column("") { width(spaceWidth); } }; class Columns { - std::vector m_columns; + std::vector m_columns; -public: + public: + class iterator { + friend Columns; + struct EndTag {}; - class iterator { - friend Columns; - struct EndTag {}; + std::vector const& m_columns; + std::vector m_iterators; + size_t m_activeIterators; - std::vector const& m_columns; - std::vector m_iterators; - size_t m_activeIterators; + iterator(Columns const& columns, EndTag) + : m_columns(columns.m_columns), m_activeIterators(0) { + m_iterators.reserve(m_columns.size()); - iterator(Columns const& columns, EndTag) - : m_columns(columns.m_columns), - m_activeIterators(0) { - m_iterators.reserve(m_columns.size()); + for (auto const& col : m_columns) m_iterators.push_back(col.end()); + } - for (auto const& col : m_columns) - m_iterators.push_back(col.end()); - } + public: + using difference_type = std::ptrdiff_t; + using value_type = std::string; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::forward_iterator_tag; - public: - using difference_type = std::ptrdiff_t; - using value_type = std::string; - using pointer = value_type * ; - using reference = value_type & ; - using iterator_category = std::forward_iterator_tag; + explicit iterator(Columns const& columns) + : m_columns(columns.m_columns), m_activeIterators(m_columns.size()) { + m_iterators.reserve(m_columns.size()); - explicit iterator(Columns const& columns) - : m_columns(columns.m_columns), - m_activeIterators(m_columns.size()) { - m_iterators.reserve(m_columns.size()); + for (auto const& col : m_columns) m_iterators.push_back(col.begin()); + } - for (auto const& col : m_columns) - m_iterators.push_back(col.begin()); - } + auto operator==(iterator const& other) const -> bool { + return m_iterators == other.m_iterators; + } + auto operator!=(iterator const& other) const -> bool { + return m_iterators != other.m_iterators; + } + auto operator*() const -> std::string { + std::string row, padding; - auto operator ==(iterator const& other) const -> bool { - return m_iterators == other.m_iterators; - } - auto operator !=(iterator const& other) const -> bool { - return m_iterators != other.m_iterators; - } - auto operator *() const -> std::string { - std::string row, padding; + for (size_t i = 0; i < m_columns.size(); ++i) { + auto width = m_columns[i].width(); + if (m_iterators[i] != m_columns[i].end()) { + std::string col = *m_iterators[i]; + row += padding + col; + if (col.size() < width) + padding = std::string(width - col.size(), ' '); + else + padding = ""; + } else { + padding += std::string(width, ' '); + } + } + return row; + } + auto operator++() -> iterator& { + for (size_t i = 0; i < m_columns.size(); ++i) { + if (m_iterators[i] != m_columns[i].end()) ++m_iterators[i]; + } + return *this; + } + auto operator++(int) -> iterator { + iterator prev(*this); + operator++(); + return prev; + } + }; + using const_iterator = iterator; - for (size_t i = 0; i < m_columns.size(); ++i) { - auto width = m_columns[i].width(); - if (m_iterators[i] != m_columns[i].end()) { - std::string col = *m_iterators[i]; - row += padding + col; - if (col.size() < width) - padding = std::string(width - col.size(), ' '); - else - padding = ""; - } else { - padding += std::string(width, ' '); - } - } - return row; - } - auto operator ++() -> iterator& { - for (size_t i = 0; i < m_columns.size(); ++i) { - if (m_iterators[i] != m_columns[i].end()) - ++m_iterators[i]; - } - return *this; - } - auto operator ++(int) -> iterator { - iterator prev(*this); - operator++(); - return prev; - } - }; - using const_iterator = iterator; + auto begin() const -> iterator { return iterator(*this); } + auto end() const -> iterator { return {*this, iterator::EndTag()}; } - auto begin() const -> iterator { return iterator(*this); } - auto end() const -> iterator { return { *this, iterator::EndTag() }; } + auto operator+=(Column const& col) -> Columns& { + m_columns.push_back(col); + return *this; + } + auto operator+(Column const& col) -> Columns { + Columns combined = *this; + combined += col; + return combined; + } - auto operator += (Column const& col) -> Columns& { - m_columns.push_back(col); - return *this; - } - auto operator + (Column const& col) -> Columns { - Columns combined = *this; - combined += col; - return combined; - } + inline friend std::ostream& operator<<(std::ostream& os, + Columns const& cols) { + bool first = true; + for (auto line : cols) { + if (first) + first = false; + else + os << "\n"; + os << line; + } + return os; + } - inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) { - - bool first = true; - for (auto line : cols) { - if (first) - first = false; - else - os << "\n"; - os << line; - } - return os; - } - - auto toString() const -> std::string { - std::ostringstream oss; - oss << *this; - return oss.str(); - } + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } }; -inline auto Column::operator + (Column const& other) -> Columns { - Columns cols; - cols += *this; - cols += other; - return cols; -} +inline auto Column::operator+(Column const& other) -> Columns { + Columns cols; + cols += *this; + cols += other; + return cols; } +} // namespace TextFlow -} -} +} // namespace clara +} // namespace Catch // ----------- end of #include from clara_textflow.hpp ----------- // ........... back in clara.hpp -#include +#include #include #include -#include +#include -#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#if !defined(CATCH_PLATFORM_WINDOWS) && \ + (defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || \ + defined(_MSC_VER)) #define CATCH_PLATFORM_WINDOWS #endif -namespace Catch { namespace clara { +namespace Catch { +namespace clara { namespace detail { - // Traits for extracting arg and return type of lambdas (for single argument lambdas) - template - struct UnaryLambdaTraits : UnaryLambdaTraits {}; +// Traits for extracting arg and return type of lambdas (for single argument +// lambdas) +template +struct UnaryLambdaTraits : UnaryLambdaTraits {}; - template - struct UnaryLambdaTraits { - static const bool isValid = false; - }; +template +struct UnaryLambdaTraits { + static const bool isValid = false; +}; - template - struct UnaryLambdaTraits { - static const bool isValid = true; - using ArgType = typename std::remove_const::type>::type; - using ReturnType = ReturnT; - }; +template +struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = typename std::remove_const< + typename std::remove_reference::type>::type; + using ReturnType = ReturnT; +}; - class TokenStream; +class TokenStream; - // Transport for raw args (copied from main args, or supplied via init list for testing) - class Args { - friend TokenStream; - std::string m_exeName; - std::vector m_args; +// Transport for raw args (copied from main args, or supplied via init list for +// testing) +class Args { + friend TokenStream; + std::string m_exeName; + std::vector m_args; - public: - Args( int argc, char const* const* argv ) - : m_exeName(argv[0]), - m_args(argv + 1, argv + argc) {} + public: + Args(int argc, char const* const* argv) + : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {} - Args( std::initializer_list args ) - : m_exeName( *args.begin() ), - m_args( args.begin()+1, args.end() ) - {} + Args(std::initializer_list args) + : m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {} - auto exeName() const -> std::string { - return m_exeName; - } - }; + auto exeName() const -> std::string { return m_exeName; } +}; - // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string - // may encode an option + its argument if the : or = form is used - enum class TokenType { - Option, Argument - }; - struct Token { - TokenType type; - std::string token; - }; +// Wraps a token coming from a token stream. These may not directly correspond +// to strings as a single string may encode an option + its argument if the : or +// = form is used +enum class TokenType { Option, Argument }; +struct Token { + TokenType type; + std::string token; +}; - inline auto isOptPrefix( char c ) -> bool { - return c == '-' +inline auto isOptPrefix(char c) -> bool { + return c == '-' #ifdef CATCH_PLATFORM_WINDOWS - || c == '/' + || c == '/' #endif - ; - } + ; +} - // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled - class TokenStream { - using Iterator = std::vector::const_iterator; - Iterator it; - Iterator itEnd; - std::vector m_tokenBuffer; +// Abstracts iterators into args as a stream of tokens, with option arguments +// uniformly handled +class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; - void loadBuffer() { - m_tokenBuffer.resize( 0 ); + void loadBuffer() { + m_tokenBuffer.resize(0); - // Skip any empty strings - while( it != itEnd && it->empty() ) - ++it; + // Skip any empty strings + while (it != itEnd && it->empty()) ++it; - if( it != itEnd ) { - auto const &next = *it; - if( isOptPrefix( next[0] ) ) { - auto delimiterPos = next.find_first_of( " :=" ); - if( delimiterPos != std::string::npos ) { - m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); - m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); - } else { - if( next[1] != '-' && next.size() > 2 ) { - std::string opt = "- "; - for( size_t i = 1; i < next.size(); ++i ) { - opt[1] = next[i]; - m_tokenBuffer.push_back( { TokenType::Option, opt } ); - } - } else { - m_tokenBuffer.push_back( { TokenType::Option, next } ); - } - } - } else { - m_tokenBuffer.push_back( { TokenType::Argument, next } ); - } + if (it != itEnd) { + auto const& next = *it; + if (isOptPrefix(next[0])) { + auto delimiterPos = next.find_first_of(" :="); + if (delimiterPos != std::string::npos) { + m_tokenBuffer.push_back( + {TokenType::Option, next.substr(0, delimiterPos)}); + m_tokenBuffer.push_back( + {TokenType::Argument, next.substr(delimiterPos + 1)}); + } else { + if (next[1] != '-' && next.size() > 2) { + std::string opt = "- "; + for (size_t i = 1; i < next.size(); ++i) { + opt[1] = next[i]; + m_tokenBuffer.push_back({TokenType::Option, opt}); } + } else { + m_tokenBuffer.push_back({TokenType::Option, next}); + } } - - public: - explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} - - TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { - loadBuffer(); - } - - explicit operator bool() const { - return !m_tokenBuffer.empty() || it != itEnd; - } - - auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } - - auto operator*() const -> Token { - assert( !m_tokenBuffer.empty() ); - return m_tokenBuffer.front(); - } - - auto operator->() const -> Token const * { - assert( !m_tokenBuffer.empty() ); - return &m_tokenBuffer.front(); - } - - auto operator++() -> TokenStream & { - if( m_tokenBuffer.size() >= 2 ) { - m_tokenBuffer.erase( m_tokenBuffer.begin() ); - } else { - if( it != itEnd ) - ++it; - loadBuffer(); - } - return *this; - } - }; - - class ResultBase { - public: - enum Type { - Ok, LogicError, RuntimeError - }; - - protected: - ResultBase( Type type ) : m_type( type ) {} - virtual ~ResultBase() = default; - - virtual void enforceOk() const = 0; - - Type m_type; - }; - - template - class ResultValueBase : public ResultBase { - public: - auto value() const -> T const & { - enforceOk(); - return m_value; - } - - protected: - ResultValueBase( Type type ) : ResultBase( type ) {} - - ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { - if( m_type == ResultBase::Ok ) - new( &m_value ) T( other.m_value ); - } - - ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { - new( &m_value ) T( value ); - } - - auto operator=( ResultValueBase const &other ) -> ResultValueBase & { - if( m_type == ResultBase::Ok ) - m_value.~T(); - ResultBase::operator=(other); - if( m_type == ResultBase::Ok ) - new( &m_value ) T( other.m_value ); - return *this; - } - - ~ResultValueBase() override { - if( m_type == Ok ) - m_value.~T(); - } - - union { - T m_value; - }; - }; - - template<> - class ResultValueBase : public ResultBase { - protected: - using ResultBase::ResultBase; - }; - - template - class BasicResult : public ResultValueBase { - public: - template - explicit BasicResult( BasicResult const &other ) - : ResultValueBase( other.type() ), - m_errorMessage( other.errorMessage() ) - { - assert( type() != ResultBase::Ok ); - } - - template - static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } - static auto ok() -> BasicResult { return { ResultBase::Ok }; } - static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } - static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } - - explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } - - protected: - void enforceOk() const override { - - // Errors shouldn't reach this point, but if they do - // the actual error message will be in m_errorMessage - assert( m_type != ResultBase::LogicError ); - assert( m_type != ResultBase::RuntimeError ); - if( m_type != ResultBase::Ok ) - std::abort(); - } - - std::string m_errorMessage; // Only populated if resultType is an error - - BasicResult( ResultBase::Type type, std::string const &message ) - : ResultValueBase(type), - m_errorMessage(message) - { - assert( m_type != ResultBase::Ok ); - } - - using ResultValueBase::ResultValueBase; - using ResultBase::m_type; - }; - - enum class ParseResultType { - Matched, NoMatch, ShortCircuitAll, ShortCircuitSame - }; - - class ParseState { - public: - - ParseState( ParseResultType type, TokenStream const &remainingTokens ) - : m_type(type), - m_remainingTokens( remainingTokens ) - {} - - auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } - - private: - ParseResultType m_type; - TokenStream m_remainingTokens; - }; - - using Result = BasicResult; - using ParserResult = BasicResult; - using InternalParseResult = BasicResult; - - struct HelpColumns { - std::string left; - std::string right; - }; - - template - inline auto convertInto( std::string const &source, T& target ) -> ParserResult { - std::stringstream ss; - ss << source; - ss >> target; - if( ss.fail() ) - return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); - else - return ParserResult::ok( ParseResultType::Matched ); + } else { + m_tokenBuffer.push_back({TokenType::Argument, next}); + } } - inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { - target = source; - return ParserResult::ok( ParseResultType::Matched ); - } - inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { - std::string srcLC = source; - std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); - if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") - target = true; - else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") - target = false; - else - return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); - return ParserResult::ok( ParseResultType::Matched ); + } + + public: + explicit TokenStream(Args const& args) + : TokenStream(args.m_args.begin(), args.m_args.end()) {} + + TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + loadBuffer(); + } + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } + + auto operator*() const -> Token { + assert(!m_tokenBuffer.empty()); + return m_tokenBuffer.front(); + } + + auto operator-> () const -> Token const* { + assert(!m_tokenBuffer.empty()); + return &m_tokenBuffer.front(); + } + + auto operator++() -> TokenStream& { + if (m_tokenBuffer.size() >= 2) { + m_tokenBuffer.erase(m_tokenBuffer.begin()); + } else { + if (it != itEnd) ++it; + loadBuffer(); } + return *this; + } +}; + +class ResultBase { + public: + enum Type { Ok, LogicError, RuntimeError }; + + protected: + ResultBase(Type type) : m_type(type) {} + virtual ~ResultBase() = default; + + virtual void enforceOk() const = 0; + + Type m_type; +}; + +template +class ResultValueBase : public ResultBase { + public: + auto value() const -> T const& { + enforceOk(); + return m_value; + } + + protected: + ResultValueBase(Type type) : ResultBase(type) {} + + ResultValueBase(ResultValueBase const& other) : ResultBase(other) { + if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value); + } + + ResultValueBase(Type, T const& value) : ResultBase(Ok) { + new (&m_value) T(value); + } + + auto operator=(ResultValueBase const& other) -> ResultValueBase& { + if (m_type == ResultBase::Ok) m_value.~T(); + ResultBase::operator=(other); + if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value); + return *this; + } + + ~ResultValueBase() override { + if (m_type == Ok) m_value.~T(); + } + + union { + T m_value; + }; +}; + +template <> +class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; +}; + +template +class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult(BasicResult const& other) + : ResultValueBase(other.type()), m_errorMessage(other.errorMessage()) { + assert(type() != ResultBase::Ok); + } + + template + static auto ok(U const& value) -> BasicResult { + return {ResultBase::Ok, value}; + } + static auto ok() -> BasicResult { return {ResultBase::Ok}; } + static auto logicError(std::string const& message) -> BasicResult { + return {ResultBase::LogicError, message}; + } + static auto runtimeError(std::string const& message) -> BasicResult { + return {ResultBase::RuntimeError, message}; + } + + explicit operator bool() const { return m_type == ResultBase::Ok; } + auto type() const -> ResultBase::Type { return m_type; } + auto errorMessage() const -> std::string { return m_errorMessage; } + + protected: + void enforceOk() const override { + // Errors shouldn't reach this point, but if they do + // the actual error message will be in m_errorMessage + assert(m_type != ResultBase::LogicError); + assert(m_type != ResultBase::RuntimeError); + if (m_type != ResultBase::Ok) std::abort(); + } + + std::string m_errorMessage; // Only populated if resultType is an error + + BasicResult(ResultBase::Type type, std::string const& message) + : ResultValueBase(type), m_errorMessage(message) { + assert(m_type != ResultBase::Ok); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; +}; + +enum class ParseResultType { + Matched, + NoMatch, + ShortCircuitAll, + ShortCircuitSame +}; + +class ParseState { + public: + ParseState(ParseResultType type, TokenStream const& remainingTokens) + : m_type(type), m_remainingTokens(remainingTokens) {} + + auto type() const -> ParseResultType { return m_type; } + auto remainingTokens() const -> TokenStream { return m_remainingTokens; } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; +}; + +using Result = BasicResult; +using ParserResult = BasicResult; +using InternalParseResult = BasicResult; + +struct HelpColumns { + std::string left; + std::string right; +}; + +template +inline auto convertInto(std::string const& source, T& target) -> ParserResult { + std::stringstream ss; + ss << source; + ss >> target; + if (ss.fail()) + return ParserResult::runtimeError("Unable to convert '" + source + + "' to destination type"); + else + return ParserResult::ok(ParseResultType::Matched); +} +inline auto convertInto(std::string const& source, std::string& target) + -> ParserResult { + target = source; + return ParserResult::ok(ParseResultType::Matched); +} +inline auto convertInto(std::string const& source, bool& target) + -> ParserResult { + std::string srcLC = source; + std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), + [](char c) { return static_cast(::tolower(c)); }); + if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || + srcLC == "on") + target = true; + else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || + srcLC == "off") + target = false; + else + return ParserResult::runtimeError( + "Expected a boolean value but did not recognise: '" + source + "'"); + return ParserResult::ok(ParseResultType::Matched); +} #ifdef CLARA_CONFIG_OPTIONAL_TYPE - template - inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE& target ) -> ParserResult { - T temp; - auto result = convertInto( source, temp ); - if( result ) - target = std::move(temp); - return result; - } -#endif // CLARA_CONFIG_OPTIONAL_TYPE +template +inline auto convertInto(std::string const& source, + CLARA_CONFIG_OPTIONAL_TYPE& target) -> ParserResult { + T temp; + auto result = convertInto(source, temp); + if (result) target = std::move(temp); + return result; +} +#endif // CLARA_CONFIG_OPTIONAL_TYPE - struct NonCopyable { - NonCopyable() = default; - NonCopyable( NonCopyable const & ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable &operator=( NonCopyable const & ) = delete; - NonCopyable &operator=( NonCopyable && ) = delete; - }; +struct NonCopyable { + NonCopyable() = default; + NonCopyable(NonCopyable const&) = delete; + NonCopyable(NonCopyable&&) = delete; + NonCopyable& operator=(NonCopyable const&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; +}; - struct BoundRef : NonCopyable { - virtual ~BoundRef() = default; - virtual auto isContainer() const -> bool { return false; } - virtual auto isFlag() const -> bool { return false; } - }; - struct BoundValueRefBase : BoundRef { - virtual auto setValue( std::string const &arg ) -> ParserResult = 0; - }; - struct BoundFlagRefBase : BoundRef { - virtual auto setFlag( bool flag ) -> ParserResult = 0; - virtual auto isFlag() const -> bool { return true; } - }; +struct BoundRef : NonCopyable { + virtual ~BoundRef() = default; + virtual auto isContainer() const -> bool { return false; } + virtual auto isFlag() const -> bool { return false; } +}; +struct BoundValueRefBase : BoundRef { + virtual auto setValue(std::string const& arg) -> ParserResult = 0; +}; +struct BoundFlagRefBase : BoundRef { + virtual auto setFlag(bool flag) -> ParserResult = 0; + virtual auto isFlag() const -> bool { return true; } +}; - template - struct BoundValueRef : BoundValueRefBase { - T &m_ref; +template +struct BoundValueRef : BoundValueRefBase { + T& m_ref; - explicit BoundValueRef( T &ref ) : m_ref( ref ) {} + explicit BoundValueRef(T& ref) : m_ref(ref) {} - auto setValue( std::string const &arg ) -> ParserResult override { - return convertInto( arg, m_ref ); - } - }; + auto setValue(std::string const& arg) -> ParserResult override { + return convertInto(arg, m_ref); + } +}; - template - struct BoundValueRef> : BoundValueRefBase { - std::vector &m_ref; +template +struct BoundValueRef> : BoundValueRefBase { + std::vector& m_ref; - explicit BoundValueRef( std::vector &ref ) : m_ref( ref ) {} + explicit BoundValueRef(std::vector& ref) : m_ref(ref) {} - auto isContainer() const -> bool override { return true; } + auto isContainer() const -> bool override { return true; } - auto setValue( std::string const &arg ) -> ParserResult override { - T temp; - auto result = convertInto( arg, temp ); - if( result ) - m_ref.push_back( temp ); - return result; - } - }; + auto setValue(std::string const& arg) -> ParserResult override { + T temp; + auto result = convertInto(arg, temp); + if (result) m_ref.push_back(temp); + return result; + } +}; - struct BoundFlagRef : BoundFlagRefBase { - bool &m_ref; +struct BoundFlagRef : BoundFlagRefBase { + bool& m_ref; - explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} + explicit BoundFlagRef(bool& ref) : m_ref(ref) {} - auto setFlag( bool flag ) -> ParserResult override { - m_ref = flag; - return ParserResult::ok( ParseResultType::Matched ); - } - }; + auto setFlag(bool flag) -> ParserResult override { + m_ref = flag; + return ParserResult::ok(ParseResultType::Matched); + } +}; - template - struct LambdaInvoker { - static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); +template +struct LambdaInvoker { + static_assert(std::is_same::value, + "Lambda must return void or clara::ParserResult"); - template - static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { - return lambda( arg ); - } - }; + template + static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult { + return lambda(arg); + } +}; - template<> - struct LambdaInvoker { - template - static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { - lambda( arg ); - return ParserResult::ok( ParseResultType::Matched ); - } - }; +template <> +struct LambdaInvoker { + template + static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult { + lambda(arg); + return ParserResult::ok(ParseResultType::Matched); + } +}; - template - inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { - ArgType temp{}; - auto result = convertInto( arg, temp ); - return !result - ? result - : LambdaInvoker::ReturnType>::invoke( lambda, temp ); - } +template +inline auto invokeLambda(L const& lambda, std::string const& arg) + -> ParserResult { + ArgType temp{}; + auto result = convertInto(arg, temp); + return !result + ? result + : LambdaInvoker::ReturnType>::invoke( + lambda, temp); +} - template - struct BoundLambda : BoundValueRefBase { - L m_lambda; +template +struct BoundLambda : BoundValueRefBase { + L m_lambda; - static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} + static_assert(UnaryLambdaTraits::isValid, + "Supplied lambda must take exactly one argument"); + explicit BoundLambda(L const& lambda) : m_lambda(lambda) {} - auto setValue( std::string const &arg ) -> ParserResult override { - return invokeLambda::ArgType>( m_lambda, arg ); - } - }; + auto setValue(std::string const& arg) -> ParserResult override { + return invokeLambda::ArgType>(m_lambda, arg); + } +}; - template - struct BoundFlagLambda : BoundFlagRefBase { - L m_lambda; +template +struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; - static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); + static_assert(UnaryLambdaTraits::isValid, + "Supplied lambda must take exactly one argument"); + static_assert( + std::is_same::ArgType, bool>::value, + "flags must be boolean"); - explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} + explicit BoundFlagLambda(L const& lambda) : m_lambda(lambda) {} - auto setFlag( bool flag ) -> ParserResult override { - return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); - } - }; + auto setFlag(bool flag) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( + m_lambda, flag); + } +}; - enum class Optionality { Optional, Required }; +enum class Optionality { Optional, Required }; - struct Parser; +struct Parser; - class ParserBase { - public: - virtual ~ParserBase() = default; - virtual auto validate() const -> Result { return Result::ok(); } - virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; - virtual auto cardinality() const -> size_t { return 1; } +class ParserBase { + public: + virtual ~ParserBase() = default; + virtual auto validate() const -> Result { return Result::ok(); } + virtual auto parse(std::string const& exeName, + TokenStream const& tokens) const + -> InternalParseResult = 0; + virtual auto cardinality() const -> size_t { return 1; } - auto parse( Args const &args ) const -> InternalParseResult { - return parse( args.exeName(), TokenStream( args ) ); - } - }; + auto parse(Args const& args) const -> InternalParseResult { + return parse(args.exeName(), TokenStream(args)); + } +}; - template - class ComposableParserImpl : public ParserBase { - public: - template - auto operator|( T const &other ) const -> Parser; +template +class ComposableParserImpl : public ParserBase { + public: + template + auto operator|(T const& other) const -> Parser; - template - auto operator+( T const &other ) const -> Parser; - }; + template + auto operator+(T const& other) const -> Parser; +}; - // Common code and state for Args and Opts - template - class ParserRefImpl : public ComposableParserImpl { - protected: - Optionality m_optionality = Optionality::Optional; - std::shared_ptr m_ref; - std::string m_hint; - std::string m_description; +// Common code and state for Args and Opts +template +class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + std::string m_hint; + std::string m_description; - explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} + explicit ParserRefImpl(std::shared_ptr const& ref) : m_ref(ref) {} - public: - template - ParserRefImpl( T &ref, std::string const &hint ) - : m_ref( std::make_shared>( ref ) ), - m_hint( hint ) - {} + public: + template + ParserRefImpl(T& ref, std::string const& hint) + : m_ref(std::make_shared>(ref)), m_hint(hint) {} - template - ParserRefImpl( LambdaT const &ref, std::string const &hint ) - : m_ref( std::make_shared>( ref ) ), - m_hint(hint) - {} + template + ParserRefImpl(LambdaT const& ref, std::string const& hint) + : m_ref(std::make_shared>(ref)), m_hint(hint) {} - auto operator()( std::string const &description ) -> DerivedT & { - m_description = description; - return static_cast( *this ); - } + auto operator()(std::string const& description) -> DerivedT& { + m_description = description; + return static_cast(*this); + } - auto optional() -> DerivedT & { - m_optionality = Optionality::Optional; - return static_cast( *this ); - }; + auto optional() -> DerivedT& { + m_optionality = Optionality::Optional; + return static_cast(*this); + }; - auto required() -> DerivedT & { - m_optionality = Optionality::Required; - return static_cast( *this ); - }; + auto required() -> DerivedT& { + m_optionality = Optionality::Required; + return static_cast(*this); + }; - auto isOptional() const -> bool { - return m_optionality == Optionality::Optional; - } + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } - auto cardinality() const -> size_t override { - if( m_ref->isContainer() ) - return 0; - else - return 1; - } + auto cardinality() const -> size_t override { + if (m_ref->isContainer()) + return 0; + else + return 1; + } - auto hint() const -> std::string { return m_hint; } - }; + auto hint() const -> std::string { return m_hint; } +}; - class ExeName : public ComposableParserImpl { - std::shared_ptr m_name; - std::shared_ptr m_ref; +class ExeName : public ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; - template - static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { - return std::make_shared>( lambda) ; - } + template + static auto makeRef(LambdaT const& lambda) + -> std::shared_ptr { + return std::make_shared>(lambda); + } - public: - ExeName() : m_name( std::make_shared( "" ) ) {} + public: + ExeName() : m_name(std::make_shared("")) {} - explicit ExeName( std::string &ref ) : ExeName() { - m_ref = std::make_shared>( ref ); - } + explicit ExeName(std::string& ref) : ExeName() { + m_ref = std::make_shared>(ref); + } - template - explicit ExeName( LambdaT const& lambda ) : ExeName() { - m_ref = std::make_shared>( lambda ); - } + template + explicit ExeName(LambdaT const& lambda) : ExeName() { + m_ref = std::make_shared>(lambda); + } - // The exe name is not parsed out of the normal tokens, but is handled specially - auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); - } + // The exe name is not parsed out of the normal tokens, but is handled + // specially + auto parse(std::string const&, TokenStream const& tokens) const + -> InternalParseResult override { + return InternalParseResult::ok( + ParseState(ParseResultType::NoMatch, tokens)); + } - auto name() const -> std::string { return *m_name; } - auto set( std::string const& newName ) -> ParserResult { + auto name() const -> std::string { return *m_name; } + auto set(std::string const& newName) -> ParserResult { + auto lastSlash = newName.find_last_of("\\/"); + auto filename = (lastSlash == std::string::npos) + ? newName + : newName.substr(lastSlash + 1); - auto lastSlash = newName.find_last_of( "\\/" ); - auto filename = ( lastSlash == std::string::npos ) - ? newName - : newName.substr( lastSlash+1 ); + *m_name = filename; + if (m_ref) + return m_ref->setValue(filename); + else + return ParserResult::ok(ParseResultType::Matched); + } +}; - *m_name = filename; - if( m_ref ) - return m_ref->setValue( filename ); - else - return ParserResult::ok( ParseResultType::Matched ); - } - }; +class Arg : public ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; - class Arg : public ParserRefImpl { - public: - using ParserRefImpl::ParserRefImpl; + auto parse(std::string const&, TokenStream const& tokens) const + -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) return InternalParseResult(validationResult); - auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { - auto validationResult = validate(); - if( !validationResult ) - return InternalParseResult( validationResult ); + auto remainingTokens = tokens; + auto const& token = *remainingTokens; + if (token.type != TokenType::Argument) + return InternalParseResult::ok( + ParseState(ParseResultType::NoMatch, remainingTokens)); - auto remainingTokens = tokens; - auto const &token = *remainingTokens; - if( token.type != TokenType::Argument ) - return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); + assert(!m_ref->isFlag()); + auto valueRef = static_cast(m_ref.get()); - assert( !m_ref->isFlag() ); - auto valueRef = static_cast( m_ref.get() ); + auto result = valueRef->setValue(remainingTokens->token); + if (!result) + return InternalParseResult(result); + else + return InternalParseResult::ok( + ParseState(ParseResultType::Matched, ++remainingTokens)); + } +}; - auto result = valueRef->setValue( remainingTokens->token ); - if( !result ) - return InternalParseResult( result ); - else - return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); - } - }; - - inline auto normaliseOpt( std::string const &optName ) -> std::string { +inline auto normaliseOpt(std::string const& optName) -> std::string { #ifdef CATCH_PLATFORM_WINDOWS - if( optName[0] == '/' ) - return "-" + optName.substr( 1 ); - else + if (optName[0] == '/') + return "-" + optName.substr(1); + else #endif - return optName; + return optName; +} + +class Opt : public ParserRefImpl { + protected: + std::vector m_optNames; + + public: + template + explicit Opt(LambdaT const& ref) + : ParserRefImpl(std::make_shared>(ref)) {} + + explicit Opt(bool& ref) + : ParserRefImpl(std::make_shared(ref)) {} + + template + Opt(LambdaT const& ref, std::string const& hint) : ParserRefImpl(ref, hint) {} + + template + Opt(T& ref, std::string const& hint) : ParserRefImpl(ref, hint) {} + + auto operator[](std::string const& optName) -> Opt& { + m_optNames.push_back(optName); + return *this; + } + + auto getHelpColumns() const -> std::vector { + std::ostringstream oss; + bool first = true; + for (auto const& opt : m_optNames) { + if (first) + first = false; + else + oss << ", "; + oss << opt; } + if (!m_hint.empty()) oss << " <" << m_hint << ">"; + return {{oss.str(), m_description}}; + } - class Opt : public ParserRefImpl { - protected: - std::vector m_optNames; + auto isMatch(std::string const& optToken) const -> bool { + auto normalisedToken = normaliseOpt(optToken); + for (auto const& name : m_optNames) { + if (normaliseOpt(name) == normalisedToken) return true; + } + return false; + } - public: - template - explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} + using ParserBase::parse; - explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} + auto parse(std::string const&, TokenStream const& tokens) const + -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) return InternalParseResult(validationResult); - template - Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - - template - Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - - auto operator[]( std::string const &optName ) -> Opt & { - m_optNames.push_back( optName ); - return *this; + auto remainingTokens = tokens; + if (remainingTokens && remainingTokens->type == TokenType::Option) { + auto const& token = *remainingTokens; + if (isMatch(token.token)) { + if (m_ref->isFlag()) { + auto flagRef = static_cast(m_ref.get()); + auto result = flagRef->setFlag(true); + if (!result) return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok( + ParseState(result.value(), remainingTokens)); + } else { + auto valueRef = static_cast(m_ref.get()); + ++remainingTokens; + if (!remainingTokens) + return InternalParseResult::runtimeError( + "Expected argument following " + token.token); + auto const& argToken = *remainingTokens; + if (argToken.type != TokenType::Argument) + return InternalParseResult::runtimeError( + "Expected argument following " + token.token); + auto result = valueRef->setValue(argToken.token); + if (!result) return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok( + ParseState(result.value(), remainingTokens)); } + return InternalParseResult::ok( + ParseState(ParseResultType::Matched, ++remainingTokens)); + } + } + return InternalParseResult::ok( + ParseState(ParseResultType::NoMatch, remainingTokens)); + } - auto getHelpColumns() const -> std::vector { - std::ostringstream oss; - bool first = true; - for( auto const &opt : m_optNames ) { - if (first) - first = false; - else - oss << ", "; - oss << opt; - } - if( !m_hint.empty() ) - oss << " <" << m_hint << ">"; - return { { oss.str(), m_description } }; - } - - auto isMatch( std::string const &optToken ) const -> bool { - auto normalisedToken = normaliseOpt( optToken ); - for( auto const &name : m_optNames ) { - if( normaliseOpt( name ) == normalisedToken ) - return true; - } - return false; - } - - using ParserBase::parse; - - auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - auto validationResult = validate(); - if( !validationResult ) - return InternalParseResult( validationResult ); - - auto remainingTokens = tokens; - if( remainingTokens && remainingTokens->type == TokenType::Option ) { - auto const &token = *remainingTokens; - if( isMatch(token.token ) ) { - if( m_ref->isFlag() ) { - auto flagRef = static_cast( m_ref.get() ); - auto result = flagRef->setFlag( true ); - if( !result ) - return InternalParseResult( result ); - if( result.value() == ParseResultType::ShortCircuitAll ) - return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); - } else { - auto valueRef = static_cast( m_ref.get() ); - ++remainingTokens; - if( !remainingTokens ) - return InternalParseResult::runtimeError( "Expected argument following " + token.token ); - auto const &argToken = *remainingTokens; - if( argToken.type != TokenType::Argument ) - return InternalParseResult::runtimeError( "Expected argument following " + token.token ); - auto result = valueRef->setValue( argToken.token ); - if( !result ) - return InternalParseResult( result ); - if( result.value() == ParseResultType::ShortCircuitAll ) - return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); - } - return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); - } - } - return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - } - - auto validate() const -> Result override { - if( m_optNames.empty() ) - return Result::logicError( "No options supplied to Opt" ); - for( auto const &name : m_optNames ) { - if( name.empty() ) - return Result::logicError( "Option name cannot be empty" ); + auto validate() const -> Result override { + if (m_optNames.empty()) + return Result::logicError("No options supplied to Opt"); + for (auto const& name : m_optNames) { + if (name.empty()) + return Result::logicError("Option name cannot be empty"); #ifdef CATCH_PLATFORM_WINDOWS - if( name[0] != '-' && name[0] != '/' ) - return Result::logicError( "Option name must begin with '-' or '/'" ); + if (name[0] != '-' && name[0] != '/') + return Result::logicError("Option name must begin with '-' or '/'"); #else - if( name[0] != '-' ) - return Result::logicError( "Option name must begin with '-'" ); + if (name[0] != '-') + return Result::logicError("Option name must begin with '-'"); #endif - } - return ParserRefImpl::validate(); - } - }; - - struct Help : Opt { - Help( bool &showHelpFlag ) - : Opt([&]( bool flag ) { - showHelpFlag = flag; - return ParserResult::ok( ParseResultType::ShortCircuitAll ); - }) - { - static_cast( *this ) - ("display usage information") - ["-?"]["-h"]["--help"] - .optional(); - } - }; - - struct Parser : ParserBase { - - mutable ExeName m_exeName; - std::vector m_options; - std::vector m_args; - - auto operator|=( ExeName const &exeName ) -> Parser & { - m_exeName = exeName; - return *this; - } - - auto operator|=( Arg const &arg ) -> Parser & { - m_args.push_back(arg); - return *this; - } - - auto operator|=( Opt const &opt ) -> Parser & { - m_options.push_back(opt); - return *this; - } - - auto operator|=( Parser const &other ) -> Parser & { - m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); - m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); - return *this; - } - - template - auto operator|( T const &other ) const -> Parser { - return Parser( *this ) |= other; - } - - // Forward deprecated interface with '+' instead of '|' - template - auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } - template - auto operator+( T const &other ) const -> Parser { return operator|( other ); } - - auto getHelpColumns() const -> std::vector { - std::vector cols; - for (auto const &o : m_options) { - auto childCols = o.getHelpColumns(); - cols.insert( cols.end(), childCols.begin(), childCols.end() ); - } - return cols; - } - - void writeToStream( std::ostream &os ) const { - if (!m_exeName.name().empty()) { - os << "usage:\n" << " " << m_exeName.name() << " "; - bool required = true, first = true; - for( auto const &arg : m_args ) { - if (first) - first = false; - else - os << " "; - if( arg.isOptional() && required ) { - os << "["; - required = false; - } - os << "<" << arg.hint() << ">"; - if( arg.cardinality() == 0 ) - os << " ... "; - } - if( !required ) - os << "]"; - if( !m_options.empty() ) - os << " options"; - os << "\n\nwhere options are:" << std::endl; - } - - auto rows = getHelpColumns(); - size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; - size_t optWidth = 0; - for( auto const &cols : rows ) - optWidth = (std::max)(optWidth, cols.left.size() + 2); - - optWidth = (std::min)(optWidth, consoleWidth/2); - - for( auto const &cols : rows ) { - auto row = - TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + - TextFlow::Spacer(4) + - TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); - os << row << std::endl; - } - } - - friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { - parser.writeToStream( os ); - return os; - } - - auto validate() const -> Result override { - for( auto const &opt : m_options ) { - auto result = opt.validate(); - if( !result ) - return result; - } - for( auto const &arg : m_args ) { - auto result = arg.validate(); - if( !result ) - return result; - } - return Result::ok(); - } - - using ParserBase::parse; - - auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - - struct ParserInfo { - ParserBase const* parser = nullptr; - size_t count = 0; - }; - const size_t totalParsers = m_options.size() + m_args.size(); - assert( totalParsers < 512 ); - // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do - ParserInfo parseInfos[512]; - - { - size_t i = 0; - for (auto const &opt : m_options) parseInfos[i++].parser = &opt; - for (auto const &arg : m_args) parseInfos[i++].parser = &arg; - } - - m_exeName.set( exeName ); - - auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); - while( result.value().remainingTokens() ) { - bool tokenParsed = false; - - for( size_t i = 0; i < totalParsers; ++i ) { - auto& parseInfo = parseInfos[i]; - if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { - result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); - if (!result) - return result; - if (result.value().type() != ParseResultType::NoMatch) { - tokenParsed = true; - ++parseInfo.count; - break; - } - } - } - - if( result.value().type() == ParseResultType::ShortCircuitAll ) - return result; - if( !tokenParsed ) - return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); - } - // !TBD Check missing required options - return result; - } - }; - - template - template - auto ComposableParserImpl::operator|( T const &other ) const -> Parser { - return Parser() | static_cast( *this ) | other; } -} // namespace detail + return ParserRefImpl::validate(); + } +}; + +struct Help : Opt { + Help(bool& showHelpFlag) + : Opt([&](bool flag) { + showHelpFlag = flag; + return ParserResult::ok(ParseResultType::ShortCircuitAll); + }) { + static_cast (*this)("display usage information")["-?"]["-h"]["--help"] + .optional(); + } +}; + +struct Parser : ParserBase { + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + auto operator|=(ExeName const& exeName) -> Parser& { + m_exeName = exeName; + return *this; + } + + auto operator|=(Arg const& arg) -> Parser& { + m_args.push_back(arg); + return *this; + } + + auto operator|=(Opt const& opt) -> Parser& { + m_options.push_back(opt); + return *this; + } + + auto operator|=(Parser const& other) -> Parser& { + m_options.insert(m_options.end(), other.m_options.begin(), + other.m_options.end()); + m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); + return *this; + } + + template + auto operator|(T const& other) const -> Parser { + return Parser(*this) |= other; + } + + // Forward deprecated interface with '+' instead of '|' + template + auto operator+=(T const& other) -> Parser& { + return operator|=(other); + } + template + auto operator+(T const& other) const -> Parser { + return operator|(other); + } + + auto getHelpColumns() const -> std::vector { + std::vector cols; + for (auto const& o : m_options) { + auto childCols = o.getHelpColumns(); + cols.insert(cols.end(), childCols.begin(), childCols.end()); + } + return cols; + } + + void writeToStream(std::ostream& os) const { + if (!m_exeName.name().empty()) { + os << "usage:\n" + << " " << m_exeName.name() << " "; + bool required = true, first = true; + for (auto const& arg : m_args) { + if (first) + first = false; + else + os << " "; + if (arg.isOptional() && required) { + os << "["; + required = false; + } + os << "<" << arg.hint() << ">"; + if (arg.cardinality() == 0) os << " ... "; + } + if (!required) os << "]"; + if (!m_options.empty()) os << " options"; + os << "\n\nwhere options are:" << std::endl; + } + + auto rows = getHelpColumns(); + size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; + size_t optWidth = 0; + for (auto const& cols : rows) + optWidth = (std::max)(optWidth, cols.left.size() + 2); + + optWidth = (std::min)(optWidth, consoleWidth / 2); + + for (auto const& cols : rows) { + auto row = + TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Spacer(4) + + TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + os << row << std::endl; + } + } + + friend auto operator<<(std::ostream& os, Parser const& parser) + -> std::ostream& { + parser.writeToStream(os); + return os; + } + + auto validate() const -> Result override { + for (auto const& opt : m_options) { + auto result = opt.validate(); + if (!result) return result; + } + for (auto const& arg : m_args) { + auto result = arg.validate(); + if (!result) return result; + } + return Result::ok(); + } + + using ParserBase::parse; + + auto parse(std::string const& exeName, TokenStream const& tokens) const + -> InternalParseResult override { + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + assert(totalParsers < 512); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want + // to do + ParserInfo parseInfos[512]; + + { + size_t i = 0; + for (auto const& opt : m_options) parseInfos[i++].parser = &opt; + for (auto const& arg : m_args) parseInfos[i++].parser = &arg; + } + + m_exeName.set(exeName); + + auto result = + InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + while (result.value().remainingTokens()) { + bool tokenParsed = false; + + for (size_t i = 0; i < totalParsers; ++i) { + auto& parseInfo = parseInfos[i]; + if (parseInfo.parser->cardinality() == 0 || + parseInfo.count < parseInfo.parser->cardinality()) { + result = parseInfo.parser->parse(exeName, + result.value().remainingTokens()); + if (!result) return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } + } + } + + if (result.value().type() == ParseResultType::ShortCircuitAll) + return result; + if (!tokenParsed) + return InternalParseResult::runtimeError( + "Unrecognised token: " + result.value().remainingTokens()->token); + } + // !TBD Check missing required options + return result; + } +}; + +template +template +auto ComposableParserImpl::operator|(T const& other) const -> Parser { + return Parser() | static_cast(*this) | other; +} +} // namespace detail // A Combined parser using detail::Parser; @@ -7213,7 +7384,8 @@ using detail::ParseResultType; // Result type for parser operation using detail::ParserResult; -}} // namespace Catch::clara +} // namespace clara +} // namespace Catch // end clara.hpp #ifdef __clang__ @@ -7222,212 +7394,193 @@ using detail::ParserResult; // Restore Clara's value for console width, if present #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH \ + CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #endif // end catch_clara.h namespace Catch { - clara::Parser makeCommandLineParser( ConfigData& config ); +clara::Parser makeCommandLineParser(ConfigData& config); -} // end namespace Catch +} // end namespace Catch // end catch_commandline.h -#include #include +#include namespace Catch { - clara::Parser makeCommandLineParser( ConfigData& config ) { +clara::Parser makeCommandLineParser(ConfigData& config) { + using namespace clara; - using namespace clara; + auto const setWarning = [&](std::string const& warning) { + auto warningSet = [&]() { + if (warning == "NoAssertions") return WarnAbout::NoAssertions; - auto const setWarning = [&]( std::string const& warning ) { - auto warningSet = [&]() { - if( warning == "NoAssertions" ) - return WarnAbout::NoAssertions; + if (warning == "NoTests") return WarnAbout::NoTests; - if ( warning == "NoTests" ) - return WarnAbout::NoTests; + return WarnAbout::Nothing; + }(); - return WarnAbout::Nothing; - }(); + if (warningSet == WarnAbout::Nothing) + return ParserResult::runtimeError("Unrecognised warning: '" + warning + + "'"); + config.warnings = + static_cast(config.warnings | warningSet); + return ParserResult::ok(ParseResultType::Matched); + }; + auto const loadTestNamesFromFile = [&](std::string const& filename) { + std::ifstream f(filename.c_str()); + if (!f.is_open()) + return ParserResult::runtimeError("Unable to load input file: '" + + filename + "'"); - if (warningSet == WarnAbout::Nothing) - return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); - config.warnings = static_cast( config.warnings | warningSet ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const loadTestNamesFromFile = [&]( std::string const& filename ) { - std::ifstream f( filename.c_str() ); - if( !f.is_open() ) - return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - config.testsOrTags.push_back( line + ',' ); - } - } - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setTestOrder = [&]( std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setRngSeed = [&]( std::string const& seed ) { - if( seed != "time" ) - return clara::detail::convertInto( seed, config.rngSeed ); - config.rngSeed = static_cast( std::time(nullptr) ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setColourUsage = [&]( std::string const& useColour ) { - auto mode = toLower( useColour ); - - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setWaitForKeypress = [&]( std::string const& keypress ) { - auto keypressLc = toLower( keypress ); - if( keypressLc == "start" ) - config.waitForKeypress = WaitForKeypress::BeforeStart; - else if( keypressLc == "exit" ) - config.waitForKeypress = WaitForKeypress::BeforeExit; - else if( keypressLc == "both" ) - config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; - else - return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setVerbosity = [&]( std::string const& verbosity ) { - auto lcVerbosity = toLower( verbosity ); - if( lcVerbosity == "quiet" ) - config.verbosity = Verbosity::Quiet; - else if( lcVerbosity == "normal" ) - config.verbosity = Verbosity::Normal; - else if( lcVerbosity == "high" ) - config.verbosity = Verbosity::High; - else - return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setReporter = [&]( std::string const& reporter ) { - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - - auto lcReporter = toLower( reporter ); - auto result = factories.find( lcReporter ); - - if( factories.end() != result ) - config.reporterName = lcReporter; - else - return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - - auto cli - = ExeName( config.processName ) - | Help( config.showHelp ) - | Opt( config.listTests ) - ["-l"]["--list-tests"] - ( "list all/matching test cases" ) - | Opt( config.listTags ) - ["-t"]["--list-tags"] - ( "list all/matching tags" ) - | Opt( config.showSuccessfulTests ) - ["-s"]["--success"] - ( "include successful tests in output" ) - | Opt( config.shouldDebugBreak ) - ["-b"]["--break"] - ( "break into debugger on failure" ) - | Opt( config.noThrow ) - ["-e"]["--nothrow"] - ( "skip exception tests" ) - | Opt( config.showInvisibles ) - ["-i"]["--invisibles"] - ( "show invisibles (tabs, newlines)" ) - | Opt( config.outputFilename, "filename" ) - ["-o"]["--out"] - ( "output filename" ) - | Opt( setReporter, "name" ) - ["-r"]["--reporter"] - ( "reporter to use (defaults to console)" ) - | Opt( config.name, "name" ) - ["-n"]["--name"] - ( "suite name" ) - | Opt( [&]( bool ){ config.abortAfter = 1; } ) - ["-a"]["--abort"] - ( "abort at first failure" ) - | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) - ["-x"]["--abortx"] - ( "abort after x failures" ) - | Opt( setWarning, "warning name" ) - ["-w"]["--warn"] - ( "enable warnings" ) - | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) - ["-d"]["--durations"] - ( "show test durations" ) - | Opt( loadTestNamesFromFile, "filename" ) - ["-f"]["--input-file"] - ( "load test names to run from a file" ) - | Opt( config.filenamesAsTags ) - ["-#"]["--filenames-as-tags"] - ( "adds a tag for the filename" ) - | Opt( config.sectionsToRun, "section name" ) - ["-c"]["--section"] - ( "specify section to run" ) - | Opt( setVerbosity, "quiet|normal|high" ) - ["-v"]["--verbosity"] - ( "set output verbosity" ) - | Opt( config.listTestNamesOnly ) - ["--list-test-names-only"] - ( "list all/matching test cases names only" ) - | Opt( config.listReporters ) - ["--list-reporters"] - ( "list all reporters" ) - | Opt( setTestOrder, "decl|lex|rand" ) - ["--order"] - ( "test case order (defaults to decl)" ) - | Opt( setRngSeed, "'time'|number" ) - ["--rng-seed"] - ( "set a specific seed for random numbers" ) - | Opt( setColourUsage, "yes|no" ) - ["--use-colour"] - ( "should output be colourised" ) - | Opt( config.libIdentify ) - ["--libidentify"] - ( "report name and version according to libidentify standard" ) - | Opt( setWaitForKeypress, "start|exit|both" ) - ["--wait-for-keypress"] - ( "waits for a keypress before exiting" ) - | Opt( config.benchmarkResolutionMultiple, "multiplier" ) - ["--benchmark-resolution-multiple"] - ( "multiple of clock resolution to run benchmarks" ) - - | Arg( config.testsOrTags, "test name|pattern|tags" ) - ( "which test or tests to use" ); - - return cli; + std::string line; + while (std::getline(f, line)) { + line = trim(line); + if (!line.empty() && !startsWith(line, '#')) { + if (!startsWith(line, '"')) line = '"' + line + '"'; + config.testsOrTags.push_back(line + ','); + } } + return ParserResult::ok(ParseResultType::Matched); + }; + auto const setTestOrder = [&](std::string const& order) { + if (startsWith("declared", order)) + config.runOrder = RunTests::InDeclarationOrder; + else if (startsWith("lexical", order)) + config.runOrder = RunTests::InLexicographicalOrder; + else if (startsWith("random", order)) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError("Unrecognised ordering: '" + + order + "'"); + return ParserResult::ok(ParseResultType::Matched); + }; + auto const setRngSeed = [&](std::string const& seed) { + if (seed != "time") return clara::detail::convertInto(seed, config.rngSeed); + config.rngSeed = static_cast(std::time(nullptr)); + return ParserResult::ok(ParseResultType::Matched); + }; + auto const setColourUsage = [&](std::string const& useColour) { + auto mode = toLower(useColour); -} // end namespace Catch + if (mode == "yes") + config.useColour = UseColour::Yes; + else if (mode == "no") + config.useColour = UseColour::No; + else if (mode == "auto") + config.useColour = UseColour::Auto; + else + return ParserResult::runtimeError( + "colour mode must be one of: auto, yes or no. '" + useColour + + "' not recognised"); + return ParserResult::ok(ParseResultType::Matched); + }; + auto const setWaitForKeypress = [&](std::string const& keypress) { + auto keypressLc = toLower(keypress); + if (keypressLc == "start") + config.waitForKeypress = WaitForKeypress::BeforeStart; + else if (keypressLc == "exit") + config.waitForKeypress = WaitForKeypress::BeforeExit; + else if (keypressLc == "both") + config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; + else + return ParserResult::runtimeError( + "keypress argument must be one of: start, exit or both. '" + + keypress + "' not recognised"); + return ParserResult::ok(ParseResultType::Matched); + }; + auto const setVerbosity = [&](std::string const& verbosity) { + auto lcVerbosity = toLower(verbosity); + if (lcVerbosity == "quiet") + config.verbosity = Verbosity::Quiet; + else if (lcVerbosity == "normal") + config.verbosity = Verbosity::Normal; + else if (lcVerbosity == "high") + config.verbosity = Verbosity::High; + else + return ParserResult::runtimeError("Unrecognised verbosity, '" + + verbosity + "'"); + return ParserResult::ok(ParseResultType::Matched); + }; + auto const setReporter = [&](std::string const& reporter) { + IReporterRegistry::FactoryMap const& factories = + getRegistryHub().getReporterRegistry().getFactories(); + + auto lcReporter = toLower(reporter); + auto result = factories.find(lcReporter); + + if (factories.end() != result) + config.reporterName = lcReporter; + else + return ParserResult::runtimeError( + "Unrecognized reporter, '" + reporter + + "'. Check available with --list-reporters"); + return ParserResult::ok(ParseResultType::Matched); + }; + + auto cli = + ExeName(config.processName) | Help(config.showHelp) | + Opt(config.listTests)["-l"]["--list-tests"]( + "list all/matching test cases") | + Opt(config.listTags)["-t"]["--list-tags"]("list all/matching tags") | + Opt(config.showSuccessfulTests)["-s"]["--success"]( + "include successful tests in output") | + Opt(config.shouldDebugBreak)["-b"]["--break"]( + "break into debugger on failure") | + Opt(config.noThrow)["-e"]["--nothrow"]("skip exception tests") | + Opt(config.showInvisibles)["-i"]["--invisibles"]( + "show invisibles (tabs, newlines)") | + Opt(config.outputFilename, "filename")["-o"]["--out"]("output filename") | + Opt(setReporter, + "name")["-r"]["--reporter"]("reporter to use (defaults to console)") | + Opt(config.name, "name")["-n"]["--name"]("suite name") | Opt([&](bool) { + config.abortAfter = 1; + })["-a"]["--abort"]("abort at first failure") | + Opt([&](int x) { config.abortAfter = x; }, + "no. failures")["-x"]["--abortx"]("abort after x failures") | + Opt(setWarning, "warning name")["-w"]["--warn"]("enable warnings") | + Opt( + [&](bool flag) { + config.showDurations = + flag ? ShowDurations::Always : ShowDurations::Never; + }, + "yes|no")["-d"]["--durations"]("show test durations") | + Opt(loadTestNamesFromFile, "filename")["-f"]["--input-file"]( + "load test names to run from a file") | + Opt(config.filenamesAsTags)["-#"]["--filenames-as-tags"]( + "adds a tag for the filename") | + Opt(config.sectionsToRun, + "section name")["-c"]["--section"]("specify section to run") | + Opt(setVerbosity, + "quiet|normal|high")["-v"]["--verbosity"]("set output verbosity") | + Opt(config.listTestNamesOnly)["--list-test-names-only"]( + "list all/matching test cases names only") | + Opt(config.listReporters)["--list-reporters"]("list all reporters") | + Opt(setTestOrder, + "decl|lex|rand")["--order"]("test case order (defaults to decl)") | + Opt(setRngSeed, "'time'|number")["--rng-seed"]( + "set a specific seed for random numbers") | + Opt(setColourUsage, + "yes|no")["--use-colour"]("should output be colourised") | + Opt(config.libIdentify)["--libidentify"]( + "report name and version according to libidentify standard") | + Opt(setWaitForKeypress, "start|exit|both")["--wait-for-keypress"]( + "waits for a keypress before exiting") | + Opt(config.benchmarkResolutionMultiple, + "multiplier")["--benchmark-resolution-multiple"]( + "multiple of clock resolution to run benchmarks") + + | Arg(config.testsOrTags, + "test name|pattern|tags")("which test or tests to use"); + + return cli; +} + +} // end namespace Catch // end catch_commandline.cpp // start catch_common.cpp @@ -7436,329 +7589,371 @@ namespace Catch { namespace Catch { - bool SourceLineInfo::empty() const noexcept { - return file[0] == '\0'; - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { - return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); - } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { - // We can assume that the same file will usually have the same pointer. - // Thus, if the pointers are the same, there is no point in calling the strcmp - return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0)); - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << '(' << info.line << ')'; -#else - os << info.file << ':' << info.line; -#endif - return os; - } - - std::string StreamEndStop::operator+() const { - return std::string(); - } - - NonCopyable::NonCopyable() = default; - NonCopyable::~NonCopyable() = default; - +bool SourceLineInfo::empty() const noexcept { return file[0] == '\0'; } +bool SourceLineInfo::operator==(SourceLineInfo const& other) const noexcept { + return line == other.line && + (file == other.file || std::strcmp(file, other.file) == 0); } +bool SourceLineInfo::operator<(SourceLineInfo const& other) const noexcept { + // We can assume that the same file will usually have the same pointer. + // Thus, if the pointers are the same, there is no point in calling the strcmp + return line < other.line || (line == other.line && file != other.file && + (std::strcmp(file, other.file) < 0)); +} + +std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info) { +#ifndef __GNUG__ + os << info.file << '(' << info.line << ')'; +#else + os << info.file << ':' << info.line; +#endif + return os; +} + +std::string StreamEndStop::operator+() const { return std::string(); } + +NonCopyable::NonCopyable() = default; +NonCopyable::~NonCopyable() = default; + +} // namespace Catch // end catch_common.cpp // start catch_config.cpp namespace Catch { - Config::Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - TestSpecParser parser(ITagAliasRegistry::get()); - if (data.testsOrTags.empty()) { - parser.parse("~[.]"); // All not hidden tests - } - else { - m_hasTestFilters = true; - for( auto const& testOrTags : data.testsOrTags ) - parser.parse( testOrTags ); - } - m_testSpec = parser.testSpec(); - } +Config::Config(ConfigData const& data) : m_data(data), m_stream(openStream()) { + TestSpecParser parser(ITagAliasRegistry::get()); + if (data.testsOrTags.empty()) { + parser.parse("~[.]"); // All not hidden tests + } else { + m_hasTestFilters = true; + for (auto const& testOrTags : data.testsOrTags) parser.parse(testOrTags); + } + m_testSpec = parser.testSpec(); +} - std::string const& Config::getFilename() const { - return m_data.outputFilename ; - } +std::string const& Config::getFilename() const { return m_data.outputFilename; } - bool Config::listTests() const { return m_data.listTests; } - bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool Config::listTags() const { return m_data.listTags; } - bool Config::listReporters() const { return m_data.listReporters; } +bool Config::listTests() const { return m_data.listTests; } +bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } +bool Config::listTags() const { return m_data.listTags; } +bool Config::listReporters() const { return m_data.listReporters; } - std::string Config::getProcessName() const { return m_data.processName; } - std::string const& Config::getReporterName() const { return m_data.reporterName; } +std::string Config::getProcessName() const { return m_data.processName; } +std::string const& Config::getReporterName() const { + return m_data.reporterName; +} - std::vector const& Config::getTestsOrTags() const { return m_data.testsOrTags; } - std::vector const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } +std::vector const& Config::getTestsOrTags() const { + return m_data.testsOrTags; +} +std::vector const& Config::getSectionsToRun() const { + return m_data.sectionsToRun; +} - TestSpec const& Config::testSpec() const { return m_testSpec; } - bool Config::hasTestFilters() const { return m_hasTestFilters; } +TestSpec const& Config::testSpec() const { return m_testSpec; } +bool Config::hasTestFilters() const { return m_hasTestFilters; } - bool Config::showHelp() const { return m_data.showHelp; } +bool Config::showHelp() const { return m_data.showHelp; } - // IConfig interface - bool Config::allowThrows() const { return !m_data.noThrow; } - std::ostream& Config::stream() const { return m_stream->stream(); } - std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } - bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } - bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } - bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } - ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } - RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } - unsigned int Config::rngSeed() const { return m_data.rngSeed; } - int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } - UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } - bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } - int Config::abortAfter() const { return m_data.abortAfter; } - bool Config::showInvisibles() const { return m_data.showInvisibles; } - Verbosity Config::verbosity() const { return m_data.verbosity; } +// IConfig interface +bool Config::allowThrows() const { return !m_data.noThrow; } +std::ostream& Config::stream() const { return m_stream->stream(); } +std::string Config::name() const { + return m_data.name.empty() ? m_data.processName : m_data.name; +} +bool Config::includeSuccessfulResults() const { + return m_data.showSuccessfulTests; +} +bool Config::warnAboutMissingAssertions() const { + return !!(m_data.warnings & WarnAbout::NoAssertions); +} +bool Config::warnAboutNoTests() const { + return !!(m_data.warnings & WarnAbout::NoTests); +} +ShowDurations::OrNot Config::showDurations() const { + return m_data.showDurations; +} +RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } +unsigned int Config::rngSeed() const { return m_data.rngSeed; } +int Config::benchmarkResolutionMultiple() const { + return m_data.benchmarkResolutionMultiple; +} +UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } +bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } +int Config::abortAfter() const { return m_data.abortAfter; } +bool Config::showInvisibles() const { return m_data.showInvisibles; } +Verbosity Config::verbosity() const { return m_data.verbosity; } - IStream const* Config::openStream() { - return Catch::makeStream(m_data.outputFilename); - } +IStream const* Config::openStream() { + return Catch::makeStream(m_data.outputFilename); +} -} // end namespace Catch +} // end namespace Catch // end catch_config.cpp // start catch_console_colour.cpp #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wexit-time-destructors" #endif // start catch_errno_guard.h namespace Catch { - class ErrnoGuard { - public: - ErrnoGuard(); - ~ErrnoGuard(); - private: - int m_oldErrno; - }; +class ErrnoGuard { + public: + ErrnoGuard(); + ~ErrnoGuard(); -} + private: + int m_oldErrno; +}; + +} // namespace Catch // end catch_errno_guard.h #include namespace Catch { - namespace { +namespace { - struct IColourImpl { - virtual ~IColourImpl() = default; - virtual void use( Colour::Code _colourCode ) = 0; - }; +struct IColourImpl { + virtual ~IColourImpl() = default; + virtual void use(Colour::Code _colourCode) = 0; +}; - struct NoColourImpl : IColourImpl { - void use( Colour::Code ) {} +struct NoColourImpl : IColourImpl { + void use(Colour::Code) {} - static IColourImpl* instance() { - static NoColourImpl s_instance; - return &s_instance; - } - }; + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } +}; - } // anon namespace -} // namespace Catch +} // namespace +} // namespace Catch -#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) -# ifdef CATCH_PLATFORM_WINDOWS -# define CATCH_CONFIG_COLOUR_WINDOWS -# else -# define CATCH_CONFIG_COLOUR_ANSI -# endif +#if !defined(CATCH_CONFIG_COLOUR_NONE) && \ + !defined(CATCH_CONFIG_COLOUR_WINDOWS) && \ + !defined(CATCH_CONFIG_COLOUR_ANSI) +#ifdef CATCH_PLATFORM_WINDOWS +#define CATCH_CONFIG_COLOUR_WINDOWS +#else +#define CATCH_CONFIG_COLOUR_ANSI +#endif #endif -#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// +#if defined( \ + CATCH_CONFIG_COLOUR_WINDOWS) ///////////////////////////////////////// namespace Catch { namespace { - class Win32ColourImpl : public IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); - originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); - } +class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)) { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + originalForegroundAttributes = + csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + originalBackgroundAttributes = + csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } - virtual void use( Colour::Code _colourCode ) override { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalForegroundAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); + virtual void use(Colour::Code _colourCode) override { + switch (_colourCode) { + case Colour::None: + return setTextAttribute(originalForegroundAttributes); + case Colour::White: + return setTextAttribute(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE); + case Colour::Red: + return setTextAttribute(FOREGROUND_RED); + case Colour::Green: + return setTextAttribute(FOREGROUND_GREEN); + case Colour::Blue: + return setTextAttribute(FOREGROUND_BLUE); + case Colour::Cyan: + return setTextAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN); + case Colour::Yellow: + return setTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN); + case Colour::Grey: + return setTextAttribute(0); - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::LightGrey: + return setTextAttribute(FOREGROUND_INTENSITY); + case Colour::BrightRed: + return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED); + case Colour::BrightGreen: + return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN); + case Colour::BrightWhite: + return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN | + FOREGROUND_RED | FOREGROUND_BLUE); + case Colour::BrightYellow: + return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED | + FOREGROUND_GREEN); - case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + case Colour::Bright: + CATCH_INTERNAL_ERROR("not a colour"); - default: - CATCH_ERROR( "Unknown colour requested" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); - } - HANDLE stdoutHandle; - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; - }; - - IColourImpl* platformColourInstance() { - static Win32ColourImpl s_instance; - - IConfigPtr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = UseColour::Yes; - return colourMode == UseColour::Yes - ? &s_instance - : NoColourImpl::instance(); + default: + CATCH_ERROR("Unknown colour requested"); } + } -} // end anon namespace -} // end namespace Catch + private: + void setTextAttribute(WORD _textAttribute) { + SetConsoleTextAttribute(stdoutHandle, + _textAttribute | originalBackgroundAttributes); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; +}; -#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// +IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + IConfigPtr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = + config ? config->useColour() : UseColour::Auto; + if (colourMode == UseColour::Auto) colourMode = UseColour::Yes; + return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance(); +} + +} // namespace +} // end namespace Catch + +#elif defined(CATCH_CONFIG_COLOUR_ANSI) ////////////////////////////////////// #include namespace Catch { namespace { - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) override { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0;34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); +// use POSIX/ ANSI console terminal codes +// Thanks to Adam Strzelecki for original contribution +// (http://github.com/nanoant) +// https://github.com/philsquared/Catch/pull/131 +class PosixColourImpl : public IColourImpl { + public: + virtual void use(Colour::Code _colourCode) override { + switch (_colourCode) { + case Colour::None: + case Colour::White: + return setColour("[0m"); + case Colour::Red: + return setColour("[0;31m"); + case Colour::Green: + return setColour("[0;32m"); + case Colour::Blue: + return setColour("[0;34m"); + case Colour::Cyan: + return setColour("[0;36m"); + case Colour::Yellow: + return setColour("[0;33m"); + case Colour::Grey: + return setColour("[1;30m"); - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - case Colour::BrightYellow: return setColour( "[1;33m" ); + case Colour::LightGrey: + return setColour("[0;37m"); + case Colour::BrightRed: + return setColour("[1;31m"); + case Colour::BrightGreen: + return setColour("[1;32m"); + case Colour::BrightWhite: + return setColour("[1;37m"); + case Colour::BrightYellow: + return setColour("[1;33m"); - case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); - default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); - } - } - static IColourImpl* instance() { - static PosixColourImpl s_instance; - return &s_instance; - } + case Colour::Bright: + CATCH_INTERNAL_ERROR("not a colour"); + default: + CATCH_INTERNAL_ERROR("Unknown colour requested"); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } - private: - void setColour( const char* _escapeCode ) { - Catch::cout() << '\033' << _escapeCode; - } - }; + private: + void setColour(const char* _escapeCode) { + Catch::cout() << '\033' << _escapeCode; + } +}; - bool useColourOnPlatform() { - return +bool useColourOnPlatform() { + return #ifdef CATCH_PLATFORM_MAC - !isDebuggerActive() && + !isDebuggerActive() && #endif #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) - isatty(STDOUT_FILENO) + isatty(STDOUT_FILENO) #else - false + false #endif - ; - } - IColourImpl* platformColourInstance() { - ErrnoGuard guard; - IConfigPtr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = useColourOnPlatform() - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? PosixColourImpl::instance() - : NoColourImpl::instance(); - } + ; +} +IColourImpl* platformColourInstance() { + ErrnoGuard guard; + IConfigPtr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = + config ? config->useColour() : UseColour::Auto; + if (colourMode == UseColour::Auto) + colourMode = useColourOnPlatform() ? UseColour::Yes : UseColour::No; + return colourMode == UseColour::Yes ? PosixColourImpl::instance() + : NoColourImpl::instance(); +} -} // end anon namespace -} // end namespace Catch +} // namespace +} // end namespace Catch #else // not Windows or ANSI /////////////////////////////////////////////// namespace Catch { - static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } +static IColourImpl* platformColourInstance() { + return NoColourImpl::instance(); +} -} // end namespace Catch +} // end namespace Catch -#endif // Windows/ ANSI/ None +#endif // Windows/ ANSI/ None namespace Catch { - Colour::Colour( Code _colourCode ) { use( _colourCode ); } - Colour::Colour( Colour&& rhs ) noexcept { - m_moved = rhs.m_moved; - rhs.m_moved = true; - } - Colour& Colour::operator=( Colour&& rhs ) noexcept { - m_moved = rhs.m_moved; - rhs.m_moved = true; - return *this; - } +Colour::Colour(Code _colourCode) { use(_colourCode); } +Colour::Colour(Colour&& rhs) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; +} +Colour& Colour::operator=(Colour&& rhs) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + return *this; +} - Colour::~Colour(){ if( !m_moved ) use( None ); } +Colour::~Colour() { + if (!m_moved) use(None); +} - void Colour::use( Code _colourCode ) { - static IColourImpl* impl = platformColourInstance(); - impl->use( _colourCode ); - } +void Colour::use(Code _colourCode) { + static IColourImpl* impl = platformColourInstance(); + impl->use(_colourCode); +} - std::ostream& operator << ( std::ostream& os, Colour const& ) { - return os; - } +std::ostream& operator<<(std::ostream& os, Colour const&) { return os; } -} // end namespace Catch +} // end namespace Catch #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif // end catch_console_colour.cpp @@ -7766,56 +7961,46 @@ namespace Catch { namespace Catch { - class Context : public IMutableContext, NonCopyable { +class Context : public IMutableContext, NonCopyable { + public: // IContext + virtual IResultCapture* getResultCapture() override { + return m_resultCapture; + } + virtual IRunner* getRunner() override { return m_runner; } - public: // IContext - virtual IResultCapture* getResultCapture() override { - return m_resultCapture; - } - virtual IRunner* getRunner() override { - return m_runner; - } + virtual IConfigPtr const& getConfig() const override { return m_config; } - virtual IConfigPtr const& getConfig() const override { - return m_config; - } + virtual ~Context() override; - virtual ~Context() override; + public: // IMutableContext + virtual void setResultCapture(IResultCapture* resultCapture) override { + m_resultCapture = resultCapture; + } + virtual void setRunner(IRunner* runner) override { m_runner = runner; } + virtual void setConfig(IConfigPtr const& config) override { + m_config = config; + } - public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) override { - m_resultCapture = resultCapture; - } - virtual void setRunner( IRunner* runner ) override { - m_runner = runner; - } - virtual void setConfig( IConfigPtr const& config ) override { - m_config = config; - } + friend IMutableContext& getCurrentMutableContext(); - friend IMutableContext& getCurrentMutableContext(); + private: + IConfigPtr m_config; + IRunner* m_runner = nullptr; + IResultCapture* m_resultCapture = nullptr; +}; - private: - IConfigPtr m_config; - IRunner* m_runner = nullptr; - IResultCapture* m_resultCapture = nullptr; - }; +IMutableContext* IMutableContext::currentContext = nullptr; - IMutableContext *IMutableContext::currentContext = nullptr; +void IMutableContext::createContext() { currentContext = new Context(); } - void IMutableContext::createContext() - { - currentContext = new Context(); - } - - void cleanUpContext() { - delete IMutableContext::currentContext; - IMutableContext::currentContext = nullptr; - } - IContext::~IContext() = default; - IMutableContext::~IMutableContext() = default; - Context::~Context() = default; +void cleanUpContext() { + delete IMutableContext::currentContext; + IMutableContext::currentContext = nullptr; } +IContext::~IContext() = default; +IMutableContext::~IMutableContext() = default; +Context::~Context() = default; +} // namespace Catch // end catch_context.cpp // start catch_debug_console.cpp @@ -7824,190 +8009,188 @@ namespace Catch { #include namespace Catch { - void writeToDebugConsole( std::string const& text ); +void writeToDebugConsole(std::string const& text); } // end catch_debug_console.h #ifdef CATCH_PLATFORM_WINDOWS - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } +namespace Catch { +void writeToDebugConsole(std::string const& text) { + ::OutputDebugStringA(text.c_str()); +} +} // namespace Catch #else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } +namespace Catch { +void writeToDebugConsole(std::string const& text) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; +} +} // namespace Catch -#endif // Platform +#endif // Platform // end catch_debug_console.cpp // start catch_debugger.cpp #ifdef CATCH_PLATFORM_MAC -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include namespace Catch { - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html +// The following function is taken directly from the following technical note: +// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ +// Returns true if the current process is being debugged (either +// running under the debugger or has a debugger attached post facto). +bool isDebuggerActive() { + int mib[4]; + struct kinfo_proc info; + std::size_t size; - int mib[4]; - struct kinfo_proc info; - std::size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. + info.kp_proc.p_flag = 0; - info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); + // Call sysctl. - // Call sysctl. + size = sizeof(info); + if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if " + "debugger is active **\n" + << std::endl; + return false; + } - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { - Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } + // We're being debugged if the P_TRACED flag is set. - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch + return ((info.kp_proc.p_flag & P_TRACED) != 0); +} +} // namespace Catch #elif defined(CATCH_PLATFORM_LINUX) - #include - #include +#include +#include - namespace Catch{ - // The standard POSIX way of detecting a debugger is to attempt to - // ptrace() the process, but this needs to be done from a child and not - // this process itself to still allow attaching to this process later - // if wanted, so is rather heavy. Under Linux we have the PID of the - // "debugger" (which doesn't need to be gdb, of course, it could also - // be strace, for example) in /proc/$PID/status, so just get it from - // there instead. - bool isDebuggerActive(){ - // Libstdc++ has a bug, where std::ifstream sets errno to 0 - // This way our users can properly assert over errno values - 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 ) { - // We're traced if the PID is not 0 and no other PID starts - // with 0 digit, so it's enough to check for just a single - // character. - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } +namespace Catch { +// The standard POSIX way of detecting a debugger is to attempt to +// ptrace() the process, but this needs to be done from a child and not +// this process itself to still allow attaching to this process later +// if wanted, so is rather heavy. Under Linux we have the PID of the +// "debugger" (which doesn't need to be gdb, of course, it could also +// be strace, for example) in /proc/$PID/status, so just get it from +// there instead. +bool isDebuggerActive() { + // Libstdc++ has a bug, where std::ifstream sets errno to 0 + // This way our users can properly assert over errno values + 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) { + // We're traced if the PID is not 0 and no other PID starts + // with 0 digit, so it's enough to check for just a single + // character. + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } - return false; - } - } // namespace Catch + return false; +} +} // namespace Catch #elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } +extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); +namespace Catch { +bool isDebuggerActive() { return IsDebuggerPresent() != 0; } +} // namespace Catch #elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } +extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); +namespace Catch { +bool isDebuggerActive() { return IsDebuggerPresent() != 0; } +} // namespace Catch #else - namespace Catch { - bool isDebuggerActive() { return false; } - } -#endif // Platform +namespace Catch { +bool isDebuggerActive() { return false; } +} // namespace Catch +#endif // Platform // end catch_debugger.cpp // start catch_decomposer.cpp namespace Catch { - ITransientExpression::~ITransientExpression() = default; +ITransientExpression::~ITransientExpression() = default; - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { - if( lhs.size() + rhs.size() < 40 && - lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos ) - os << lhs << " " << op << " " << rhs; - else - os << lhs << "\n" << op << "\n" << rhs; - } +void formatReconstructedExpression(std::ostream& os, std::string const& lhs, + StringRef op, std::string const& rhs) { + if (lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && + rhs.find('\n') == std::string::npos) + os << lhs << " " << op << " " << rhs; + else + os << lhs << "\n" << op << "\n" << rhs; } +} // namespace Catch // end catch_decomposer.cpp // start catch_enforce.cpp namespace Catch { -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) - [[noreturn]] - void throw_exception(std::exception const& e) { - Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; - std::terminate(); - } +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && \ + !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) +[[noreturn]] void throw_exception(std::exception const& e) { + Catch::cerr() + << "Catch will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; + std::terminate(); +} #endif -} // namespace Catch; +} // namespace Catch // end catch_enforce.cpp // start catch_errno_guard.cpp #include namespace Catch { - ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} - ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } -} +ErrnoGuard::ErrnoGuard() : m_oldErrno(errno) {} +ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } +} // namespace Catch // end catch_errno_guard.cpp // start catch_exception_translator_registry.cpp // start catch_exception_translator_registry.h -#include -#include #include +#include +#include namespace Catch { - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry(); - virtual void registerTranslator( const IExceptionTranslator* translator ); - virtual std::string translateActiveException() const override; - std::string tryTranslators() const; +class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry(); + virtual void registerTranslator(const IExceptionTranslator* translator); + virtual std::string translateActiveException() const override; + std::string tryTranslators() const; - private: - std::vector> m_translators; - }; -} + private: + std::vector> m_translators; +}; +} // namespace Catch // end catch_exception_translator_registry.h #ifdef __OBJC__ @@ -8016,229 +8199,227 @@ namespace Catch { namespace Catch { - ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { - } +ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {} - void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( std::unique_ptr( translator ) ); - } +void ExceptionTranslatorRegistry::registerTranslator( + const IExceptionTranslator* translator) { + m_translators.push_back( + std::unique_ptr(translator)); +} #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - std::string ExceptionTranslatorRegistry::translateActiveException() const { - try { +std::string ExceptionTranslatorRegistry::translateActiveException() const { + try { #ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::Detail::stringify( [exception description] ); - } + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } @catch (NSException* exception) { + return Catch::Detail::stringify([exception description]); + } #else - // Compiling a mixed mode project with MSVC means that CLR - // exceptions will be caught in (...) as well. However, these - // do not fill-in std::current_exception and thus lead to crash - // when attempting rethrow. - // /EHa switch also causes structured exceptions to be caught - // here, but they fill-in current_exception properly, so - // at worst the output should be a little weird, instead of - // causing a crash. - if (std::current_exception() == nullptr) { - return "Non C++ exception. Possibly a CLR exception."; - } - return tryTranslators(); + // Compiling a mixed mode project with MSVC means that CLR + // exceptions will be caught in (...) as well. However, these + // do not fill-in std::current_exception and thus lead to crash + // when attempting rethrow. + // /EHa switch also causes structured exceptions to be caught + // here, but they fill-in current_exception properly, so + // at worst the output should be a little weird, instead of + // causing a crash. + if (std::current_exception() == nullptr) { + return "Non C++ exception. Possibly a CLR exception."; + } + return tryTranslators(); #endif - } - catch( TestFailureException& ) { - std::rethrow_exception(std::current_exception()); - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return "Unknown exception"; - } - } - -#else // ^^ Exceptions are enabled // Exceptions are disabled vv - std::string ExceptionTranslatorRegistry::translateActiveException() const { - CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); - } -#endif - - std::string ExceptionTranslatorRegistry::tryTranslators() const { - if( m_translators.empty() ) - std::rethrow_exception(std::current_exception()); - else - return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); - } + } catch (TestFailureException&) { + std::rethrow_exception(std::current_exception()); + } catch (std::exception& ex) { return ex.what(); } catch (std::string& msg) { + return msg; + } catch (const char* msg) { return msg; } catch (...) { + return "Unknown exception"; + } } + +#else // ^^ Exceptions are enabled // Exceptions are disabled vv +std::string ExceptionTranslatorRegistry::translateActiveException() const { + CATCH_INTERNAL_ERROR( + "Attempted to translate active exception under " + "CATCH_CONFIG_DISABLE_EXCEPTIONS!"); +} +#endif + +std::string ExceptionTranslatorRegistry::tryTranslators() const { + if (m_translators.empty()) + std::rethrow_exception(std::current_exception()); + else + return m_translators[0]->translate(m_translators.begin() + 1, + m_translators.end()); +} +} // namespace Catch // end catch_exception_translator_registry.cpp // start catch_fatal_condition.cpp #if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif -#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) +#if defined(CATCH_CONFIG_WINDOWS_SEH) || defined(CATCH_CONFIG_POSIX_SIGNALS) namespace { - // Report the error condition - void reportFatal( char const * const message ) { - Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); - } +// Report the error condition +void reportFatal(char const* const message) { + Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( + message); } +} // namespace -#endif // signals/SEH handling +#endif // signals/SEH handling -#if defined( CATCH_CONFIG_WINDOWS_SEH ) +#if defined(CATCH_CONFIG_WINDOWS_SEH) namespace Catch { - struct SignalDefs { DWORD id; const char* name; }; +struct SignalDefs { + DWORD id; + const char* name; +}; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - static 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" }, - }; +// There is no 1-1 mapping between signals and windows exceptions. +// Windows can easily distinguish between SO and SigSegV, +// but SigInt, SigTerm, etc are handled differently. +static 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"}, +}; - LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (auto const& def : signalDefs) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { - reportFatal(def.name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; +LONG CALLBACK FatalConditionHandler::handleVectoredException( + PEXCEPTION_POINTERS ExceptionInfo) { + for (auto const& def : signalDefs) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { + reportFatal(def.name); } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; +} - FatalConditionHandler::FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = nullptr; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } +FatalConditionHandler::FatalConditionHandler() { + isSet = true; + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + exceptionHandlerHandle = nullptr; + // Register as first handler in current chain + exceptionHandlerHandle = + AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); +} - void FatalConditionHandler::reset() { - if (isSet) { - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = nullptr; - isSet = false; - } - } +void FatalConditionHandler::reset() { + if (isSet) { + RemoveVectoredExceptionHandler(exceptionHandlerHandle); + SetThreadStackGuarantee(&guaranteeSize); + exceptionHandlerHandle = nullptr; + isSet = false; + } +} - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } +FatalConditionHandler::~FatalConditionHandler() { reset(); } bool FatalConditionHandler::isSet = false; ULONG FatalConditionHandler::guaranteeSize = 0; PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; -} // namespace Catch +} // namespace Catch -#elif defined( CATCH_CONFIG_POSIX_SIGNALS ) +#elif defined(CATCH_CONFIG_POSIX_SIGNALS) namespace Catch { - struct SignalDefs { - int id; - const char* name; - }; +struct SignalDefs { + int id; + const char* name; +}; - // 32kb for the alternate stack seems to be sufficient. However, this value - // is experimentally determined, so that's not guaranteed. - constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; +// 32kb for the alternate stack seems to be sufficient. However, this value +// is experimentally determined, so that's not guaranteed. +constexpr static std::size_t sigStackSize = + 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; - static SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; +static SignalDefs signalDefs[] = { + {SIGINT, "SIGINT - Terminal interrupt signal"}, + {SIGILL, "SIGILL - Illegal instruction signal"}, + {SIGFPE, "SIGFPE - Floating point error signal"}, + {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, + {SIGTERM, "SIGTERM - Termination request signal"}, + {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}}; - void FatalConditionHandler::handleSignal( int sig ) { - char const * name = ""; - for (auto const& def : signalDefs) { - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); +void FatalConditionHandler::handleSignal(int sig) { + char const* name = ""; + for (auto const& def : signalDefs) { + if (sig == def.id) { + name = def.name; + break; } + } + reset(); + reportFatal(name); + raise(sig); +} - FatalConditionHandler::FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = sigStackSize; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { }; +FatalConditionHandler::FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = sigStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {}; - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } +} + +FatalConditionHandler::~FatalConditionHandler() { reset(); } + +void FatalConditionHandler::reset() { + if (isSet) { + // Set signals back to previous values -- hopefully nobody overwrote them in + // the meantime + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } +} - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } +bool FatalConditionHandler::isSet = false; +struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs) / + sizeof(SignalDefs)] = {}; +stack_t FatalConditionHandler::oldSigStack = {}; +char FatalConditionHandler::altStackMem[sigStackSize] = {}; - void FatalConditionHandler::reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[sigStackSize] = {}; - -} // namespace Catch +} // namespace Catch #else namespace Catch { - void FatalConditionHandler::reset() {} -} +void FatalConditionHandler::reset() {} +} // namespace Catch -#endif // signals/SEH handling +#endif // signals/SEH handling #if defined(__GNUC__) -# pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif // end catch_fatal_condition.cpp // start catch_generators.cpp @@ -8250,13 +8431,13 @@ namespace Catch { namespace Catch { - struct IConfig; +struct IConfig; - std::mt19937& rng(); - void seedRng( IConfig const& config ); - unsigned int rngSeed(); +std::mt19937& rng(); +void seedRng(IConfig const& config); +unsigned int rngSeed(); -} +} // namespace Catch // end catch_random_number_generator.h #include @@ -8268,62 +8449,62 @@ IGeneratorTracker::~IGeneratorTracker() {} namespace Generators { - GeneratorBase::~GeneratorBase() {} +GeneratorBase::~GeneratorBase() {} - std::vector randomiseIndices( size_t selectionSize, size_t sourceSize ) { +std::vector randomiseIndices(size_t selectionSize, size_t sourceSize) { + assert(selectionSize <= sourceSize); + std::vector indices; + indices.reserve(selectionSize); + std::uniform_int_distribution uid(0, sourceSize - 1); - assert( selectionSize <= sourceSize ); - std::vector indices; - indices.reserve( selectionSize ); - std::uniform_int_distribution uid( 0, sourceSize-1 ); + std::set seen; + // !TBD: improve this algorithm + while (indices.size() < selectionSize) { + auto index = uid(rng()); + if (seen.insert(index).second) indices.push_back(index); + } + return indices; +} - std::set seen; - // !TBD: improve this algorithm - while( indices.size() < selectionSize ) { - auto index = uid( rng() ); - if( seen.insert( index ).second ) - indices.push_back( index ); - } - return indices; - } +auto acquireGeneratorTracker(SourceLineInfo const& lineInfo) + -> IGeneratorTracker& { + return getResultCapture().acquireGeneratorTracker(lineInfo); +} - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { - return getResultCapture().acquireGeneratorTracker( lineInfo ); - } +template <> +auto all() -> Generator { + return range(std::numeric_limits::min(), + std::numeric_limits::max()); +} - template<> - auto all() -> Generator { - return range( std::numeric_limits::min(), std::numeric_limits::max() ); - } - -} // namespace Generators -} // namespace Catch +} // namespace Generators +} // namespace Catch // end catch_generators.cpp // start catch_interfaces_capture.cpp namespace Catch { - IResultCapture::~IResultCapture() = default; +IResultCapture::~IResultCapture() = default; } // end catch_interfaces_capture.cpp // start catch_interfaces_config.cpp namespace Catch { - IConfig::~IConfig() = default; +IConfig::~IConfig() = default; } // end catch_interfaces_config.cpp // start catch_interfaces_exception.cpp namespace Catch { - IExceptionTranslator::~IExceptionTranslator() = default; - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; -} +IExceptionTranslator::~IExceptionTranslator() = default; +IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; +} // namespace Catch // end catch_interfaces_exception.cpp // start catch_interfaces_registry_hub.cpp namespace Catch { - IRegistryHub::~IRegistryHub() = default; - IMutableRegistryHub::~IMutableRegistryHub() = default; -} +IRegistryHub::~IRegistryHub() = default; +IMutableRegistryHub::~IMutableRegistryHub() = default; +} // namespace Catch // end catch_interfaces_registry_hub.cpp // start catch_interfaces_reporter.cpp @@ -8331,164 +8512,146 @@ namespace Catch { namespace Catch { - class ListeningReporter : public IStreamingReporter { - using Reporters = std::vector; - Reporters m_listeners; - IStreamingReporterPtr m_reporter = nullptr; - ReporterPreferences m_preferences; +class ListeningReporter : public IStreamingReporter { + using Reporters = std::vector; + Reporters m_listeners; + IStreamingReporterPtr m_reporter = nullptr; + ReporterPreferences m_preferences; - public: - ListeningReporter(); + public: + ListeningReporter(); - void addListener( IStreamingReporterPtr&& listener ); - void addReporter( IStreamingReporterPtr&& reporter ); + void addListener(IStreamingReporterPtr&& listener); + void addReporter(IStreamingReporterPtr&& reporter); - public: // IStreamingReporter + public: // IStreamingReporter + ReporterPreferences getPreferences() const override; - ReporterPreferences getPreferences() const override; + void noMatchingTestCases(std::string const& spec) override; - void noMatchingTestCases( std::string const& spec ) override; + static std::set getSupportedVerbosities(); - static std::set getSupportedVerbosities(); + void benchmarkStarting(BenchmarkInfo const& benchmarkInfo) override; + void benchmarkEnded(BenchmarkStats const& benchmarkStats) override; - void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; - void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; + void testRunStarting(TestRunInfo const& testRunInfo) override; + void testGroupStarting(GroupInfo const& groupInfo) override; + void testCaseStarting(TestCaseInfo const& testInfo) override; + void sectionStarting(SectionInfo const& sectionInfo) override; + void assertionStarting(AssertionInfo const& assertionInfo) override; - void testRunStarting( TestRunInfo const& testRunInfo ) override; - void testGroupStarting( GroupInfo const& groupInfo ) override; - void testCaseStarting( TestCaseInfo const& testInfo ) override; - void sectionStarting( SectionInfo const& sectionInfo ) override; - void assertionStarting( AssertionInfo const& assertionInfo ) override; + // The return value indicates if the messages buffer should be cleared: + bool assertionEnded(AssertionStats const& assertionStats) override; + void sectionEnded(SectionStats const& sectionStats) override; + void testCaseEnded(TestCaseStats const& testCaseStats) override; + void testGroupEnded(TestGroupStats const& testGroupStats) override; + void testRunEnded(TestRunStats const& testRunStats) override; - // The return value indicates if the messages buffer should be cleared: - bool assertionEnded( AssertionStats const& assertionStats ) override; - void sectionEnded( SectionStats const& sectionStats ) override; - void testCaseEnded( TestCaseStats const& testCaseStats ) override; - void testGroupEnded( TestGroupStats const& testGroupStats ) override; - void testRunEnded( TestRunStats const& testRunStats ) override; + void skipTest(TestCaseInfo const& testInfo) override; + bool isMulti() const override; +}; - void skipTest( TestCaseInfo const& testInfo ) override; - bool isMulti() const override; - - }; - -} // end namespace Catch +} // end namespace Catch // end catch_reporter_listening.h namespace Catch { - ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} +ReporterConfig::ReporterConfig(IConfigPtr const& _fullConfig) + : m_stream(&_fullConfig->stream()), m_fullConfig(_fullConfig) {} - ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} +ReporterConfig::ReporterConfig(IConfigPtr const& _fullConfig, + std::ostream& _stream) + : m_stream(&_stream), m_fullConfig(_fullConfig) {} - std::ostream& ReporterConfig::stream() const { return *m_stream; } - IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } +std::ostream& ReporterConfig::stream() const { return *m_stream; } +IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } - TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} +TestRunInfo::TestRunInfo(std::string const& _name) : name(_name) {} - GroupInfo::GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} +GroupInfo::GroupInfo(std::string const& _name, std::size_t _groupIndex, + std::size_t _groupsCount) + : name(_name), groupIndex(_groupIndex), groupsCounts(_groupsCount) {} - AssertionStats::AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; +AssertionStats::AssertionStats(AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals) + : assertionResult(_assertionResult), + infoMessages(_infoMessages), + totals(_totals) { + assertionResult.m_resultData.lazyExpression.m_transientExpression = + _assertionResult.m_resultData.lazyExpression.m_transientExpression; - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); + if (assertionResult.hasMessage()) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder(assertionResult.getTestMacroName(), + assertionResult.getSourceInfo(), + assertionResult.getResultType()); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); - infoMessages.push_back( builder.m_info ); - } - } + infoMessages.push_back(builder.m_info); + } +} - AssertionStats::~AssertionStats() = default; +AssertionStats::~AssertionStats() = default; - SectionStats::SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} +SectionStats::SectionStats(SectionInfo const& _sectionInfo, + Counts const& _assertions, double _durationInSeconds, + bool _missingAssertions) + : sectionInfo(_sectionInfo), + assertions(_assertions), + durationInSeconds(_durationInSeconds), + missingAssertions(_missingAssertions) {} - SectionStats::~SectionStats() = default; +SectionStats::~SectionStats() = default; - TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} +TestCaseStats::TestCaseStats(TestCaseInfo const& _testInfo, + Totals const& _totals, std::string const& _stdOut, + std::string const& _stdErr, bool _aborting) + : testInfo(_testInfo), + totals(_totals), + stdOut(_stdOut), + stdErr(_stdErr), + aborting(_aborting) {} - TestCaseStats::~TestCaseStats() = default; +TestCaseStats::~TestCaseStats() = default; - TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} +TestGroupStats::TestGroupStats(GroupInfo const& _groupInfo, + Totals const& _totals, bool _aborting) + : groupInfo(_groupInfo), totals(_totals), aborting(_aborting) {} - TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} +TestGroupStats::TestGroupStats(GroupInfo const& _groupInfo) + : groupInfo(_groupInfo), aborting(false) {} - TestGroupStats::~TestGroupStats() = default; +TestGroupStats::~TestGroupStats() = default; - TestRunStats::TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} +TestRunStats::TestRunStats(TestRunInfo const& _runInfo, Totals const& _totals, + bool _aborting) + : runInfo(_runInfo), totals(_totals), aborting(_aborting) {} - TestRunStats::~TestRunStats() = default; +TestRunStats::~TestRunStats() = default; - void IStreamingReporter::fatalErrorEncountered( StringRef ) {} - bool IStreamingReporter::isMulti() const { return false; } +void IStreamingReporter::fatalErrorEncountered(StringRef) {} +bool IStreamingReporter::isMulti() const { return false; } - IReporterFactory::~IReporterFactory() = default; - IReporterRegistry::~IReporterRegistry() = default; +IReporterFactory::~IReporterFactory() = default; +IReporterRegistry::~IReporterRegistry() = default; -} // end namespace Catch +} // end namespace Catch // end catch_interfaces_reporter.cpp // start catch_interfaces_runner.cpp namespace Catch { - IRunner::~IRunner() = default; +IRunner::~IRunner() = default; } // end catch_interfaces_runner.cpp // start catch_interfaces_testcase.cpp namespace Catch { - ITestInvoker::~ITestInvoker() = default; - ITestCaseRegistry::~ITestCaseRegistry() = default; -} +ITestInvoker::~ITestInvoker() = default; +ITestCaseRegistry::~ITestCaseRegistry() = default; +} // namespace Catch // end catch_interfaces_testcase.cpp // start catch_leak_detector.cpp @@ -8497,27 +8660,25 @@ namespace Catch { namespace Catch { - LeakDetector::LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } +LeakDetector::LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); } +} // namespace Catch #else - Catch::LeakDetector::LeakDetector() {} +Catch::LeakDetector::LeakDetector() {} #endif -Catch::LeakDetector::~LeakDetector() { - Catch::cleanUp(); -} +Catch::LeakDetector::~LeakDetector() { Catch::cleanUp(); } // end catch_leak_detector.cpp // start catch_list.cpp @@ -8527,205 +8688,210 @@ Catch::LeakDetector::~LeakDetector() { namespace Catch { - std::size_t listTests( Config const& config ); +std::size_t listTests(Config const& config); - std::size_t listTestsNamesOnly( Config const& config ); +std::size_t listTestsNamesOnly(Config const& config); - struct TagInfo { - void add( std::string const& spelling ); - std::string all() const; +struct TagInfo { + void add(std::string const& spelling); + std::string all() const; - std::set spellings; - std::size_t count = 0; - }; + std::set spellings; + std::size_t count = 0; +}; - std::size_t listTags( Config const& config ); +std::size_t listTags(Config const& config); - std::size_t listReporters(); +std::size_t listReporters(); - Option list( Config const& config ); +Option list(Config const& config); -} // end namespace Catch +} // end namespace Catch // end catch_list.h // start catch_text.h namespace Catch { - using namespace clara::TextFlow; +using namespace clara::TextFlow; } // end catch_text.h -#include #include #include +#include namespace Catch { - std::size_t listTests( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.hasTestFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - } +std::size_t listTests(Config const& config) { + TestSpec testSpec = config.testSpec(); + if (config.hasTestFilters()) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + } - auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( auto const& testCaseInfo : matchedTestCases ) { - Colour::Code colour = testCaseInfo.isHidden() - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard( colour ); + auto matchedTestCases = + filterTests(getAllTestCasesSorted(config), testSpec, config); + for (auto const& testCaseInfo : matchedTestCases) { + Colour::Code colour = + testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None; + Colour colourGuard(colour); - Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; - if( config.verbosity() >= Verbosity::High ) { - Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; - std::string description = testCaseInfo.description; - if( description.empty() ) - description = "(NO DESCRIPTION)"; - Catch::cout() << Column( description ).indent(4) << std::endl; - } - if( !testCaseInfo.tags.empty() ) - Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; - } - - if( !config.hasTestFilters() ) - Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; - else - Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; - return matchedTestCases.size(); + Catch::cout() << Column(testCaseInfo.name).initialIndent(2).indent(4) + << "\n"; + if (config.verbosity() >= Verbosity::High) { + Catch::cout() + << Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) + << std::endl; + std::string description = testCaseInfo.description; + if (description.empty()) description = "(NO DESCRIPTION)"; + Catch::cout() << Column(description).indent(4) << std::endl; } + if (!testCaseInfo.tags.empty()) + Catch::cout() << Column(testCaseInfo.tagsAsString()).indent(6) << "\n"; + } - std::size_t listTestsNamesOnly( Config const& config ) { - TestSpec testSpec = config.testSpec(); - std::size_t matchedTests = 0; - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( auto const& testCaseInfo : matchedTestCases ) { - matchedTests++; - if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"'; - else - Catch::cout() << testCaseInfo.name; - if ( config.verbosity() >= Verbosity::High ) - Catch::cout() << "\t@" << testCaseInfo.lineInfo; - Catch::cout() << std::endl; - } - return matchedTests; + if (!config.hasTestFilters()) + Catch::cout() << pluralise(matchedTestCases.size(), "test case") << '\n' + << std::endl; + else + Catch::cout() << pluralise(matchedTestCases.size(), "matching test case") + << '\n' + << std::endl; + return matchedTestCases.size(); +} + +std::size_t listTestsNamesOnly(Config const& config) { + TestSpec testSpec = config.testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = + filterTests(getAllTestCasesSorted(config), testSpec, config); + for (auto const& testCaseInfo : matchedTestCases) { + matchedTests++; + if (startsWith(testCaseInfo.name, '#')) + Catch::cout() << '"' << testCaseInfo.name << '"'; + else + Catch::cout() << testCaseInfo.name; + if (config.verbosity() >= Verbosity::High) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << std::endl; + } + return matchedTests; +} + +void TagInfo::add(std::string const& spelling) { + ++count; + spellings.insert(spelling); +} + +std::string TagInfo::all() const { + std::string out; + for (auto const& spelling : spellings) out += "[" + spelling + "]"; + return out; +} + +std::size_t listTags(Config const& config) { + TestSpec testSpec = config.testSpec(); + if (config.hasTestFilters()) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + } + + std::map tagCounts; + + std::vector matchedTestCases = + filterTests(getAllTestCasesSorted(config), testSpec, config); + for (auto const& testCase : matchedTestCases) { + for (auto const& tagName : testCase.getTestCaseInfo().tags) { + std::string lcaseTagName = toLower(tagName); + auto countIt = tagCounts.find(lcaseTagName); + if (countIt == tagCounts.end()) + countIt = + tagCounts.insert(std::make_pair(lcaseTagName, TagInfo())).first; + countIt->second.add(tagName); } + } - void TagInfo::add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); - } + for (auto const& tagCount : tagCounts) { + ReusableStringStream rss; + rss << " " << std::setw(2) << tagCount.second.count << " "; + auto str = rss.str(); + auto wrapper = Column(tagCount.second.all()) + .initialIndent(0) + .indent(str.size()) + .width(CATCH_CONFIG_CONSOLE_WIDTH - 10); + Catch::cout() << str << wrapper << '\n'; + } + Catch::cout() << pluralise(tagCounts.size(), "tag") << '\n' << std::endl; + return tagCounts.size(); +} - std::string TagInfo::all() const { - std::string out; - for( auto const& spelling : spellings ) - out += "[" + spelling + "]"; - return out; - } +std::size_t listReporters() { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = + getRegistryHub().getReporterRegistry().getFactories(); + std::size_t maxNameLen = 0; + for (auto const& factoryKvp : factories) + maxNameLen = (std::max)(maxNameLen, factoryKvp.first.size()); - std::size_t listTags( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.hasTestFilters() ) - Catch::cout() << "Tags for matching test cases:\n"; - else { - Catch::cout() << "All available tags:\n"; - } + for (auto const& factoryKvp : factories) { + Catch::cout() + << Column(factoryKvp.first + ":").indent(2).width(5 + maxNameLen) + + Column(factoryKvp.second->getDescription()) + .initialIndent(0) + .indent(2) + .width(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8) + << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); +} - std::map tagCounts; +Option list(Config const& config) { + Option listedCount; + if (config.listTests()) + listedCount = listedCount.valueOr(0) + listTests(config); + if (config.listTestNamesOnly()) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly(config); + if (config.listTags()) + listedCount = listedCount.valueOr(0) + listTags(config); + if (config.listReporters()) + listedCount = listedCount.valueOr(0) + listReporters(); + return listedCount; +} - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( auto const& testCase : matchedTestCases ) { - for( auto const& tagName : testCase.getTestCaseInfo().tags ) { - std::string lcaseTagName = toLower( tagName ); - auto countIt = tagCounts.find( lcaseTagName ); - if( countIt == tagCounts.end() ) - countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; - countIt->second.add( tagName ); - } - } - - for( auto const& tagCount : tagCounts ) { - ReusableStringStream rss; - rss << " " << std::setw(2) << tagCount.second.count << " "; - auto str = rss.str(); - auto wrapper = Column( tagCount.second.all() ) - .initialIndent( 0 ) - .indent( str.size() ) - .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); - Catch::cout() << str << wrapper << '\n'; - } - Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; - return tagCounts.size(); - } - - std::size_t listReporters() { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - std::size_t maxNameLen = 0; - for( auto const& factoryKvp : factories ) - maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); - - for( auto const& factoryKvp : factories ) { - Catch::cout() - << Column( factoryKvp.first + ":" ) - .indent(2) - .width( 5+maxNameLen ) - + Column( factoryKvp.second->getDescription() ) - .initialIndent(0) - .indent(2) - .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) - << "\n"; - } - Catch::cout() << std::endl; - return factories.size(); - } - - Option list( Config const& config ) { - Option listedCount; - if( config.listTests() ) - listedCount = listedCount.valueOr(0) + listTests( config ); - if( config.listTestNamesOnly() ) - listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); - if( config.listTags() ) - listedCount = listedCount.valueOr(0) + listTags( config ); - if( config.listReporters() ) - listedCount = listedCount.valueOr(0) + listReporters(); - return listedCount; - } - -} // end namespace Catch +} // end namespace Catch // end catch_list.cpp // start catch_matchers.cpp namespace Catch { namespace Matchers { - namespace Impl { +namespace Impl { - std::string MatcherUntypedBase::toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; - } +std::string MatcherUntypedBase::toString() const { + if (m_cachedToString.empty()) m_cachedToString = describe(); + return m_cachedToString; +} - MatcherUntypedBase::~MatcherUntypedBase() = default; +MatcherUntypedBase::~MatcherUntypedBase() = default; - } // namespace Impl -} // namespace Matchers +} // namespace Impl +} // namespace Matchers using namespace Matchers; using Matchers::Impl::MatcherBase; -} // namespace Catch +} // namespace Catch // end catch_matchers.cpp // start catch_matchers_floating.cpp // start catch_polyfills.hpp namespace Catch { - bool isnan(float f); - bool isnan(double d); -} +bool isnan(float f); +bool isnan(double d); +} // namespace Catch // end catch_polyfills.hpp // start catch_to_string.hpp @@ -8733,33 +8899,30 @@ namespace Catch { #include namespace Catch { - template - std::string to_string(T const& t) { +template +std::string to_string(T const& t) { #if defined(CATCH_CONFIG_CPP11_TO_STRING) - return std::to_string(t); + return std::to_string(t); #else - ReusableStringStream rss; - rss << t; - return rss.str(); + ReusableStringStream rss; + rss << t; + return rss.str(); #endif - } -} // end namespace Catch +} +} // end namespace Catch // end catch_to_string.hpp -#include #include +#include #include namespace Catch { namespace Matchers { namespace Floating { -enum class FloatingPointKind : uint8_t { - Float, - Double -}; -} -} +enum class FloatingPointKind : uint8_t { Float, Double }; } +} // namespace Matchers +} // namespace Catch namespace { @@ -8768,73 +8931,73 @@ struct Converter; template <> struct Converter { - static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); - Converter(float f) { - std::memcpy(&i, &f, sizeof(f)); - } - int32_t i; + static_assert(sizeof(float) == sizeof(int32_t), + "Important ULP matcher assumption violated"); + Converter(float f) { std::memcpy(&i, &f, sizeof(f)); } + int32_t i; }; template <> struct Converter { - static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); - Converter(double d) { - std::memcpy(&i, &d, sizeof(d)); - } - int64_t i; + static_assert(sizeof(double) == sizeof(int64_t), + "Important ULP matcher assumption violated"); + Converter(double d) { std::memcpy(&i, &d, sizeof(d)); } + int64_t i; }; template auto convert(T t) -> Converter { - return Converter(t); + return Converter(t); } template bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) { - // Comparison with NaN should always be false. - // This way we can rule it out before getting into the ugly details - if (Catch::isnan(lhs) || Catch::isnan(rhs)) { - return false; - } + // Comparison with NaN should always be false. + // This way we can rule it out before getting into the ugly details + if (Catch::isnan(lhs) || Catch::isnan(rhs)) { return false; } - auto lc = convert(lhs); - auto rc = convert(rhs); + auto lc = convert(lhs); + auto rc = convert(rhs); - if ((lc.i < 0) != (rc.i < 0)) { - // Potentially we can have +0 and -0 - return lhs == rhs; - } + if ((lc.i < 0) != (rc.i < 0)) { + // Potentially we can have +0 and -0 + return lhs == rhs; + } - auto ulpDiff = std::abs(lc.i - rc.i); - return ulpDiff <= maxUlpDiff; + auto ulpDiff = std::abs(lc.i - rc.i); + return ulpDiff <= maxUlpDiff; } -} +} // namespace namespace Catch { namespace Matchers { namespace Floating { - WithinAbsMatcher::WithinAbsMatcher(double target, double margin) - :m_target{ target }, m_margin{ margin } { - CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' - << " Margin has to be non-negative."); - } +WithinAbsMatcher::WithinAbsMatcher(double target, double margin) + : m_target{target}, m_margin{margin} { + CATCH_ENFORCE( + margin >= 0, + "Invalid margin: " << margin << '.' << " Margin has to be non-negative."); +} - // Performs equivalent check of std::fabs(lhs - rhs) <= margin - // But without the subtraction to allow for INFINITY in comparison - bool WithinAbsMatcher::match(double const& matchee) const { - return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); - } +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool WithinAbsMatcher::match(double const& matchee) const { + return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); +} - std::string WithinAbsMatcher::describe() const { - return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); - } +std::string WithinAbsMatcher::describe() const { + return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + + ::Catch::Detail::stringify(m_target); +} - WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType) - :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { - CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.' - << " ULPs have to be non-negative."); - } +WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, + FloatingPointKind baseType) + : m_target{target}, m_ulps{ulps}, m_type{baseType} { + CATCH_ENFORCE(ulps >= 0, + "Invalid ULP setting: " << ulps << '.' + << " ULPs have to be non-negative."); +} #if defined(__clang__) #pragma clang diagnostic push @@ -8842,51 +9005,57 @@ namespace Floating { #pragma clang diagnostic ignored "-Wunreachable-code" #endif - bool WithinUlpsMatcher::match(double const& matchee) const { - switch (m_type) { - case FloatingPointKind::Float: - return almostEqualUlps(static_cast(matchee), static_cast(m_target), m_ulps); - case FloatingPointKind::Double: - return almostEqualUlps(matchee, m_target, m_ulps); - default: - CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" ); - } - } +bool WithinUlpsMatcher::match(double const& matchee) const { + switch (m_type) { + case FloatingPointKind::Float: + return almostEqualUlps(static_cast(matchee), + static_cast(m_target), m_ulps); + case FloatingPointKind::Double: + return almostEqualUlps(matchee, m_target, m_ulps); + default: + CATCH_INTERNAL_ERROR("Unknown FloatingPointKind value"); + } +} #if defined(__clang__) #pragma clang diagnostic pop #endif - std::string WithinUlpsMatcher::describe() const { - return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); - } +std::string WithinUlpsMatcher::describe() const { + return "is within " + Catch::to_string(m_ulps) + " ULPs of " + + ::Catch::Detail::stringify(m_target) + + ((m_type == FloatingPointKind::Float) ? "f" : ""); +} -}// namespace Floating +} // namespace Floating Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) { - return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); + return Floating::WithinUlpsMatcher(target, maxUlpDiff, + Floating::FloatingPointKind::Double); } Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) { - return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); + return Floating::WithinUlpsMatcher(target, maxUlpDiff, + Floating::FloatingPointKind::Float); } Floating::WithinAbsMatcher WithinAbs(double target, double margin) { - return Floating::WithinAbsMatcher(target, margin); + return Floating::WithinAbsMatcher(target, margin); } -} // namespace Matchers -} // namespace Catch +} // namespace Matchers +} // namespace Catch // end catch_matchers_floating.cpp // start catch_matchers_generic.cpp -std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) { - if (desc.empty()) { - return "matches undescribed predicate"; - } else { - return "matches predicate: \"" + desc + '"'; - } +std::string Catch::Matchers::Generic::Detail::finalizeDescription( + const std::string& desc) { + if (desc.empty()) { + return "matches undescribed predicate"; + } else { + return "matches predicate: \"" + desc + '"'; + } } // end catch_matchers_generic.cpp // start catch_matchers_string.cpp @@ -8896,108 +9065,121 @@ std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::str namespace Catch { namespace Matchers { - namespace StdString { +namespace StdString { - CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_str( adjustString( str ) ) - {} - std::string CasedString::adjustString( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No - ? toLower( str ) - : str; - } - std::string CasedString::caseSensitivitySuffix() const { - return m_caseSensitivity == CaseSensitive::No - ? " (case insensitive)" - : std::string(); - } +CasedString::CasedString(std::string const& str, + CaseSensitive::Choice caseSensitivity) + : m_caseSensitivity(caseSensitivity), m_str(adjustString(str)) {} +std::string CasedString::adjustString(std::string const& str) const { + return m_caseSensitivity == CaseSensitive::No ? toLower(str) : str; +} +std::string CasedString::caseSensitivitySuffix() const { + return m_caseSensitivity == CaseSensitive::No ? " (case insensitive)" + : std::string(); +} - StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) - : m_comparator( comparator ), - m_operation( operation ) { - } +StringMatcherBase::StringMatcherBase(std::string const& operation, + CasedString const& comparator) + : m_comparator(comparator), m_operation(operation) {} - std::string StringMatcherBase::describe() const { - std::string description; - description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + - m_comparator.caseSensitivitySuffix().size()); - description += m_operation; - description += ": \""; - description += m_comparator.m_str; - description += "\""; - description += m_comparator.caseSensitivitySuffix(); - return description; - } +std::string StringMatcherBase::describe() const { + std::string description; + description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + + m_comparator.caseSensitivitySuffix().size()); + description += m_operation; + description += ": \""; + description += m_comparator.m_str; + description += "\""; + description += m_comparator.caseSensitivitySuffix(); + return description; +} - EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} +EqualsMatcher::EqualsMatcher(CasedString const& comparator) + : StringMatcherBase("equals", comparator) {} - bool EqualsMatcher::match( std::string const& source ) const { - return m_comparator.adjustString( source ) == m_comparator.m_str; - } +bool EqualsMatcher::match(std::string const& source) const { + return m_comparator.adjustString(source) == m_comparator.m_str; +} - ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} +ContainsMatcher::ContainsMatcher(CasedString const& comparator) + : StringMatcherBase("contains", comparator) {} - bool ContainsMatcher::match( std::string const& source ) const { - return contains( m_comparator.adjustString( source ), m_comparator.m_str ); - } +bool ContainsMatcher::match(std::string const& source) const { + return contains(m_comparator.adjustString(source), m_comparator.m_str); +} - StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} +StartsWithMatcher::StartsWithMatcher(CasedString const& comparator) + : StringMatcherBase("starts with", comparator) {} - bool StartsWithMatcher::match( std::string const& source ) const { - return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); - } +bool StartsWithMatcher::match(std::string const& source) const { + return startsWith(m_comparator.adjustString(source), m_comparator.m_str); +} - EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} +EndsWithMatcher::EndsWithMatcher(CasedString const& comparator) + : StringMatcherBase("ends with", comparator) {} - bool EndsWithMatcher::match( std::string const& source ) const { - return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); - } +bool EndsWithMatcher::match(std::string const& source) const { + return endsWith(m_comparator.adjustString(source), m_comparator.m_str); +} - RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} +RegexMatcher::RegexMatcher(std::string regex, + CaseSensitive::Choice caseSensitivity) + : m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} - bool RegexMatcher::match(std::string const& matchee) const { - auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway - if (m_caseSensitivity == CaseSensitive::Choice::No) { - flags |= std::regex::icase; - } - auto reg = std::regex(m_regex, flags); - return std::regex_match(matchee, reg); - } +bool RegexMatcher::match(std::string const& matchee) const { + auto flags = + std::regex::ECMAScript; // ECMAScript is the default syntax option anyway + if (m_caseSensitivity == CaseSensitive::Choice::No) { + flags |= std::regex::icase; + } + auto reg = std::regex(m_regex, flags); + return std::regex_match(matchee, reg); +} - std::string RegexMatcher::describe() const { - return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); - } +std::string RegexMatcher::describe() const { + return "matches " + ::Catch::Detail::stringify(m_regex) + + ((m_caseSensitivity == CaseSensitive::Choice::Yes) + ? " case sensitively" + : " case insensitively"); +} - } // namespace StdString +} // namespace StdString - StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); - } +StdString::EqualsMatcher Equals(std::string const& str, + CaseSensitive::Choice caseSensitivity) { + return StdString::EqualsMatcher(StdString::CasedString(str, caseSensitivity)); +} +StdString::ContainsMatcher Contains(std::string const& str, + CaseSensitive::Choice caseSensitivity) { + return StdString::ContainsMatcher( + StdString::CasedString(str, caseSensitivity)); +} +StdString::EndsWithMatcher EndsWith(std::string const& str, + CaseSensitive::Choice caseSensitivity) { + return StdString::EndsWithMatcher( + StdString::CasedString(str, caseSensitivity)); +} +StdString::StartsWithMatcher StartsWith(std::string const& str, + CaseSensitive::Choice caseSensitivity) { + return StdString::StartsWithMatcher( + StdString::CasedString(str, caseSensitivity)); +} - StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { - return StdString::RegexMatcher(regex, caseSensitivity); - } +StdString::RegexMatcher Matches(std::string const& regex, + CaseSensitive::Choice caseSensitivity) { + return StdString::RegexMatcher(regex, caseSensitivity); +} -} // namespace Matchers -} // namespace Catch +} // namespace Matchers +} // namespace Catch // end catch_matchers_string.cpp // start catch_message.cpp // start catch_uncaught_exceptions.h namespace Catch { - bool uncaught_exceptions(); -} // end namespace Catch +bool uncaught_exceptions(); +} // end namespace Catch // end catch_uncaught_exceptions.h #include @@ -9005,108 +9187,101 @@ namespace Catch { namespace Catch { - MessageInfo::MessageInfo( StringRef const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} +MessageInfo::MessageInfo(StringRef const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type) + : macroName(_macroName), + lineInfo(_lineInfo), + type(_type), + sequence(++globalCount) {} - bool MessageInfo::operator==( MessageInfo const& other ) const { - return sequence == other.sequence; - } +bool MessageInfo::operator==(MessageInfo const& other) const { + return sequence == other.sequence; +} - bool MessageInfo::operator<( MessageInfo const& other ) const { - return sequence < other.sequence; - } +bool MessageInfo::operator<(MessageInfo const& other) const { + return sequence < other.sequence; +} - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; +// This may need protecting if threading support is added +unsigned int MessageInfo::globalCount = 0; - //////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// - Catch::MessageBuilder::MessageBuilder( StringRef const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - :m_info(macroName, lineInfo, type) {} +Catch::MessageBuilder::MessageBuilder(StringRef const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type) + : m_info(macroName, lineInfo, type) {} - //////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } +ScopedMessage::ScopedMessage(MessageBuilder const& builder) + : m_info(builder.m_info) { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage(m_info); +} - ScopedMessage::~ScopedMessage() { - if ( !uncaught_exceptions() ){ - getResultCapture().popScopedMessage(m_info); +ScopedMessage::~ScopedMessage() { + if (!uncaught_exceptions()) { getResultCapture().popScopedMessage(m_info); } +} + +Capturer::Capturer(StringRef macroName, SourceLineInfo const& lineInfo, + ResultWas::OfType resultType, StringRef names) { + auto trimmed = [&](size_t start, size_t end) { + while (names[start] == ',' || isspace(names[start])) { ++start; } + while (names[end] == ',' || isspace(names[end])) { --end; } + return names.substr(start, end - start + 1); + }; + + size_t start = 0; + std::stack openings; + for (size_t pos = 0; pos < names.size(); ++pos) { + char c = names[pos]; + switch (c) { + case '[': + case '{': + case '(': + // It is basically impossible to disambiguate between + // comparison and start of template args in this context + // case '<': + openings.push(c); + break; + case ']': + case '}': + case ')': + // case '>': + openings.pop(); + break; + case ',': + if (start != pos && openings.size() == 0) { + m_messages.emplace_back(macroName, lineInfo, resultType); + m_messages.back().message = trimmed(start, pos); + m_messages.back().message += " := "; + start = pos; } } + } + assert(openings.size() == 0 && "Mismatched openings"); + m_messages.emplace_back(macroName, lineInfo, resultType); + m_messages.back().message = trimmed(start, names.size() - 1); + m_messages.back().message += " := "; +} +Capturer::~Capturer() { + if (!uncaught_exceptions()) { + assert(m_captured == m_messages.size()); + for (size_t i = 0; i < m_captured; ++i) + m_resultCapture.popScopedMessage(m_messages[i]); + } +} - Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { - auto trimmed = [&] (size_t start, size_t end) { - while (names[start] == ',' || isspace(names[start])) { - ++start; - } - while (names[end] == ',' || isspace(names[end])) { - --end; - } - return names.substr(start, end - start + 1); - }; +void Capturer::captureValue(size_t index, std::string const& value) { + assert(index < m_messages.size()); + m_messages[index].message += value; + m_resultCapture.pushScopedMessage(m_messages[index]); + m_captured++; +} - size_t start = 0; - std::stack openings; - for (size_t pos = 0; pos < names.size(); ++pos) { - char c = names[pos]; - switch (c) { - case '[': - case '{': - case '(': - // It is basically impossible to disambiguate between - // comparison and start of template args in this context -// case '<': - openings.push(c); - break; - case ']': - case '}': - case ')': -// case '>': - openings.pop(); - break; - case ',': - if (start != pos && openings.size() == 0) { - m_messages.emplace_back(macroName, lineInfo, resultType); - m_messages.back().message = trimmed(start, pos); - m_messages.back().message += " := "; - start = pos; - } - } - } - assert(openings.size() == 0 && "Mismatched openings"); - m_messages.emplace_back(macroName, lineInfo, resultType); - m_messages.back().message = trimmed(start, names.size() - 1); - m_messages.back().message += " := "; - } - Capturer::~Capturer() { - if ( !uncaught_exceptions() ){ - assert( m_captured == m_messages.size() ); - for( size_t i = 0; i < m_captured; ++i ) - m_resultCapture.popScopedMessage( m_messages[i] ); - } - } - - void Capturer::captureValue( size_t index, std::string const& value ) { - assert( index < m_messages.size() ); - m_messages[index].message += value; - m_resultCapture.pushScopedMessage( m_messages[index] ); - m_captured++; - } - -} // end namespace Catch +} // end namespace Catch // end catch_message.cpp // start catch_output_redirect.cpp @@ -9120,86 +9295,89 @@ namespace Catch { namespace Catch { - class RedirectedStream { - std::ostream& m_originalStream; - std::ostream& m_redirectionStream; - std::streambuf* m_prevBuf; +class RedirectedStream { + std::ostream& m_originalStream; + std::ostream& m_redirectionStream; + std::streambuf* m_prevBuf; - public: - RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); - ~RedirectedStream(); - }; + public: + RedirectedStream(std::ostream& originalStream, + std::ostream& redirectionStream); + ~RedirectedStream(); +}; - class RedirectedStdOut { - ReusableStringStream m_rss; - RedirectedStream m_cout; - public: - RedirectedStdOut(); - auto str() const -> std::string; - }; +class RedirectedStdOut { + ReusableStringStream m_rss; + RedirectedStream m_cout; - // StdErr has two constituent streams in C++, std::cerr and std::clog - // This means that we need to redirect 2 streams into 1 to keep proper - // order of writes - class RedirectedStdErr { - ReusableStringStream m_rss; - RedirectedStream m_cerr; - RedirectedStream m_clog; - public: - RedirectedStdErr(); - auto str() const -> std::string; - }; + public: + RedirectedStdOut(); + auto str() const -> std::string; +}; + +// StdErr has two constituent streams in C++, std::cerr and std::clog +// This means that we need to redirect 2 streams into 1 to keep proper +// order of writes +class RedirectedStdErr { + ReusableStringStream m_rss; + RedirectedStream m_cerr; + RedirectedStream m_clog; + + public: + RedirectedStdErr(); + auto str() const -> std::string; +}; #if defined(CATCH_CONFIG_NEW_CAPTURE) - // Windows's implementation of std::tmpfile is terrible (it tries - // to create a file inside system folder, thus requiring elevated - // privileges for the binary), so we have to use tmpnam(_s) and - // create the file ourselves there. - class TempFile { - public: - TempFile(TempFile const&) = delete; - TempFile& operator=(TempFile const&) = delete; - TempFile(TempFile&&) = delete; - TempFile& operator=(TempFile&&) = delete; +// Windows's implementation of std::tmpfile is terrible (it tries +// to create a file inside system folder, thus requiring elevated +// privileges for the binary), so we have to use tmpnam(_s) and +// create the file ourselves there. +class TempFile { + public: + TempFile(TempFile const&) = delete; + TempFile& operator=(TempFile const&) = delete; + TempFile(TempFile&&) = delete; + TempFile& operator=(TempFile&&) = delete; - TempFile(); - ~TempFile(); + TempFile(); + ~TempFile(); - std::FILE* getFile(); - std::string getContents(); + std::FILE* getFile(); + std::string getContents(); - private: - std::FILE* m_file = nullptr; - #if defined(_MSC_VER) - char m_buffer[L_tmpnam] = { 0 }; - #endif - }; + private: + std::FILE* m_file = nullptr; +#if defined(_MSC_VER) + char m_buffer[L_tmpnam] = {0}; +#endif +}; - class OutputRedirect { - public: - OutputRedirect(OutputRedirect const&) = delete; - OutputRedirect& operator=(OutputRedirect const&) = delete; - OutputRedirect(OutputRedirect&&) = delete; - OutputRedirect& operator=(OutputRedirect&&) = delete; +class OutputRedirect { + public: + OutputRedirect(OutputRedirect const&) = delete; + OutputRedirect& operator=(OutputRedirect const&) = delete; + OutputRedirect(OutputRedirect&&) = delete; + OutputRedirect& operator=(OutputRedirect&&) = delete; - OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); - ~OutputRedirect(); + OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); + ~OutputRedirect(); - private: - int m_originalStdout = -1; - int m_originalStderr = -1; - TempFile m_stdoutFile; - TempFile m_stderrFile; - std::string& m_stdoutDest; - std::string& m_stderrDest; - }; + private: + int m_originalStdout = -1; + int m_originalStderr = -1; + TempFile m_stdoutFile; + TempFile m_stderrFile; + std::string& m_stdoutDest; + std::string& m_stderrDest; +}; #endif -} // end namespace Catch +} // end namespace Catch -#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H +#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H // end catch_output_redirect.h #include #include @@ -9208,123 +9386,115 @@ namespace Catch { #include #if defined(CATCH_CONFIG_NEW_CAPTURE) - #if defined(_MSC_VER) - #include //_dup and _dup2 - #define dup _dup - #define dup2 _dup2 - #define fileno _fileno - #else - #include // dup and dup2 - #endif +#if defined(_MSC_VER) +#include //_dup and _dup2 +#define dup _dup +#define dup2 _dup2 +#define fileno _fileno +#else +#include // dup and dup2 +#endif #endif namespace Catch { - RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) - : m_originalStream( originalStream ), - m_redirectionStream( redirectionStream ), - m_prevBuf( m_originalStream.rdbuf() ) - { - m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); - } +RedirectedStream::RedirectedStream(std::ostream& originalStream, + std::ostream& redirectionStream) + : m_originalStream(originalStream), + m_redirectionStream(redirectionStream), + m_prevBuf(m_originalStream.rdbuf()) { + m_originalStream.rdbuf(m_redirectionStream.rdbuf()); +} - RedirectedStream::~RedirectedStream() { - m_originalStream.rdbuf( m_prevBuf ); - } +RedirectedStream::~RedirectedStream() { m_originalStream.rdbuf(m_prevBuf); } - RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} - auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } +RedirectedStdOut::RedirectedStdOut() : m_cout(Catch::cout(), m_rss.get()) {} +auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } - RedirectedStdErr::RedirectedStdErr() - : m_cerr( Catch::cerr(), m_rss.get() ), - m_clog( Catch::clog(), m_rss.get() ) - {} - auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } +RedirectedStdErr::RedirectedStdErr() + : m_cerr(Catch::cerr(), m_rss.get()), m_clog(Catch::clog(), m_rss.get()) {} +auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } #if defined(CATCH_CONFIG_NEW_CAPTURE) #if defined(_MSC_VER) - TempFile::TempFile() { - if (tmpnam_s(m_buffer)) { - CATCH_RUNTIME_ERROR("Could not get a temp filename"); - } - if (fopen_s(&m_file, m_buffer, "w")) { - char buffer[100]; - if (strerror_s(buffer, errno)) { - CATCH_RUNTIME_ERROR("Could not translate errno to a string"); - } - CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer); - } +TempFile::TempFile() { + if (tmpnam_s(m_buffer)) { + CATCH_RUNTIME_ERROR("Could not get a temp filename"); + } + if (fopen_s(&m_file, m_buffer, "w")) { + char buffer[100]; + if (strerror_s(buffer, errno)) { + CATCH_RUNTIME_ERROR("Could not translate errno to a string"); } + CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" + << m_buffer << "' because: " << buffer); + } +} #else - TempFile::TempFile() { - m_file = std::tmpfile(); - if (!m_file) { - CATCH_RUNTIME_ERROR("Could not create a temp file."); - } - } +TempFile::TempFile() { + m_file = std::tmpfile(); + if (!m_file) { CATCH_RUNTIME_ERROR("Could not create a temp file."); } +} #endif - TempFile::~TempFile() { - // TBD: What to do about errors here? - std::fclose(m_file); - // We manually create the file on Windows only, on Linux - // it will be autodeleted +TempFile::~TempFile() { + // TBD: What to do about errors here? + std::fclose(m_file); + // We manually create the file on Windows only, on Linux + // it will be autodeleted #if defined(_MSC_VER) - std::remove(m_buffer); + std::remove(m_buffer); #endif - } +} - FILE* TempFile::getFile() { - return m_file; - } +FILE* TempFile::getFile() { return m_file; } - std::string TempFile::getContents() { - std::stringstream sstr; - char buffer[100] = {}; - std::rewind(m_file); - while (std::fgets(buffer, sizeof(buffer), m_file)) { - sstr << buffer; - } - return sstr.str(); - } +std::string TempFile::getContents() { + std::stringstream sstr; + char buffer[100] = {}; + std::rewind(m_file); + while (std::fgets(buffer, sizeof(buffer), m_file)) { sstr << buffer; } + return sstr.str(); +} - OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : - m_originalStdout(dup(1)), - m_originalStderr(dup(2)), - m_stdoutDest(stdout_dest), - m_stderrDest(stderr_dest) { - dup2(fileno(m_stdoutFile.getFile()), 1); - dup2(fileno(m_stderrFile.getFile()), 2); - } +OutputRedirect::OutputRedirect(std::string& stdout_dest, + std::string& stderr_dest) + : m_originalStdout(dup(1)), + m_originalStderr(dup(2)), + m_stdoutDest(stdout_dest), + m_stderrDest(stderr_dest) { + dup2(fileno(m_stdoutFile.getFile()), 1); + dup2(fileno(m_stderrFile.getFile()), 2); +} - OutputRedirect::~OutputRedirect() { - Catch::cout() << std::flush; - fflush(stdout); - // Since we support overriding these streams, we flush cerr - // even though std::cerr is unbuffered - Catch::cerr() << std::flush; - Catch::clog() << std::flush; - fflush(stderr); +OutputRedirect::~OutputRedirect() { + Catch::cout() << std::flush; + fflush(stdout); + // Since we support overriding these streams, we flush cerr + // even though std::cerr is unbuffered + Catch::cerr() << std::flush; + Catch::clog() << std::flush; + fflush(stderr); - dup2(m_originalStdout, 1); - dup2(m_originalStderr, 2); + dup2(m_originalStdout, 1); + dup2(m_originalStderr, 2); - m_stdoutDest += m_stdoutFile.getContents(); - m_stderrDest += m_stderrFile.getContents(); - } + m_stdoutDest += m_stdoutFile.getContents(); + m_stderrDest += m_stderrFile.getContents(); +} -#endif // CATCH_CONFIG_NEW_CAPTURE +#endif // CATCH_CONFIG_NEW_CAPTURE -} // namespace Catch +} // namespace Catch #if defined(CATCH_CONFIG_NEW_CAPTURE) - #if defined(_MSC_VER) - #undef dup - #undef dup2 - #undef fileno - #endif +#if defined(_MSC_VER) +#undef dup +#undef dup2 +#undef fileno +#endif #endif // end catch_output_redirect.cpp // start catch_polyfills.cpp @@ -9334,99 +9504,96 @@ namespace Catch { namespace Catch { #if !defined(CATCH_CONFIG_POLYFILL_ISNAN) - bool isnan(float f) { - return std::isnan(f); - } - bool isnan(double d) { - return std::isnan(d); - } +bool isnan(float f) { return std::isnan(f); } +bool isnan(double d) { return std::isnan(d); } #else - // For now we only use this for embarcadero - bool isnan(float f) { - return std::_isnan(f); - } - bool isnan(double d) { - return std::_isnan(d); - } +// For now we only use this for embarcadero +bool isnan(float f) { return std::_isnan(f); } +bool isnan(double d) { return std::_isnan(d); } #endif -} // end namespace Catch +} // end namespace Catch // end catch_polyfills.cpp // start catch_random_number_generator.cpp namespace Catch { - std::mt19937& rng() { - static std::mt19937 s_rng; - return s_rng; - } - - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) { - std::srand( config.rngSeed() ); - rng().seed( config.rngSeed() ); - } - } - - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } +std::mt19937& rng() { + static std::mt19937 s_rng; + return s_rng; } + +void seedRng(IConfig const& config) { + if (config.rngSeed() != 0) { + std::srand(config.rngSeed()); + rng().seed(config.rngSeed()); + } +} + +unsigned int rngSeed() { return getCurrentContext().getConfig()->rngSeed(); } +} // namespace Catch // end catch_random_number_generator.cpp // start catch_registry_hub.cpp // start catch_test_case_registry_impl.h -#include -#include #include #include +#include +#include namespace Catch { - class TestCase; - struct IConfig; +class TestCase; +struct IConfig; - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); +std::vector sortTests(IConfig const& config, + std::vector const& unsortedTestCases); +bool matchTest(TestCase const& testCase, TestSpec const& testSpec, + IConfig const& config); - void enforceNoDuplicateTestCases( std::vector const& functions ); +void enforceNoDuplicateTestCases(std::vector const& functions); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); +std::vector filterTests(std::vector const& testCases, + TestSpec const& testSpec, + IConfig const& config); +std::vector const& getAllTestCasesSorted(IConfig const& config); - class TestRegistry : public ITestCaseRegistry { - public: - virtual ~TestRegistry() = default; +class TestRegistry : public ITestCaseRegistry { + public: + virtual ~TestRegistry() = default; - virtual void registerTest( TestCase const& testCase ); + virtual void registerTest(TestCase const& testCase); - std::vector const& getAllTests() const override; - std::vector const& getAllTestsSorted( IConfig const& config ) const override; + std::vector const& getAllTests() const override; + std::vector const& getAllTestsSorted( + IConfig const& config) const override; - private: - std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; - mutable std::vector m_sortedFunctions; - std::size_t m_unnamedCount = 0; - std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised - }; + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder = + RunTests::InDeclarationOrder; + mutable std::vector m_sortedFunctions; + std::size_t m_unnamedCount = 0; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised +}; - /////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// - class TestInvokerAsFunction : public ITestInvoker { - void(*m_testAsFunction)(); - public: - TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; +class TestInvokerAsFunction : public ITestInvoker { + void (*m_testAsFunction)(); - void invoke() const override; - }; + public: + TestInvokerAsFunction(void (*testAsFunction)()) noexcept; - std::string extractClassName( StringRef const& classOrQualifiedMethodName ); + void invoke() const override; +}; - /////////////////////////////////////////////////////////////////////////// +std::string extractClassName(StringRef const& classOrQualifiedMethodName); -} // end namespace Catch +/////////////////////////////////////////////////////////////////////////// + +} // end namespace Catch // end catch_test_case_registry_impl.h // start catch_reporter_registry.h @@ -9435,25 +9602,25 @@ namespace Catch { namespace Catch { - class ReporterRegistry : public IReporterRegistry { +class ReporterRegistry : public IReporterRegistry { + public: + ~ReporterRegistry() override; - public: + IStreamingReporterPtr create(std::string const& name, + IConfigPtr const& config) const override; - ~ReporterRegistry() override; + void registerReporter(std::string const& name, + IReporterFactoryPtr const& factory); + void registerListener(IReporterFactoryPtr const& factory); - IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; + FactoryMap const& getFactories() const override; + Listeners const& getListeners() const override; - void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); - void registerListener( IReporterFactoryPtr const& factory ); - - FactoryMap const& getFactories() const override; - Listeners const& getListeners() const override; - - private: - FactoryMap m_factories; - Listeners m_listeners; - }; -} + private: + FactoryMap m_factories; + Listeners m_listeners; +}; +} // namespace Catch // end catch_reporter_registry.h // start catch_tag_alias_registry.h @@ -9464,742 +9631,738 @@ namespace Catch { namespace Catch { - struct TagAlias { - TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); +struct TagAlias { + TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); - std::string tag; - SourceLineInfo lineInfo; - }; + std::string tag; + SourceLineInfo lineInfo; +}; -} // end namespace Catch +} // end namespace Catch // end catch_tag_alias.h #include namespace Catch { - class TagAliasRegistry : public ITagAliasRegistry { - public: - ~TagAliasRegistry() override; - TagAlias const* find( std::string const& alias ) const override; - std::string expandAliases( std::string const& unexpandedTestSpec ) const override; - void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); +class TagAliasRegistry : public ITagAliasRegistry { + public: + ~TagAliasRegistry() override; + TagAlias const* find(std::string const& alias) const override; + std::string expandAliases( + std::string const& unexpandedTestSpec) const override; + void add(std::string const& alias, std::string const& tag, + SourceLineInfo const& lineInfo); - private: - std::map m_registry; - }; + private: + std::map m_registry; +}; -} // end namespace Catch +} // end namespace Catch // end catch_tag_alias_registry.h // start catch_startup_exception_registry.h -#include #include +#include namespace Catch { - class StartupExceptionRegistry { - public: - void add(std::exception_ptr const& exception) noexcept; - std::vector const& getExceptions() const noexcept; - private: - std::vector m_exceptions; - }; +class StartupExceptionRegistry { + public: + void add(std::exception_ptr const& exception) noexcept; + std::vector const& getExceptions() const noexcept; -} // end namespace Catch + private: + std::vector m_exceptions; +}; + +} // end namespace Catch // end catch_startup_exception_registry.h // start catch_singletons.hpp namespace Catch { - struct ISingleton { - virtual ~ISingleton(); - }; +struct ISingleton { + virtual ~ISingleton(); +}; - void addSingleton( ISingleton* singleton ); - void cleanupSingletons(); +void addSingleton(ISingleton* singleton); +void cleanupSingletons(); - template - class Singleton : SingletonImplT, public ISingleton { +template +class Singleton : SingletonImplT, public ISingleton { + static auto getInternal() -> Singleton* { + static Singleton* s_instance = nullptr; + if (!s_instance) { + s_instance = new Singleton; + addSingleton(s_instance); + } + return s_instance; + } - static auto getInternal() -> Singleton* { - static Singleton* s_instance = nullptr; - if( !s_instance ) { - s_instance = new Singleton; - addSingleton( s_instance ); - } - return s_instance; - } + public: + static auto get() -> InterfaceT const& { return *getInternal(); } + static auto getMutable() -> MutableInterfaceT& { return *getInternal(); } +}; - public: - static auto get() -> InterfaceT const& { - return *getInternal(); - } - static auto getMutable() -> MutableInterfaceT& { - return *getInternal(); - } - }; - -} // namespace Catch +} // namespace Catch // end catch_singletons.hpp namespace Catch { - namespace { +namespace { - class RegistryHub : public IRegistryHub, public IMutableRegistryHub, - private NonCopyable { +class RegistryHub : public IRegistryHub, + public IMutableRegistryHub, + private NonCopyable { + public: // IRegistryHub + RegistryHub() = default; + IReporterRegistry const& getReporterRegistry() const override { + return m_reporterRegistry; + } + ITestCaseRegistry const& getTestCaseRegistry() const override { + return m_testCaseRegistry; + } + IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() + const override { + return m_exceptionTranslatorRegistry; + } + ITagAliasRegistry const& getTagAliasRegistry() const override { + return m_tagAliasRegistry; + } + StartupExceptionRegistry const& getStartupExceptionRegistry() const override { + return m_exceptionRegistry; + } - public: // IRegistryHub - RegistryHub() = default; - IReporterRegistry const& getReporterRegistry() const override { - return m_reporterRegistry; - } - ITestCaseRegistry const& getTestCaseRegistry() const override { - return m_testCaseRegistry; - } - IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override { - return m_exceptionTranslatorRegistry; - } - ITagAliasRegistry const& getTagAliasRegistry() const override { - return m_tagAliasRegistry; - } - StartupExceptionRegistry const& getStartupExceptionRegistry() const override { - return m_exceptionRegistry; - } + public: // IMutableRegistryHub + void registerReporter(std::string const& name, + IReporterFactoryPtr const& factory) override { + m_reporterRegistry.registerReporter(name, factory); + } + void registerListener(IReporterFactoryPtr const& factory) override { + m_reporterRegistry.registerListener(factory); + } + void registerTest(TestCase const& testInfo) override { + m_testCaseRegistry.registerTest(testInfo); + } + void registerTranslator(const IExceptionTranslator* translator) override { + m_exceptionTranslatorRegistry.registerTranslator(translator); + } + void registerTagAlias(std::string const& alias, std::string const& tag, + SourceLineInfo const& lineInfo) override { + m_tagAliasRegistry.add(alias, tag, lineInfo); + } + void registerStartupException() noexcept override { + m_exceptionRegistry.add(std::current_exception()); + } - public: // IMutableRegistryHub - void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { - m_reporterRegistry.registerReporter( name, factory ); - } - void registerListener( IReporterFactoryPtr const& factory ) override { - m_reporterRegistry.registerListener( factory ); - } - void registerTest( TestCase const& testInfo ) override { - m_testCaseRegistry.registerTest( testInfo ); - } - void registerTranslator( const IExceptionTranslator* translator ) override { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { - m_tagAliasRegistry.add( alias, tag, lineInfo ); - } - void registerStartupException() noexcept override { - m_exceptionRegistry.add(std::current_exception()); - } + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + TagAliasRegistry m_tagAliasRegistry; + StartupExceptionRegistry m_exceptionRegistry; +}; +} // namespace - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - TagAliasRegistry m_tagAliasRegistry; - StartupExceptionRegistry m_exceptionRegistry; - }; - } +using RegistryHubSingleton = + Singleton; - using RegistryHubSingleton = Singleton; +IRegistryHub const& getRegistryHub() { return RegistryHubSingleton::get(); } +IMutableRegistryHub& getMutableRegistryHub() { + return RegistryHubSingleton::getMutable(); +} +void cleanUp() { + cleanupSingletons(); + cleanUpContext(); +} +std::string translateActiveException() { + return getRegistryHub() + .getExceptionTranslatorRegistry() + .translateActiveException(); +} - IRegistryHub const& getRegistryHub() { - return RegistryHubSingleton::get(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return RegistryHubSingleton::getMutable(); - } - void cleanUp() { - cleanupSingletons(); - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch +} // end namespace Catch // end catch_registry_hub.cpp // start catch_reporter_registry.cpp namespace Catch { - ReporterRegistry::~ReporterRegistry() = default; - - IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { - auto it = m_factories.find( name ); - if( it == m_factories.end() ) - return nullptr; - return it->second->create( ReporterConfig( config ) ); - } - - void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.emplace(name, factory); - } - void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { - m_listeners.push_back( factory ); - } - - IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { - return m_factories; - } - IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { - return m_listeners; - } +ReporterRegistry::~ReporterRegistry() = default; +IStreamingReporterPtr ReporterRegistry::create(std::string const& name, + IConfigPtr const& config) const { + auto it = m_factories.find(name); + if (it == m_factories.end()) return nullptr; + return it->second->create(ReporterConfig(config)); } + +void ReporterRegistry::registerReporter(std::string const& name, + IReporterFactoryPtr const& factory) { + m_factories.emplace(name, factory); +} +void ReporterRegistry::registerListener(IReporterFactoryPtr const& factory) { + m_listeners.push_back(factory); +} + +IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { + return m_factories; +} +IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { + return m_listeners; +} + +} // namespace Catch // end catch_reporter_registry.cpp // start catch_result_type.cpp namespace Catch { - bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } +bool isOk(ResultWas::OfType resultType) { + return (resultType & ResultWas::FailureBit) == 0; +} +bool isJustInfo(int flags) { return flags == ResultWas::Info; } - ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } +ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, + ResultDisposition::Flags rhs) { + return static_cast(static_cast(lhs) | + static_cast(rhs)); +} - bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } +bool shouldContinueOnFailure(int flags) { + return (flags & ResultDisposition::ContinueOnFailure) != 0; +} +bool shouldSuppressFailure(int flags) { + return (flags & ResultDisposition::SuppressFail) != 0; +} -} // end namespace Catch +} // end namespace Catch // end catch_result_type.cpp // start catch_run_context.cpp -#include #include +#include #include namespace Catch { - namespace Generators { - struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { - size_t m_index = static_cast( -1 ); - GeneratorBasePtr m_generator; +namespace Generators { +struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { + size_t m_index = static_cast(-1); + GeneratorBasePtr m_generator; - GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - {} - ~GeneratorTracker(); + GeneratorTracker(TestCaseTracking::NameAndLocation const& nameAndLocation, + TrackerContext& ctx, ITracker* parent) + : TrackerBase(nameAndLocation, ctx, parent) {} + ~GeneratorTracker(); - static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { - std::shared_ptr tracker; + static GeneratorTracker& acquire( + TrackerContext& ctx, + TestCaseTracking::NameAndLocation const& nameAndLocation) { + std::shared_ptr tracker; - ITracker& currentTracker = ctx.currentTracker(); - if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = std::static_pointer_cast( childTracker ); - } - else { - tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( tracker ); - } - - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - void moveNext() { - m_index++; - m_children.clear(); - } - - // TrackerBase interface - bool isIndexTracker() const override { return true; } - auto hasGenerator() const -> bool override { - return !!m_generator; - } - void close() override { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 ) - m_runState = Executing; - } - - // IGeneratorTracker interface - auto getGenerator() const -> GeneratorBasePtr const& override { - return m_generator; - } - void setGenerator( GeneratorBasePtr&& generator ) override { - m_generator = std::move( generator ); - } - auto getIndex() const -> size_t override { - return m_index; - } - }; - GeneratorTracker::~GeneratorTracker() {} + ITracker& currentTracker = ctx.currentTracker(); + if (TestCaseTracking::ITrackerPtr childTracker = + currentTracker.findChild(nameAndLocation)) { + assert(childTracker); + assert(childTracker->isIndexTracker()); + tracker = std::static_pointer_cast(childTracker); + } else { + tracker = std::make_shared(nameAndLocation, ctx, + ¤tTracker); + currentTracker.addChild(tracker); } - RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) - : m_runInfo(_config->name()), - m_context(getCurrentMutableContext()), - m_config(_config), - m_reporter(std::move(reporter)), - m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, - m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) - { - m_context.setRunner(this); - m_context.setConfig(m_config); - m_context.setResultCapture(this); - m_reporter->testRunStarting(m_runInfo); + if (!ctx.completedCycle() && !tracker->isComplete()) { + if (tracker->m_runState != ExecutingChildren && + tracker->m_runState != NeedsAnotherRun) + tracker->moveNext(); + tracker->open(); } - RunContext::~RunContext() { - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); - } - - void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { - m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); - } - - void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { - m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); - } - - Totals RunContext::runTest(TestCase const& testCase) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - auto const& testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting(testInfo); - - m_activeTestCase = &testCase; - - ITracker& rootTracker = m_trackerContext.startRun(); - assert(rootTracker.isSectionTracker()); - static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); - runCurrentTest(redirectedCout, redirectedCerr); - } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); - - Totals deltaTotals = m_totals.delta(prevTotals); - if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded(TestCaseStats(testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting())); - - m_activeTestCase = nullptr; - m_testCaseTracker = nullptr; - - return deltaTotals; - } - - IConfigPtr RunContext::config() const { - return m_config; - } - - IStreamingReporter& RunContext::reporter() const { - return *m_reporter; - } - - void RunContext::assertionEnded(AssertionResult const & result) { - if (result.getResultType() == ResultWas::Ok) { - m_totals.assertions.passed++; - m_lastAssertionPassed = true; - } else if (!result.isOk()) { - m_lastAssertionPassed = false; - if( m_activeTestCase->getTestCaseInfo().okToFail() ) - m_totals.assertions.failedButOk++; - else - m_totals.assertions.failed++; - } - else { - m_lastAssertionPassed = true; - } - - // We have no use for the return value (whether messages should be cleared), because messages were made scoped - // and should be let to clear themselves out. - static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); - - // Reset working state - resetAssertionInfo(); - m_lastResult = result; - } - void RunContext::resetAssertionInfo() { - m_lastAssertionInfo.macroName = StringRef(); - m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; - } - - bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { - ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); - if (!sectionTracker.isOpen()) - return false; - m_activeSections.push_back(§ionTracker); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting(sectionInfo); - - assertions = m_totals.assertions; - - return true; - } - auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { - using namespace Generators; - GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) ); - assert( tracker.isOpen() ); - m_lastAssertionInfo.lineInfo = lineInfo; - return tracker; - } - - bool RunContext::testForMissingAssertions(Counts& assertions) { - if (assertions.total() != 0) - return false; - if (!m_config->warnAboutMissingAssertions()) - return false; - if (m_trackerContext.currentTracker().hasChildren()) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - void RunContext::sectionEnded(SectionEndInfo const & endInfo) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions(assertions); - - if (!m_activeSections.empty()) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); - m_messages.clear(); - } - - void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { - if (m_unfinishedSections.empty()) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back(endInfo); - } - void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { - m_reporter->benchmarkStarting( info ); - } - void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { - m_reporter->benchmarkEnded( stats ); - } - - void RunContext::pushScopedMessage(MessageInfo const & message) { - m_messages.push_back(message); - } - - void RunContext::popScopedMessage(MessageInfo const & message) { - m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); - } - - std::string RunContext::getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : std::string(); - } - - const AssertionResult * RunContext::getLastResult() const { - return &(*m_lastResult); - } - - void RunContext::exceptionEarlyReported() { - m_shouldReportUnexpected = false; - } - - void RunContext::handleFatalErrorCondition( StringRef message ) { - // First notify reporter that bad things happened - m_reporter->fatalErrorEncountered(message); - - // Don't rebuild the result -- the stringification itself can cause more fatal errors - // Instead, fake a result data. - AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); - tempResult.message = message; - AssertionResult result(m_lastAssertionInfo, tempResult); - - assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); - m_reporter->sectionEnded(testCaseSectionStats); - - auto const& testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - deltaTotals.assertions.failed = 1; - m_reporter->testCaseEnded(TestCaseStats(testInfo, - deltaTotals, - std::string(), - std::string(), - false)); - m_totals.testCases.failed++; - testGroupEnded(std::string(), m_totals, 1, 1); - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); - } - - bool RunContext::lastAssertionPassed() { - return m_lastAssertionPassed; - } - - void RunContext::assertionPassed() { - m_lastAssertionPassed = true; - ++m_totals.assertions.passed; - resetAssertionInfo(); - } - - bool RunContext::aborting() const { - return m_totals.assertions.failed >= static_cast(m_config->abortAfter()); - } - - void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { - auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); - m_reporter->sectionStarting(testCaseSection); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - m_shouldReportUnexpected = true; - m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; - - seedRng(*m_config); - - Timer timer; - CATCH_TRY { - if (m_reporter->getPreferences().shouldRedirectStdOut) { -#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) - RedirectedStdOut redirectedStdOut; - RedirectedStdErr redirectedStdErr; - - timer.start(); - invokeActiveTestCase(); - redirectedCout += redirectedStdOut.str(); - redirectedCerr += redirectedStdErr.str(); -#else - OutputRedirect r(redirectedCout, redirectedCerr); - timer.start(); - invokeActiveTestCase(); -#endif - } else { - timer.start(); - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } CATCH_CATCH_ANON (TestFailureException&) { - // This just means the test was aborted due to failure - } CATCH_CATCH_ALL { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions - // are reported without translation at the point of origin. - if( m_shouldReportUnexpected ) { - AssertionReaction dummyReaction; - handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); - } - } - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions(assertions); - - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); - m_reporter->sectionEnded(testCaseSectionStats); - } - - void RunContext::invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - void RunContext::handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for (auto it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it) - sectionEnded(*it); - m_unfinishedSections.clear(); - } - - void RunContext::handleExpr( - AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction - ) { - m_reporter->assertionStarting( info ); - - bool negated = isFalseTest( info.resultDisposition ); - bool result = expr.getResult() != negated; - - if( result ) { - if (!m_includeSuccessfulResults) { - assertionPassed(); - } - else { - reportExpr(info, ResultWas::Ok, &expr, negated); - } - } - else { - reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); - populateReaction( reaction ); - } - } - void RunContext::reportExpr( - AssertionInfo const &info, - ResultWas::OfType resultType, - ITransientExpression const *expr, - bool negated ) { - - m_lastAssertionInfo = info; - AssertionResultData data( resultType, LazyExpression( negated ) ); - - AssertionResult assertionResult{ info, data }; - assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; - - assertionEnded( assertionResult ); - } - - void RunContext::handleMessage( - AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef const& message, - AssertionReaction& reaction - ) { - m_reporter->assertionStarting( info ); - - m_lastAssertionInfo = info; - - AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = message; - AssertionResult assertionResult{ m_lastAssertionInfo, data }; - assertionEnded( assertionResult ); - if( !assertionResult.isOk() ) - populateReaction( reaction ); - } - void RunContext::handleUnexpectedExceptionNotThrown( - AssertionInfo const& info, - AssertionReaction& reaction - ) { - handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); - } - - void RunContext::handleUnexpectedInflightException( - AssertionInfo const& info, - std::string const& message, - AssertionReaction& reaction - ) { - m_lastAssertionInfo = info; - - AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); - data.message = message; - AssertionResult assertionResult{ info, data }; - assertionEnded( assertionResult ); - populateReaction( reaction ); - } - - void RunContext::populateReaction( AssertionReaction& reaction ) { - reaction.shouldDebugBreak = m_config->shouldDebugBreak(); - reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); - } - - void RunContext::handleIncomplete( - AssertionInfo const& info - ) { - m_lastAssertionInfo = info; - - AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); - data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; - AssertionResult assertionResult{ info, data }; - assertionEnded( assertionResult ); - } - void RunContext::handleNonExpr( - AssertionInfo const &info, - ResultWas::OfType resultType, - AssertionReaction &reaction - ) { - m_lastAssertionInfo = info; - - AssertionResultData data( resultType, LazyExpression( false ) ); - AssertionResult assertionResult{ info, data }; - assertionEnded( assertionResult ); - - if( !assertionResult.isOk() ) - populateReaction( reaction ); - } - - IResultCapture& getResultCapture() { - if (auto* capture = getCurrentContext().getResultCapture()) - return *capture; - else - CATCH_INTERNAL_ERROR("No result capture instance"); - } + return *tracker; + } + + void moveNext() { + m_index++; + m_children.clear(); + } + + // TrackerBase interface + bool isIndexTracker() const override { return true; } + auto hasGenerator() const -> bool override { return !!m_generator; } + void close() override { + TrackerBase::close(); + if (m_runState == CompletedSuccessfully && + m_index < m_generator->size() - 1) + m_runState = Executing; + } + + // IGeneratorTracker interface + auto getGenerator() const -> GeneratorBasePtr const& override { + return m_generator; + } + void setGenerator(GeneratorBasePtr&& generator) override { + m_generator = std::move(generator); + } + auto getIndex() const -> size_t override { return m_index; } +}; +GeneratorTracker::~GeneratorTracker() {} +} // namespace Generators + +RunContext::RunContext(IConfigPtr const& _config, + IStreamingReporterPtr&& reporter) + : m_runInfo(_config->name()), + m_context(getCurrentMutableContext()), + m_config(_config), + m_reporter(std::move(reporter)), + m_lastAssertionInfo{StringRef(), SourceLineInfo("", 0), StringRef(), + ResultDisposition::Normal}, + m_includeSuccessfulResults( + m_config->includeSuccessfulResults() || + m_reporter->getPreferences().shouldReportAllAssertions) { + m_context.setRunner(this); + m_context.setConfig(m_config); + m_context.setResultCapture(this); + m_reporter->testRunStarting(m_runInfo); } + +RunContext::~RunContext() { + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); +} + +void RunContext::testGroupStarting(std::string const& testSpec, + std::size_t groupIndex, + std::size_t groupsCount) { + m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); +} + +void RunContext::testGroupEnded(std::string const& testSpec, + Totals const& totals, std::size_t groupIndex, + std::size_t groupsCount) { + m_reporter->testGroupEnded(TestGroupStats( + GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); +} + +Totals RunContext::runTest(TestCase const& testCase) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + auto const& testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting(testInfo); + + m_activeTestCase = &testCase; + + ITracker& rootTracker = m_trackerContext.startRun(); + assert(rootTracker.isSectionTracker()); + static_cast(rootTracker) + .addInitialFilters(m_config->getSectionsToRun()); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( + m_trackerContext, + TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); + runCurrentTest(redirectedCout, redirectedCerr); + } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); + + Totals deltaTotals = m_totals.delta(prevTotals); + if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded(TestCaseStats(testInfo, deltaTotals, redirectedCout, + redirectedCerr, aborting())); + + m_activeTestCase = nullptr; + m_testCaseTracker = nullptr; + + return deltaTotals; +} + +IConfigPtr RunContext::config() const { return m_config; } + +IStreamingReporter& RunContext::reporter() const { return *m_reporter; } + +void RunContext::assertionEnded(AssertionResult const& result) { + if (result.getResultType() == ResultWas::Ok) { + m_totals.assertions.passed++; + m_lastAssertionPassed = true; + } else if (!result.isOk()) { + m_lastAssertionPassed = false; + if (m_activeTestCase->getTestCaseInfo().okToFail()) + m_totals.assertions.failedButOk++; + else + m_totals.assertions.failed++; + } else { + m_lastAssertionPassed = true; + } + + // We have no use for the return value (whether messages should be cleared), + // because messages were made scoped and should be let to clear themselves + // out. + static_cast( + m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + + // Reset working state + resetAssertionInfo(); + m_lastResult = result; +} +void RunContext::resetAssertionInfo() { + m_lastAssertionInfo.macroName = StringRef(); + m_lastAssertionInfo.capturedExpression = + "{Unknown expression after the reported line}"_sr; +} + +bool RunContext::sectionStarted(SectionInfo const& sectionInfo, + Counts& assertions) { + ITracker& sectionTracker = SectionTracker::acquire( + m_trackerContext, TestCaseTracking::NameAndLocation( + sectionInfo.name, sectionInfo.lineInfo)); + if (!sectionTracker.isOpen()) return false; + m_activeSections.push_back(§ionTracker); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting(sectionInfo); + + assertions = m_totals.assertions; + + return true; +} +auto RunContext::acquireGeneratorTracker(SourceLineInfo const& lineInfo) + -> IGeneratorTracker& { + using namespace Generators; + GeneratorTracker& tracker = GeneratorTracker::acquire( + m_trackerContext, + TestCaseTracking::NameAndLocation("generator", lineInfo)); + assert(tracker.isOpen()); + m_lastAssertionInfo.lineInfo = lineInfo; + return tracker; +} + +bool RunContext::testForMissingAssertions(Counts& assertions) { + if (assertions.total() != 0) return false; + if (!m_config->warnAboutMissingAssertions()) return false; + if (m_trackerContext.currentTracker().hasChildren()) return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; +} + +void RunContext::sectionEnded(SectionEndInfo const& endInfo) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (!m_activeSections.empty()) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, + endInfo.durationInSeconds, + missingAssertions)); + m_messages.clear(); +} + +void RunContext::sectionEndedEarly(SectionEndInfo const& endInfo) { + if (m_unfinishedSections.empty()) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back(endInfo); +} +void RunContext::benchmarkStarting(BenchmarkInfo const& info) { + m_reporter->benchmarkStarting(info); +} +void RunContext::benchmarkEnded(BenchmarkStats const& stats) { + m_reporter->benchmarkEnded(stats); +} + +void RunContext::pushScopedMessage(MessageInfo const& message) { + m_messages.push_back(message); +} + +void RunContext::popScopedMessage(MessageInfo const& message) { + m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), + m_messages.end()); +} + +std::string RunContext::getCurrentTestName() const { + return m_activeTestCase ? m_activeTestCase->getTestCaseInfo().name + : std::string(); +} + +const AssertionResult* RunContext::getLastResult() const { + return &(*m_lastResult); +} + +void RunContext::exceptionEarlyReported() { m_shouldReportUnexpected = false; } + +void RunContext::handleFatalErrorCondition(StringRef message) { + // First notify reporter that bad things happened + m_reporter->fatalErrorEncountered(message); + + // Don't rebuild the result -- the stringification itself can cause more fatal + // errors Instead, fake a result data. + AssertionResultData tempResult(ResultWas::FatalErrorCondition, {false}); + tempResult.message = message; + AssertionResult result(m_lastAssertionInfo, tempResult); + + assertionEnded(result); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); + m_reporter->sectionEnded(testCaseSectionStats); + + auto const& testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + deltaTotals.assertions.failed = 1; + m_reporter->testCaseEnded(TestCaseStats(testInfo, deltaTotals, std::string(), + std::string(), false)); + m_totals.testCases.failed++; + testGroupEnded(std::string(), m_totals, 1, 1); + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); +} + +bool RunContext::lastAssertionPassed() { return m_lastAssertionPassed; } + +void RunContext::assertionPassed() { + m_lastAssertionPassed = true; + ++m_totals.assertions.passed; + resetAssertionInfo(); +} + +bool RunContext::aborting() const { + return m_totals.assertions.failed >= + static_cast(m_config->abortAfter()); +} + +void RunContext::runCurrentTest(std::string& redirectedCout, + std::string& redirectedCerr) { + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); + m_reporter->sectionStarting(testCaseSection); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + m_shouldReportUnexpected = true; + m_lastAssertionInfo = {"TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), + ResultDisposition::Normal}; + + seedRng(*m_config); + + Timer timer; + CATCH_TRY { + if (m_reporter->getPreferences().shouldRedirectStdOut) { +#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) + RedirectedStdOut redirectedStdOut; + RedirectedStdErr redirectedStdErr; + + timer.start(); + invokeActiveTestCase(); + redirectedCout += redirectedStdOut.str(); + redirectedCerr += redirectedStdErr.str(); +#else + OutputRedirect r(redirectedCout, redirectedCerr); + timer.start(); + invokeActiveTestCase(); +#endif + } else { + timer.start(); + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + CATCH_CATCH_ANON(TestFailureException&) { + // This just means the test was aborted due to failure + } + CATCH_CATCH_ALL { + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE + // assertions are reported without translation at the point of origin. + if (m_shouldReportUnexpected) { + AssertionReaction dummyReaction; + handleUnexpectedInflightException( + m_lastAssertionInfo, translateActiveException(), dummyReaction); + } + } + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + SectionStats testCaseSectionStats(testCaseSection, assertions, duration, + missingAssertions); + m_reporter->sectionEnded(testCaseSectionStats); +} + +void RunContext::invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); +} + +void RunContext::handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for (auto it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; ++it) + sectionEnded(*it); + m_unfinishedSections.clear(); +} + +void RunContext::handleExpr(AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction) { + m_reporter->assertionStarting(info); + + bool negated = isFalseTest(info.resultDisposition); + bool result = expr.getResult() != negated; + + if (result) { + if (!m_includeSuccessfulResults) { + assertionPassed(); + } else { + reportExpr(info, ResultWas::Ok, &expr, negated); + } + } else { + reportExpr(info, ResultWas::ExpressionFailed, &expr, negated); + populateReaction(reaction); + } +} +void RunContext::reportExpr(AssertionInfo const& info, + ResultWas::OfType resultType, + ITransientExpression const* expr, bool negated) { + m_lastAssertionInfo = info; + AssertionResultData data(resultType, LazyExpression(negated)); + + AssertionResult assertionResult{info, data}; + assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; + + assertionEnded(assertionResult); +} + +void RunContext::handleMessage(AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef const& message, + AssertionReaction& reaction) { + m_reporter->assertionStarting(info); + + m_lastAssertionInfo = info; + + AssertionResultData data(resultType, LazyExpression(false)); + data.message = message; + AssertionResult assertionResult{m_lastAssertionInfo, data}; + assertionEnded(assertionResult); + if (!assertionResult.isOk()) populateReaction(reaction); +} +void RunContext::handleUnexpectedExceptionNotThrown( + AssertionInfo const& info, AssertionReaction& reaction) { + handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); +} + +void RunContext::handleUnexpectedInflightException( + AssertionInfo const& info, std::string const& message, + AssertionReaction& reaction) { + m_lastAssertionInfo = info; + + AssertionResultData data(ResultWas::ThrewException, LazyExpression(false)); + data.message = message; + AssertionResult assertionResult{info, data}; + assertionEnded(assertionResult); + populateReaction(reaction); +} + +void RunContext::populateReaction(AssertionReaction& reaction) { + reaction.shouldDebugBreak = m_config->shouldDebugBreak(); + reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & + ResultDisposition::Normal); +} + +void RunContext::handleIncomplete(AssertionInfo const& info) { + m_lastAssertionInfo = info; + + AssertionResultData data(ResultWas::ThrewException, LazyExpression(false)); + data.message = + "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; + AssertionResult assertionResult{info, data}; + assertionEnded(assertionResult); +} +void RunContext::handleNonExpr(AssertionInfo const& info, + ResultWas::OfType resultType, + AssertionReaction& reaction) { + m_lastAssertionInfo = info; + + AssertionResultData data(resultType, LazyExpression(false)); + AssertionResult assertionResult{info, data}; + assertionEnded(assertionResult); + + if (!assertionResult.isOk()) populateReaction(reaction); +} + +IResultCapture& getResultCapture() { + if (auto* capture = getCurrentContext().getResultCapture()) + return *capture; + else + CATCH_INTERNAL_ERROR("No result capture instance"); +} +} // namespace Catch // end catch_run_context.cpp // start catch_section.cpp namespace Catch { - Section::Section( SectionInfo const& info ) - : m_info( info ), - m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } +Section::Section(SectionInfo const& info) + : m_info(info), + m_sectionIncluded( + getResultCapture().sectionStarted(m_info, m_assertions)) { + m_timer.start(); +} - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() }; - if( uncaught_exceptions() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); - } - } +Section::~Section() { + if (m_sectionIncluded) { + SectionEndInfo endInfo{m_info, m_assertions, m_timer.getElapsedSeconds()}; + if (uncaught_exceptions()) + getResultCapture().sectionEndedEarly(endInfo); + else + getResultCapture().sectionEnded(endInfo); + } +} - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; - } +// This indicates whether the section should be executed or not +Section::operator bool() const { return m_sectionIncluded; } -} // end namespace Catch +} // end namespace Catch // end catch_section.cpp // start catch_section_info.cpp namespace Catch { - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name ) - : name( _name ), - lineInfo( _lineInfo ) - {} +SectionInfo::SectionInfo(SourceLineInfo const& _lineInfo, + std::string const& _name) + : name(_name), lineInfo(_lineInfo) {} -} // end namespace Catch +} // end namespace Catch // end catch_section_info.cpp // start catch_session.cpp @@ -10209,48 +10372,46 @@ namespace Catch { namespace Catch { - class Session : NonCopyable { - public: +class Session : NonCopyable { + public: + Session(); + ~Session() override; - Session(); - ~Session() override; + void showHelp() const; + void libIdentify(); - void showHelp() const; - void libIdentify(); + int applyCommandLine(int argc, char const* const* argv); +#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) + int applyCommandLine(int argc, wchar_t const* const* argv); +#endif - int applyCommandLine( int argc, char const * const * argv ); - #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) - int applyCommandLine( int argc, wchar_t const * const * argv ); - #endif + void useConfigData(ConfigData const& configData); - void useConfigData( ConfigData const& configData ); + template + int run(int argc, CharT const* const argv[]) { + if (m_startupExceptions) return 1; + int returnCode = applyCommandLine(argc, argv); + if (returnCode == 0) returnCode = run(); + return returnCode; + } - template - int run(int argc, CharT const * const argv[]) { - if (m_startupExceptions) - return 1; - int returnCode = applyCommandLine(argc, argv); - if (returnCode == 0) - returnCode = run(); - return returnCode; - } + int run(); - int run(); + clara::Parser const& cli() const; + void cli(clara::Parser const& newParser); + ConfigData& configData(); + Config& config(); - clara::Parser const& cli() const; - void cli( clara::Parser const& newParser ); - ConfigData& configData(); - Config& config(); - private: - int runInternal(); + private: + int runInternal(); - clara::Parser m_cli; - ConfigData m_configData; - std::shared_ptr m_config; - bool m_startupExceptions = false; - }; + clara::Parser m_cli; + ConfigData m_configData; + std::shared_ptr m_config; + bool m_startupExceptions = false; +}; -} // end namespace Catch +} // end namespace Catch // end catch_session.h // start catch_version.h @@ -10259,29 +10420,27 @@ namespace Catch { namespace Catch { - // Versioning information - struct Version { - Version( Version const& ) = delete; - Version& operator=( Version const& ) = delete; - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ); +// Versioning information +struct Version { + Version(Version const&) = delete; + Version& operator=(Version const&) = delete; + Version(unsigned int _majorVersion, unsigned int _minorVersion, + unsigned int _patchNumber, char const* const _branchName, + unsigned int _buildNumber); - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; - // buildNumber is only used if branchName is not null - char const * const branchName; - unsigned int const buildNumber; + // buildNumber is only used if branchName is not null + char const* const branchName; + unsigned int const buildNumber; - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - }; + friend std::ostream& operator<<(std::ostream& os, Version const& version); +}; - Version const& libraryVersion(); -} +Version const& libraryVersion(); +} // namespace Catch // end catch_version.h #include @@ -10289,253 +10448,248 @@ namespace Catch { namespace Catch { - namespace { - const int MaxExitCode = 255; +namespace { +const int MaxExitCode = 255; - IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { - auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); - CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); +IStreamingReporterPtr createReporter(std::string const& reporterName, + IConfigPtr const& config) { + auto reporter = Catch::getRegistryHub().getReporterRegistry().create( + reporterName, config); + CATCH_ENFORCE(reporter, + "No reporter registered with name: '" << reporterName << "'"); - return reporter; - } + return reporter; +} - IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { - if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { - return createReporter(config->getReporterName(), config); - } +IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { + if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { + return createReporter(config->getReporterName(), config); + } - auto multi = std::unique_ptr(new ListeningReporter); + auto multi = std::unique_ptr(new ListeningReporter); - auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); - for (auto const& listener : listeners) { - multi->addListener(listener->create(Catch::ReporterConfig(config))); - } - multi->addReporter(createReporter(config->getReporterName(), config)); - return std::move(multi); - } + auto const& listeners = + Catch::getRegistryHub().getReporterRegistry().getListeners(); + for (auto const& listener : listeners) { + multi->addListener(listener->create(Catch::ReporterConfig(config))); + } + multi->addReporter(createReporter(config->getReporterName(), config)); + return std::move(multi); +} - Catch::Totals runTests(std::shared_ptr const& config) { - auto reporter = makeReporter(config); +Catch::Totals runTests(std::shared_ptr const& config) { + auto reporter = makeReporter(config); - RunContext context(config, std::move(reporter)); + RunContext context(config, std::move(reporter)); - Totals totals; + Totals totals; - context.testGroupStarting(config->name(), 1, 1); + context.testGroupStarting(config->name(), 1, 1); - TestSpec testSpec = config->testSpec(); + TestSpec testSpec = config->testSpec(); - auto const& allTestCases = getAllTestCasesSorted(*config); - for (auto const& testCase : allTestCases) { - if (!context.aborting() && matchTest(testCase, testSpec, *config)) - totals += context.runTest(testCase); - else - context.reporter().skipTest(testCase); - } + auto const& allTestCases = getAllTestCasesSorted(*config); + for (auto const& testCase : allTestCases) { + if (!context.aborting() && matchTest(testCase, testSpec, *config)) + totals += context.runTest(testCase); + else + context.reporter().skipTest(testCase); + } - if (config->warnAboutNoTests() && totals.testCases.total() == 0) { - ReusableStringStream testConfig; + if (config->warnAboutNoTests() && totals.testCases.total() == 0) { + ReusableStringStream testConfig; - bool first = true; - for (const auto& input : config->getTestsOrTags()) { - if (!first) { testConfig << ' '; } - first = false; - testConfig << input; - } + bool first = true; + for (const auto& input : config->getTestsOrTags()) { + if (!first) { testConfig << ' '; } + first = false; + testConfig << input; + } - context.reporter().noMatchingTestCases(testConfig.str()); - totals.error = -1; - } + context.reporter().noMatchingTestCases(testConfig.str()); + totals.error = -1; + } - context.testGroupEnded(config->name(), totals, 1, 1); - return totals; - } + context.testGroupEnded(config->name(), totals, 1, 1); + return totals; +} - void applyFilenamesAsTags(Catch::IConfig const& config) { - auto& tests = const_cast&>(getAllTestCasesSorted(config)); - for (auto& testCase : tests) { - auto tags = testCase.tags; +void applyFilenamesAsTags(Catch::IConfig const& config) { + auto& tests = + const_cast&>(getAllTestCasesSorted(config)); + for (auto& testCase : tests) { + auto tags = testCase.tags; - std::string filename = testCase.lineInfo.file; - auto lastSlash = filename.find_last_of("\\/"); - if (lastSlash != std::string::npos) { - filename.erase(0, lastSlash); - filename[0] = '#'; - } + std::string filename = testCase.lineInfo.file; + auto lastSlash = filename.find_last_of("\\/"); + if (lastSlash != std::string::npos) { + filename.erase(0, lastSlash); + filename[0] = '#'; + } - auto lastDot = filename.find_last_of('.'); - if (lastDot != std::string::npos) { - filename.erase(lastDot); - } + auto lastDot = filename.find_last_of('.'); + if (lastDot != std::string::npos) { filename.erase(lastDot); } - tags.push_back(std::move(filename)); - setTags(testCase, tags); - } - } + tags.push_back(std::move(filename)); + setTags(testCase, tags); + } +} - } // anon namespace +} // namespace - Session::Session() { - static bool alreadyInstantiated = false; - if( alreadyInstantiated ) { - CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } - CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } - } +Session::Session() { + static bool alreadyInstantiated = false; + if (alreadyInstantiated) { + CATCH_TRY { + CATCH_INTERNAL_ERROR( + "Only one instance of Catch::Session can ever be used"); + } + CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } + } - // There cannot be exceptions at startup in no-exception mode. + // There cannot be exceptions at startup in no-exception mode. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - m_startupExceptions = true; - Colour colourGuard( Colour::Red ); - Catch::cerr() << "Errors occurred during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; - } - } - } + const auto& exceptions = + getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if (!exceptions.empty()) { + m_startupExceptions = true; + Colour colourGuard(Colour::Red); + Catch::cerr() << "Errors occurred during startup!" << '\n'; + // iterate over all exceptions and notify user + for (const auto& ex_ptr : exceptions) { + try { + std::rethrow_exception(ex_ptr); + } catch (std::exception const& ex) { + Catch::cerr() << Column(ex.what()).indent(2) << '\n'; + } + } + } #endif - alreadyInstantiated = true; - m_cli = makeCommandLineParser( m_configData ); - } - Session::~Session() { - Catch::cleanUp(); - } + alreadyInstantiated = true; + m_cli = makeCommandLineParser(m_configData); +} +Session::~Session() { Catch::cleanUp(); } - void Session::showHelp() const { - Catch::cout() - << "\nCatch v" << libraryVersion() << "\n" +void Session::showHelp() const { + Catch::cout() << "\nCatch v" << libraryVersion() << "\n" << m_cli << std::endl - << "For more detailed usage please see the project docs\n" << std::endl; - } - void Session::libIdentify() { - Catch::cout() - << std::left << std::setw(16) << "description: " << "A Catch test executable\n" - << std::left << std::setw(16) << "category: " << "testframework\n" - << std::left << std::setw(16) << "framework: " << "Catch Test\n" - << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; - } + << "For more detailed usage please see the project docs\n" + << std::endl; +} +void Session::libIdentify() { + Catch::cout() << std::left << std::setw(16) << "description: " + << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " + << "testframework\n" + << std::left << std::setw(16) << "framework: " + << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() + << std::endl; +} - int Session::applyCommandLine( int argc, char const * const * argv ) { - if( m_startupExceptions ) - return 1; +int Session::applyCommandLine(int argc, char const* const* argv) { + if (m_startupExceptions) return 1; - auto result = m_cli.parse( clara::Args( argc, argv ) ); - if( !result ) { - Catch::cerr() - << Colour( Colour::Red ) - << "\nError(s) in input:\n" - << Column( result.errorMessage() ).indent( 2 ) - << "\n\n"; - Catch::cerr() << "Run with -? for usage\n" << std::endl; - return MaxExitCode; - } + auto result = m_cli.parse(clara::Args(argc, argv)); + if (!result) { + Catch::cerr() << Colour(Colour::Red) << "\nError(s) in input:\n" + << Column(result.errorMessage()).indent(2) << "\n\n"; + Catch::cerr() << "Run with -? for usage\n" << std::endl; + return MaxExitCode; + } - if( m_configData.showHelp ) - showHelp(); - if( m_configData.libIdentify ) - libIdentify(); - m_config.reset(); - return 0; - } + if (m_configData.showHelp) showHelp(); + if (m_configData.libIdentify) libIdentify(); + m_config.reset(); + return 0; +} #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) - int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { +int Session::applyCommandLine(int argc, wchar_t const* const* argv) { + char** utf8Argv = new char*[argc]; - char **utf8Argv = new char *[ argc ]; + for (int i = 0; i < argc; ++i) { + int bufSize = + WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL); - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + utf8Argv[i] = new char[bufSize]; - utf8Argv[ i ] = new char[ bufSize ]; + WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, + NULL); + } - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); - } + int returnCode = applyCommandLine(argc, utf8Argv); - int returnCode = applyCommandLine( argc, utf8Argv ); + for (int i = 0; i < argc; ++i) delete[] utf8Argv[i]; - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; + delete[] utf8Argv; - delete [] utf8Argv; - - return returnCode; - } + return returnCode; +} #endif - void Session::useConfigData( ConfigData const& configData ) { - m_configData = configData; - m_config.reset(); - } +void Session::useConfigData(ConfigData const& configData) { + m_configData = configData; + m_config.reset(); +} - int Session::run() { - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before starting" << std::endl; - static_cast(std::getchar()); - } - int exitCode = runInternal(); - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; - static_cast(std::getchar()); - } - return exitCode; - } +int Session::run() { + if ((m_configData.waitForKeypress & WaitForKeypress::BeforeStart) != 0) { + Catch::cout() << "...waiting for enter/ return before starting" + << std::endl; + static_cast(std::getchar()); + } + int exitCode = runInternal(); + if ((m_configData.waitForKeypress & WaitForKeypress::BeforeExit) != 0) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " + << exitCode << std::endl; + static_cast(std::getchar()); + } + return exitCode; +} - clara::Parser const& Session::cli() const { - return m_cli; - } - void Session::cli( clara::Parser const& newParser ) { - m_cli = newParser; - } - ConfigData& Session::configData() { - return m_configData; - } - Config& Session::config() { - if( !m_config ) - m_config = std::make_shared( m_configData ); - return *m_config; - } +clara::Parser const& Session::cli() const { return m_cli; } +void Session::cli(clara::Parser const& newParser) { m_cli = newParser; } +ConfigData& Session::configData() { return m_configData; } +Config& Session::config() { + if (!m_config) m_config = std::make_shared(m_configData); + return *m_config; +} - int Session::runInternal() { - if( m_startupExceptions ) - return 1; +int Session::runInternal() { + if (m_startupExceptions) return 1; - if (m_configData.showHelp || m_configData.libIdentify) { - return 0; - } + if (m_configData.showHelp || m_configData.libIdentify) { return 0; } - CATCH_TRY { - config(); // Force config to be constructed + CATCH_TRY { + config(); // Force config to be constructed - seedRng( *m_config ); + seedRng(*m_config); - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); + if (m_configData.filenamesAsTags) applyFilenamesAsTags(*m_config); - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); + // Handle list request + if (Option listed = list(config())) + return static_cast(*listed); - auto totals = runTests( m_config ); - // Note that on unices only the lower 8 bits are usually used, clamping - // the return value to 255 prevents false negative when some multiple - // of 256 tests has failed - return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast(totals.assertions.failed))); - } + auto totals = runTests(m_config); + // Note that on unices only the lower 8 bits are usually used, clamping + // the return value to 255 prevents false negative when some multiple + // of 256 tests has failed + return (std::min)( + MaxExitCode, + (std::max)(totals.error, static_cast(totals.assertions.failed))); + } #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return MaxExitCode; - } + catch (std::exception& ex) { + Catch::cerr() << ex.what() << std::endl; + return MaxExitCode; + } #endif - } +} -} // end namespace Catch +} // end namespace Catch // end catch_session.cpp // start catch_singletons.cpp @@ -10543,433 +10697,424 @@ namespace Catch { namespace Catch { - namespace { - static auto getSingletons() -> std::vector*& { - static std::vector* g_singletons = nullptr; - if( !g_singletons ) - g_singletons = new std::vector(); - return g_singletons; - } - } +namespace { +static auto getSingletons() -> std::vector*& { + static std::vector* g_singletons = nullptr; + if (!g_singletons) g_singletons = new std::vector(); + return g_singletons; +} +} // namespace - ISingleton::~ISingleton() {} +ISingleton::~ISingleton() {} - void addSingleton(ISingleton* singleton ) { - getSingletons()->push_back( singleton ); - } - void cleanupSingletons() { - auto& singletons = getSingletons(); - for( auto singleton : *singletons ) - delete singleton; - delete singletons; - singletons = nullptr; - } +void addSingleton(ISingleton* singleton) { + getSingletons()->push_back(singleton); +} +void cleanupSingletons() { + auto& singletons = getSingletons(); + for (auto singleton : *singletons) delete singleton; + delete singletons; + singletons = nullptr; +} -} // namespace Catch +} // namespace Catch // end catch_singletons.cpp // start catch_startup_exception_registry.cpp namespace Catch { -void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { - CATCH_TRY { - m_exceptions.push_back(exception); - } CATCH_CATCH_ALL { - // If we run out of memory during start-up there's really not a lot more we can do about it - std::terminate(); - } - } +void StartupExceptionRegistry::add( + std::exception_ptr const& exception) noexcept { + CATCH_TRY { m_exceptions.push_back(exception); } + CATCH_CATCH_ALL { + // If we run out of memory during start-up there's really not a lot more we + // can do about it + std::terminate(); + } +} - std::vector const& StartupExceptionRegistry::getExceptions() const noexcept { - return m_exceptions; - } +std::vector const& StartupExceptionRegistry::getExceptions() + const noexcept { + return m_exceptions; +} -} // end namespace Catch +} // end namespace Catch // end catch_startup_exception_registry.cpp // start catch_stream.cpp #include -#include #include +#include +#include #include #include -#include namespace Catch { - Catch::IStream::~IStream() = default; +Catch::IStream::~IStream() = default; - namespace detail { namespace { - template - class StreamBufImpl : public std::streambuf { - char data[bufferSize]; - WriterF m_writer; +namespace detail { +namespace { +template +class StreamBufImpl : public std::streambuf { + char data[bufferSize]; + WriterF m_writer; - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } + public: + StreamBufImpl() { setp(data, data + sizeof(data)); } - ~StreamBufImpl() noexcept { - StreamBufImpl::sync(); - } + ~StreamBufImpl() noexcept { StreamBufImpl::sync(); } - private: - int overflow( int c ) override { - sync(); + private: + int overflow(int c) override { + sync(); - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() override { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - /////////////////////////////////////////////////////////////////////////// - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( StringRef filename ) { - m_ofs.open( filename.c_str() ); - CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); - } - ~FileStream() override = default; - public: // IStream - std::ostream& stream() const override { - return m_ofs; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream() : m_os( Catch::cout().rdbuf() ) {} - ~CoutStream() override = default; - - public: // IStream - std::ostream& stream() const override { return m_os; } - }; - - /////////////////////////////////////////////////////////////////////////// - - class DebugOutStream : public IStream { - std::unique_ptr> m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream() - : m_streamBuf( new StreamBufImpl() ), - m_os( m_streamBuf.get() ) - {} - - ~DebugOutStream() override = default; - - public: // IStream - std::ostream& stream() const override { return m_os; } - }; - - }} // namespace anon::detail - - /////////////////////////////////////////////////////////////////////////// - - auto makeStream( StringRef const &filename ) -> IStream const* { - if( filename.empty() ) - return new detail::CoutStream(); - else if( filename[0] == '%' ) { - if( filename == "%debug" ) - return new detail::DebugOutStream(); - else - CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); - } - else - return new detail::FileStream( filename ); + if (c != EOF) { + if (pbase() == epptr()) + m_writer(std::string(1, static_cast(c))); + else + sputc(static_cast(c)); } + return 0; + } - // This class encapsulates the idea of a pool of ostringstreams that can be reused. - struct StringStreams { - std::vector> m_streams; - std::vector m_unused; - std::ostringstream m_referenceStream; // Used for copy state/ flags from - - auto add() -> std::size_t { - if( m_unused.empty() ) { - m_streams.push_back( std::unique_ptr( new std::ostringstream ) ); - return m_streams.size()-1; - } - else { - auto index = m_unused.back(); - m_unused.pop_back(); - return index; - } - } - - void release( std::size_t index ) { - m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state - m_unused.push_back(index); - } - }; - - ReusableStringStream::ReusableStringStream() - : m_index( Singleton::getMutable().add() ), - m_oss( Singleton::getMutable().m_streams[m_index].get() ) - {} - - ReusableStringStream::~ReusableStringStream() { - static_cast( m_oss )->str(""); - m_oss->clear(); - Singleton::getMutable().release( m_index ); + int sync() override { + if (pbase() != pptr()) { + m_writer(std::string( + pbase(), static_cast(pptr() - pbase()))); + setp(pbase(), epptr()); } + return 0; + } +}; - auto ReusableStringStream::str() const -> std::string { - return static_cast( m_oss )->str(); - } +/////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// +struct OutputDebugWriter { + void operator()(std::string const& str) { writeToDebugConsole(str); } +}; -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions - std::ostream& cout() { return std::cout; } - std::ostream& cerr() { return std::cerr; } - std::ostream& clog() { return std::clog; } -#endif +/////////////////////////////////////////////////////////////////////////// + +class FileStream : public IStream { + mutable std::ofstream m_ofs; + + public: + FileStream(StringRef filename) { + m_ofs.open(filename.c_str()); + CATCH_ENFORCE(!m_ofs.fail(), "Unable to open file: '" << filename << "'"); + } + ~FileStream() override = default; + + public: // IStream + std::ostream& stream() const override { return m_ofs; } +}; + +/////////////////////////////////////////////////////////////////////////// + +class CoutStream : public IStream { + mutable std::ostream m_os; + + public: + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream() : m_os(Catch::cout().rdbuf()) {} + ~CoutStream() override = default; + + public: // IStream + std::ostream& stream() const override { return m_os; } +}; + +/////////////////////////////////////////////////////////////////////////// + +class DebugOutStream : public IStream { + std::unique_ptr> m_streamBuf; + mutable std::ostream m_os; + + public: + DebugOutStream() + : m_streamBuf(new StreamBufImpl()), + m_os(m_streamBuf.get()) {} + + ~DebugOutStream() override = default; + + public: // IStream + std::ostream& stream() const override { return m_os; } +}; + +} // namespace +} // namespace detail + +/////////////////////////////////////////////////////////////////////////// + +auto makeStream(StringRef const& filename) -> IStream const* { + if (filename.empty()) + return new detail::CoutStream(); + else if (filename[0] == '%') { + if (filename == "%debug") + return new detail::DebugOutStream(); + else + CATCH_ERROR("Unrecognised stream: '" << filename << "'"); + } else + return new detail::FileStream(filename); } + +// This class encapsulates the idea of a pool of ostringstreams that can be +// reused. +struct StringStreams { + std::vector> m_streams; + std::vector m_unused; + std::ostringstream m_referenceStream; // Used for copy state/ flags from + + auto add() -> std::size_t { + if (m_unused.empty()) { + m_streams.push_back( + std::unique_ptr(new std::ostringstream)); + return m_streams.size() - 1; + } else { + auto index = m_unused.back(); + m_unused.pop_back(); + return index; + } + } + + void release(std::size_t index) { + m_streams[index]->copyfmt( + m_referenceStream); // Restore initial flags and other state + m_unused.push_back(index); + } +}; + +ReusableStringStream::ReusableStringStream() + : m_index(Singleton::getMutable().add()), + m_oss(Singleton::getMutable().m_streams[m_index].get()) {} + +ReusableStringStream::~ReusableStringStream() { + static_cast(m_oss)->str(""); + m_oss->clear(); + Singleton::getMutable().release(m_index); +} + +auto ReusableStringStream::str() const -> std::string { + return static_cast(m_oss)->str(); +} + +/////////////////////////////////////////////////////////////////////////// + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these + // functions +std::ostream& cout() { return std::cout; } +std::ostream& cerr() { return std::cerr; } +std::ostream& clog() { return std::clog; } +#endif +} // namespace Catch // end catch_stream.cpp // start catch_string_manip.cpp #include -#include -#include #include +#include +#include namespace Catch { - namespace { - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - } - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } +namespace { +char toLowerCh(char c) { return static_cast(std::tolower(c)); } +} // namespace +bool startsWith(std::string const& s, std::string const& prefix) { + return s.size() >= prefix.size() && + std::equal(prefix.begin(), prefix.end(), s.begin()); } +bool startsWith(std::string const& s, char prefix) { + return !s.empty() && s[0] == prefix; +} +bool endsWith(std::string const& s, std::string const& suffix) { + return s.size() >= suffix.size() && + std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); +} +bool endsWith(std::string const& s, char suffix) { + return !s.empty() && s[s.size() - 1] == suffix; +} +bool contains(std::string const& s, std::string const& infix) { + return s.find(infix) != std::string::npos; +} +void toLowerInPlace(std::string& s) { + std::transform(s.begin(), s.end(), s.begin(), toLowerCh); +} +std::string toLower(std::string const& s) { + std::string lc = s; + toLowerInPlace(lc); + return lc; +} +std::string trim(std::string const& str) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of(whitespaceChars); + std::string::size_type end = str.find_last_not_of(whitespaceChars); + + return start != std::string::npos ? str.substr(start, 1 + end - start) + : std::string(); +} + +bool replaceInPlace(std::string& str, std::string const& replaceThis, + std::string const& withThis) { + bool replaced = false; + std::size_t i = str.find(replaceThis); + while (i != std::string::npos) { + replaced = true; + str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size()); + if (i < str.size() - withThis.size()) + i = str.find(replaceThis, i + withThis.size()); + else + i = std::string::npos; + } + return replaced; +} + +pluralise::pluralise(std::size_t count, std::string const& label) + : m_count(count), m_label(label) {} + +std::ostream& operator<<(std::ostream& os, pluralise const& pluraliser) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if (pluraliser.m_count != 1) os << 's'; + return os; +} + +} // namespace Catch // end catch_string_manip.cpp // start catch_stringref.cpp #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wexit-time-destructors" #endif -#include -#include #include +#include +#include namespace { - const uint32_t byte_2_lead = 0xC0; - const uint32_t byte_3_lead = 0xE0; - const uint32_t byte_4_lead = 0xF0; -} +const uint32_t byte_2_lead = 0xC0; +const uint32_t byte_3_lead = 0xE0; +const uint32_t byte_4_lead = 0xF0; +} // namespace namespace Catch { - StringRef::StringRef( char const* rawChars ) noexcept - : StringRef( rawChars, static_cast(std::strlen(rawChars) ) ) - {} +StringRef::StringRef(char const* rawChars) noexcept + : StringRef(rawChars, + static_cast(std::strlen(rawChars))) {} - StringRef::operator std::string() const { - return std::string( m_start, m_size ); - } +StringRef::operator std::string() const { return std::string(m_start, m_size); } - void StringRef::swap( StringRef& other ) noexcept { - std::swap( m_start, other.m_start ); - std::swap( m_size, other.m_size ); - std::swap( m_data, other.m_data ); - } +void StringRef::swap(StringRef& other) noexcept { + std::swap(m_start, other.m_start); + std::swap(m_size, other.m_size); + std::swap(m_data, other.m_data); +} - auto StringRef::c_str() const -> char const* { - if( isSubstring() ) - const_cast( this )->takeOwnership(); - return m_start; - } - auto StringRef::currentData() const noexcept -> char const* { - return m_start; - } +auto StringRef::c_str() const -> char const* { + if (isSubstring()) const_cast(this)->takeOwnership(); + return m_start; +} +auto StringRef::currentData() const noexcept -> char const* { return m_start; } - auto StringRef::isOwned() const noexcept -> bool { - return m_data != nullptr; - } - auto StringRef::isSubstring() const noexcept -> bool { - return m_start[m_size] != '\0'; - } +auto StringRef::isOwned() const noexcept -> bool { return m_data != nullptr; } +auto StringRef::isSubstring() const noexcept -> bool { + return m_start[m_size] != '\0'; +} - void StringRef::takeOwnership() { - if( !isOwned() ) { - m_data = new char[m_size+1]; - memcpy( m_data, m_start, m_size ); - m_data[m_size] = '\0'; - m_start = m_data; - } - } - auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { - if( start < m_size ) - return StringRef( m_start+start, size ); - else - return StringRef(); - } - auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { - return - size() == other.size() && - (std::strncmp( m_start, other.m_start, size() ) == 0); - } - auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { - return !operator==( other ); - } +void StringRef::takeOwnership() { + if (!isOwned()) { + m_data = new char[m_size + 1]; + memcpy(m_data, m_start, m_size); + m_data[m_size] = '\0'; + m_start = m_data; + } +} +auto StringRef::substr(size_type start, size_type size) const noexcept + -> StringRef { + if (start < m_size) + return StringRef(m_start + start, size); + else + return StringRef(); +} +auto StringRef::operator==(StringRef const& other) const noexcept -> bool { + return size() == other.size() && + (std::strncmp(m_start, other.m_start, size()) == 0); +} +auto StringRef::operator!=(StringRef const& other) const noexcept -> bool { + return !operator==(other); +} - auto StringRef::operator[](size_type index) const noexcept -> char { - return m_start[index]; - } +auto StringRef::operator[](size_type index) const noexcept -> char { + return m_start[index]; +} - auto StringRef::numberOfCharacters() const noexcept -> size_type { - size_type noChars = m_size; - // Make adjustments for uft encodings - for( size_type i=0; i < m_size; ++i ) { - char c = m_start[i]; - if( ( c & byte_2_lead ) == byte_2_lead ) { - noChars--; - if (( c & byte_3_lead ) == byte_3_lead ) - noChars--; - if( ( c & byte_4_lead ) == byte_4_lead ) - noChars--; - } - } - return noChars; +auto StringRef::numberOfCharacters() const noexcept -> size_type { + size_type noChars = m_size; + // Make adjustments for uft encodings + for (size_type i = 0; i < m_size; ++i) { + char c = m_start[i]; + if ((c & byte_2_lead) == byte_2_lead) { + noChars--; + if ((c & byte_3_lead) == byte_3_lead) noChars--; + if ((c & byte_4_lead) == byte_4_lead) noChars--; } + } + return noChars; +} - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { - std::string str; - str.reserve( lhs.size() + rhs.size() ); - str += lhs; - str += rhs; - return str; - } - auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { - return std::string( lhs ) + std::string( rhs ); - } - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { - return std::string( lhs ) + std::string( rhs ); - } +auto operator+(StringRef const& lhs, StringRef const& rhs) -> std::string { + std::string str; + str.reserve(lhs.size() + rhs.size()); + str += lhs; + str += rhs; + return str; +} +auto operator+(StringRef const& lhs, const char* rhs) -> std::string { + return std::string(lhs) + std::string(rhs); +} +auto operator+(char const* lhs, StringRef const& rhs) -> std::string { + return std::string(lhs) + std::string(rhs); +} - auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { - return os.write(str.currentData(), str.size()); - } +auto operator<<(std::ostream& os, StringRef const& str) -> std::ostream& { + return os.write(str.currentData(), str.size()); +} - auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { - lhs.append(rhs.currentData(), rhs.size()); - return lhs; - } +auto operator+=(std::string& lhs, StringRef const& rhs) -> std::string& { + lhs.append(rhs.currentData(), rhs.size()); + return lhs; +} -} // namespace Catch +} // namespace Catch #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif // end catch_stringref.cpp // start catch_tag_alias.cpp namespace Catch { - TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} -} +TagAlias::TagAlias(std::string const& _tag, SourceLineInfo _lineInfo) + : tag(_tag), lineInfo(_lineInfo) {} +} // namespace Catch // end catch_tag_alias.cpp // start catch_tag_alias_autoregistrar.cpp namespace Catch { - RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { - CATCH_TRY { - getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); - } CATCH_CATCH_ALL { - // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException(); - } - } - +RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, + char const* tag, + SourceLineInfo const& lineInfo) { + CATCH_TRY { getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); } + CATCH_CATCH_ALL { + // Do not throw when constructing global objects, instead register the + // exception to be processed later + getMutableRegistryHub().registerStartupException(); + } } + +} // namespace Catch // end catch_tag_alias_autoregistrar.cpp // start catch_tag_alias_registry.cpp @@ -10977,213 +11122,205 @@ namespace Catch { namespace Catch { - TagAliasRegistry::~TagAliasRegistry() {} +TagAliasRegistry::~TagAliasRegistry() {} - TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { - auto it = m_registry.find( alias ); - if( it != m_registry.end() ) - return &(it->second); - else - return nullptr; +TagAlias const* TagAliasRegistry::find(std::string const& alias) const { + auto it = m_registry.find(alias); + if (it != m_registry.end()) + return &(it->second); + else + return nullptr; +} + +std::string TagAliasRegistry::expandAliases( + std::string const& unexpandedTestSpec) const { + std::string expandedTestSpec = unexpandedTestSpec; + for (auto const& registryKvp : m_registry) { + std::size_t pos = expandedTestSpec.find(registryKvp.first); + if (pos != std::string::npos) { + expandedTestSpec = + expandedTestSpec.substr(0, pos) + registryKvp.second.tag + + expandedTestSpec.substr(pos + registryKvp.first.size()); } + } + return expandedTestSpec; +} - std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { - std::string expandedTestSpec = unexpandedTestSpec; - for( auto const& registryKvp : m_registry ) { - std::size_t pos = expandedTestSpec.find( registryKvp.first ); - if( pos != std::string::npos ) { - expandedTestSpec = expandedTestSpec.substr( 0, pos ) + - registryKvp.second.tag + - expandedTestSpec.substr( pos + registryKvp.first.size() ); - } - } - return expandedTestSpec; - } +void TagAliasRegistry::add(std::string const& alias, std::string const& tag, + SourceLineInfo const& lineInfo) { + CATCH_ENFORCE(startsWith(alias, "[@") && endsWith(alias, ']'), + "error: tag alias, '" << alias + << "' is not of the form [@alias name].\n" + << lineInfo); - void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), - "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); + CATCH_ENFORCE( + m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo + << "\n" + << "\tRedefined at: " << lineInfo); +} - CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, - "error: tag alias, '" << alias << "' already registered.\n" - << "\tFirst seen at: " << find(alias)->lineInfo << "\n" - << "\tRedefined at: " << lineInfo ); - } +ITagAliasRegistry::~ITagAliasRegistry() {} - ITagAliasRegistry::~ITagAliasRegistry() {} +ITagAliasRegistry const& ITagAliasRegistry::get() { + return getRegistryHub().getTagAliasRegistry(); +} - ITagAliasRegistry const& ITagAliasRegistry::get() { - return getRegistryHub().getTagAliasRegistry(); - } - -} // end namespace Catch +} // end namespace Catch // end catch_tag_alias_registry.cpp // start catch_test_case_info.cpp +#include #include #include -#include #include namespace Catch { - namespace { - TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { - if( startsWith( tag, '.' ) || - tag == "!hide" ) - return TestCaseInfo::IsHidden; - else if( tag == "!throws" ) - return TestCaseInfo::Throws; - else if( tag == "!shouldfail" ) - return TestCaseInfo::ShouldFail; - else if( tag == "!mayfail" ) - return TestCaseInfo::MayFail; - else if( tag == "!nonportable" ) - return TestCaseInfo::NonPortable; - else if( tag == "!benchmark" ) - return static_cast( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); - else - return TestCaseInfo::None; - } - bool isReservedTag( std::string const& tag ) { - return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast(tag[0]) ); - } - void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - CATCH_ENFORCE( !isReservedTag(tag), - "Tag name: [" << tag << "] is not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << _lineInfo ); - } +namespace { +TestCaseInfo::SpecialProperties parseSpecialTag(std::string const& tag) { + if (startsWith(tag, '.') || tag == "!hide") + return TestCaseInfo::IsHidden; + else if (tag == "!throws") + return TestCaseInfo::Throws; + else if (tag == "!shouldfail") + return TestCaseInfo::ShouldFail; + else if (tag == "!mayfail") + return TestCaseInfo::MayFail; + else if (tag == "!nonportable") + return TestCaseInfo::NonPortable; + else if (tag == "!benchmark") + return static_cast( + TestCaseInfo::Benchmark | TestCaseInfo::IsHidden); + else + return TestCaseInfo::None; +} +bool isReservedTag(std::string const& tag) { + return parseSpecialTag(tag) == TestCaseInfo::None && tag.size() > 0 && + !std::isalnum(static_cast(tag[0])); +} +void enforceNotReservedTag(std::string const& tag, + SourceLineInfo const& _lineInfo) { + CATCH_ENFORCE(!isReservedTag(tag), + "Tag name: [" << tag << "] is not allowed.\n" + << "Tag names starting with non alpha-numeric " + "characters are reserved\n" + << _lineInfo); +} +} // namespace + +TestCase makeTestCase(ITestInvoker* _testCase, std::string const& _className, + NameAndTags const& nameAndTags, + SourceLineInfo const& _lineInfo) { + bool isHidden = false; + + // Parse out tags + std::vector tags; + std::string desc, tag; + bool inTag = false; + std::string _descOrTags = nameAndTags.tags; + for (char c : _descOrTags) { + if (!inTag) { + if (c == '[') + inTag = true; + else + desc += c; + } else { + if (c == ']') { + TestCaseInfo::SpecialProperties prop = parseSpecialTag(tag); + if ((prop & TestCaseInfo::IsHidden) != 0) + isHidden = true; + else if (prop == TestCaseInfo::None) + enforceNotReservedTag(tag, _lineInfo); + + tags.push_back(tag); + tag.clear(); + inTag = false; + } else + tag += c; } + } + if (isHidden) { tags.push_back("."); } - TestCase makeTestCase( ITestInvoker* _testCase, - std::string const& _className, - NameAndTags const& nameAndTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden = false; + TestCaseInfo info(nameAndTags.name, _className, desc, tags, _lineInfo); + return TestCase(_testCase, std::move(info)); +} - // Parse out tags - std::vector tags; - std::string desc, tag; - bool inTag = false; - std::string _descOrTags = nameAndTags.tags; - for (char c : _descOrTags) { - if( !inTag ) { - if( c == '[' ) - inTag = true; - else - desc += c; - } - else { - if( c == ']' ) { - TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); - if( ( prop & TestCaseInfo::IsHidden ) != 0 ) - isHidden = true; - else if( prop == TestCaseInfo::None ) - enforceNotReservedTag( tag, _lineInfo ); +void setTags(TestCaseInfo& testCaseInfo, std::vector tags) { + std::sort(begin(tags), end(tags)); + tags.erase(std::unique(begin(tags), end(tags)), end(tags)); + testCaseInfo.lcaseTags.clear(); - tags.push_back( tag ); - tag.clear(); - inTag = false; - } - else - tag += c; - } - } - if( isHidden ) { - tags.push_back( "." ); - } + for (auto const& tag : tags) { + std::string lcaseTag = toLower(tag); + testCaseInfo.properties = static_cast( + testCaseInfo.properties | parseSpecialTag(lcaseTag)); + testCaseInfo.lcaseTags.push_back(lcaseTag); + } + testCaseInfo.tags = std::move(tags); +} - TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo ); - return TestCase( _testCase, std::move(info) ); - } +TestCaseInfo::TestCaseInfo(std::string const& _name, + std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo) + : name(_name), + className(_className), + description(_description), + lineInfo(_lineInfo), + properties(None) { + setTags(*this, _tags); +} - void setTags( TestCaseInfo& testCaseInfo, std::vector tags ) { - std::sort(begin(tags), end(tags)); - tags.erase(std::unique(begin(tags), end(tags)), end(tags)); - testCaseInfo.lcaseTags.clear(); +bool TestCaseInfo::isHidden() const { return (properties & IsHidden) != 0; } +bool TestCaseInfo::throws() const { return (properties & Throws) != 0; } +bool TestCaseInfo::okToFail() const { + return (properties & (ShouldFail | MayFail)) != 0; +} +bool TestCaseInfo::expectedToFail() const { + return (properties & (ShouldFail)) != 0; +} - for( auto const& tag : tags ) { - std::string lcaseTag = toLower( tag ); - testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); - testCaseInfo.lcaseTags.push_back( lcaseTag ); - } - testCaseInfo.tags = std::move(tags); - } +std::string TestCaseInfo::tagsAsString() const { + std::string ret; + // '[' and ']' per tag + std::size_t full_size = 2 * tags.size(); + for (const auto& tag : tags) { full_size += tag.size(); } + ret.reserve(full_size); + for (const auto& tag : tags) { + ret.push_back('['); + ret.append(tag); + ret.push_back(']'); + } - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::vector const& _tags, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - lineInfo( _lineInfo ), - properties( None ) - { - setTags( *this, _tags ); - } + return ret; +} - bool TestCaseInfo::isHidden() const { - return ( properties & IsHidden ) != 0; - } - bool TestCaseInfo::throws() const { - return ( properties & Throws ) != 0; - } - bool TestCaseInfo::okToFail() const { - return ( properties & (ShouldFail | MayFail ) ) != 0; - } - bool TestCaseInfo::expectedToFail() const { - return ( properties & (ShouldFail ) ) != 0; - } +TestCase::TestCase(ITestInvoker* testCase, TestCaseInfo&& info) + : TestCaseInfo(std::move(info)), test(testCase) {} - std::string TestCaseInfo::tagsAsString() const { - std::string ret; - // '[' and ']' per tag - std::size_t full_size = 2 * tags.size(); - for (const auto& tag : tags) { - full_size += tag.size(); - } - ret.reserve(full_size); - for (const auto& tag : tags) { - ret.push_back('['); - ret.append(tag); - ret.push_back(']'); - } +TestCase TestCase::withName(std::string const& _newName) const { + TestCase other(*this); + other.name = _newName; + return other; +} - return ret; - } +void TestCase::invoke() const { test->invoke(); } - TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} +bool TestCase::operator==(TestCase const& other) const { + return test.get() == other.test.get() && name == other.name && + className == other.className; +} - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } +bool TestCase::operator<(TestCase const& other) const { + return name < other.name; +} - void TestCase::invoke() const { - test->invoke(); - } +TestCaseInfo const& TestCase::getTestCaseInfo() const { return *this; } - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } - -} // end namespace Catch +} // end namespace Catch // end catch_test_case_info.cpp // start catch_test_case_registry_impl.cpp @@ -11191,529 +11328,522 @@ namespace Catch { namespace Catch { - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { +std::vector sortTests( + IConfig const& config, std::vector const& unsortedTestCases) { + std::vector sorted = unsortedTestCases; - std::vector sorted = unsortedTestCases; + switch (config.runOrder()) { + case RunTests::InLexicographicalOrder: + std::sort(sorted.begin(), sorted.end()); + break; + case RunTests::InRandomOrder: + seedRng(config); + std::shuffle(sorted.begin(), sorted.end(), rng()); + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; +} +bool matchTest(TestCase const& testCase, TestSpec const& testSpec, + IConfig const& config) { + return testSpec.matches(testCase) && + (config.allowThrows() || !testCase.throws()); +} - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - seedRng( config ); - std::shuffle( sorted.begin(), sorted.end(), rng() ); - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - return sorted; - } - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); - } +void enforceNoDuplicateTestCases(std::vector const& functions) { + std::set seenFunctions; + for (auto const& function : functions) { + auto prev = seenFunctions.insert(function); + CATCH_ENFORCE(prev.second, "error: TEST_CASE( \"" + << function.name << "\" ) already defined.\n" + << "\tFirst seen at " + << prev.first->getTestCaseInfo().lineInfo + << "\n" + << "\tRedefined at " + << function.getTestCaseInfo().lineInfo); + } +} - void enforceNoDuplicateTestCases( std::vector const& functions ) { - std::set seenFunctions; - for( auto const& function : functions ) { - auto prev = seenFunctions.insert( function ); - CATCH_ENFORCE( prev.second, - "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); - } - } +std::vector filterTests(std::vector const& testCases, + TestSpec const& testSpec, + IConfig const& config) { + std::vector filtered; + filtered.reserve(testCases.size()); + for (auto const& testCase : testCases) + if (matchTest(testCase, testSpec, config)) filtered.push_back(testCase); + return filtered; +} +std::vector const& getAllTestCasesSorted(IConfig const& config) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted(config); +} - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { - std::vector filtered; - filtered.reserve( testCases.size() ); - for( auto const& testCase : testCases ) - if( matchTest( testCase, testSpec, config ) ) - filtered.push_back( testCase ); - return filtered; - } - std::vector const& getAllTestCasesSorted( IConfig const& config ) { - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); - } +void TestRegistry::registerTest(TestCase const& testCase) { + std::string name = testCase.getTestCaseInfo().name; + if (name.empty()) { + ReusableStringStream rss; + rss << "Anonymous test case " << ++m_unnamedCount; + return registerTest(testCase.withName(rss.str())); + } + m_functions.push_back(testCase); +} - void TestRegistry::registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name.empty() ) { - ReusableStringStream rss; - rss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( rss.str() ) ); - } - m_functions.push_back( testCase ); - } +std::vector const& TestRegistry::getAllTests() const { + return m_functions; +} +std::vector const& TestRegistry::getAllTestsSorted( + IConfig const& config) const { + if (m_sortedFunctions.empty()) enforceNoDuplicateTestCases(m_functions); - std::vector const& TestRegistry::getAllTests() const { - return m_functions; - } - std::vector const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { - if( m_sortedFunctions.empty() ) - enforceNoDuplicateTestCases( m_functions ); + if (m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty()) { + m_sortedFunctions = sortTests(config, m_functions); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; +} - if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { - m_sortedFunctions = sortTests( config, m_functions ); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; - } +/////////////////////////////////////////////////////////////////////////// +TestInvokerAsFunction::TestInvokerAsFunction(void (*testAsFunction)()) noexcept + : m_testAsFunction(testAsFunction) {} - /////////////////////////////////////////////////////////////////////////// - TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} +void TestInvokerAsFunction::invoke() const { m_testAsFunction(); } - void TestInvokerAsFunction::invoke() const { - m_testAsFunction(); - } +std::string extractClassName(StringRef const& classOrQualifiedMethodName) { + std::string className = classOrQualifiedMethodName; + if (startsWith(className, '&')) { + std::size_t lastColons = className.rfind("::"); + std::size_t penultimateColons = className.rfind("::", lastColons - 1); + if (penultimateColons == std::string::npos) penultimateColons = 1; + className = + className.substr(penultimateColons, lastColons - penultimateColons); + } + return className; +} - std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, '&' ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } - -} // end namespace Catch +} // end namespace Catch // end catch_test_case_registry_impl.cpp // start catch_test_case_tracker.cpp #include #include -#include #include #include +#include #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wexit-time-destructors" #endif namespace Catch { namespace TestCaseTracking { - NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} +NameAndLocation::NameAndLocation(std::string const& _name, + SourceLineInfo const& _location) + : name(_name), location(_location) {} - ITracker::~ITracker() = default; +ITracker::~ITracker() = default; - TrackerContext& TrackerContext::instance() { - static TrackerContext s_instance; - return s_instance; - } +TrackerContext& TrackerContext::instance() { + static TrackerContext s_instance; + return s_instance; +} - ITracker& TrackerContext::startRun() { - m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); - m_currentTracker = nullptr; - m_runState = Executing; - return *m_rootTracker; - } +ITracker& TrackerContext::startRun() { + m_rootTracker = std::make_shared( + NameAndLocation("{root}", CATCH_INTERNAL_LINEINFO), *this, nullptr); + m_currentTracker = nullptr; + m_runState = Executing; + return *m_rootTracker; +} - void TrackerContext::endRun() { - m_rootTracker.reset(); - m_currentTracker = nullptr; - m_runState = NotStarted; - } +void TrackerContext::endRun() { + m_rootTracker.reset(); + m_currentTracker = nullptr; + m_runState = NotStarted; +} - void TrackerContext::startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void TrackerContext::completeCycle() { - m_runState = CompletedCycle; - } +void TrackerContext::startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; +} +void TrackerContext::completeCycle() { m_runState = CompletedCycle; } - bool TrackerContext::completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& TrackerContext::currentTracker() { - return *m_currentTracker; - } - void TrackerContext::setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } +bool TrackerContext::completedCycle() const { + return m_runState == CompletedCycle; +} +ITracker& TrackerContext::currentTracker() { return *m_currentTracker; } +void TrackerContext::setCurrentTracker(ITracker* tracker) { + m_currentTracker = tracker; +} - TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ) - {} +TrackerBase::TrackerBase(NameAndLocation const& nameAndLocation, + TrackerContext& ctx, ITracker* parent) + : m_nameAndLocation(nameAndLocation), m_ctx(ctx), m_parent(parent) {} - NameAndLocation const& TrackerBase::nameAndLocation() const { - return m_nameAndLocation; - } - bool TrackerBase::isComplete() const { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - bool TrackerBase::isSuccessfullyCompleted() const { - return m_runState == CompletedSuccessfully; - } - bool TrackerBase::isOpen() const { - return m_runState != NotStarted && !isComplete(); - } - bool TrackerBase::hasChildren() const { - return !m_children.empty(); - } +NameAndLocation const& TrackerBase::nameAndLocation() const { + return m_nameAndLocation; +} +bool TrackerBase::isComplete() const { + return m_runState == CompletedSuccessfully || m_runState == Failed; +} +bool TrackerBase::isSuccessfullyCompleted() const { + return m_runState == CompletedSuccessfully; +} +bool TrackerBase::isOpen() const { + return m_runState != NotStarted && !isComplete(); +} +bool TrackerBase::hasChildren() const { return !m_children.empty(); } - void TrackerBase::addChild( ITrackerPtr const& child ) { - m_children.push_back( child ); - } +void TrackerBase::addChild(ITrackerPtr const& child) { + m_children.push_back(child); +} - ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { - auto it = std::find_if( m_children.begin(), m_children.end(), - [&nameAndLocation]( ITrackerPtr const& tracker ){ - return - tracker->nameAndLocation().location == nameAndLocation.location && - tracker->nameAndLocation().name == nameAndLocation.name; - } ); - return( it != m_children.end() ) - ? *it - : nullptr; - } - ITracker& TrackerBase::parent() { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } +ITrackerPtr TrackerBase::findChild(NameAndLocation const& nameAndLocation) { + auto it = std::find_if(m_children.begin(), m_children.end(), + [&nameAndLocation](ITrackerPtr const& tracker) { + return tracker->nameAndLocation().location == + nameAndLocation.location && + tracker->nameAndLocation().name == + nameAndLocation.name; + }); + return (it != m_children.end()) ? *it : nullptr; +} +ITracker& TrackerBase::parent() { + assert(m_parent); // Should always be non-null except for root + return *m_parent; +} - void TrackerBase::openChild() { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } +void TrackerBase::openChild() { + if (m_runState != ExecutingChildren) { + m_runState = ExecutingChildren; + if (m_parent) m_parent->openChild(); + } +} - bool TrackerBase::isSectionTracker() const { return false; } - bool TrackerBase::isIndexTracker() const { return false; } +bool TrackerBase::isSectionTracker() const { return false; } +bool TrackerBase::isIndexTracker() const { return false; } - void TrackerBase::open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } +void TrackerBase::open() { + m_runState = Executing; + moveToThis(); + if (m_parent) m_parent->openChild(); +} - void TrackerBase::close() { +void TrackerBase::close() { + // Close any still open children (e.g. generators) + while (&m_ctx.currentTracker() != this) m_ctx.currentTracker().close(); - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); + switch (m_runState) { + case NeedsAnotherRun: + break; - switch( m_runState ) { - case NeedsAnotherRun: - break; + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if (m_children.empty() || m_children.back()->isComplete()) + m_runState = CompletedSuccessfully; + break; - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; + case NotStarted: + case CompletedSuccessfully: + case Failed: + CATCH_INTERNAL_ERROR("Illogical state: " << m_runState); - case NotStarted: - case CompletedSuccessfully: - case Failed: - CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); + default: + CATCH_INTERNAL_ERROR("Unknown state: " << m_runState); + } + moveToParent(); + m_ctx.completeCycle(); +} +void TrackerBase::fail() { + m_runState = Failed; + if (m_parent) m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); +} +void TrackerBase::markAsNeedingAnotherRun() { m_runState = NeedsAnotherRun; } - default: - CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); - } - moveToParent(); - m_ctx.completeCycle(); - } - void TrackerBase::fail() { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - void TrackerBase::markAsNeedingAnotherRun() { - m_runState = NeedsAnotherRun; - } +void TrackerBase::moveToParent() { + assert(m_parent); + m_ctx.setCurrentTracker(m_parent); +} +void TrackerBase::moveToThis() { m_ctx.setCurrentTracker(this); } - void TrackerBase::moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void TrackerBase::moveToThis() { - m_ctx.setCurrentTracker( this ); - } +SectionTracker::SectionTracker(NameAndLocation const& nameAndLocation, + TrackerContext& ctx, ITracker* parent) + : TrackerBase(nameAndLocation, ctx, parent) { + if (parent) { + while (!parent->isSectionTracker()) parent = &parent->parent(); - SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - { - if( parent ) { - while( !parent->isSectionTracker() ) - parent = &parent->parent(); + SectionTracker& parentSection = static_cast(*parent); + addNextFilters(parentSection.m_filters); + } +} - SectionTracker& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } +bool SectionTracker::isSectionTracker() const { return true; } - bool SectionTracker::isSectionTracker() const { return true; } +SectionTracker& SectionTracker::acquire( + TrackerContext& ctx, NameAndLocation const& nameAndLocation) { + std::shared_ptr section; - SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - std::shared_ptr section; + ITracker& currentTracker = ctx.currentTracker(); + if (ITrackerPtr childTracker = currentTracker.findChild(nameAndLocation)) { + assert(childTracker); + assert(childTracker->isSectionTracker()); + section = std::static_pointer_cast(childTracker); + } else { + section = + std::make_shared(nameAndLocation, ctx, ¤tTracker); + currentTracker.addChild(section); + } + if (!ctx.completedCycle()) section->tryOpen(); + return *section; +} - ITracker& currentTracker = ctx.currentTracker(); - if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = std::static_pointer_cast( childTracker ); - } - else { - section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() ) - section->tryOpen(); - return *section; - } +void SectionTracker::tryOpen() { + if (!isComplete() && (m_filters.empty() || m_filters[0].empty() || + m_filters[0] == m_nameAndLocation.name)) + open(); +} - void SectionTracker::tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) - open(); - } +void SectionTracker::addInitialFilters( + std::vector const& filters) { + if (!filters.empty()) { + m_filters.push_back(""); // Root - should never be consulted + m_filters.push_back(""); // Test Case - not a section filter + m_filters.insert(m_filters.end(), filters.begin(), filters.end()); + } +} +void SectionTracker::addNextFilters(std::vector const& filters) { + if (filters.size() > 1) + m_filters.insert(m_filters.end(), ++filters.begin(), filters.end()); +} - void SectionTracker::addInitialFilters( std::vector const& filters ) { - if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void SectionTracker::addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); - } +IndexTracker::IndexTracker(NameAndLocation const& nameAndLocation, + TrackerContext& ctx, ITracker* parent, int size) + : TrackerBase(nameAndLocation, ctx, parent), m_size(size) {} - IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ) - {} +bool IndexTracker::isIndexTracker() const { return true; } - bool IndexTracker::isIndexTracker() const { return true; } +IndexTracker& IndexTracker::acquire(TrackerContext& ctx, + NameAndLocation const& nameAndLocation, + int size) { + std::shared_ptr tracker; - IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - std::shared_ptr tracker; + ITracker& currentTracker = ctx.currentTracker(); + if (ITrackerPtr childTracker = currentTracker.findChild(nameAndLocation)) { + assert(childTracker); + assert(childTracker->isIndexTracker()); + tracker = std::static_pointer_cast(childTracker); + } else { + tracker = std::make_shared(nameAndLocation, ctx, + ¤tTracker, size); + currentTracker.addChild(tracker); + } - ITracker& currentTracker = ctx.currentTracker(); - if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = std::static_pointer_cast( childTracker ); - } - else { - tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } + if (!ctx.completedCycle() && !tracker->isComplete()) { + if (tracker->m_runState != ExecutingChildren && + tracker->m_runState != NeedsAnotherRun) + tracker->moveNext(); + tracker->open(); + } - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } + return *tracker; +} - return *tracker; - } +int IndexTracker::index() const { return m_index; } - int IndexTracker::index() const { return m_index; } +void IndexTracker::moveNext() { + m_index++; + m_children.clear(); +} - void IndexTracker::moveNext() { - m_index++; - m_children.clear(); - } +void IndexTracker::close() { + TrackerBase::close(); + if (m_runState == CompletedSuccessfully && m_index < m_size - 1) + m_runState = Executing; +} - void IndexTracker::close() { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } +} // namespace TestCaseTracking -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; using TestCaseTracking::IndexTracker; +using TestCaseTracking::ITracker; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::TrackerContext; -} // namespace Catch +} // namespace Catch #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif // end catch_test_case_tracker.cpp // start catch_test_registry.cpp namespace Catch { - auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { - return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); - } - - NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} - - AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { - CATCH_TRY { - getMutableRegistryHub() - .registerTest( - makeTestCase( - invoker, - extractClassName( classOrMethod ), - nameAndTags, - lineInfo)); - } CATCH_CATCH_ALL { - // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException(); - } - } - - AutoReg::~AutoReg() = default; +auto makeTestInvoker(void (*testAsFunction)()) noexcept -> ITestInvoker* { + return new (std::nothrow) TestInvokerAsFunction(testAsFunction); } + +NameAndTags::NameAndTags(StringRef const& name_, + StringRef const& tags_) noexcept + : name(name_), tags(tags_) {} + +AutoReg::AutoReg(ITestInvoker* invoker, SourceLineInfo const& lineInfo, + StringRef const& classOrMethod, + NameAndTags const& nameAndTags) noexcept { + CATCH_TRY { + getMutableRegistryHub().registerTest(makeTestCase( + invoker, extractClassName(classOrMethod), nameAndTags, lineInfo)); + } + CATCH_CATCH_ALL { + // Do not throw when constructing global objects, instead register the + // exception to be processed later + getMutableRegistryHub().registerStartupException(); + } +} + +AutoReg::~AutoReg() = default; +} // namespace Catch // end catch_test_registry.cpp // start catch_test_spec.cpp #include +#include #include #include -#include namespace Catch { - TestSpec::Pattern::~Pattern() = default; - TestSpec::NamePattern::~NamePattern() = default; - TestSpec::TagPattern::~TagPattern() = default; - TestSpec::ExcludedPattern::~ExcludedPattern() = default; +TestSpec::Pattern::~Pattern() = default; +TestSpec::NamePattern::~NamePattern() = default; +TestSpec::TagPattern::~TagPattern() = default; +TestSpec::ExcludedPattern::~ExcludedPattern() = default; - TestSpec::NamePattern::NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } - - TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { - return std::find(begin(testCase.lcaseTags), - end(testCase.lcaseTags), - m_tag) != end(testCase.lcaseTags); - } - - TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - - bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( auto const& pattern : m_patterns ) { - if( !pattern->matches( testCase ) ) - return false; - } - return true; - } - - bool TestSpec::hasFilters() const { - return !m_filters.empty(); - } - bool TestSpec::matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( auto const& filter : m_filters ) - if( filter.matches( testCase ) ) - return true; - return false; - } +TestSpec::NamePattern::NamePattern(std::string const& name) + : m_wildcardPattern(toLower(name), CaseSensitive::No) {} +bool TestSpec::NamePattern::matches(TestCaseInfo const& testCase) const { + return m_wildcardPattern.matches(toLower(testCase.name)); } + +TestSpec::TagPattern::TagPattern(std::string const& tag) + : m_tag(toLower(tag)) {} +bool TestSpec::TagPattern::matches(TestCaseInfo const& testCase) const { + return std::find(begin(testCase.lcaseTags), end(testCase.lcaseTags), m_tag) != + end(testCase.lcaseTags); +} + +TestSpec::ExcludedPattern::ExcludedPattern(PatternPtr const& underlyingPattern) + : m_underlyingPattern(underlyingPattern) {} +bool TestSpec::ExcludedPattern::matches(TestCaseInfo const& testCase) const { + return !m_underlyingPattern->matches(testCase); +} + +bool TestSpec::Filter::matches(TestCaseInfo const& testCase) const { + // All patterns in a filter must match for the filter to be a match + for (auto const& pattern : m_patterns) { + if (!pattern->matches(testCase)) return false; + } + return true; +} + +bool TestSpec::hasFilters() const { return !m_filters.empty(); } +bool TestSpec::matches(TestCaseInfo const& testCase) const { + // A TestSpec matches if any filter matches + for (auto const& filter : m_filters) + if (filter.matches(testCase)) return true; + return false; +} +} // namespace Catch // end catch_test_spec.cpp // start catch_test_spec_parser.cpp namespace Catch { - TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} +TestSpecParser::TestSpecParser(ITagAliasRegistry const& tagAliases) + : m_tagAliases(&tagAliases) {} - TestSpecParser& TestSpecParser::parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - m_escapeChars.clear(); - for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern(); - return *this; - } - TestSpec TestSpecParser::testSpec() { - addFilter(); - return m_testSpec; - } +TestSpecParser& TestSpecParser::parse(std::string const& arg) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases(arg); + m_escapeChars.clear(); + for (m_pos = 0; m_pos < m_arg.size(); ++m_pos) visitChar(m_arg[m_pos]); + if (m_mode == Name) addPattern(); + return *this; +} +TestSpec TestSpecParser::testSpec() { + addFilter(); + return m_testSpec; +} - void TestSpecParser::visitChar( char c ) { - if( m_mode == None ) { - switch( c ) { - case ' ': return; - case '~': m_exclusion = true; return; - case '[': return startNewMode( Tag, ++m_pos ); - case '"': return startNewMode( QuotedName, ++m_pos ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; - } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); - } - else if( m_mode == EscapedName ) - m_mode = Name; - else if( m_mode == QuotedName && c == '"' ) - addPattern(); - else if( m_mode == Tag && c == ']' ) - addPattern(); +void TestSpecParser::visitChar(char c) { + if (m_mode == None) { + switch (c) { + case ' ': + return; + case '~': + m_exclusion = true; + return; + case '[': + return startNewMode(Tag, ++m_pos); + case '"': + return startNewMode(QuotedName, ++m_pos); + case '\\': + return escape(); + default: + startNewMode(Name, m_pos); + break; } - void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { - m_mode = mode; - m_start = start; - } - void TestSpecParser::escape() { - if( m_mode == None ) - m_start = m_pos; - m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); - } - std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + } + if (m_mode == Name) { + if (c == ',') { + addPattern(); + addFilter(); + } else if (c == '[') { + if (subString() == "exclude:") + m_exclusion = true; + else + addPattern(); + startNewMode(Tag, ++m_pos); + } else if (c == '\\') + escape(); + } else if (m_mode == EscapedName) + m_mode = Name; + else if (m_mode == QuotedName && c == '"') + addPattern(); + else if (m_mode == Tag && c == ']') + addPattern(); +} +void TestSpecParser::startNewMode(Mode mode, std::size_t start) { + m_mode = mode; + m_start = start; +} +void TestSpecParser::escape() { + if (m_mode == None) m_start = m_pos; + m_mode = EscapedName; + m_escapeChars.push_back(m_pos); +} +std::string TestSpecParser::subString() const { + return m_arg.substr(m_start, m_pos - m_start); +} - void TestSpecParser::addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } +void TestSpecParser::addFilter() { + if (!m_currentFilter.m_patterns.empty()) { + m_testSpec.m_filters.push_back(m_currentFilter); + m_currentFilter = TestSpec::Filter(); + } +} - TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } +TestSpec parseTestSpec(std::string const& arg) { + return TestSpecParser(ITagAliasRegistry::get()).parse(arg).testSpec(); +} -} // namespace Catch +} // namespace Catch // end catch_test_spec_parser.cpp // start catch_timer.cpp @@ -11723,70 +11853,68 @@ static const uint64_t nanosecondsInSecond = 1000000000; namespace Catch { - auto getCurrentNanosecondsSinceEpoch() -> uint64_t { - return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); - } +auto getCurrentNanosecondsSinceEpoch() -> uint64_t { + return std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(); +} - namespace { - auto estimateClockResolution() -> uint64_t { - uint64_t sum = 0; - static const uint64_t iterations = 1000000; +namespace { +auto estimateClockResolution() -> uint64_t { + uint64_t sum = 0; + static const uint64_t iterations = 1000000; - auto startTime = getCurrentNanosecondsSinceEpoch(); + auto startTime = getCurrentNanosecondsSinceEpoch(); - for( std::size_t i = 0; i < iterations; ++i ) { + for (std::size_t i = 0; i < iterations; ++i) { + uint64_t ticks; + uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); + do { + ticks = getCurrentNanosecondsSinceEpoch(); + } while (ticks == baseTicks); - uint64_t ticks; - uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); - do { - ticks = getCurrentNanosecondsSinceEpoch(); - } while( ticks == baseTicks ); + auto delta = ticks - baseTicks; + sum += delta; - auto delta = ticks - baseTicks; - sum += delta; + // If we have been calibrating for over 3 seconds -- the clock + // is terrible and we should move on. + // TBD: How to signal that the measured resolution is probably wrong? + if (ticks > startTime + 3 * nanosecondsInSecond) { return sum / i; } + } - // If we have been calibrating for over 3 seconds -- the clock - // is terrible and we should move on. - // TBD: How to signal that the measured resolution is probably wrong? - if (ticks > startTime + 3 * nanosecondsInSecond) { - return sum / i; - } - } + // We're just taking the mean, here. To do better we could take the std. dev + // and exclude outliers + // - and potentially do more iterations if there's a high variance. + return sum / iterations; +} +} // namespace +auto getEstimatedClockResolution() -> uint64_t { + static auto s_resolution = estimateClockResolution(); + return s_resolution; +} - // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers - // - and potentially do more iterations if there's a high variance. - return sum/iterations; - } - } - auto getEstimatedClockResolution() -> uint64_t { - static auto s_resolution = estimateClockResolution(); - return s_resolution; - } +void Timer::start() { m_nanoseconds = getCurrentNanosecondsSinceEpoch(); } +auto Timer::getElapsedNanoseconds() const -> uint64_t { + return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; +} +auto Timer::getElapsedMicroseconds() const -> uint64_t { + return getElapsedNanoseconds() / 1000; +} +auto Timer::getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds() / 1000); +} +auto Timer::getElapsedSeconds() const -> double { + return getElapsedMicroseconds() / 1000000.0; +} - void Timer::start() { - m_nanoseconds = getCurrentNanosecondsSinceEpoch(); - } - auto Timer::getElapsedNanoseconds() const -> uint64_t { - return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; - } - auto Timer::getElapsedMicroseconds() const -> uint64_t { - return getElapsedNanoseconds()/1000; - } - auto Timer::getElapsedMilliseconds() const -> unsigned int { - return static_cast(getElapsedMicroseconds()/1000); - } - auto Timer::getElapsedSeconds() const -> double { - return getElapsedMicroseconds()/1000000.0; - } - -} // namespace Catch +} // namespace Catch // end catch_timer.cpp // start catch_tostring.cpp #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" -# pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wglobal-constructors" #endif // Enable specific decls locally @@ -11801,61 +11929,56 @@ namespace Catch { namespace Detail { - const std::string unprintableString = "{?}"; +const std::string unprintableString = "{?}"; - namespace { - const int hexThreshold = 255; +namespace { +const int hexThreshold = 255; - struct Endianness { - enum Arch { Big, Little }; +struct Endianness { + enum Arch { Big, Little }; - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; + static Arch which() { + union _ { + int asInt; + char asChar[sizeof(int)]; + } u; - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - } + u.asInt = 1; + return (u.asChar[sizeof(int) - 1] == 1) ? Big : Little; + } +}; +} // namespace - std::string rawMemoryToString( const void *object, std::size_t size ) { - // Reverse order for little endian architectures - int i = 0, end = static_cast( size ), inc = 1; - if( Endianness::which() == Endianness::Little ) { - i = end-1; - end = inc = -1; - } +std::string rawMemoryToString(const void* object, std::size_t size) { + // Reverse order for little endian architectures + int i = 0, end = static_cast(size), inc = 1; + if (Endianness::which() == Endianness::Little) { + i = end - 1; + end = inc = -1; + } - unsigned char const *bytes = static_cast(object); - ReusableStringStream rss; - rss << "0x" << std::setfill('0') << std::hex; - for( ; i != end; i += inc ) - rss << std::setw(2) << static_cast(bytes[i]); - return rss.str(); - } + unsigned char const* bytes = static_cast(object); + ReusableStringStream rss; + rss << "0x" << std::setfill('0') << std::hex; + for (; i != end; i += inc) + rss << std::setw(2) << static_cast(bytes[i]); + return rss.str(); } +} // namespace Detail -template -std::string fpToString( T value, int precision ) { - if (Catch::isnan(value)) { - return "nan"; - } +template +std::string fpToString(T value, int precision) { + if (Catch::isnan(value)) { return "nan"; } - ReusableStringStream rss; - rss << std::setprecision( precision ) - << std::fixed - << value; - std::string d = rss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; + ReusableStringStream rss; + rss << std::setprecision(precision) << std::fixed << value; + std::string d = rss.str(); + std::size_t i = d.find_last_not_of('0'); + if (i != std::string::npos && i != d.size() - 1) { + if (d[i] == '.') i++; + d = d.substr(0, i + 1); + } + return d; } //// ======================================================= //// @@ -11865,148 +11988,144 @@ std::string fpToString( T value, int precision ) { //// ======================================================= //// std::string StringMaker::convert(const std::string& str) { - if (!getCurrentContext().getConfig()->showInvisibles()) { - return '"' + str + '"'; - } + if (!getCurrentContext().getConfig()->showInvisibles()) { + return '"' + str + '"'; + } - std::string s("\""); - for (char c : str) { - switch (c) { - case '\n': - s.append("\\n"); - break; - case '\t': - s.append("\\t"); - break; - default: - s.push_back(c); - break; - } + std::string s("\""); + for (char c : str) { + switch (c) { + case '\n': + s.append("\\n"); + break; + case '\t': + s.append("\\t"); + break; + default: + s.push_back(c); + break; } - s.append("\""); - return s; + } + s.append("\""); + return s; } #ifdef CATCH_CONFIG_CPP17_STRING_VIEW std::string StringMaker::convert(std::string_view str) { - return ::Catch::Detail::stringify(std::string{ str }); + return ::Catch::Detail::stringify(std::string{str}); } #endif std::string StringMaker::convert(char const* str) { - if (str) { - return ::Catch::Detail::stringify(std::string{ str }); - } else { - return{ "{null string}" }; - } + if (str) { + return ::Catch::Detail::stringify(std::string{str}); + } else { + return {"{null string}"}; + } } std::string StringMaker::convert(char* str) { - if (str) { - return ::Catch::Detail::stringify(std::string{ str }); - } else { - return{ "{null string}" }; - } + if (str) { + return ::Catch::Detail::stringify(std::string{str}); + } else { + return {"{null string}"}; + } } #ifdef CATCH_CONFIG_WCHAR std::string StringMaker::convert(const std::wstring& wstr) { - std::string s; - s.reserve(wstr.size()); - for (auto c : wstr) { - s += (c <= 0xff) ? static_cast(c) : '?'; - } - return ::Catch::Detail::stringify(s); + std::string s; + s.reserve(wstr.size()); + for (auto c : wstr) { s += (c <= 0xff) ? static_cast(c) : '?'; } + return ::Catch::Detail::stringify(s); } -# ifdef CATCH_CONFIG_CPP17_STRING_VIEW +#ifdef CATCH_CONFIG_CPP17_STRING_VIEW std::string StringMaker::convert(std::wstring_view str) { - return StringMaker::convert(std::wstring(str)); + return StringMaker::convert(std::wstring(str)); } -# endif +#endif -std::string StringMaker::convert(wchar_t const * str) { - if (str) { - return ::Catch::Detail::stringify(std::wstring{ str }); - } else { - return{ "{null string}" }; - } +std::string StringMaker::convert(wchar_t const* str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{str}); + } else { + return {"{null string}"}; + } } -std::string StringMaker::convert(wchar_t * str) { - if (str) { - return ::Catch::Detail::stringify(std::wstring{ str }); - } else { - return{ "{null string}" }; - } +std::string StringMaker::convert(wchar_t* str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{str}); + } else { + return {"{null string}"}; + } } #endif std::string StringMaker::convert(int value) { - return ::Catch::Detail::stringify(static_cast(value)); + return ::Catch::Detail::stringify(static_cast(value)); } std::string StringMaker::convert(long value) { - return ::Catch::Detail::stringify(static_cast(value)); + return ::Catch::Detail::stringify(static_cast(value)); } std::string StringMaker::convert(long long value) { - ReusableStringStream rss; - rss << value; - if (value > Detail::hexThreshold) { - rss << " (0x" << std::hex << value << ')'; - } - return rss.str(); + ReusableStringStream rss; + rss << value; + if (value > Detail::hexThreshold) { + rss << " (0x" << std::hex << value << ')'; + } + return rss.str(); } std::string StringMaker::convert(unsigned int value) { - return ::Catch::Detail::stringify(static_cast(value)); + return ::Catch::Detail::stringify(static_cast(value)); } std::string StringMaker::convert(unsigned long value) { - return ::Catch::Detail::stringify(static_cast(value)); + return ::Catch::Detail::stringify(static_cast(value)); } std::string StringMaker::convert(unsigned long long value) { - ReusableStringStream rss; - rss << value; - if (value > Detail::hexThreshold) { - rss << " (0x" << std::hex << value << ')'; - } - return rss.str(); + ReusableStringStream rss; + rss << value; + if (value > Detail::hexThreshold) { + rss << " (0x" << std::hex << value << ')'; + } + return rss.str(); } -std::string StringMaker::convert(bool b) { - return b ? "true" : "false"; -} +std::string StringMaker::convert(bool b) { return b ? "true" : "false"; } std::string StringMaker::convert(signed char value) { - if (value == '\r') { - return "'\\r'"; - } else if (value == '\f') { - return "'\\f'"; - } else if (value == '\n') { - return "'\\n'"; - } else if (value == '\t') { - return "'\\t'"; - } else if ('\0' <= value && value < ' ') { - return ::Catch::Detail::stringify(static_cast(value)); - } else { - char chstr[] = "' '"; - chstr[1] = value; - return chstr; - } + if (value == '\r') { + return "'\\r'"; + } else if (value == '\f') { + return "'\\f'"; + } else if (value == '\n') { + return "'\\n'"; + } else if (value == '\t') { + return "'\\t'"; + } else if ('\0' <= value && value < ' ') { + return ::Catch::Detail::stringify(static_cast(value)); + } else { + char chstr[] = "' '"; + chstr[1] = value; + return chstr; + } } std::string StringMaker::convert(char c) { - return ::Catch::Detail::stringify(static_cast(c)); + return ::Catch::Detail::stringify(static_cast(c)); } std::string StringMaker::convert(unsigned char c) { - return ::Catch::Detail::stringify(static_cast(c)); + return ::Catch::Detail::stringify(static_cast(c)); } std::string StringMaker::convert(std::nullptr_t) { - return "nullptr"; + return "nullptr"; } std::string StringMaker::convert(float value) { - return fpToString(value, 5) + 'f'; + return fpToString(value, 5) + 'f'; } std::string StringMaker::convert(double value) { - return fpToString(value, 10); + return fpToString(value, 10); } std::string ratio_string::symbol() { return "a"; } @@ -12016,10 +12135,10 @@ std::string ratio_string::symbol() { return "n"; } std::string ratio_string::symbol() { return "u"; } std::string ratio_string::symbol() { return "m"; } -} // end namespace Catch +} // end namespace Catch #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif // end catch_tostring.cpp @@ -12027,70 +12146,64 @@ std::string ratio_string::symbol() { return "m"; } namespace Catch { - Counts Counts::operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; - } - - Counts& Counts::operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } - - std::size_t Counts::total() const { - return passed + failed + failedButOk; - } - bool Counts::allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool Counts::allOk() const { - return failed == 0; - } - - Totals Totals::operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals& Totals::operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Totals Totals::delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else if( diff.assertions.failedButOk > 0 ) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; - } - +Counts Counts::operator-(Counts const& other) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; } + +Counts& Counts::operator+=(Counts const& other) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; +} + +std::size_t Counts::total() const { return passed + failed + failedButOk; } +bool Counts::allPassed() const { return failed == 0 && failedButOk == 0; } +bool Counts::allOk() const { return failed == 0; } + +Totals Totals::operator-(Totals const& other) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; +} + +Totals& Totals::operator+=(Totals const& other) { + assertions += other.assertions; + testCases += other.testCases; + return *this; +} + +Totals Totals::delta(Totals const& prevTotals) const { + Totals diff = *this - prevTotals; + if (diff.assertions.failed > 0) + ++diff.testCases.failed; + else if (diff.assertions.failedButOk > 0) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; +} + +} // namespace Catch // end catch_totals.cpp // start catch_uncaught_exceptions.cpp #include namespace Catch { - bool uncaught_exceptions() { +bool uncaught_exceptions() { #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) - return std::uncaught_exceptions() > 0; + return std::uncaught_exceptions() > 0; #else - return std::uncaught_exception(); + return std::uncaught_exception(); #endif - } -} // end namespace Catch +} +} // end namespace Catch // end catch_uncaught_exceptions.cpp // start catch_version.cpp @@ -12098,37 +12211,31 @@ namespace Catch { namespace Catch { - Version::Version - ( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << '.' - << version.minorVersion << '.' - << version.patchNumber; - // branchName is never null -> 0th char is \0 if it is empty - if (version.branchName[0]) { - os << '-' << version.branchName - << '.' << version.buildNumber; - } - return os; - } - - Version const& libraryVersion() { - static Version version( 2, 5, 0, "", 0 ); - return version; - } +Version::Version(unsigned int _majorVersion, unsigned int _minorVersion, + unsigned int _patchNumber, char const* const _branchName, + unsigned int _buildNumber) + : majorVersion(_majorVersion), + minorVersion(_minorVersion), + patchNumber(_patchNumber), + branchName(_branchName), + buildNumber(_buildNumber) {} +std::ostream& operator<<(std::ostream& os, Version const& version) { + os << version.majorVersion << '.' << version.minorVersion << '.' + << version.patchNumber; + // branchName is never null -> 0th char is \0 if it is empty + if (version.branchName[0]) { + os << '-' << version.branchName << '.' << version.buildNumber; + } + return os; } + +Version const& libraryVersion() { + static Version version(2, 5, 0, "", 0); + return version; +} + +} // namespace Catch // end catch_version.cpp // start catch_wildcard_pattern.cpp @@ -12136,40 +12243,38 @@ namespace Catch { namespace Catch { - WildcardPattern::WildcardPattern( std::string const& pattern, - CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - - bool WildcardPattern::matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - default: - CATCH_INTERNAL_ERROR( "Unknown enum" ); - } - } - - std::string WildcardPattern::adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } +WildcardPattern::WildcardPattern(std::string const& pattern, + CaseSensitive::Choice caseSensitivity) + : m_caseSensitivity(caseSensitivity), m_pattern(adjustCase(pattern)) { + if (startsWith(m_pattern, '*')) { + m_pattern = m_pattern.substr(1); + m_wildcard = WildcardAtStart; + } + if (endsWith(m_pattern, '*')) { + m_pattern = m_pattern.substr(0, m_pattern.size() - 1); + m_wildcard = static_cast(m_wildcard | WildcardAtEnd); + } } + +bool WildcardPattern::matches(std::string const& str) const { + switch (m_wildcard) { + case NoWildcard: + return m_pattern == adjustCase(str); + case WildcardAtStart: + return endsWith(adjustCase(str), m_pattern); + case WildcardAtEnd: + return startsWith(adjustCase(str), m_pattern); + case WildcardAtBothEnds: + return contains(adjustCase(str), m_pattern); + default: + CATCH_INTERNAL_ERROR("Unknown enum"); + } +} + +std::string WildcardPattern::adjustCase(std::string const& str) const { + return m_caseSensitivity == CaseSensitive::No ? toLower(str) : str; +} +} // namespace Catch // end catch_wildcard_pattern.cpp // start catch_xmlwriter.cpp @@ -12181,340 +12286,318 @@ namespace Catch { namespace { - size_t trailingBytes(unsigned char c) { - if ((c & 0xE0) == 0xC0) { - return 2; - } - if ((c & 0xF0) == 0xE0) { - return 3; - } - if ((c & 0xF8) == 0xF0) { - return 4; - } - CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); - } - - uint32_t headerValue(unsigned char c) { - if ((c & 0xE0) == 0xC0) { - return c & 0x1F; - } - if ((c & 0xF0) == 0xE0) { - return c & 0x0F; - } - if ((c & 0xF8) == 0xF0) { - return c & 0x07; - } - CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); - } - - void hexEscapeChar(std::ostream& os, unsigned char c) { - os << "\\x" - << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast(c); - } - -} // anonymous namespace - - XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) - : m_str( str ), - m_forWhat( forWhat ) - {} - - void XmlEncode::encodeTo( std::ostream& os ) const { - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { - uchar c = m_str[idx]; - switch (c) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') - os << ">"; - else - os << c; - break; - - case '\"': - if (m_forWhat == ForAttributes) - os << """; - else - os << c; - break; - - default: - // Check for control characters and invalid utf-8 - - // Escape control characters in standard ascii - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { - hexEscapeChar(os, c); - break; - } - - // Plain ASCII: Write it to stream - if (c < 0x7F) { - os << c; - break; - } - - // UTF-8 territory - // Check if the encoding is valid and if it is not, hex escape bytes. - // Important: We do not check the exact decoded values for validity, only the encoding format - // First check that this bytes is a valid lead byte: - // This means that it is not encoded as 1111 1XXX - // Or as 10XX XXXX - if (c < 0xC0 || - c >= 0xF8) { - hexEscapeChar(os, c); - break; - } - - auto encBytes = trailingBytes(c); - // Are there enough bytes left to avoid accessing out-of-bounds memory? - if (idx + encBytes - 1 >= m_str.size()) { - hexEscapeChar(os, c); - break; - } - // The header is valid, check data - // The next encBytes bytes must together be a valid utf-8 - // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) - bool valid = true; - uint32_t value = headerValue(c); - for (std::size_t n = 1; n < encBytes; ++n) { - uchar nc = m_str[idx + n]; - valid &= ((nc & 0xC0) == 0x80); - value = (value << 6) | (nc & 0x3F); - } - - if ( - // Wrong bit pattern of following bytes - (!valid) || - // Overlong encodings - (value < 0x80) || - (0x80 <= value && value < 0x800 && encBytes > 2) || - (0x800 < value && value < 0x10000 && encBytes > 3) || - // Encoded value out of range - (value >= 0x110000) - ) { - hexEscapeChar(os, c); - break; - } - - // If we got here, this is in fact a valid(ish) utf-8 sequence - for (std::size_t n = 0; n < encBytes; ++n) { - os << m_str[idx + n]; - } - idx += encBytes - 1; - break; - } - } - } - - std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } - - XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept - : m_writer( other.m_writer ){ - other.m_writer = nullptr; - } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { - if ( m_writer ) { - m_writer->endElement(); - } - m_writer = other.m_writer; - other.m_writer = nullptr; - return *this; - } - - XmlWriter::ScopedElement::~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { - m_writer->writeText( text, indent ); - return *this; - } - - XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) - { - writeDeclaration(); - } - - XmlWriter::~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& XmlWriter::startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& XmlWriter::endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& XmlWriter::writeComment( std::string const& text ) { - ensureTagClosed(); - m_os << m_indent << ""; - m_needsNewline = true; - return *this; - } - - void XmlWriter::writeStylesheetRef( std::string const& url ) { - m_os << "\n"; - } - - XmlWriter& XmlWriter::writeBlankLine() { - ensureTagClosed(); - m_os << '\n'; - return *this; - } - - void XmlWriter::ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } - - void XmlWriter::writeDeclaration() { - m_os << "\n"; - } - - void XmlWriter::newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } +size_t trailingBytes(unsigned char c) { + if ((c & 0xE0) == 0xC0) { return 2; } + if ((c & 0xF0) == 0xE0) { return 3; } + if ((c & 0xF8) == 0xF0) { return 4; } + CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); } + +uint32_t headerValue(unsigned char c) { + if ((c & 0xE0) == 0xC0) { return c & 0x1F; } + if ((c & 0xF0) == 0xE0) { return c & 0x0F; } + if ((c & 0xF8) == 0xF0) { return c & 0x07; } + CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); +} + +void hexEscapeChar(std::ostream& os, unsigned char c) { + os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast(c); +} + +} // anonymous namespace + +XmlEncode::XmlEncode(std::string const& str, ForWhat forWhat) + : m_str(str), m_forWhat(forWhat) {} + +void XmlEncode::encodeTo(std::ostream& os) const { + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for (std::size_t idx = 0; idx < m_str.size(); ++idx) { + uchar c = m_str[idx]; + switch (c) { + case '<': + os << "<"; + break; + case '&': + os << "&"; + break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') + os << ">"; + else + os << c; + break; + + case '\"': + if (m_forWhat == ForAttributes) + os << """; + else + os << c; + break; + + default: + // Check for control characters and invalid utf-8 + + // Escape control characters in standard ascii + // see + // http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { + hexEscapeChar(os, c); + break; + } + + // Plain ASCII: Write it to stream + if (c < 0x7F) { + os << c; + break; + } + + // UTF-8 territory + // Check if the encoding is valid and if it is not, hex escape bytes. + // Important: We do not check the exact decoded values for validity, + // only the encoding format First check that this bytes is a valid lead + // byte: This means that it is not encoded as 1111 1XXX Or as 10XX XXXX + if (c < 0xC0 || c >= 0xF8) { + hexEscapeChar(os, c); + break; + } + + auto encBytes = trailingBytes(c); + // Are there enough bytes left to avoid accessing out-of-bounds memory? + if (idx + encBytes - 1 >= m_str.size()) { + hexEscapeChar(os, c); + break; + } + // The header is valid, check data + // The next encBytes bytes must together be a valid utf-8 + // This means: bitpattern 10XX XXXX and the extracted value is sane + // (ish) + bool valid = true; + uint32_t value = headerValue(c); + for (std::size_t n = 1; n < encBytes; ++n) { + uchar nc = m_str[idx + n]; + valid &= ((nc & 0xC0) == 0x80); + value = (value << 6) | (nc & 0x3F); + } + + if ( + // Wrong bit pattern of following bytes + (!valid) || + // Overlong encodings + (value < 0x80) || + (0x80 <= value && value < 0x800 && encBytes > 2) || + (0x800 < value && value < 0x10000 && encBytes > 3) || + // Encoded value out of range + (value >= 0x110000)) { + hexEscapeChar(os, c); + break; + } + + // If we got here, this is in fact a valid(ish) utf-8 sequence + for (std::size_t n = 0; n < encBytes; ++n) { os << m_str[idx + n]; } + idx += encBytes - 1; + break; + } + } +} + +std::ostream& operator<<(std::ostream& os, XmlEncode const& xmlEncode) { + xmlEncode.encodeTo(os); + return os; +} + +XmlWriter::ScopedElement::ScopedElement(XmlWriter* writer) : m_writer(writer) {} + +XmlWriter::ScopedElement::ScopedElement(ScopedElement&& other) noexcept + : m_writer(other.m_writer) { + other.m_writer = nullptr; +} +XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( + ScopedElement&& other) noexcept { + if (m_writer) { m_writer->endElement(); } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; +} + +XmlWriter::ScopedElement::~ScopedElement() { + if (m_writer) m_writer->endElement(); +} + +XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( + std::string const& text, bool indent) { + m_writer->writeText(text, indent); + return *this; +} + +XmlWriter::XmlWriter(std::ostream& os) : m_os(os) { writeDeclaration(); } + +XmlWriter::~XmlWriter() { + while (!m_tags.empty()) endElement(); +} + +XmlWriter& XmlWriter::startElement(std::string const& name) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back(name); + m_indent += " "; + m_tagIsOpen = true; + return *this; +} + +XmlWriter::ScopedElement XmlWriter::scopedElement(std::string const& name) { + ScopedElement scoped(this); + startElement(name); + return scoped; +} + +XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr(0, m_indent.size() - 2); + if (m_tagIsOpen) { + m_os << "/>"; + m_tagIsOpen = false; + } else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; +} + +XmlWriter& XmlWriter::writeAttribute(std::string const& name, + std::string const& attribute) { + if (!name.empty() && !attribute.empty()) + m_os << ' ' << name << "=\"" + << XmlEncode(attribute, XmlEncode::ForAttributes) << '"'; + return *this; +} + +XmlWriter& XmlWriter::writeAttribute(std::string const& name, bool attribute) { + m_os << ' ' << name << "=\"" << (attribute ? "true" : "false") << '"'; + return *this; +} + +XmlWriter& XmlWriter::writeText(std::string const& text, bool indent) { + if (!text.empty()) { + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if (tagWasOpen && indent) m_os << m_indent; + m_os << XmlEncode(text); + m_needsNewline = true; + } + return *this; +} + +XmlWriter& XmlWriter::writeComment(std::string const& text) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; +} + +void XmlWriter::writeStylesheetRef(std::string const& url) { + m_os << "\n"; +} + +XmlWriter& XmlWriter::writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; +} + +void XmlWriter::ensureTagClosed() { + if (m_tagIsOpen) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } +} + +void XmlWriter::writeDeclaration() { + m_os << "\n"; +} + +void XmlWriter::newlineIfNecessary() { + if (m_needsNewline) { + m_os << std::endl; + m_needsNewline = false; + } +} +} // namespace Catch // end catch_xmlwriter.cpp // start catch_reporter_bases.cpp -#include +#include #include #include -#include +#include #include namespace Catch { - void prepareExpandedExpression(AssertionResult& result) { - result.getExpandedExpression(); - } +void prepareExpandedExpression(AssertionResult& result) { + result.getExpandedExpression(); +} - // Because formatting using c++ streams is stateful, drop down to C is required - // Alternatively we could use stringstream, but its performance is... not good. - std::string getFormattedDuration( double duration ) { - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; +// Because formatting using c++ streams is stateful, drop down to C is required +// Alternatively we could use stringstream, but its performance is... not good. +std::string getFormattedDuration(double duration) { + // Max exponent + 1 is required to represent the whole part + // + 1 for decimal point + // + 3 for the 3 decimal places + // + 1 for null terminator + const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + char buffer[maxDoubleSize]; - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; #ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); + sprintf_s(buffer, "%.3f", duration); #else - sprintf(buffer, "%.3f", duration); + sprintf(buffer, "%.3f", duration); #endif - return std::string(buffer); - } + return std::string(buffer); +} - TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) - :StreamingReporterBase(_config) {} +TestEventListenerBase::TestEventListenerBase(ReporterConfig const& _config) + : StreamingReporterBase(_config) {} - std::set TestEventListenerBase::getSupportedVerbosities() { - return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High }; - } +std::set TestEventListenerBase::getSupportedVerbosities() { + return {Verbosity::Quiet, Verbosity::Normal, Verbosity::High}; +} - void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} +void TestEventListenerBase::assertionStarting(AssertionInfo const&) {} - bool TestEventListenerBase::assertionEnded(AssertionStats const &) { - return false; - } +bool TestEventListenerBase::assertionEnded(AssertionStats const&) { + return false; +} -} // end namespace Catch +} // end namespace Catch // end catch_reporter_bases.cpp // start catch_reporter_compact.cpp namespace { #ifdef CATCH_PLATFORM_MAC - const char* failedString() { return "FAILED"; } - const char* passedString() { return "PASSED"; } +const char* failedString() { return "FAILED"; } +const char* passedString() { return "PASSED"; } #else - const char* failedString() { return "failed"; } - const char* passedString() { return "passed"; } +const char* failedString() { return "failed"; } +const char* passedString() { return "passed"; } #endif - // Colour::LightGrey - Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } +// Colour::LightGrey +Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } - std::string bothOrAll( std::size_t count ) { - return count == 1 ? std::string() : - count == 2 ? "both " : "all " ; - } +std::string bothOrAll(std::size_t count) { + return count == 1 ? std::string() : count == 2 ? "both " : "all "; +} -} // anon namespace +} // namespace namespace Catch { namespace { @@ -12525,256 +12608,256 @@ namespace { // - red: Failed N tests cases, failed M assertions. // - green: Passed [both/all] N tests cases with M assertions. void printTotals(std::ostream& out, const Totals& totals) { - if (totals.testCases.total() == 0) { - out << "No tests ran."; - } else if (totals.testCases.failed == totals.testCases.total()) { - Colour colour(Colour::ResultError); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll(totals.assertions.failed) : std::string(); - out << - "Failed " << bothOrAll(totals.testCases.failed) - << pluralise(totals.testCases.failed, "test case") << ", " - "failed " << qualify_assertions_failed << - pluralise(totals.assertions.failed, "assertion") << '.'; - } else if (totals.assertions.total() == 0) { - out << - "Passed " << bothOrAll(totals.testCases.total()) - << pluralise(totals.testCases.total(), "test case") - << " (no assertions)."; - } else if (totals.assertions.failed) { - Colour colour(Colour::ResultError); - out << - "Failed " << pluralise(totals.testCases.failed, "test case") << ", " - "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; - } else { - Colour colour(Colour::ResultSuccess); - out << - "Passed " << bothOrAll(totals.testCases.passed) - << pluralise(totals.testCases.passed, "test case") << - " with " << pluralise(totals.assertions.passed, "assertion") << '.'; - } + if (totals.testCases.total() == 0) { + out << "No tests ran."; + } else if (totals.testCases.failed == totals.testCases.total()) { + Colour colour(Colour::ResultError); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() + ? bothOrAll(totals.assertions.failed) + : std::string(); + out << "Failed " << bothOrAll(totals.testCases.failed) + << pluralise(totals.testCases.failed, "test case") + << ", " + "failed " + << qualify_assertions_failed + << pluralise(totals.assertions.failed, "assertion") << '.'; + } else if (totals.assertions.total() == 0) { + out << "Passed " << bothOrAll(totals.testCases.total()) + << pluralise(totals.testCases.total(), "test case") + << " (no assertions)."; + } else if (totals.assertions.failed) { + Colour colour(Colour::ResultError); + out << "Failed " << pluralise(totals.testCases.failed, "test case") + << ", " + "failed " + << pluralise(totals.assertions.failed, "assertion") << '.'; + } else { + Colour colour(Colour::ResultSuccess); + out << "Passed " << bothOrAll(totals.testCases.passed) + << pluralise(totals.testCases.passed, "test case") << " with " + << pluralise(totals.assertions.passed, "assertion") << '.'; + } } // Implementation of CompactReporter formatting class AssertionPrinter { -public: - AssertionPrinter& operator= (AssertionPrinter const&) = delete; - AssertionPrinter(AssertionPrinter const&) = delete; - AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) - : stream(_stream) - , result(_stats.assertionResult) - , messages(_stats.infoMessages) - , itMessage(_stats.infoMessages.begin()) - , printInfoMessages(_printInfoMessages) {} + public: + AssertionPrinter& operator=(AssertionPrinter const&) = delete; + AssertionPrinter(AssertionPrinter const&) = delete; + AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, + bool _printInfoMessages) + : stream(_stream), + result(_stats.assertionResult), + messages(_stats.infoMessages), + itMessage(_stats.infoMessages.begin()), + printInfoMessages(_printInfoMessages) {} - void print() { - printSourceInfo(); + void print() { + printSourceInfo(); - itMessage = messages.begin(); + itMessage = messages.begin(); - switch (result.getResultType()) { - case ResultWas::Ok: - printResultType(Colour::ResultSuccess, passedString()); - printOriginalExpression(); - printReconstructedExpression(); - if (!result.hasExpression()) - printRemainingMessages(Colour::None); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if (result.isOk()) - printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); - else - printResultType(Colour::Error, failedString()); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType(Colour::Error, failedString()); - printIssue("unexpected exception with message:"); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType(Colour::Error, failedString()); - printIssue("fatal error condition with message:"); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType(Colour::Error, failedString()); - printIssue("expected exception, got none"); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType(Colour::None, "info"); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType(Colour::None, "warning"); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType(Colour::Error, failedString()); - printIssue("explicitly"); - printRemainingMessages(Colour::None); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType(Colour::Error, "** internal error **"); - break; + switch (result.getResultType()) { + case ResultWas::Ok: + printResultType(Colour::ResultSuccess, passedString()); + printOriginalExpression(); + printReconstructedExpression(); + if (!result.hasExpression()) + printRemainingMessages(Colour::None); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if (result.isOk()) + printResultType(Colour::ResultSuccess, + failedString() + std::string(" - but was ok")); + else + printResultType(Colour::Error, failedString()); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType(Colour::Error, failedString()); + printIssue("unexpected exception with message:"); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType(Colour::Error, failedString()); + printIssue("fatal error condition with message:"); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType(Colour::Error, failedString()); + printIssue("expected exception, got none"); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType(Colour::None, "info"); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType(Colour::None, "warning"); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType(Colour::Error, failedString()); + printIssue("explicitly"); + printRemainingMessages(Colour::None); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType(Colour::Error, "** internal error **"); + break; + } + } + + private: + void printSourceInfo() const { + Colour colourGuard(Colour::FileName); + stream << result.getSourceInfo() << ':'; + } + + void printResultType(Colour::Code colour, + std::string const& passOrFail) const { + if (!passOrFail.empty()) { + { + Colour colourGuard(colour); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } + + void printIssue(std::string const& issue) const { stream << ' ' << issue; } + + void printExpressionWas() { + if (result.hasExpression()) { + stream << ';'; + { + Colour colour(dimColour()); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if (result.hasExpression()) { stream << ' ' << result.getExpression(); } + } + + void printReconstructedExpression() const { + if (result.hasExpandedExpression()) { + { + Colour colour(dimColour()); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if (itMessage != messages.end()) { + stream << " '" << itMessage->message << '\''; + ++itMessage; + } + } + + void printRemainingMessages(Colour::Code colour = dimColour()) { + if (itMessage == messages.end()) return; + + // using messages.end() directly yields (or auto) compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = + static_cast(std::distance(itMessage, itEnd)); + + { + Colour colourGuard(colour); + stream << " with " << pluralise(N, "message") << ':'; + } + + for (; itMessage != itEnd;) { + // If this assertion is a warning ignore any INFO messages + if (printInfoMessages || itMessage->type != ResultWas::Info) { + stream << " '" << itMessage->message << '\''; + if (++itMessage != itEnd) { + Colour colourGuard(dimColour()); + stream << " and"; } + } } + } -private: - void printSourceInfo() const { - Colour colourGuard(Colour::FileName); - stream << result.getSourceInfo() << ':'; - } - - void printResultType(Colour::Code colour, std::string const& passOrFail) const { - if (!passOrFail.empty()) { - { - Colour colourGuard(colour); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue(std::string const& issue) const { - stream << ' ' << issue; - } - - void printExpressionWas() { - if (result.hasExpression()) { - stream << ';'; - { - Colour colour(dimColour()); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if (result.hasExpression()) { - stream << ' ' << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if (result.hasExpandedExpression()) { - { - Colour colour(dimColour()); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() { - if (itMessage != messages.end()) { - stream << " '" << itMessage->message << '\''; - ++itMessage; - } - } - - void printRemainingMessages(Colour::Code colour = dimColour()) { - if (itMessage == messages.end()) - return; - - // using messages.end() directly yields (or auto) compilation error: - std::vector::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast(std::distance(itMessage, itEnd)); - - { - Colour colourGuard(colour); - stream << " with " << pluralise(N, "message") << ':'; - } - - for (; itMessage != itEnd; ) { - // If this assertion is a warning ignore any INFO messages - if (printInfoMessages || itMessage->type != ResultWas::Info) { - stream << " '" << itMessage->message << '\''; - if (++itMessage != itEnd) { - Colour colourGuard(dimColour()); - stream << " and"; - } - } - } - } - -private: - std::ostream& stream; - AssertionResult const& result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; + private: + std::ostream& stream; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; }; -} // anon namespace +} // namespace - std::string CompactReporter::getDescription() { - return "Reports test results on a single line, suitable for IDEs"; - } +std::string CompactReporter::getDescription() { + return "Reports test results on a single line, suitable for IDEs"; +} - ReporterPreferences CompactReporter::getPreferences() const { - return m_reporterPrefs; - } +ReporterPreferences CompactReporter::getPreferences() const { + return m_reporterPrefs; +} - void CompactReporter::noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } +void CompactReporter::noMatchingTestCases(std::string const& spec) { + stream << "No test cases matched '" << spec << '\'' << std::endl; +} - void CompactReporter::assertionStarting( AssertionInfo const& ) {} +void CompactReporter::assertionStarting(AssertionInfo const&) {} - bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; +bool CompactReporter::assertionEnded(AssertionStats const& _assertionStats) { + AssertionResult const& result = _assertionStats.assertionResult; - bool printInfoMessages = true; + bool printInfoMessages = true; - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } + // Drop out if result was successful and we're not printing those + if (!m_config->includeSuccessfulResults() && result.isOk()) { + if (result.getResultType() != ResultWas::Warning) return false; + printInfoMessages = false; + } - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); + AssertionPrinter printer(stream, _assertionStats, printInfoMessages); + printer.print(); - stream << std::endl; - return true; - } + stream << std::endl; + return true; +} - void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - } +void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) + << " s: " << _sectionStats.sectionInfo.name << std::endl; + } +} - void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( stream, _testRunStats.totals ); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } +void CompactReporter::testRunEnded(TestRunStats const& _testRunStats) { + printTotals(stream, _testRunStats.totals); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded(_testRunStats); +} - CompactReporter::~CompactReporter() {} +CompactReporter::~CompactReporter() {} - CATCH_REGISTER_REPORTER( "compact", CompactReporter ) +CATCH_REGISTER_REPORTER("compact", CompactReporter) -} // end namespace Catch +} // end namespace Catch // end catch_reporter_compact.cpp // start catch_reporter_console.cpp @@ -12783,9 +12866,9 @@ private: #if defined(_MSC_VER) #pragma warning(push) -#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch - // Note that 4062 (not all labels are handled - // and default is missing) is enabled +#pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in + // switch Note that 4062 (not all labels are + // handled and default is missing) is enabled #endif namespace Catch { @@ -12794,599 +12877,589 @@ namespace { // Formatter impl for ConsoleReporter class ConsoleAssertionPrinter { -public: - ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; - ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; - ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) - : stream(_stream), + public: + ConsoleAssertionPrinter& operator=(ConsoleAssertionPrinter const&) = delete; + ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; + ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, + bool _printInfoMessages) + : stream(_stream), stats(_stats), result(_stats.assertionResult), colour(Colour::None), message(result.getMessage()), messages(_stats.infoMessages), printInfoMessages(_printInfoMessages) { - switch (result.getResultType()) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if (_stats.infoMessages.size() == 1) - messageLabel = "with message"; - if (_stats.infoMessages.size() > 1) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if (result.isOk()) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if (_stats.infoMessages.size() == 1) - messageLabel = "with message"; - if (_stats.infoMessages.size() > 1) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with "; - if (_stats.infoMessages.size() == 1) - messageLabel += "message"; - if (_stats.infoMessages.size() > 1) - messageLabel += "messages"; - break; - case ResultWas::FatalErrorCondition: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to a fatal error condition"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if (_stats.infoMessages.size() == 1) - messageLabel = "explicitly with message"; - if (_stats.infoMessages.size() > 1) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if (stats.totals.assertions.total() > 0) { - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); + switch (result.getResultType()) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + // if( result.hasMessage() ) + if (_stats.infoMessages.size() == 1) messageLabel = "with message"; + if (_stats.infoMessages.size() > 1) messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if (result.isOk()) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; } else { - stream << '\n'; + colour = Colour::Error; + passOrFail = "FAILED"; } - printMessage(); + if (_stats.infoMessages.size() == 1) messageLabel = "with message"; + if (_stats.infoMessages.size() > 1) messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with "; + if (_stats.infoMessages.size() == 1) messageLabel += "message"; + if (_stats.infoMessages.size() > 1) messageLabel += "messages"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if (_stats.infoMessages.size() == 1) + messageLabel = "explicitly with message"; + if (_stats.infoMessages.size() > 1) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; } + } -private: - void printResultType() const { - if (!passOrFail.empty()) { - Colour colourGuard(colour); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if (result.hasExpression()) { - Colour colourGuard(Colour::OriginalExpression); - stream << " "; - stream << result.getExpressionInMacro(); - stream << '\n'; - } - } - void printReconstructedExpression() const { - if (result.hasExpandedExpression()) { - stream << "with expansion:\n"; - Colour colourGuard(Colour::ReconstructedExpression); - stream << Column(result.getExpandedExpression()).indent(2) << '\n'; - } - } - void printMessage() const { - if (!messageLabel.empty()) - stream << messageLabel << ':' << '\n'; - for (auto const& msg : messages) { - // If this assertion is a warning ignore any INFO messages - if (printInfoMessages || msg.type != ResultWas::Info) - stream << Column(msg.message).indent(2) << '\n'; - } - } - void printSourceInfo() const { - Colour colourGuard(Colour::FileName); - stream << result.getSourceInfo() << ": "; + void print() const { + printSourceInfo(); + if (stats.totals.assertions.total() > 0) { + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } else { + stream << '\n'; } + printMessage(); + } - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; + private: + void printResultType() const { + if (!passOrFail.empty()) { + Colour colourGuard(colour); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if (result.hasExpression()) { + Colour colourGuard(Colour::OriginalExpression); + stream << " "; + stream << result.getExpressionInMacro(); + stream << '\n'; + } + } + void printReconstructedExpression() const { + if (result.hasExpandedExpression()) { + stream << "with expansion:\n"; + Colour colourGuard(Colour::ReconstructedExpression); + stream << Column(result.getExpandedExpression()).indent(2) << '\n'; + } + } + void printMessage() const { + if (!messageLabel.empty()) stream << messageLabel << ':' << '\n'; + for (auto const& msg : messages) { + // If this assertion is a warning ignore any INFO messages + if (printInfoMessages || msg.type != ResultWas::Info) + stream << Column(msg.message).indent(2) << '\n'; + } + } + void printSourceInfo() const { + Colour colourGuard(Colour::FileName); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; }; std::size_t makeRatio(std::size_t number, std::size_t total) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; - return (ratio == 0 && number > 0) ? 1 : ratio; + std::size_t ratio = + total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; + return (ratio == 0 && number > 0) ? 1 : ratio; } std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { - if (i > j && i > k) - return i; - else if (j > k) - return j; - else - return k; + if (i > j && i > k) + return i; + else if (j > k) + return j; + else + return k; } struct ColumnInfo { - enum Justification { Left, Right }; - std::string name; - int width; - Justification justification; + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; }; struct ColumnBreak {}; struct RowBreak {}; class Duration { - enum class Unit { - Auto, - Nanoseconds, - Microseconds, - Milliseconds, - Seconds, - Minutes - }; - static const uint64_t s_nanosecondsInAMicrosecond = 1000; - static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; - static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; - static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = + 1000 * s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = + 1000 * s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; - uint64_t m_inNanoseconds; - Unit m_units; - -public: - explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto) - : m_inNanoseconds(inNanoseconds), - m_units(units) { - if (m_units == Unit::Auto) { - if (m_inNanoseconds < s_nanosecondsInAMicrosecond) - m_units = Unit::Nanoseconds; - else if (m_inNanoseconds < s_nanosecondsInAMillisecond) - m_units = Unit::Microseconds; - else if (m_inNanoseconds < s_nanosecondsInASecond) - m_units = Unit::Milliseconds; - else if (m_inNanoseconds < s_nanosecondsInAMinute) - m_units = Unit::Seconds; - else - m_units = Unit::Minutes; - } + uint64_t m_inNanoseconds; + Unit m_units; + public: + explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto) + : m_inNanoseconds(inNanoseconds), m_units(units) { + if (m_units == Unit::Auto) { + if (m_inNanoseconds < s_nanosecondsInAMicrosecond) + m_units = Unit::Nanoseconds; + else if (m_inNanoseconds < s_nanosecondsInAMillisecond) + m_units = Unit::Microseconds; + else if (m_inNanoseconds < s_nanosecondsInASecond) + m_units = Unit::Milliseconds; + else if (m_inNanoseconds < s_nanosecondsInAMinute) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; } + } - auto value() const -> double { - switch (m_units) { - case Unit::Microseconds: - return m_inNanoseconds / static_cast(s_nanosecondsInAMicrosecond); - case Unit::Milliseconds: - return m_inNanoseconds / static_cast(s_nanosecondsInAMillisecond); - case Unit::Seconds: - return m_inNanoseconds / static_cast(s_nanosecondsInASecond); - case Unit::Minutes: - return m_inNanoseconds / static_cast(s_nanosecondsInAMinute); - default: - return static_cast(m_inNanoseconds); - } + auto value() const -> double { + switch (m_units) { + case Unit::Microseconds: + return m_inNanoseconds / + static_cast(s_nanosecondsInAMicrosecond); + case Unit::Milliseconds: + return m_inNanoseconds / + static_cast(s_nanosecondsInAMillisecond); + case Unit::Seconds: + return m_inNanoseconds / static_cast(s_nanosecondsInASecond); + case Unit::Minutes: + return m_inNanoseconds / static_cast(s_nanosecondsInAMinute); + default: + return static_cast(m_inNanoseconds); } - auto unitsAsString() const -> std::string { - switch (m_units) { - case Unit::Nanoseconds: - return "ns"; - case Unit::Microseconds: - return "µs"; - case Unit::Milliseconds: - return "ms"; - case Unit::Seconds: - return "s"; - case Unit::Minutes: - return "m"; - default: - return "** internal error **"; - } - - } - friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { - return os << duration.value() << " " << duration.unitsAsString(); + } + auto unitsAsString() const -> std::string { + switch (m_units) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; } + } + friend auto operator<<(std::ostream& os, Duration const& duration) + -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } }; -} // end anon namespace +} // namespace class TablePrinter { - std::ostream& m_os; - std::vector m_columnInfos; - std::ostringstream m_oss; - int m_currentColumn = -1; - bool m_isOpen = false; + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; -public: - TablePrinter( std::ostream& os, std::vector columnInfos ) - : m_os( os ), - m_columnInfos( std::move( columnInfos ) ) {} + public: + TablePrinter(std::ostream& os, std::vector columnInfos) + : m_os(os), m_columnInfos(std::move(columnInfos)) {} - auto columnInfos() const -> std::vector const& { - return m_columnInfos; + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if (!m_isOpen) { + m_isOpen = true; + *this << RowBreak(); + for (auto const& info : m_columnInfos) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; } - - void open() { - if (!m_isOpen) { - m_isOpen = true; - *this << RowBreak(); - for (auto const& info : m_columnInfos) - *this << info.name << ColumnBreak(); - *this << RowBreak(); - m_os << Catch::getLineOfChars<'-'>() << "\n"; - } - } - void close() { - if (m_isOpen) { - *this << RowBreak(); - m_os << std::endl; - m_isOpen = false; - } + } + void close() { + if (m_isOpen) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; } + } - template - friend TablePrinter& operator << (TablePrinter& tp, T const& value) { - tp.m_oss << value; - return tp; - } + template + friend TablePrinter& operator<<(TablePrinter& tp, T const& value) { + tp.m_oss << value; + return tp; + } - friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { - auto colStr = tp.m_oss.str(); - // This takes account of utf8 encodings - auto strSize = Catch::StringRef(colStr).numberOfCharacters(); - tp.m_oss.str(""); - tp.open(); - if (tp.m_currentColumn == static_cast(tp.m_columnInfos.size() - 1)) { - tp.m_currentColumn = -1; - tp.m_os << "\n"; - } - tp.m_currentColumn++; - - auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = (strSize + 2 < static_cast(colInfo.width)) - ? std::string(colInfo.width - (strSize + 2), ' ') - : std::string(); - if (colInfo.justification == ColumnInfo::Left) - tp.m_os << colStr << padding << " "; - else - tp.m_os << padding << colStr << " "; - return tp; + friend TablePrinter& operator<<(TablePrinter& tp, ColumnBreak) { + auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef(colStr).numberOfCharacters(); + tp.m_oss.str(""); + tp.open(); + if (tp.m_currentColumn == static_cast(tp.m_columnInfos.size() - 1)) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; } + tp.m_currentColumn++; - friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { - if (tp.m_currentColumn > 0) { - tp.m_os << "\n"; - tp.m_currentColumn = -1; - } - return tp; + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = (strSize + 2 < static_cast(colInfo.width)) + ? std::string(colInfo.width - (strSize + 2), ' ') + : std::string(); + if (colInfo.justification == ColumnInfo::Left) + tp.m_os << colStr << padding << " "; + else + tp.m_os << padding << colStr << " "; + return tp; + } + + friend TablePrinter& operator<<(TablePrinter& tp, RowBreak) { + if (tp.m_currentColumn > 0) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; } + return tp; + } }; ConsoleReporter::ConsoleReporter(ReporterConfig const& config) : StreamingReporterBase(config), - m_tablePrinter(new TablePrinter(config.stream(), - { - { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left }, - { "iters", 8, ColumnInfo::Right }, - { "elapsed ns", 14, ColumnInfo::Right }, - { "average", 14, ColumnInfo::Right } - })) {} + m_tablePrinter(new TablePrinter( + config.stream(), {{"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, + ColumnInfo::Left}, + {"iters", 8, ColumnInfo::Right}, + {"elapsed ns", 14, ColumnInfo::Right}, + {"average", 14, ColumnInfo::Right}})) {} ConsoleReporter::~ConsoleReporter() = default; std::string ConsoleReporter::getDescription() { - return "Reports test results as plain lines of text"; + return "Reports test results as plain lines of text"; } void ConsoleReporter::noMatchingTestCases(std::string const& spec) { - stream << "No test cases matched '" << spec << '\'' << std::endl; + stream << "No test cases matched '" << spec << '\'' << std::endl; } void ConsoleReporter::assertionStarting(AssertionInfo const&) {} bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { - AssertionResult const& result = _assertionStats.assertionResult; + AssertionResult const& result = _assertionStats.assertionResult; - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); - // Drop out if result was successful but we're not printing them. - if (!includeResults && result.getResultType() != ResultWas::Warning) - return false; + // Drop out if result was successful but we're not printing them. + if (!includeResults && result.getResultType() != ResultWas::Warning) + return false; - lazyPrint(); + lazyPrint(); - ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); - printer.print(); - stream << std::endl; - return true; + ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); + printer.print(); + stream << std::endl; + return true; } void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting(_sectionInfo); + m_headerPrinted = false; + StreamingReporterBase::sectionStarting(_sectionInfo); } void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { - m_tablePrinter->close(); - if (_sectionStats.missingAssertions) { - lazyPrint(); - Colour colour(Colour::ResultError); - if (m_sectionStack.size() > 1) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - if (m_headerPrinted) { - m_headerPrinted = false; - } - StreamingReporterBase::sectionEnded(_sectionStats); + m_tablePrinter->close(); + if (_sectionStats.missingAssertions) { + lazyPrint(); + Colour colour(Colour::ResultError); + if (m_sectionStack.size() > 1) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) + << " s: " << _sectionStats.sectionInfo.name << std::endl; + } + if (m_headerPrinted) { m_headerPrinted = false; } + StreamingReporterBase::sectionEnded(_sectionStats); } void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { - lazyPrintWithoutClosingBenchmarkTable(); + lazyPrintWithoutClosingBenchmarkTable(); - auto nameCol = Column( info.name ).width( static_cast( m_tablePrinter->columnInfos()[0].width - 2 ) ); + auto nameCol = Column(info.name).width( + static_cast(m_tablePrinter->columnInfos()[0].width - 2)); - bool firstLine = true; - for (auto line : nameCol) { - if (!firstLine) - (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); - else - firstLine = false; + bool firstLine = true; + for (auto line : nameCol) { + if (!firstLine) + (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); + else + firstLine = false; - (*m_tablePrinter) << line << ColumnBreak(); - } + (*m_tablePrinter) << line << ColumnBreak(); + } } void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) { - Duration average(stats.elapsedTimeInNanoseconds / stats.iterations); - (*m_tablePrinter) - << stats.iterations << ColumnBreak() - << stats.elapsedTimeInNanoseconds << ColumnBreak() - << average << ColumnBreak(); + Duration average(stats.elapsedTimeInNanoseconds / stats.iterations); + (*m_tablePrinter) << stats.iterations << ColumnBreak() + << stats.elapsedTimeInNanoseconds << ColumnBreak() + << average << ColumnBreak(); } void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { - m_tablePrinter->close(); - StreamingReporterBase::testCaseEnded(_testCaseStats); - m_headerPrinted = false; + m_tablePrinter->close(); + StreamingReporterBase::testCaseEnded(_testCaseStats); + m_headerPrinted = false; } void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { - if (currentGroupInfo.used) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals(_testGroupStats.totals); - stream << '\n' << std::endl; - } - StreamingReporterBase::testGroupEnded(_testGroupStats); + if (currentGroupInfo.used) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals(_testGroupStats.totals); + stream << '\n' << std::endl; + } + StreamingReporterBase::testGroupEnded(_testGroupStats); } void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { - printTotalsDivider(_testRunStats.totals); - printTotals(_testRunStats.totals); - stream << std::endl; - StreamingReporterBase::testRunEnded(_testRunStats); + printTotalsDivider(_testRunStats.totals); + printTotals(_testRunStats.totals); + stream << std::endl; + StreamingReporterBase::testRunEnded(_testRunStats); } void ConsoleReporter::lazyPrint() { - - m_tablePrinter->close(); - lazyPrintWithoutClosingBenchmarkTable(); + m_tablePrinter->close(); + lazyPrintWithoutClosingBenchmarkTable(); } void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { + if (!currentTestRunInfo.used) lazyPrintRunInfo(); + if (!currentGroupInfo.used) lazyPrintGroupInfo(); - if (!currentTestRunInfo.used) - lazyPrintRunInfo(); - if (!currentGroupInfo.used) - lazyPrintGroupInfo(); - - if (!m_headerPrinted) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } + if (!m_headerPrinted) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } } void ConsoleReporter::lazyPrintRunInfo() { - stream << '\n' << getLineOfChars<'~'>() << '\n'; - Colour colour(Colour::SecondaryText); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion() << " host application.\n" - << "Run with -? for options\n\n"; + stream << '\n' << getLineOfChars<'~'>() << '\n'; + Colour colour(Colour::SecondaryText); + stream << currentTestRunInfo->name << " is a Catch v" << libraryVersion() + << " host application.\n" + << "Run with -? for options\n\n"; - if (m_config->rngSeed() != 0) - stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + if (m_config->rngSeed() != 0) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; - currentTestRunInfo.used = true; + currentTestRunInfo.used = true; } void ConsoleReporter::lazyPrintGroupInfo() { - if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { - printClosedHeader("Group: " + currentGroupInfo->name); - currentGroupInfo.used = true; - } + if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { + printClosedHeader("Group: " + currentGroupInfo->name); + currentGroupInfo.used = true; + } } void ConsoleReporter::printTestCaseAndSectionHeader() { - assert(!m_sectionStack.empty()); - printOpenHeader(currentTestCaseInfo->name); + assert(!m_sectionStack.empty()); + printOpenHeader(currentTestCaseInfo->name); - if (m_sectionStack.size() > 1) { - Colour colourGuard(Colour::Headers); + if (m_sectionStack.size() > 1) { + Colour colourGuard(Colour::Headers); - auto - it = m_sectionStack.begin() + 1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for (; it != itEnd; ++it) - printHeaderString(it->name, 2); - } + auto it = m_sectionStack.begin() + 1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for (; it != itEnd; ++it) printHeaderString(it->name, 2); + } - SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; + SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; - if (!lineInfo.empty()) { - stream << getLineOfChars<'-'>() << '\n'; - Colour colourGuard(Colour::FileName); - stream << lineInfo << '\n'; - } - stream << getLineOfChars<'.'>() << '\n' << std::endl; + if (!lineInfo.empty()) { + stream << getLineOfChars<'-'>() << '\n'; + Colour colourGuard(Colour::FileName); + stream << lineInfo << '\n'; + } + stream << getLineOfChars<'.'>() << '\n' << std::endl; } void ConsoleReporter::printClosedHeader(std::string const& _name) { - printOpenHeader(_name); - stream << getLineOfChars<'.'>() << '\n'; + printOpenHeader(_name); + stream << getLineOfChars<'.'>() << '\n'; } void ConsoleReporter::printOpenHeader(std::string const& _name) { - stream << getLineOfChars<'-'>() << '\n'; - { - Colour colourGuard(Colour::Headers); - printHeaderString(_name); - } + stream << getLineOfChars<'-'>() << '\n'; + { + Colour colourGuard(Colour::Headers); + printHeaderString(_name); + } } // if string has a : in first line will set indent to follow it on // subsequent lines -void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { - std::size_t i = _string.find(": "); - if (i != std::string::npos) - i += 2; - else - i = 0; - stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; +void ConsoleReporter::printHeaderString(std::string const& _string, + std::size_t indent) { + std::size_t i = _string.find(": "); + if (i != std::string::npos) + i += 2; + else + i = 0; + stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; } struct SummaryColumn { - - SummaryColumn( std::string _label, Colour::Code _colour ) - : label( std::move( _label ) ), - colour( _colour ) {} - SummaryColumn addRow( std::size_t count ) { - ReusableStringStream rss; - rss << count; - std::string row = rss.str(); - for (auto& oldRow : rows) { - while (oldRow.size() < row.size()) - oldRow = ' ' + oldRow; - while (oldRow.size() > row.size()) - row = ' ' + row; - } - rows.push_back(row); - return *this; + SummaryColumn(std::string _label, Colour::Code _colour) + : label(std::move(_label)), colour(_colour) {} + SummaryColumn addRow(std::size_t count) { + ReusableStringStream rss; + rss << count; + std::string row = rss.str(); + for (auto& oldRow : rows) { + while (oldRow.size() < row.size()) oldRow = ' ' + oldRow; + while (oldRow.size() > row.size()) row = ' ' + row; } + rows.push_back(row); + return *this; + } - std::string label; - Colour::Code colour; - std::vector rows; - + std::string label; + Colour::Code colour; + std::vector rows; }; -void ConsoleReporter::printTotals( Totals const& totals ) { - if (totals.testCases.total() == 0) { - stream << Colour(Colour::Warning) << "No tests ran\n"; - } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { - stream << Colour(Colour::ResultSuccess) << "All tests passed"; - stream << " (" - << pluralise(totals.assertions.passed, "assertion") << " in " - << pluralise(totals.testCases.passed, "test case") << ')' - << '\n'; - } else { - - std::vector columns; - columns.push_back(SummaryColumn("", Colour::None) +void ConsoleReporter::printTotals(Totals const& totals) { + if (totals.testCases.total() == 0) { + stream << Colour(Colour::Warning) << "No tests ran\n"; + } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { + stream << Colour(Colour::ResultSuccess) << "All tests passed"; + stream << " (" << pluralise(totals.assertions.passed, "assertion") << " in " + << pluralise(totals.testCases.passed, "test case") << ')' << '\n'; + } else { + std::vector columns; + columns.push_back(SummaryColumn("", Colour::None) .addRow(totals.testCases.total()) .addRow(totals.assertions.total())); - columns.push_back(SummaryColumn("passed", Colour::Success) + columns.push_back(SummaryColumn("passed", Colour::Success) .addRow(totals.testCases.passed) .addRow(totals.assertions.passed)); - columns.push_back(SummaryColumn("failed", Colour::ResultError) + columns.push_back(SummaryColumn("failed", Colour::ResultError) .addRow(totals.testCases.failed) .addRow(totals.assertions.failed)); - columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) - .addRow(totals.testCases.failedButOk) - .addRow(totals.assertions.failedButOk)); + columns.push_back( + SummaryColumn("failed as expected", Colour::ResultExpectedFailure) + .addRow(totals.testCases.failedButOk) + .addRow(totals.assertions.failedButOk)); - printSummaryRow("test cases", columns, 0); - printSummaryRow("assertions", columns, 1); - } + printSummaryRow("test cases", columns, 0); + printSummaryRow("assertions", columns, 1); + } } -void ConsoleReporter::printSummaryRow(std::string const& label, std::vector const& cols, std::size_t row) { - for (auto col : cols) { - std::string value = col.rows[row]; - if (col.label.empty()) { - stream << label << ": "; - if (value != "0") - stream << value; - else - stream << Colour(Colour::Warning) << "- none -"; - } else if (value != "0") { - stream << Colour(Colour::LightGrey) << " | "; - stream << Colour(col.colour) - << value << ' ' << col.label; - } +void ConsoleReporter::printSummaryRow(std::string const& label, + std::vector const& cols, + std::size_t row) { + for (auto col : cols) { + std::string value = col.rows[row]; + if (col.label.empty()) { + stream << label << ": "; + if (value != "0") + stream << value; + else + stream << Colour(Colour::Warning) << "- none -"; + } else if (value != "0") { + stream << Colour(Colour::LightGrey) << " | "; + stream << Colour(col.colour) << value << ' ' << col.label; } - stream << '\n'; + } + stream << '\n'; } void ConsoleReporter::printTotalsDivider(Totals const& totals) { - if (totals.testCases.total() > 0) { - std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); - std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); - std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); - while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) - findMax(failedRatio, failedButOkRatio, passedRatio)++; - while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) - findMax(failedRatio, failedButOkRatio, passedRatio)--; + if (totals.testCases.total() > 0) { + std::size_t failedRatio = + makeRatio(totals.testCases.failed, totals.testCases.total()); + std::size_t failedButOkRatio = + makeRatio(totals.testCases.failedButOk, totals.testCases.total()); + std::size_t passedRatio = + makeRatio(totals.testCases.passed, totals.testCases.total()); + while (failedRatio + failedButOkRatio + passedRatio < + CATCH_CONFIG_CONSOLE_WIDTH - 1) + findMax(failedRatio, failedButOkRatio, passedRatio)++; + while (failedRatio + failedButOkRatio + passedRatio > + CATCH_CONFIG_CONSOLE_WIDTH - 1) + findMax(failedRatio, failedButOkRatio, passedRatio)--; - stream << Colour(Colour::Error) << std::string(failedRatio, '='); - stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); - if (totals.testCases.allPassed()) - stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); - else - stream << Colour(Colour::Success) << std::string(passedRatio, '='); - } else { - stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); - } - stream << '\n'; + stream << Colour(Colour::Error) << std::string(failedRatio, '='); + stream << Colour(Colour::ResultExpectedFailure) + << std::string(failedButOkRatio, '='); + if (totals.testCases.allPassed()) + stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); + else + stream << Colour(Colour::Success) << std::string(passedRatio, '='); + } else { + stream << Colour(Colour::Warning) + << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); + } + stream << '\n'; } void ConsoleReporter::printSummaryDivider() { - stream << getLineOfChars<'-'>() << '\n'; + stream << getLineOfChars<'-'>() << '\n'; } CATCH_REGISTER_REPORTER("console", ConsoleReporter) -} // end namespace Catch +} // end namespace Catch #if defined(_MSC_VER) #pragma warning(pop) @@ -13394,239 +13467,234 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter) // end catch_reporter_console.cpp // start catch_reporter_junit.cpp -#include -#include -#include #include +#include +#include +#include namespace Catch { - namespace { - 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) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); +namespace { +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) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); #ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &rawtime); + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &rawtime); #else - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); + std::tm* timeInfo; + timeInfo = std::gmtime(&rawtime); #endif - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; #ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); #else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); #endif - return std::string(timeStamp); - } + return std::string(timeStamp); +} - std::string fileNameTag(const std::vector &tags) { - auto it = std::find_if(begin(tags), - end(tags), - [] (std::string const& tag) {return tag.front() == '#'; }); - if (it != tags.end()) - return it->substr(1); - return std::string(); - } - } // anonymous namespace +std::string fileNameTag(const std::vector& tags) { + auto it = std::find_if(begin(tags), end(tags), [](std::string const& tag) { + return tag.front() == '#'; + }); + if (it != tags.end()) return it->substr(1); + return std::string(); +} +} // anonymous namespace - JunitReporter::JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - m_reporterPrefs.shouldReportAllAssertions = true; - } +JunitReporter::JunitReporter(ReporterConfig const& _config) + : CumulativeReporterBase(_config), xml(_config.stream()) { + m_reporterPrefs.shouldRedirectStdOut = true; + m_reporterPrefs.shouldReportAllAssertions = true; +} - JunitReporter::~JunitReporter() {} +JunitReporter::~JunitReporter() {} - std::string JunitReporter::getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; +std::string JunitReporter::getDescription() { + return "Reports test results in an XML format that looks like Ant's " + "junitreport target"; +} + +void JunitReporter::noMatchingTestCases(std::string const& /*spec*/) {} + +void JunitReporter::testRunStarting(TestRunInfo const& runInfo) { + CumulativeReporterBase::testRunStarting(runInfo); + xml.startElement("testsuites"); +} + +void JunitReporter::testGroupStarting(GroupInfo const& groupInfo) { + suiteTimer.start(); + stdOutForSuite.clear(); + stdErrForSuite.clear(); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting(groupInfo); +} + +void JunitReporter::testCaseStarting(TestCaseInfo const& testCaseInfo) { + m_okToFail = testCaseInfo.okToFail(); +} + +bool JunitReporter::assertionEnded(AssertionStats const& assertionStats) { + if (assertionStats.assertionResult.getResultType() == + ResultWas::ThrewException && + !m_okToFail) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded(assertionStats); +} + +void JunitReporter::testCaseEnded(TestCaseStats const& testCaseStats) { + stdOutForSuite += testCaseStats.stdOut; + stdErrForSuite += testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded(testCaseStats); +} + +void JunitReporter::testGroupEnded(TestGroupStats const& testGroupStats) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded(testGroupStats); + writeGroup(*m_testGroups.back(), suiteTime); +} + +void JunitReporter::testRunEndedCumulative() { xml.endElement(); } + +void JunitReporter::writeGroup(TestGroupNode const& groupNode, + double suiteTime) { + XmlWriter::ScopedElement e = xml.scopedElement("testsuite"); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute("name", stats.groupInfo.name); + xml.writeAttribute("errors", unexpectedExceptions); + xml.writeAttribute("failures", + stats.totals.assertions.failed - unexpectedExceptions); + xml.writeAttribute("tests", stats.totals.assertions.total()); + xml.writeAttribute("hostname", "tbd"); // !TBD + if (m_config->showDurations() == ShowDurations::Never) + xml.writeAttribute("time", ""); + else + xml.writeAttribute("time", suiteTime); + xml.writeAttribute("timestamp", getCurrentTimestamp()); + + // Write test cases + for (auto const& child : groupNode.children) writeTestCase(*child); + + xml.scopedElement("system-out").writeText(trim(stdOutForSuite), false); + xml.scopedElement("system-err").writeText(trim(stdErrForSuite), false); +} + +void JunitReporter::writeTestCase(TestCaseNode const& testCaseNode) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert(testCaseNode.children.size() == 1); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if (className.empty()) { + className = fileNameTag(stats.testInfo.tags); + if (className.empty()) className = "global"; + } + + if (!m_config->name().empty()) className = m_config->name() + "." + className; + + writeSection(className, "", rootSection); +} + +void JunitReporter::writeSection(std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode) { + std::string name = trim(sectionNode.stats.sectionInfo.name); + if (!rootName.empty()) name = rootName + '/' + name; + + if (!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty()) { + XmlWriter::ScopedElement e = xml.scopedElement("testcase"); + if (className.empty()) { + xml.writeAttribute("classname", name); + xml.writeAttribute("name", "root"); + } else { + xml.writeAttribute("classname", className); + xml.writeAttribute("name", name); + } + xml.writeAttribute("time", ::Catch::Detail::stringify( + sectionNode.stats.durationInSeconds)); + + writeAssertions(sectionNode); + + if (!sectionNode.stdOut.empty()) + xml.scopedElement("system-out") + .writeText(trim(sectionNode.stdOut), false); + if (!sectionNode.stdErr.empty()) + xml.scopedElement("system-err") + .writeText(trim(sectionNode.stdErr), false); + } + for (auto const& childNode : sectionNode.childSections) + if (className.empty()) + writeSection(name, "", *childNode); + else + writeSection(className, name, *childNode); +} + +void JunitReporter::writeAssertions(SectionNode const& sectionNode) { + for (auto const& assertion : sectionNode.assertions) + writeAssertion(assertion); +} + +void JunitReporter::writeAssertion(AssertionStats const& stats) { + AssertionResult const& result = stats.assertionResult; + if (!result.isOk()) { + std::string elementName; + switch (result.getResultType()) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; } - void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} + XmlWriter::ScopedElement e = xml.scopedElement(elementName); - void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } + xml.writeAttribute("message", result.getExpandedExpression()); + xml.writeAttribute("type", result.getTestMacroName()); - void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { - suiteTimer.start(); - stdOutForSuite.clear(); - stdErrForSuite.clear(); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } + ReusableStringStream rss; + if (!result.getMessage().empty()) rss << result.getMessage() << '\n'; + for (auto const& msg : stats.infoMessages) + if (msg.type == ResultWas::Info) rss << msg.message << '\n'; - void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { - m_okToFail = testCaseInfo.okToFail(); - } + rss << "at " << result.getSourceInfo(); + xml.writeText(rss.str(), false); + } +} - bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } +CATCH_REGISTER_REPORTER("junit", JunitReporter) - void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { - stdOutForSuite += testCaseStats.stdOut; - stdErrForSuite += testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - void JunitReporter::testRunEndedCumulative() { - xml.endElement(); - } - - void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", getCurrentTimestamp() ); - - // Write test cases - for( auto const& child : groupNode.children ) - writeTestCase( *child ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false ); - } - - void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - className = fileNameTag(stats.testInfo.tags); - if ( className.empty() ) - className = "global"; - } - - if ( !m_config->name().empty() ) - className = m_config->name() + "." + className; - - writeSection( className, "", rootSection ); - } - - void JunitReporter::writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + '/' + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( auto const& childNode : sectionNode.childSections ) - if( className.empty() ) - writeSection( name, "", *childNode ); - else - writeSection( className, name, *childNode ); - } - - void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { - for( auto const& assertion : sectionNode.assertions ) - writeAssertion( assertion ); - } - - void JunitReporter::writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - ReusableStringStream rss; - if( !result.getMessage().empty() ) - rss << result.getMessage() << '\n'; - for( auto const& msg : stats.infoMessages ) - if( msg.type == ResultWas::Info ) - rss << msg.message << '\n'; - - rss << "at " << result.getSourceInfo(); - xml.writeText( rss.str(), false ); - } - } - - CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch +} // end namespace Catch // end catch_reporter_junit.cpp // start catch_reporter_listening.cpp @@ -13634,343 +13702,327 @@ namespace Catch { namespace Catch { - ListeningReporter::ListeningReporter() { - // We will assume that listeners will always want all assertions - m_preferences.shouldReportAllAssertions = true; - } +ListeningReporter::ListeningReporter() { + // We will assume that listeners will always want all assertions + m_preferences.shouldReportAllAssertions = true; +} - void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { - m_listeners.push_back( std::move( listener ) ); - } +void ListeningReporter::addListener(IStreamingReporterPtr&& listener) { + m_listeners.push_back(std::move(listener)); +} - void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { - assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); - m_reporter = std::move( reporter ); - m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut; - } +void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { + assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); + m_reporter = std::move(reporter); + m_preferences.shouldRedirectStdOut = + m_reporter->getPreferences().shouldRedirectStdOut; +} - ReporterPreferences ListeningReporter::getPreferences() const { - return m_preferences; - } +ReporterPreferences ListeningReporter::getPreferences() const { + return m_preferences; +} - std::set ListeningReporter::getSupportedVerbosities() { - return std::set{ }; - } +std::set ListeningReporter::getSupportedVerbosities() { + return std::set{}; +} - void ListeningReporter::noMatchingTestCases( std::string const& spec ) { - for ( auto const& listener : m_listeners ) { - listener->noMatchingTestCases( spec ); - } - m_reporter->noMatchingTestCases( spec ); - } +void ListeningReporter::noMatchingTestCases(std::string const& spec) { + for (auto const& listener : m_listeners) { + listener->noMatchingTestCases(spec); + } + m_reporter->noMatchingTestCases(spec); +} - void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { - for ( auto const& listener : m_listeners ) { - listener->benchmarkStarting( benchmarkInfo ); - } - m_reporter->benchmarkStarting( benchmarkInfo ); - } - void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { - for ( auto const& listener : m_listeners ) { - listener->benchmarkEnded( benchmarkStats ); - } - m_reporter->benchmarkEnded( benchmarkStats ); - } +void ListeningReporter::benchmarkStarting(BenchmarkInfo const& benchmarkInfo) { + for (auto const& listener : m_listeners) { + listener->benchmarkStarting(benchmarkInfo); + } + m_reporter->benchmarkStarting(benchmarkInfo); +} +void ListeningReporter::benchmarkEnded(BenchmarkStats const& benchmarkStats) { + for (auto const& listener : m_listeners) { + listener->benchmarkEnded(benchmarkStats); + } + m_reporter->benchmarkEnded(benchmarkStats); +} - void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { - for ( auto const& listener : m_listeners ) { - listener->testRunStarting( testRunInfo ); - } - m_reporter->testRunStarting( testRunInfo ); - } +void ListeningReporter::testRunStarting(TestRunInfo const& testRunInfo) { + for (auto const& listener : m_listeners) { + listener->testRunStarting(testRunInfo); + } + m_reporter->testRunStarting(testRunInfo); +} - void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { - for ( auto const& listener : m_listeners ) { - listener->testGroupStarting( groupInfo ); - } - m_reporter->testGroupStarting( groupInfo ); - } +void ListeningReporter::testGroupStarting(GroupInfo const& groupInfo) { + for (auto const& listener : m_listeners) { + listener->testGroupStarting(groupInfo); + } + m_reporter->testGroupStarting(groupInfo); +} - void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { - for ( auto const& listener : m_listeners ) { - listener->testCaseStarting( testInfo ); - } - m_reporter->testCaseStarting( testInfo ); - } +void ListeningReporter::testCaseStarting(TestCaseInfo const& testInfo) { + for (auto const& listener : m_listeners) { + listener->testCaseStarting(testInfo); + } + m_reporter->testCaseStarting(testInfo); +} - void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { - for ( auto const& listener : m_listeners ) { - listener->sectionStarting( sectionInfo ); - } - m_reporter->sectionStarting( sectionInfo ); - } +void ListeningReporter::sectionStarting(SectionInfo const& sectionInfo) { + for (auto const& listener : m_listeners) { + listener->sectionStarting(sectionInfo); + } + m_reporter->sectionStarting(sectionInfo); +} - void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { - for ( auto const& listener : m_listeners ) { - listener->assertionStarting( assertionInfo ); - } - m_reporter->assertionStarting( assertionInfo ); - } +void ListeningReporter::assertionStarting(AssertionInfo const& assertionInfo) { + for (auto const& listener : m_listeners) { + listener->assertionStarting(assertionInfo); + } + m_reporter->assertionStarting(assertionInfo); +} - // The return value indicates if the messages buffer should be cleared: - bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { - for( auto const& listener : m_listeners ) { - static_cast( listener->assertionEnded( assertionStats ) ); - } - return m_reporter->assertionEnded( assertionStats ); - } +// The return value indicates if the messages buffer should be cleared: +bool ListeningReporter::assertionEnded(AssertionStats const& assertionStats) { + for (auto const& listener : m_listeners) { + static_cast(listener->assertionEnded(assertionStats)); + } + return m_reporter->assertionEnded(assertionStats); +} - void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { - for ( auto const& listener : m_listeners ) { - listener->sectionEnded( sectionStats ); - } - m_reporter->sectionEnded( sectionStats ); - } +void ListeningReporter::sectionEnded(SectionStats const& sectionStats) { + for (auto const& listener : m_listeners) { + listener->sectionEnded(sectionStats); + } + m_reporter->sectionEnded(sectionStats); +} - void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { - for ( auto const& listener : m_listeners ) { - listener->testCaseEnded( testCaseStats ); - } - m_reporter->testCaseEnded( testCaseStats ); - } +void ListeningReporter::testCaseEnded(TestCaseStats const& testCaseStats) { + for (auto const& listener : m_listeners) { + listener->testCaseEnded(testCaseStats); + } + m_reporter->testCaseEnded(testCaseStats); +} - void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { - for ( auto const& listener : m_listeners ) { - listener->testGroupEnded( testGroupStats ); - } - m_reporter->testGroupEnded( testGroupStats ); - } +void ListeningReporter::testGroupEnded(TestGroupStats const& testGroupStats) { + for (auto const& listener : m_listeners) { + listener->testGroupEnded(testGroupStats); + } + m_reporter->testGroupEnded(testGroupStats); +} - void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { - for ( auto const& listener : m_listeners ) { - listener->testRunEnded( testRunStats ); - } - m_reporter->testRunEnded( testRunStats ); - } +void ListeningReporter::testRunEnded(TestRunStats const& testRunStats) { + for (auto const& listener : m_listeners) { + listener->testRunEnded(testRunStats); + } + m_reporter->testRunEnded(testRunStats); +} - void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { - for ( auto const& listener : m_listeners ) { - listener->skipTest( testInfo ); - } - m_reporter->skipTest( testInfo ); - } +void ListeningReporter::skipTest(TestCaseInfo const& testInfo) { + for (auto const& listener : m_listeners) { listener->skipTest(testInfo); } + m_reporter->skipTest(testInfo); +} - bool ListeningReporter::isMulti() const { - return true; - } +bool ListeningReporter::isMulti() const { return true; } -} // end namespace Catch +} // end namespace Catch // end catch_reporter_listening.cpp // start catch_reporter_xml.cpp #if defined(_MSC_VER) #pragma warning(push) -#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch - // Note that 4062 (not all labels are handled - // and default is missing) is enabled +#pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in + // switch Note that 4062 (not all labels are + // handled and default is missing) is enabled #endif namespace Catch { - XmlReporter::XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()) - { - m_reporterPrefs.shouldRedirectStdOut = true; - m_reporterPrefs.shouldReportAllAssertions = true; +XmlReporter::XmlReporter(ReporterConfig const& _config) + : StreamingReporterBase(_config), m_xml(_config.stream()) { + m_reporterPrefs.shouldRedirectStdOut = true; + m_reporterPrefs.shouldReportAllAssertions = true; +} + +XmlReporter::~XmlReporter() = default; + +std::string XmlReporter::getDescription() { + return "Reports test results as an XML document"; +} + +std::string XmlReporter::getStylesheetRef() const { return std::string(); } + +void XmlReporter::writeSourceInfo(SourceLineInfo const& sourceInfo) { + m_xml.writeAttribute("filename", sourceInfo.file) + .writeAttribute("line", sourceInfo.line); +} + +void XmlReporter::noMatchingTestCases(std::string const& s) { + StreamingReporterBase::noMatchingTestCases(s); +} + +void XmlReporter::testRunStarting(TestRunInfo const& testInfo) { + StreamingReporterBase::testRunStarting(testInfo); + std::string stylesheetRef = getStylesheetRef(); + if (!stylesheetRef.empty()) m_xml.writeStylesheetRef(stylesheetRef); + m_xml.startElement("Catch"); + if (!m_config->name().empty()) m_xml.writeAttribute("name", m_config->name()); + if (m_config->rngSeed() != 0) + m_xml.scopedElement("Randomness") + .writeAttribute("seed", m_config->rngSeed()); +} + +void XmlReporter::testGroupStarting(GroupInfo const& groupInfo) { + StreamingReporterBase::testGroupStarting(groupInfo); + m_xml.startElement("Group").writeAttribute("name", groupInfo.name); +} + +void XmlReporter::testCaseStarting(TestCaseInfo const& testInfo) { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement("TestCase") + .writeAttribute("name", trim(testInfo.name)) + .writeAttribute("description", testInfo.description) + .writeAttribute("tags", testInfo.tagsAsString()); + + writeSourceInfo(testInfo.lineInfo); + + if (m_config->showDurations() == ShowDurations::Always) + m_testCaseTimer.start(); + m_xml.ensureTagClosed(); +} + +void XmlReporter::sectionStarting(SectionInfo const& sectionInfo) { + StreamingReporterBase::sectionStarting(sectionInfo); + if (m_sectionDepth++ > 0) { + m_xml.startElement("Section").writeAttribute("name", + trim(sectionInfo.name)); + writeSourceInfo(sectionInfo.lineInfo); + m_xml.ensureTagClosed(); + } +} + +void XmlReporter::assertionStarting(AssertionInfo const&) {} + +bool XmlReporter::assertionEnded(AssertionStats const& assertionStats) { + AssertionResult const& result = assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + if (includeResults || result.getResultType() == ResultWas::Warning) { + // Print any info messages in tags. + for (auto const& msg : assertionStats.infoMessages) { + if (msg.type == ResultWas::Info && includeResults) { + m_xml.scopedElement("Info").writeText(msg.message); + } else if (msg.type == ResultWas::Warning) { + m_xml.scopedElement("Warning").writeText(msg.message); + } } + } - XmlReporter::~XmlReporter() = default; + // Drop out if result was successful but we're not printing them. + if (!includeResults && result.getResultType() != ResultWas::Warning) + return true; - std::string XmlReporter::getDescription() { - return "Reports test results as an XML document"; - } + // Print the expression if there is one. + if (result.hasExpression()) { + m_xml.startElement("Expression") + .writeAttribute("success", result.succeeded()) + .writeAttribute("type", result.getTestMacroName()); - std::string XmlReporter::getStylesheetRef() const { - return std::string(); - } + writeSourceInfo(result.getSourceInfo()); - void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { - m_xml - .writeAttribute( "filename", sourceInfo.file ) - .writeAttribute( "line", sourceInfo.line ); - } + m_xml.scopedElement("Original").writeText(result.getExpression()); + m_xml.scopedElement("Expanded").writeText(result.getExpandedExpression()); + } - void XmlReporter::noMatchingTestCases( std::string const& s ) { - StreamingReporterBase::noMatchingTestCases( s ); - } + // And... Print a result applicable to each result type. + switch (result.getResultType()) { + case ResultWas::ThrewException: + m_xml.startElement("Exception"); + writeSourceInfo(result.getSourceInfo()); + m_xml.writeText(result.getMessage()); + m_xml.endElement(); + break; + case ResultWas::FatalErrorCondition: + m_xml.startElement("FatalErrorCondition"); + writeSourceInfo(result.getSourceInfo()); + m_xml.writeText(result.getMessage()); + m_xml.endElement(); + break; + case ResultWas::Info: + m_xml.scopedElement("Info").writeText(result.getMessage()); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.startElement("Failure"); + writeSourceInfo(result.getSourceInfo()); + m_xml.writeText(result.getMessage()); + m_xml.endElement(); + break; + default: + break; + } - void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { - StreamingReporterBase::testRunStarting( testInfo ); - std::string stylesheetRef = getStylesheetRef(); - if( !stylesheetRef.empty() ) - m_xml.writeStylesheetRef( stylesheetRef ); - m_xml.startElement( "Catch" ); - if( !m_config->name().empty() ) - m_xml.writeAttribute( "name", m_config->name() ); - if( m_config->rngSeed() != 0 ) - m_xml.scopedElement( "Randomness" ) - .writeAttribute( "seed", m_config->rngSeed() ); - } + if (result.hasExpression()) m_xml.endElement(); - void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { - StreamingReporterBase::testGroupStarting( groupInfo ); - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupInfo.name ); - } + return true; +} - void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { - StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ) - .writeAttribute( "name", trim( testInfo.name ) ) - .writeAttribute( "description", testInfo.description ) - .writeAttribute( "tags", testInfo.tagsAsString() ); +void XmlReporter::sectionEnded(SectionStats const& sectionStats) { + StreamingReporterBase::sectionEnded(sectionStats); + if (--m_sectionDepth > 0) { + XmlWriter::ScopedElement e = m_xml.scopedElement("OverallResults"); + e.writeAttribute("successes", sectionStats.assertions.passed); + e.writeAttribute("failures", sectionStats.assertions.failed); + e.writeAttribute("expectedFailures", sectionStats.assertions.failedButOk); - writeSourceInfo( testInfo.lineInfo ); + if (m_config->showDurations() == ShowDurations::Always) + e.writeAttribute("durationInSeconds", sectionStats.durationInSeconds); - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - m_xml.ensureTagClosed(); - } + m_xml.endElement(); + } +} - void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ); - writeSourceInfo( sectionInfo.lineInfo ); - m_xml.ensureTagClosed(); - } - } +void XmlReporter::testCaseEnded(TestCaseStats const& testCaseStats) { + StreamingReporterBase::testCaseEnded(testCaseStats); + XmlWriter::ScopedElement e = m_xml.scopedElement("OverallResult"); + e.writeAttribute("success", testCaseStats.totals.assertions.allOk()); - void XmlReporter::assertionStarting( AssertionInfo const& ) { } + if (m_config->showDurations() == ShowDurations::Always) + e.writeAttribute("durationInSeconds", m_testCaseTimer.getElapsedSeconds()); - bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { + if (!testCaseStats.stdOut.empty()) + m_xml.scopedElement("StdOut").writeText(trim(testCaseStats.stdOut), false); + if (!testCaseStats.stdErr.empty()) + m_xml.scopedElement("StdErr").writeText(trim(testCaseStats.stdErr), false); - AssertionResult const& result = assertionStats.assertionResult; + m_xml.endElement(); +} - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); +void XmlReporter::testGroupEnded(TestGroupStats const& testGroupStats) { + StreamingReporterBase::testGroupEnded(testGroupStats); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement("OverallResults") + .writeAttribute("successes", testGroupStats.totals.assertions.passed) + .writeAttribute("failures", testGroupStats.totals.assertions.failed) + .writeAttribute("expectedFailures", + testGroupStats.totals.assertions.failedButOk); + m_xml.endElement(); +} - if( includeResults || result.getResultType() == ResultWas::Warning ) { - // Print any info messages in tags. - for( auto const& msg : assertionStats.infoMessages ) { - if( msg.type == ResultWas::Info && includeResults ) { - m_xml.scopedElement( "Info" ) - .writeText( msg.message ); - } else if ( msg.type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( msg.message ); - } - } - } +void XmlReporter::testRunEnded(TestRunStats const& testRunStats) { + StreamingReporterBase::testRunEnded(testRunStats); + m_xml.scopedElement("OverallResults") + .writeAttribute("successes", testRunStats.totals.assertions.passed) + .writeAttribute("failures", testRunStats.totals.assertions.failed) + .writeAttribute("expectedFailures", + testRunStats.totals.assertions.failedButOk); + m_xml.endElement(); +} - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return true; +CATCH_REGISTER_REPORTER("xml", XmlReporter) - // Print the expression if there is one. - if( result.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", result.succeeded() ) - .writeAttribute( "type", result.getTestMacroName() ); - - writeSourceInfo( result.getSourceInfo() ); - - m_xml.scopedElement( "Original" ) - .writeText( result.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( result.getExpandedExpression() ); - } - - // And... Print a result applicable to each result type. - switch( result.getResultType() ) { - case ResultWas::ThrewException: - m_xml.startElement( "Exception" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::FatalErrorCondition: - m_xml.startElement( "FatalErrorCondition" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( result.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.startElement( "Failure" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - default: - break; - } - - if( result.hasExpression() ) - m_xml.endElement(); - - return true; - } - - void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); - } - } - - void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); - if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); - - m_xml.endElement(); - } - - void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - CATCH_REGISTER_REPORTER( "xml", XmlReporter ) - -} // end namespace Catch +} // end namespace Catch #if defined(_MSC_VER) #pragma warning(pop) @@ -13978,7 +14030,7 @@ namespace Catch { // end catch_reporter_xml.cpp namespace Catch { - LeakDetector leakDetector; +LeakDetector leakDetector; } #ifdef __clang__ @@ -13993,36 +14045,37 @@ namespace Catch { #ifndef __OBJC__ -#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) +#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && \ + !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +extern "C" int wmain(int argc, wchar_t* argv[], wchar_t*[]) { #else // Standard C/C++ main entry point -int main (int argc, char * argv[]) { +int main(int argc, char* argv[]) { #endif - return Catch::Session().run( argc, argv ); + return Catch::Session().run(argc, argv); } -#else // __OBJC__ +#else // __OBJC__ // Objective-C entry point -int main (int argc, char * const argv[]) { +int main(int argc, char* const argv[]) { #if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; #endif - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char**)argv ); + Catch::registerTestMethods(); + int result = Catch::Session().run(argc, (char**)argv); #if !CATCH_ARC_ENABLED - [pool drain]; + [pool drain]; #endif - return result; + return result; } -#endif // __OBJC__ +#endif // __OBJC__ // end catch_default_main.hpp #endif @@ -14030,338 +14083,544 @@ int main (int argc, char * const argv[]) { #if !defined(CATCH_CONFIG_IMPL_ONLY) #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -# undef CLARA_CONFIG_MAIN +#undef CLARA_CONFIG_MAIN #endif #if !defined(CATCH_CONFIG_DISABLE) ////// -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +// If this config identifier is defined then all CATCH macros are prefixed with +// CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL -#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CATCH_REQUIRE(...) \ + INTERNAL_CATCH_TEST("CATCH_REQUIRE", Catch::ResultDisposition::Normal, \ + __VA_ARGS__) +#define CATCH_REQUIRE_FALSE(...) \ + INTERNAL_CATCH_TEST( \ + "CATCH_REQUIRE_FALSE", \ + Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, \ + __VA_ARGS__) -#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define CATCH_REQUIRE_THROWS(...) \ + INTERNAL_CATCH_THROWS("CATCH_REQUIRE_THROWS", \ + Catch::ResultDisposition::Normal, "", __VA_ARGS__) +#define CATCH_REQUIRE_THROWS_AS(expr, exceptionType) \ + INTERNAL_CATCH_THROWS_AS("CATCH_REQUIRE_THROWS_AS", exceptionType, \ + Catch::ResultDisposition::Normal, expr) +#define CATCH_REQUIRE_THROWS_WITH(expr, matcher) \ + INTERNAL_CATCH_THROWS_STR_MATCHES("CATCH_REQUIRE_THROWS_WITH", \ + Catch::ResultDisposition::Normal, matcher, \ + expr) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) -#endif// CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) \ + INTERNAL_CATCH_THROWS_MATCHES("CATCH_REQUIRE_THROWS_MATCHES", exceptionType, \ + Catch::ResultDisposition::Normal, matcher, \ + expr) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW(...) \ + INTERNAL_CATCH_NO_THROW("CATCH_REQUIRE_NOTHROW", \ + Catch::ResultDisposition::Normal, __VA_ARGS__) -#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) +#define CATCH_CHECK(...) \ + INTERNAL_CATCH_TEST( \ + "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) +#define CATCH_CHECK_FALSE(...) \ + INTERNAL_CATCH_TEST("CATCH_CHECK_FALSE", \ + Catch::ResultDisposition::ContinueOnFailure | \ + Catch::ResultDisposition::FalseTest, \ + __VA_ARGS__) +#define CATCH_CHECKED_IF(...) \ + INTERNAL_CATCH_IF("CATCH_CHECKED_IF", \ + Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) +#define CATCH_CHECKED_ELSE(...) \ + INTERNAL_CATCH_ELSE("CATCH_CHECKED_ELSE", \ + Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) +#define CATCH_CHECK_NOFAIL(...) \ + INTERNAL_CATCH_TEST("CATCH_CHECK_NOFAIL", \ + Catch::ResultDisposition::ContinueOnFailure | \ + Catch::ResultDisposition::SuppressFail, \ + __VA_ARGS__) -#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CATCH_CHECK_THROWS(...) \ + INTERNAL_CATCH_THROWS("CATCH_CHECK_THROWS", \ + Catch::ResultDisposition::ContinueOnFailure, "", \ + __VA_ARGS__) +#define CATCH_CHECK_THROWS_AS(expr, exceptionType) \ + INTERNAL_CATCH_THROWS_AS("CATCH_CHECK_THROWS_AS", exceptionType, \ + Catch::ResultDisposition::ContinueOnFailure, expr) +#define CATCH_CHECK_THROWS_WITH(expr, matcher) \ + INTERNAL_CATCH_THROWS_STR_MATCHES( \ + "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, \ + matcher, expr) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_THROWS_MATCHES(expr, exceptionType, matcher) \ + INTERNAL_CATCH_THROWS_MATCHES("CATCH_CHECK_THROWS_MATCHES", exceptionType, \ + Catch::ResultDisposition::ContinueOnFailure, \ + matcher, expr) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW(...) \ + INTERNAL_CATCH_NO_THROW("CATCH_CHECK_NOTHROW", \ + Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) +#define CATCH_CHECK_THAT(arg, matcher) \ + INTERNAL_CHECK_THAT("CATCH_CHECK_THAT", matcher, \ + Catch::ResultDisposition::ContinueOnFailure, arg) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_THAT(arg, matcher) \ + INTERNAL_CHECK_THAT("CATCH_REQUIRE_THAT", matcher, \ + Catch::ResultDisposition::Normal, arg) +#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) +#define CATCH_INFO(msg) INTERNAL_CATCH_INFO("CATCH_INFO", msg) +#define CATCH_WARN(msg) \ + INTERNAL_CATCH_MSG("CATCH_WARN", Catch::ResultWas::Warning, \ + Catch::ResultDisposition::ContinueOnFailure, msg) +#define CATCH_CAPTURE(...) \ + INTERNAL_CATCH_CAPTURE(INTERNAL_CATCH_UNIQUE_NAME(capturer), \ + "CATCH_CAPTURE", __VA_ARGS__) -#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) -#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) -#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) -#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) -#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) -#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) -#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_TEST_CASE(...) INTERNAL_CATCH_TESTCASE(__VA_ARGS__) +#define CATCH_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TEST_CASE_METHOD(className, __VA_ARGS__) +#define CATCH_METHOD_AS_TEST_CASE(method, ...) \ + INTERNAL_CATCH_METHOD_AS_TEST_CASE(method, __VA_ARGS__) +#define CATCH_REGISTER_TEST_CASE(Function, ...) \ + INTERNAL_CATCH_REGISTER_TESTCASE(Function, __VA_ARGS__) +#define CATCH_SECTION(...) INTERNAL_CATCH_SECTION(__VA_ARGS__) +#define CATCH_DYNAMIC_SECTION(...) INTERNAL_CATCH_DYNAMIC_SECTION(__VA_ARGS__) +#define CATCH_FAIL(...) \ + INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, \ + Catch::ResultDisposition::Normal, __VA_ARGS__) +#define CATCH_FAIL_CHECK(...) \ + INTERNAL_CATCH_MSG("CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, \ + Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) +#define CATCH_SUCCEED(...) \ + INTERNAL_CATCH_MSG("CATCH_SUCCEED", Catch::ResultWas::Ok, \ + Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) -#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define CATCH_TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) +#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) #else -#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) -#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) +#define CATCH_TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)) +#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)) #endif #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) -#define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) -#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) +#define CATCH_STATIC_REQUIRE(...) \ + static_assert(__VA_ARGS__, #__VA_ARGS__); \ + CATCH_SUCCEED(#__VA_ARGS__) +#define CATCH_STATIC_REQUIRE_FALSE(...) \ + static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")"); \ + CATCH_SUCCEED(#__VA_ARGS__) #else -#define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) -#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) +#define CATCH_STATIC_REQUIRE(...) CATCH_REQUIRE(__VA_ARGS__) +#define CATCH_STATIC_REQUIRE_FALSE(...) CATCH_REQUIRE_FALSE(__VA_ARGS__) #endif // "BDD-style" convenience wrappers -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) -#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) -#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) -#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) -#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) -#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) +#define CATCH_SCENARIO(...) CATCH_TEST_CASE("Scenario: " __VA_ARGS__) +#define CATCH_SCENARIO_METHOD(className, ...) \ + INTERNAL_CATCH_TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__) +#define CATCH_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Given: " << desc) +#define CATCH_AND_GIVEN(desc) \ + INTERNAL_CATCH_DYNAMIC_SECTION("And given: " << desc) +#define CATCH_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" When: " << desc) +#define CATCH_AND_WHEN(desc) \ + INTERNAL_CATCH_DYNAMIC_SECTION(" And when: " << desc) +#define CATCH_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Then: " << desc) +#define CATCH_AND_THEN(desc) \ + INTERNAL_CATCH_DYNAMIC_SECTION(" And: " << desc) -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not +// required #else -#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define REQUIRE(...) \ + INTERNAL_CATCH_TEST("REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__) +#define REQUIRE_FALSE(...) \ + INTERNAL_CATCH_TEST( \ + "REQUIRE_FALSE", \ + Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, \ + __VA_ARGS__) -#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define REQUIRE_THROWS(...) \ + INTERNAL_CATCH_THROWS("REQUIRE_THROWS", Catch::ResultDisposition::Normal, \ + __VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, exceptionType) \ + INTERNAL_CATCH_THROWS_AS("REQUIRE_THROWS_AS", exceptionType, \ + Catch::ResultDisposition::Normal, expr) +#define REQUIRE_THROWS_WITH(expr, matcher) \ + INTERNAL_CATCH_THROWS_STR_MATCHES( \ + "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) \ + INTERNAL_CATCH_THROWS_MATCHES("REQUIRE_THROWS_MATCHES", exceptionType, \ + Catch::ResultDisposition::Normal, matcher, \ + expr) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW(...) \ + INTERNAL_CATCH_NO_THROW("REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, \ + __VA_ARGS__) -#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) +#define CHECK(...) \ + INTERNAL_CATCH_TEST("CHECK", Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) +#define CHECK_FALSE(...) \ + INTERNAL_CATCH_TEST("CHECK_FALSE", \ + Catch::ResultDisposition::ContinueOnFailure | \ + Catch::ResultDisposition::FalseTest, \ + __VA_ARGS__) +#define CHECKED_IF(...) \ + INTERNAL_CATCH_IF("CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) +#define CHECKED_ELSE(...) \ + INTERNAL_CATCH_ELSE("CHECKED_ELSE", \ + Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) +#define CHECK_NOFAIL(...) \ + INTERNAL_CATCH_TEST("CHECK_NOFAIL", \ + Catch::ResultDisposition::ContinueOnFailure | \ + Catch::ResultDisposition::SuppressFail, \ + __VA_ARGS__) -#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CHECK_THROWS(...) \ + INTERNAL_CATCH_THROWS("CHECK_THROWS", \ + Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) +#define CHECK_THROWS_AS(expr, exceptionType) \ + INTERNAL_CATCH_THROWS_AS("CHECK_THROWS_AS", exceptionType, \ + Catch::ResultDisposition::ContinueOnFailure, expr) +#define CHECK_THROWS_WITH(expr, matcher) \ + INTERNAL_CATCH_THROWS_STR_MATCHES( \ + "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, \ + matcher, expr) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_THROWS_MATCHES(expr, exceptionType, matcher) \ + INTERNAL_CATCH_THROWS_MATCHES("CHECK_THROWS_MATCHES", exceptionType, \ + Catch::ResultDisposition::ContinueOnFailure, \ + matcher, expr) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW(...) \ + INTERNAL_CATCH_NO_THROW("CHECK_NOTHROW", \ + Catch::ResultDisposition::ContinueOnFailure, \ + __VA_ARGS__) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) +#define CHECK_THAT(arg, matcher) \ + INTERNAL_CHECK_THAT("CHECK_THAT", matcher, \ + Catch::ResultDisposition::ContinueOnFailure, arg) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_THAT(arg, matcher) \ + INTERNAL_CHECK_THAT("REQUIRE_THAT", matcher, \ + Catch::ResultDisposition::Normal, arg) +#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) +#define INFO(msg) INTERNAL_CATCH_INFO("INFO", msg) +#define WARN(msg) \ + INTERNAL_CATCH_MSG("WARN", Catch::ResultWas::Warning, \ + Catch::ResultDisposition::ContinueOnFailure, msg) +#define CAPTURE(...) \ + INTERNAL_CATCH_CAPTURE(INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", \ + __VA_ARGS__) -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) -#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) -#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) -#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) -#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) -#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define TEST_CASE(...) INTERNAL_CATCH_TESTCASE(__VA_ARGS__) +#define TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TEST_CASE_METHOD(className, __VA_ARGS__) +#define METHOD_AS_TEST_CASE(method, ...) \ + INTERNAL_CATCH_METHOD_AS_TEST_CASE(method, __VA_ARGS__) +#define REGISTER_TEST_CASE(Function, ...) \ + INTERNAL_CATCH_REGISTER_TESTCASE(Function, __VA_ARGS__) +#define SECTION(...) INTERNAL_CATCH_SECTION(__VA_ARGS__) +#define DYNAMIC_SECTION(...) INTERNAL_CATCH_DYNAMIC_SECTION(__VA_ARGS__) +#define FAIL(...) \ + INTERNAL_CATCH_MSG("FAIL", Catch::ResultWas::ExplicitFailure, \ + Catch::ResultDisposition::Normal, __VA_ARGS__) +#define FAIL_CHECK(...) \ + INTERNAL_CATCH_MSG("FAIL_CHECK", Catch::ResultWas::ExplicitFailure, \ + Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) +#define SUCCEED(...) \ + INTERNAL_CATCH_MSG("SUCCEED", Catch::ResultWas::Ok, \ + Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) -#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) +#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) #else -#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) -#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) +#define TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)) +#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)) #endif #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) -#define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) -#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) +#define STATIC_REQUIRE(...) \ + static_assert(__VA_ARGS__, #__VA_ARGS__); \ + SUCCEED(#__VA_ARGS__) +#define STATIC_REQUIRE_FALSE(...) \ + static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")"); \ + SUCCEED("!(" #__VA_ARGS__ ")") #else -#define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) -#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) +#define STATIC_REQUIRE(...) REQUIRE(__VA_ARGS__) +#define STATIC_REQUIRE_FALSE(...) REQUIRE_FALSE(__VA_ARGS__) #endif #endif -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) +#define CATCH_TRANSLATE_EXCEPTION(signature) \ + INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature) // "BDD-style" convenience wrappers -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#define SCENARIO(...) TEST_CASE("Scenario: " __VA_ARGS__) +#define SCENARIO_METHOD(className, ...) \ + INTERNAL_CATCH_TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__) -#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) -#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) -#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) -#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) -#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) -#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) +#define GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Given: " << desc) +#define AND_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION("And given: " << desc) +#define WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" When: " << desc) +#define AND_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And when: " << desc) +#define THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Then: " << desc) +#define AND_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And: " << desc) using Catch::Detail::Approx; -#else // CATCH_CONFIG_DISABLE +#else // CATCH_CONFIG_DISABLE ////// -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +// If this config identifier is defined then all CATCH macros are prefixed with +// CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL -#define CATCH_REQUIRE( ... ) (void)(0) -#define CATCH_REQUIRE_FALSE( ... ) (void)(0) +#define CATCH_REQUIRE(...) (void)(0) +#define CATCH_REQUIRE_FALSE(...) (void)(0) -#define CATCH_REQUIRE_THROWS( ... ) (void)(0) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#define CATCH_REQUIRE_THROWS(...) (void)(0) +#define CATCH_REQUIRE_THROWS_AS(expr, exceptionType) (void)(0) +#define CATCH_REQUIRE_THROWS_WITH(expr, matcher) (void)(0) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif// CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) +#define CATCH_REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW(...) (void)(0) -#define CATCH_CHECK( ... ) (void)(0) -#define CATCH_CHECK_FALSE( ... ) (void)(0) -#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) -#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) -#define CATCH_CHECK_NOFAIL( ... ) (void)(0) +#define CATCH_CHECK(...) (void)(0) +#define CATCH_CHECK_FALSE(...) (void)(0) +#define CATCH_CHECKED_IF(...) if (__VA_ARGS__) +#define CATCH_CHECKED_ELSE(...) if (!(__VA_ARGS__)) +#define CATCH_CHECK_NOFAIL(...) (void)(0) -#define CATCH_CHECK_THROWS( ... ) (void)(0) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#define CATCH_CHECK_THROWS(...) (void)(0) +#define CATCH_CHECK_THROWS_AS(expr, exceptionType) (void)(0) +#define CATCH_CHECK_THROWS_WITH(expr, matcher) (void)(0) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_CHECK_NOTHROW( ... ) (void)(0) +#define CATCH_CHECK_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW(...) (void)(0) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THAT( arg, matcher ) (void)(0) +#define CATCH_CHECK_THAT(arg, matcher) (void)(0) -#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_THAT(arg, matcher) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_INFO( msg ) (void)(0) -#define CATCH_WARN( msg ) (void)(0) -#define CATCH_CAPTURE( msg ) (void)(0) +#define CATCH_INFO(msg) (void)(0) +#define CATCH_WARN(msg) (void)(0) +#define CATCH_CAPTURE(msg) (void)(0) -#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_METHOD_AS_TEST_CASE( method, ... ) -#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) -#define CATCH_SECTION( ... ) -#define CATCH_DYNAMIC_SECTION( ... ) -#define CATCH_FAIL( ... ) (void)(0) -#define CATCH_FAIL_CHECK( ... ) (void)(0) -#define CATCH_SUCCEED( ... ) (void)(0) +#define CATCH_TEST_CASE(...) \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) +#define CATCH_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) +#define CATCH_METHOD_AS_TEST_CASE(method, ...) +#define CATCH_REGISTER_TEST_CASE(Function, ...) (void)(0) +#define CATCH_SECTION(...) +#define CATCH_DYNAMIC_SECTION(...) +#define CATCH_FAIL(...) (void)(0) +#define CATCH_FAIL_CHECK(...) (void)(0) +#define CATCH_SUCCEED(...) (void)(0) -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_ANON_TEST_CASE() \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) -#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) +#define CATCH_TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____)) +#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + className) #else -#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) ) -#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) ) +#define CATCH_TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____))) +#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + className)) #endif // "BDD-style" convenience wrappers -#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) -#define CATCH_GIVEN( desc ) -#define CATCH_AND_GIVEN( desc ) -#define CATCH_WHEN( desc ) -#define CATCH_AND_WHEN( desc ) -#define CATCH_THEN( desc ) -#define CATCH_AND_THEN( desc ) +#define CATCH_SCENARIO(...) \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) +#define CATCH_SCENARIO_METHOD(className, ...) \ + INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), className) +#define CATCH_GIVEN(desc) +#define CATCH_AND_GIVEN(desc) +#define CATCH_WHEN(desc) +#define CATCH_AND_WHEN(desc) +#define CATCH_THEN(desc) +#define CATCH_AND_THEN(desc) -#define CATCH_STATIC_REQUIRE( ... ) (void)(0) -#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) +#define CATCH_STATIC_REQUIRE(...) (void)(0) +#define CATCH_STATIC_REQUIRE_FALSE(...) (void)(0) -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not +// required #else -#define REQUIRE( ... ) (void)(0) -#define REQUIRE_FALSE( ... ) (void)(0) +#define REQUIRE(...) (void)(0) +#define REQUIRE_FALSE(...) (void)(0) -#define REQUIRE_THROWS( ... ) (void)(0) -#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) -#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#define REQUIRE_THROWS(...) (void)(0) +#define REQUIRE_THROWS_AS(expr, exceptionType) (void)(0) +#define REQUIRE_THROWS_WITH(expr, matcher) (void)(0) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define REQUIRE_NOTHROW( ... ) (void)(0) +#define REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW(...) (void)(0) -#define CHECK( ... ) (void)(0) -#define CHECK_FALSE( ... ) (void)(0) -#define CHECKED_IF( ... ) if (__VA_ARGS__) -#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) -#define CHECK_NOFAIL( ... ) (void)(0) +#define CHECK(...) (void)(0) +#define CHECK_FALSE(...) (void)(0) +#define CHECKED_IF(...) if (__VA_ARGS__) +#define CHECKED_ELSE(...) if (!(__VA_ARGS__)) +#define CHECK_NOFAIL(...) (void)(0) -#define CHECK_THROWS( ... ) (void)(0) -#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) -#define CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#define CHECK_THROWS(...) (void)(0) +#define CHECK_THROWS_AS(expr, exceptionType) (void)(0) +#define CHECK_THROWS_WITH(expr, matcher) (void)(0) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CHECK_NOTHROW( ... ) (void)(0) +#define CHECK_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW(...) (void)(0) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THAT( arg, matcher ) (void)(0) +#define CHECK_THAT(arg, matcher) (void)(0) -#define REQUIRE_THAT( arg, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_THAT(arg, matcher) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define INFO( msg ) (void)(0) -#define WARN( msg ) (void)(0) -#define CAPTURE( msg ) (void)(0) +#define INFO(msg) (void)(0) +#define WARN(msg) (void)(0) +#define CAPTURE(msg) (void)(0) -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define METHOD_AS_TEST_CASE( method, ... ) -#define REGISTER_TEST_CASE( Function, ... ) (void)(0) -#define SECTION( ... ) -#define DYNAMIC_SECTION( ... ) -#define FAIL( ... ) (void)(0) -#define FAIL_CHECK( ... ) (void)(0) -#define SUCCEED( ... ) (void)(0) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE(...) \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) +#define TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) +#define METHOD_AS_TEST_CASE(method, ...) +#define REGISTER_TEST_CASE(Function, ...) (void)(0) +#define SECTION(...) +#define DYNAMIC_SECTION(...) +#define FAIL(...) (void)(0) +#define FAIL_CHECK(...) (void)(0) +#define SUCCEED(...) (void)(0) +#define ANON_TEST_CASE() \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) -#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) +#define TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____)) +#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + className) #else -#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) ) -#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) ) +#define TEMPLATE_TEST_CASE(...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____))) +#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME( \ + ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \ + className)) #endif -#define STATIC_REQUIRE( ... ) (void)(0) -#define STATIC_REQUIRE_FALSE( ... ) (void)(0) +#define STATIC_REQUIRE(...) (void)(0) +#define STATIC_REQUIRE_FALSE(...) (void)(0) #endif -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) +#define CATCH_TRANSLATE_EXCEPTION(signature) \ + INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( \ + INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator), \ + signature) // "BDD-style" convenience wrappers -#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define SCENARIO(...) \ + INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)) +#define SCENARIO_METHOD(className, ...) \ + INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( \ + INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), className) -#define GIVEN( desc ) -#define AND_GIVEN( desc ) -#define WHEN( desc ) -#define AND_WHEN( desc ) -#define THEN( desc ) -#define AND_THEN( desc ) +#define GIVEN(desc) +#define AND_GIVEN(desc) +#define WHEN(desc) +#define AND_WHEN(desc) +#define THEN(desc) +#define AND_THEN(desc) using Catch::Detail::Approx; #endif -#endif // ! CATCH_CONFIG_IMPL_ONLY +#endif // ! CATCH_CONFIG_IMPL_ONLY // start catch_reenable_warnings.h - #ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif +#ifdef __ICC // icpc defines the __clang__ macro +#pragma warning(pop) +#else +#pragma clang diagnostic pop +#endif #elif defined __GNUC__ -# pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif // end catch_reenable_warnings.h // end catch.hpp -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED