diff --git a/.check-formatting.py b/.check-formatting.py new file mode 100644 index 000000000..627499812 --- /dev/null +++ b/.check-formatting.py @@ -0,0 +1,220 @@ +#! /usr/bin/env python + +import argparse +import os.path +import sys + +try: + from colorama import Fore, Style + + CYAN = Fore.CYAN + GREEN = Fore.GREEN + MAGENTA = Fore.MAGENTA + RESET_ALL = Style.RESET_ALL +except ImportError: + MAGENTA = "\033[35m" + CYAN = "\033[36m" + GREEN = "\033[32m" + RESET_ALL = "\033[0m" + + +args_parser = argparse.ArgumentParser( + description="Check basic formatting rules on text files" +) +args_parser.add_argument( + "--autofix", + action="store_true", + help="When possible, update files to fix detected formatting issues", +) +args_parser.add_argument( + "--force-colors", + action="store_true", + help=( + "Force colored output. This is necessary when the output is not a TTY" + " but still supports ANSI codes." + ), +) +args_parser.add_argument( + "--ignore-non-source", + action="store_true", + help=( + "If set, filter the given files to only keep those which would have" + " been detected automatically" + ), +) +args_parser.add_argument( + "files", + nargs="*", + help=( + "List of files on which to run. If none is passed, process all source" + " files found in the current directory that look like source files." + ), +) + + +class Checker: + filename_extensions = { + "adb", + "adc", + "ads", + "c", + "cc", + "cpp", + "gpr", + "h", + "hh", + "hpp", + "opt", + "py", + } + """ + List of file extensions that look like source files. + """ + + ignore_list = [ + "testsuite/tests/354-source-encoding/latin1.ads", + ] + """ + List of files to intentionally ignore for style checking purposes. + """ + + def __init__(self, autofix: bool = False, force_colors: bool = False): + self.issue_found = False + """ + Whether at least one issue was found so far. + """ + + self.use_colors = force_colors or os.isatty(sys.stdout.fileno()) + """ + Whether to colorize the error messages. + """ + + self.autofix = autofix + """ + Whether to attempt to fix the style issues found in place. + """ + + def report( + self, + filename: str, + message: str, + lineno: int | None = None, + ) -> None: + """ + Report a style issue. + + :param filename: File in which the issue was found. + :param message: Human-readable description of the issue. + :param lineno: Line number for the issue, if applicable, None + otherwise. + """ + self.issue_found = True + + # Build a list of text chunks to print. Put colorama elements in tuples + # so that we can keep only text chunks if the output is not a TTY. + chunks = [ + (MAGENTA,), + filename, + (CYAN,), + ":", + ] + if lineno is not None: + chunks += [ + (GREEN,), + str(lineno), + (CYAN,), + ":", + ] + chunks += [ + (RESET_ALL,), + " ", + message, + ] + + filtered_chunks = [] + for c in chunks: + if isinstance(c, str): + filtered_chunks.append(c) + elif isinstance(c, tuple): + if self.use_colors: + filtered_chunks += c + else: + raise AssertionError + print("".join(filtered_chunks)) + + def process_file(self, filename: str) -> None: + """ + Look for style issues in the given file. + """ + + with open(filename, encoding="utf-8") as f: + try: + content = f.read() + except UnicodeDecodeError as exc: + self.report(filename, str(exc)) + return + if not content: + return + + lines = content.splitlines() + modified = False + + if not content.endswith("\n"): + modified = True + self.report(filename, "missing trailing newline") + + for i, line in enumerate(lines, 1): + stripped_line = line.rstrip() + if line != stripped_line: + modified = True + self.report(filename, "trailing whitespace", i) + lines[i - 1] = stripped_line + + while not lines[-1].strip(): + modified = True + self.report(filename, "last line is empty") + lines.pop() + + # If requested, fix the issues that were found + if self.autofix and modified: + with open(filename, "w") as f: + if lines: + for line in lines: + f.write(line) + f.write("\n") + + @classmethod + def main(cls, argv: list[str] | None = None): + args = args_parser.parse_args(argv) + checker = cls( + autofix=args.autofix, + force_colors=args.force_colors, + ) + + ignore_set = {os.path.realpath(f) for f in checker.ignore_list} + + # Process the list of files to check if present, otherwise look for all + # source files in the current directory. + if args.files: + for filename in args.files: + realpath = os.path.realpath(filename) + if not args.ignore_non_source or ( + realpath not in ignore_set + and filename.rsplit(".", 1)[-1] in cls.filename_extensions + ): + checker.process_file(filename) + else: + for path, _, filenames in os.walk("."): + for f in filenames: + realpath = os.path.realpath(os.path.join(path, f)) + if ( + realpath not in ignore_set + and f.rsplit(".", 1)[-1] in cls.filename_extensions + ): + checker.process_file(realpath) + + return 1 if checker.issue_found else 0 + + +if __name__ == "__main__": + sys.exit(Checker.main()) diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..17eee26f2 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +ignore = E203,E402,W503 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 309ea38be..000000000 --- a/.gitattributes +++ /dev/null @@ -1,13 +0,0 @@ -testsuite/Qualif/**/*.adb no-precommit-check -testsuite/Qualif/**/*.ads no-precommit-check -testsuite/Qualif/**/*.c no-precommit-check -testsuite/Qualif/**/*.h no-precommit-check - -# gnattest auto generated files are not style-check compliant -examples/integration/tests/*-test_data-tests.adb no-precommit-check -examples/integration/tests/*-test_data-tests.ads no-precommit-check - -# Until converted to python 3 and full style compliance ... -testsuite/STR/*.py no-precommit-check -testsuite/Qualif/qmconf.py no-precommit-check -qualification/**/*.py no-precommit-check diff --git a/.gitignore b/.gitignore index 0c701ac4b..a78ede2c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ obj +obj-* lib *.pyc *.pkl @@ -11,9 +12,12 @@ lib /tools/gnatcov/obj32/ /tools/gnatcov/obj64/ /tools/gnatcov/obj-gnatcov_rts/ +/tools/gnatcov/objlib64/ +/tools/gnatcov/examples/support/conf.gpr /tools/gnatcov/examples/support/lib /tools/gnatcov/examples/support/obj /tools/gnatcov/rts-instr +/tools/gnatcov/ada-rts/gnatcov_rts.ads /tools/gnatcov/share/lib-gnatcov_rts_full.* /tools/gnatcov/share/obj-gnatcov_rts /tools/gnatcov/share/obj-gnatcov_rts_full.* @@ -21,10 +25,30 @@ lib /testsuite/out /testsuite/suite.cgpr /testsuite/support -/testsuite/tests /testsuite/tmp +/testsuite/altrun/ccg_native/ccg_gnatcov_rts +/testsuite/altrun/ccg_native/adainclude gnatcov-loc.xml gnatinspect.db README.html TAGS -*.~undo-tree~ \ No newline at end of file +*.~undo-tree~ +*.log + +# temporary output of genrest.py +qualification/qualkit/tor/source/ + +# local copy/link to the gnatcheck-qualkit sources +qualification/gnatcheck_qualkit_common + +# generated output of genbundle.py +qualification/**/build +qualification/**/source +qualification/**/missing_tr_log.txt +testsuite/STR/build +testsuite/STR/source + +# vscode local settings +.env +.vscode + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..a3198ff54 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,371 @@ +workflow: + rules: + # Run the CI on merge requests only + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + +variables: + PACKAGE_BASE_NAME: gnatcoverage.tar.gz + PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME + GNATFORMAT_DATE: 20250917 + +include: + - component: $CI_SERVER_FQDN/eng/gitlab-templates/pre-commit@~latest + inputs: + stage: check + # Do not run gnatformat in pre-commit as it is missing from the environment. + # A specific CI job is used instead. + pre-commit-skip: "gnatformat" + + - component: $CI_SERVER_FQDN/eng/gitlab-templates/gnatformat@~latest + inputs: + stage: check + anod-spec: gnatcov + gnatformat-args: --no-project --check $(find tools/gnatcov -iname '*.ad[bs]') + install-gnatformat: true + install-gnatformat-extra-anod-args: -Qedge -Qdate=$GNATFORMAT_DATE + + #TODO: workaround to allow dynamically setting the interruptible policy until https://gitlab.com/gitlab-org/gitlab/-/issues/194023 is implemented + - local: utils/ci/interruptible.yml + rules: + - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH + + # Run gnatsas on GNATcoverage sources + - component: $CI_SERVER_FQDN/eng/gitlab-templates/static-analysis@topic/move-ci-to-generic-anod-ci + inputs: + anod-spec: gnatcov-gnatsas-check + cache-paths: + - $CI_PROJECT_DIR/$GNATSAS_OBJ_DIR + save-anod-logs: true + +.basic_setup: &basic_setup + - generic_anod_ci --add-dep eng/das/cov/gnatcoverage-extra + - cat /tmp/ci_env.sh + - . /tmp/ci_env.sh + +stages: + - build + - test + - check + +build: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: build + script: + - require_issue + - *basic_setup + + # 1. Install / build the dependencies of gnatcov using the smart rebuilder + # to allow testing of breaking changes. Do not use the -Qinstr qualifier + # as this would trigger a rebuild of the vanilla gnatcov. + - anod build --smart-rebuild --deps-only gnatcov $ACI_TRACK_QUALIFIER + + # 2. Install vanilla gnatcov from cathod + - anod install gnatcov $ACI_TRACK_QUALIFIER --latest + + # 3. Build using anod, but minimally as all dependencies are supposed to be + # already built/installed via 1, but we don't want to re-build the + # gnatcov installed via 2 with --smart-rebuild. + - anod build --minimal gnatcov -Qinstr $ACI_TRACK_QUALIFIER + + # Package all components created so far + - anod-copy-components --standalone-export $ANOD_DEFAULT_SANDBOX_DIR $ANOD_DEFAULT_SANDBOX_DIR/exp-comps + - tar czf $PACKAGE_ABSOLUTE_NAME -C / $ANOD_DEFAULT_SANDBOX_DIR/exp-comps + + - cd $CI_PROJECT_DIR + - ls -l $PACKAGE_BASE_NAME + + artifacts: + paths: + - $PACKAGE_BASE_NAME + +build_docs: + stage: build + services: + - image:pe-base + needs: [] + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH) + changes: + - doc/**/* + when: always + script: + - *basic_setup + - anod build gnatdas-doc -Qwarn-errors --latest + - DOC_BSN=$(anod eval gnatdas-doc -Qwarn-errors build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$DOC_BSN/install/share/doc/gnatdas/ $CI_PROJECT_DIR + artifacts: + when: + always + paths: + - gnatdas/pdf/gnatdas.pdf + - gnatdas/html + +build_community: + interruptible: true + services: + - image:pe-base + - cpu:8 + - mem:16 + stage: test + script: + - *basic_setup + # Build using anod, we can use the smart rebuilder here as gnatcov does not + # depend on itself in this case. + - anod build --smart-rebuild gnatcov -Qno-c $ACI_TRACK_QUALIFIER + +.common_test_bits: &basic_test_setup + # Setup the sandbox + - *basic_setup + + # Import components from the artifact and install the instrumented gnatcov, + # then remove temporaries to save disk space. + - tar zxf $PACKAGE_ABSOLUTE_NAME -C / + - anod-copy-components $ANOD_DEFAULT_SANDBOX_DIR/exp-comps $ANOD_DEFAULT_SANDBOX_DIR + - anod install gnatcov -Qinstr $ACI_TRACK_QUALIFIER + - rm -rf $PACKAGE_ABSOLUTE_NAME $ANOD_DEFAULT_SANDBOX_DIR/exp-comps + + # Setup the CI directory to host coverage results + - mkdir $CI_PROJECT_DIR/coverage + + +.common_artifacts_bits: &artifacts + artifacts: + paths: + - xunit-*.xml + - coverage/cobertura.xml + + reports: + junit: xunit-*.xml + coverage_report: + coverage_format: cobertura + path: coverage/cobertura.xml + +test_bin_traces: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - testsuite_reports + + <<: *artifacts + +test_src_traces: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal -Qsrc-traces,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - testsuite_reports + + <<: *artifacts + +test_5.04a1_src_traces: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # GNAT 5.04a1 does not ship "ar" nor "ld". Make the ones from gnat/stable + # available as if they were installed system-wide. + - anod install gnat -Qstable + - STABLE_GNAT_BSN=$(anod eval --primitive=install gnat -Qstable build_space_name) + - STABLE_GNAT_PREFIX="$ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$STABLE_GNAT_BSN/install" + - mkdir build-essentials + - export PATH="$PWD/build-essentials:$PATH" + - ln -s $STABLE_GNAT_PREFIX/bin/ar build-essentials/ + - ln -s $STABLE_GNAT_PREFIX/x86_64-pc-linux-gnu/bin/ld build-essentials/ + # Test using anod + - anod test gnatcov --minimal -Q5.04a1,src-traces,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Q5.04a1,src-traces,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - testsuite_reports + + <<: *artifacts + +test_spark: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal -Qspark-tests,src-traces,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qspark-tests,src-traces,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - testsuite_reports + + <<: *artifacts + +########## +# Checks # +########## + +pre-commit: + before_script: + - *basic_setup + + # Install the clang-format executable and make it available + - anod install libclang -Qstable + - eval `anod printenv libclang -Qstable` + +static-analysis: + variables: + GNATSAS_OBJ_DIR: tools/gnatcov/obj64/prod + GNATSAS_OUT_DIR: tools/gnatcov/analyzer + +################# +# Optional jobs # +################# + +# Optional job for block instrumentation. +# +# To be run when Ada or C instrumentation is modified to ensure the new +# changes are also compatible with block instrumentation. +test_block_instr: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + when: manual + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal -Qsrc-traces,instr,block $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr,block $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - testsuite_reports + + <<: *artifacts + +# Optional job for light runtime testing on source traces. Dump trigger +# strategies differ on that runtime, and not all tests are compatible with +# this runtime depending on the needed features (e.g. --dump-channel=bin-file) +# or the test sources make use of Ada features not available on this runtime. +# +# Only needs to be run when large batches of src-trace specific tests are added, +# or if instrumentation code related to buffer dump is modified. +test_src_light: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + when: manual + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal -Qsrc-traces,instr,RTS=light-stm32f4 --target=arm-elf,,qemu-stm32 $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr,RTS=light-stm32f4 --target=arm-elf,,qemu-stm32 $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - testsuite_reports + + <<: *artifacts + +test_qualkit: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # Use the gnatcov-qualrun and gnatcov-qualkit specs to run the + # qualification testsuite and create a qualification kit + - anod test gnatcov-qualrun --minimal -Qci $ACI_TRACK_QUALIFIER + - anod build gnatcov-qualkit --minimal -Qci $ACI_TRACK_QUALIFIER + - QUALKIT_BSN=$(anod eval --primitive=build gnatcov-qualkit -Qci $ACI_TRACK_QUALIFIER build_space_name) + - QUALRUN_BSN=$(anod eval --primitive=test gnatcov-qualrun -Qci $ACI_TRACK_QUALIFIER build_space_name) + - mkdir $CI_PROJECT_DIR/qualkits + - mkdir $CI_PROJECT_DIR/qualrun + - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALRUN_BSN/tmp/attachment-testsuite_tree.tgz $CI_PROJECT_DIR/qualrun/ + - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALKIT_BSN/install/*.zip $CI_PROJECT_DIR/qualkits/ + - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALKIT_BSN/install/consistency.log $CI_PROJECT_DIR/qualkits/ + - testsuite_reports + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + paths: + - "qualification/**/*" + - "testsuite/Qualif/**/*" + - "testsuite/STR/**/*" + - "testsuite/SCOV/**/*" + compare_to: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME + artifacts: + when: always + paths: + - xunit-*.xml + - qualkits/*.zip + - qualkits/consistency.log + - qualrun/attachment-testsuite_tree.tgz + reports: + junit: xunit-*.xml + +# Temporary gnatcov 25 CI run, to simplify verification of the new +# qualification tests for gnatcov 25. +# +# TODO: remove this when the qualification project for +# eng/cert/projects#45 is finished. +test_qualrun_25: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + # Test using gnatcov-qualrun to be able to test gnatcov 25. We don't need + # to produce a qualkit so skip that to keep the CI job short. + - anod test gnatcov-qualrun -Qgnatcov_version=25.2 --minimal -Qci $ACI_TRACK_QUALIFIER + - testsuite_reports + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + paths: + - "qualification/**/*" + - "testsuite/Qualif/**/*" + - "testsuite/STR/**/*" + - "testsuite/SCOV/**/*" + compare_to: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME + artifacts: + when: always + paths: + - xunit-*.xml + reports: + junit: xunit-*.xml diff --git a/.gitreview b/.gitreview deleted file mode 100644 index a5d94509a..000000000 --- a/.gitreview +++ /dev/null @@ -1,6 +0,0 @@ -[gerrit] -host = git.adacore.com -port = 29418 -project = gnatcoverage -defaultbranch = master -defaultremote = origin diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 84f22d470..e327ac177 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,5 +4,47 @@ repos: hooks: - id: clang-format types: [file] - files: \.(cc|c|h)$ - args: ["--style=gnu"] + files: \.(cc|c|h|cpp|hh)$ + args: ["--style={ + BasedOnStyle: gnu, + ContinuationIndentWidth: 2, + + # Unfortunately, a bug in clang-format makes this ineffective + IndentExternBlock: NoIndent, + + SpaceAfterCStyleCast: true, + SpacesInLineCommentPrefix: { + Minimum: 0, + Maximum: -1 + }}"] + - repo: https://github.com/pycqa/flake8 + rev: 7.1.1 + hooks: + - id: flake8 + additional_dependencies: + - flake8-bugbear + - flake8-builtins + - flake8-comprehensions + - pygments + args: ["--config=.flake8"] + - repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + args: ["--line-length=79"] + - repo: local + hooks: + - id: check-formatting + name: check-formatting + entry: python .check-formatting.py + language: system + args: ["--autofix", "--ignore-non-source"] + - repo: local + hooks: + - id: gnatformat + name: Run gnatformat + entry: gnatformat + args: ["--no-project"] + language: system + files: "^tools/gnatcov/.*\\.ad(b|s)$" + diff --git a/doc/Makefile b/doc/Makefile index 8cf357103..7a67f6cab 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -41,7 +41,7 @@ prepare-installdir.%: # expect to have a line like << master_doc = "bla" or 'bla' >> someplace. MASTER_DOC=$(shell sed -n -e \ - "s/master_doc.*=[^'\"]*['\"]\([^'\"]*\).*/\1/p" conf.py) + "s/master_doc.*=[^'\"]*['\"]\([^'\"]*\).*/\1/p" conf.py) # Make sure the PDF we install has a meaningful name and leave the html # alone so internal hyperlinks to the toplevel page remain functional. @@ -74,7 +74,7 @@ install.html: prepare-installdir.html gnatcov/fig_%.png: gnatcov/fig_%.dot gnatcov/fig_%.pdf: gnatcov/fig_%.dot -FIGURES=fig_consolidation fig_multipath-bdd fig_flow0 +FIGURES=fig_consolidation fig_multipath-bdd fig_flow_compare fig_flow_srctraces prepare-images:: $(foreach fig, $(FIGURES), gnatcov/$(fig).pdf) prepare-images:: $(foreach fig, $(FIGURES), gnatcov/$(fig).png) @@ -107,9 +107,9 @@ prepare-builddir.%: $(PREPARE_IMAGES) # bits to find it in index.rst. look_for_gnatfuzz: if [ -e "gnatfuzz/gnatfuzz_part.rst" ]; then \ - if [ "`grep "gnatfuzz" index.rst`" = "" ]; then \ - echo " gnatfuzz/gnatfuzz_part" >> index.rst; \ - fi; \ + if [ "`grep "gnatfuzz" index.rst`" = "" ]; then \ + sed -i -e 's/\.\. Optional GNATfuzz part/ gnatfuzz\/gnatfuzz_part/g' index.rst; \ + fi; \ fi build.pdf: look_for_gnatfuzz prepare-builddir.pdf diff --git a/doc/adacore-logo-white.png b/doc/adacore-logo-white.png new file mode 100644 index 000000000..115c90f74 Binary files /dev/null and b/doc/adacore-logo-white.png differ diff --git a/doc/conf.py b/doc/conf.py index c035ef4a7..4d102252c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -12,6 +12,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. +from datetime import datetime import os import docutils.nodes as nodes @@ -24,13 +25,13 @@ # -- General configuration ------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.8' +needs_sphinx = "1.8" # 1.2 for multiple glossary entries # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ - 'sphinx.ext.imgmath', + "sphinx.ext.imgmath", "sphinx.ext.autodoc", "sphinx.ext.coverage", "sphinx.ext.doctest", @@ -44,10 +45,10 @@ autosectionlabel_prefix_document = True # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' @@ -58,20 +59,25 @@ master_doc = "index" # General information about the project. -project = u"GNATDAS" -copyright = u"2009-2022, AdaCore" -docname = u"Manuals" +project = "GNAT DAS" +copyright = f"2009-{datetime.now().year}, AdaCore" # noqa: A001 +docname = "Manuals" rst_epilog = """ +.. |do| replace:: **DO-178C** .. |gcv| replace:: :command:`gnatcov` .. |gcvrun| replace:: :command:`gnatcov` :command:`run` .. |gcvcov| replace:: :command:`gnatcov` :command:`coverage` .. |gcvstp| replace:: :command:`gnatcov` :command:`setup` +.. |gcvsti| replace:: :command:`gnatcov` :command:`setup-integration` .. |gcvins| replace:: :command:`gnatcov` :command:`instrument` .. |gcvxtr| replace:: :command:`gnatcov` :command:`extract-base64-trace` .. |gcvcnv| replace:: :command:`gnatcov` :command:`convert` .. |gcvdsp| replace:: :command:`gnatcov` :command:`disp-routines` .. |gcvmap| replace:: :command:`gnatcov` :command:`map-routines` +.. |gcvaddan| replace:: :command:`gnatcov` :command:`add-annotation` +.. |gcvdelan| replace:: :command:`gnatcov` :command:`delete-annotation` +.. |gcvshoan| replace:: :command:`gnatcov` :command:`show-annotations` .. |gdas| replace:: {} .. |gcp| replace:: GNATcoverage @@ -85,7 +91,7 @@ .. |rarg| replace:: possibly repeated and accepting :term:`@listfile arguments <@listfile argument>` """.format( - project + project ) # The version info for the project you're documenting, acts as replacement for @@ -95,12 +101,12 @@ # Tool version & release. Nightly setups are expected to store this # in a version.txt file for us. Assume we're in a development tree otherwise. -version_file = 'version.txt' +version_file = "version.txt" if os.path.exists(version_file): - with open(version_file, 'r') as f: + with open(version_file, "r") as f: version = f.read() else: - version = 'dev-tree' + version = "dev-tree" release = version @@ -116,7 +122,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. @@ -151,13 +157,14 @@ # a list of builtin themes. html_theme = "sphinx_rtd_theme" -html_sidebars = { - '**': ['globaltoc.html', 'sourcelink.html', 'searchbox.html']} +html_sidebars = {"**": ["globaltoc.html", "sourcelink.html", "searchbox.html"]} # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -# html_theme_options = {} +html_theme_options = { + "style_nav_header_background": "#12284c", +} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] @@ -171,7 +178,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -# html_logo = None +html_logo = "adacore-logo-white.png" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 @@ -241,19 +248,24 @@ # to our latex_preamble. latex_documents = [ - (master_doc, master_doc+'.tex', "%s %s" % (project, docname), - u'AdaCore', 'manual'), + ( + master_doc, + master_doc + ".tex", + "%s %s" % (project, docname), + "AdaCore", + "manual", + ), ] # Get rid of the "Release" tag before the version number # in the first page subtitle -latex_additional_files = ['latex_preamble.inc'] +latex_additional_files = ["latex_preamble.inc"] latex_elements = { - 'releasename': 'Version', - 'preamble': r'\input{latex_preamble.inc}', - } + "releasename": "Version", + "preamble": r"\input{latex_preamble.inc}", +} # The name of an image file (relative to this directory) to place at the top # of the title page. @@ -261,7 +273,7 @@ # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -latex_toplevel_sectioning = 'part' +latex_toplevel_sectioning = "part" # If true, show page references after internal links. # latex_show_pagerefs = False @@ -281,8 +293,10 @@ # Custom :cmd-option: role def cmd_option_role( - name, rawtext, text, lineno, inliner, options={}, content=[] + name, rawtext, text, lineno, inliner, options=None, content=None ): + options = options or {} + content = content or [] node = nodes.literal(rawtext, text, *content, **options) return [node], [] diff --git a/doc/gnatcov/appendix.rst b/doc/gnatcov/appendix.rst index 67e6ad730..34f5509b0 100644 --- a/doc/gnatcov/appendix.rst +++ b/doc/gnatcov/appendix.rst @@ -17,109 +17,3 @@ Sample html annotated source .. image:: sample_sc_html_unit.png :scale: 80% - - -.. _target_specific_notes: - -Target specific points of note with Binary traces -================================================= - -The following list summarizes points of note for each target where some -aspects of the build/execution/analysis process depart from the general -instructions. - -For **cross** configurations in general: - -- Need to convey the target to |gcvrun|, either with a :cmd-option:`--target` - switch or a ``Target`` project file attribute; - -- Need to convey the target and Ada runtime when using project files - to state units of interest, for |gcvcov|, |gcvins| or |gcvrun|. See - :ref:`sunits`, :ref:`gpr_context`. - -For **powerpc-vxworks6**: - -- Need to compile with -gno-strict-dwarf -mlongcall for source coverage - analysis; - -- Need to add a --kernel argument on |gcvrun|; - -- The provided kernel has to be augmented with a specific module - for gnatcov purposes. Please refer to the |gem| documentation for this - part of the process; - -- Support for the ``kernel`` Ada RTS and Downloadable Kernel Modules only. - -.. _known_limitations: - -Known Limitations with Binary traces -==================================== - -Incomplete statement coverage on lines with multiple statements ---------------------------------------------------------------- - -On lines with multiple statements, the tool may not be able to infer -accurate statement coverage results for each individual statement. The -tool emits explicit diagnostics in this case. - -In :cmd-option:`=report` outputs (with :cmd-option:`--annotate=report`), this -translates as a statement coverage violation like:: - - : multiple statements on line, unable to establish full statement coverage - -where is a source-filename:line:column source location of the -problematic line. - -In annotated sources kinds of outputs, this materializes as '!' note indicating -partial coverage on the affected lines, with the :cmd-option:`=report` -violation text quoted above available as part of the line extra-details -expanded on demand (:cmd-option:`=html+` and :cmd-option:`xcov+` output -formats). - -.. _mcdc-limitations: - -MCDC inaccuracies with interrupts and multi-threaded applications ------------------------------------------------------------------ - -There is one limitation in |gcp| with respect to MCDC assessments from binary -traces: potential inaccuracies in results reported for particular decisions -when these decisions are evaluated concurrently by different threads or mixed -with interrupt processing in bareboard configurations. - -Technically, the decisions of concern are those for which the associated -binary decision diagram is not a tree, that is, those with at least one -condition node joining several possible evaluation paths. - -The code sample below illustrates the simplest possible problematic decision -and the following figure depicts the corresponding Binary Decision Diagram -(commonly abbreviated as *BDD*), which states how sequence of operand -evaluations, starting from the left, eventually lead to the expression -outcome, here on the right: - -.. code-block:: ada - - function Mp (A, B, C : Boolean) return Boolean is - begin - return (A or else B) and then C; - end; - -.. figure:: fig_multipath-bdd.* - :align: center - - BDD for ``(A or else B) and then C``, not a tree - -The expression BDD is indeed not a tree, as the node representing the -evaluation of C is reachable either directly from A, when A is True, or -via B when A is False. - -According to measures performed on a few large real code bases, occurrences of -such decisions are statistically rare. |gcv| can report about them on demand, -thanks to the :command:`scan-decisions` command together with the the set of -coverage obligations to examine. Below is an excerpt of a an execution for a -project which encompasses this function, where we see that |gcv| provides the -source location of conditions rechable through multiple paths:: - - gnatcov scan-decisions -Pmytest.gpr - ... - *** mp.adb:4:33: warning: condition is reachable through multiple paths - diff --git a/doc/gnatcov/bin_convert.rst b/doc/gnatcov/bin_convert.rst new file mode 100644 index 000000000..6817a6367 --- /dev/null +++ b/doc/gnatcov/bin_convert.rst @@ -0,0 +1,16 @@ +.. _bin_convert: + +##################################### +Importing binary traces with |gcvcnv| +##################################### + +Traces generated from external sources (other than by using |gcvrun|) +can be imported into |gcp| by converting them to the |gcp| format +using |gcvcnv|. + +.. toctree:: + :maxdepth: 2 + + convert_commandline + nexus_5634 + trace32 diff --git a/doc/gnatcov/bin_gps.rst b/doc/gnatcov/bin_gps.rst new file mode 100644 index 000000000..af2a579e0 --- /dev/null +++ b/doc/gnatcov/bin_gps.rst @@ -0,0 +1,28 @@ +###################### +Using |gcp| from |gps| +###################### + +Starting from GNATcoverage version 22.0, binary traces (using gnatcov run) are +no longer supported in native profiles. This mode is still supported for cross +configurations, and the IDE integrated use in such cases is similar to the use +for source traces: + +Go to the :menuselection:`Analyze --> Coverage --> GNATcoverage Binary Traces` +menu to perform each step individually, or use the ``Run All Actions`` item to +do everything at once. + +In configurations where binary traces are not supported, the menu entry just +wouldn't show up. + +You can also replace the toolbar button (dedicated to the instrumentation-based +scheme) with an alike button, but for binary traces. Go to GNATstudio +Preferences in :menuselection:`Edit --> Preferences`. + +Then, go to the ``Build Targets`` section, and find the ``Run GNATcoverage`` +workflow: add it to the toolbar as shown below. + +.. image:: gps_screenshots/7-binary-traces.png + +Remove the ``Run GNATcoverage with instrumentation`` entry from the toolbar in +the same fashion. + diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst new file mode 100644 index 000000000..398eebd1b --- /dev/null +++ b/doc/gnatcov/bin_intro.rst @@ -0,0 +1,189 @@ +************ +Introduction +************ + +Definition and main characteristics +----------------------------------- + +Unlike *source traces* produced by the execution of instrumented +programs in their regular environment, :dfn:`binary traces` are +coverage trace files produced by the execution of uninstrumented +programs under the control of an instrumented execution environment. +*"Binary"* in this designation refers to the nature of the collected +data, which consists in low level information about executed blocks of +machine instructions. + +From binary traces, |gcp| is able to compute both *source coverage* +metrics as with source traces, and :dfn:`object coverage` metrics +assessing the coverage of machine level instructions. |gcp| supports +two criteria of the latter kind: + +- :dfn:`Instruction Coverage`, where we evaluate for each machine instruction + whether it has been executed at least once or not; and + +- :dfn:`Branch Coverage`, where we also evaluate for each conditional + branch instruction whether it was only taken, or went fallthrough or both. + +Source coverage metrics are only available for a subset of the target +configurations supported with source traces, though, and new tool +functionalities are most often implemented for source traces only. + +The matrix below summarizes the main characteristics of the two +trace production modes: + + +.. list-table:: + :widths: 20 20 20 + :header-rows: 1 + :stub-columns: 1 + + * - + - **With Source Traces** + - **With Binary Traces** + * - *Tracing mechanism* + - Program instrumentation + - Execution environment + * - ~ + - ~ + - ~ + * - *Native applications* + - Yes (including shared-libraries) + - No + * - *Cross configurations with RTOS* + - Yes + - No + * - *Bareboard configurations* + - Yes + - Specific CPUs only, through GNATemulator or + hardware probes + * - ~ + - ~ + - ~ + * - *Object coverage analysis* + - No + - Yes + * - *New features* + - Often not + - Yes (source level metrics for C++, scoped metrics in html) + + +Workflow overview +----------------- + +A high level view comparing the processes involved in the use of +binary or source traces is provided on :numref:`fig-flow_compare`. The +use of coverage *traces* in both modes allows lots of similarities +between workflows, in particular in the steps processing traces after +they have been produced. + +We don't support mixing the two kinds of traces together, though, and have +depicted a separate analysis/consolidation step to emphasize this: + +.. _fig-flow_compare: +.. figure:: fig_flow_compare.* + :align: center + + Workflows using source or binary coverage traces + +For binary traces, |gcv| relies on an instrumented execution +environment to produce the traces instead of having to instrument the +program itself with extra code and data structures. |gem| provides +such an environment for bareboard configurations, as well as hardware +probes assisted with means to convert their output to the format |gcv| +expects. + +Programs are built from their original sources, only requiring the use of +:cmd-option:`-g -fpreserve-control-flow -fdump-scos` compilation options to +generate coverage obligation lists and let us associate execution traces to +these obligations afterwards. + + + +A simple example +---------------- + +For the original "Getting Started" use case, we first use the GNAT Pro +toolset for ``powerpc-elf`` to build, using :command:`gprbuild` as +follows:: + + gprbuild --target=powerpc-elf --RTS=light-mpc8641 -Ptests.gpr \ + -cargs -g -fpreserve-control-flow -fdump-scos + +We pass the project file with ``-P``, the required compilation flags +with ``-cargs`` and request the use of a ``light`` runtime library tailored +for the ``mpc8641`` board. + +The build command produces a ``test_inc`` executable in the object +subdirectory. To automate the execution of this program within |gem| +to produce a trace, we provide the |gcvrun| command. For the use case +at hand, we would simply do:: + + gnatcov run --target=powerpc-elf obj-tests/test_inc + + +This produces a ``test_inc.trace`` binary trace file in the current +directory. By default, such a trace is amenable to statement and decision +coverage at most. If MCDC analysis is needed, ``--level=stmt+mcdc`` must be +passed to |gcvrun| as well and we recommend also providing source coverage +obligations in this case. + +Producing report is then achieved as for sources traces, using the +binary trace files as inputs to the |gcvcov| commands. + +Units of interest can be conveyed with either the GPR oriented +facilities as with source traces, or with :cmd-option:`--scos` +switches to provide lists of files holding coverage obligations in a +similar fashion as :cmd-option:`--sid` switches for ``.sid`` files out +of source instrumentation. + +The files to list with :cmd-option:`--scos` are the *Library +Information* files produced by the compiler along with object files, +which are ``.ali`` files for Ada and ``.gli`` files for C. + +The GNAT toolchain provides a helpful device in this process for Ada +units: the :cmd-option:`-A` command line argument to +:command:`gnatbind` which produces a list of all the ``.ali`` files +involved in an executable construction. By default, the list goes to +standard output. It may be directed to a file on request with +:cmd-option:`-A=`, and users may of course filter this +list as they see fit depending on their analysis purposes. + +Below is a complete example sequence of commands to illustrate, using +the standard Unix ``grep`` tool to filter out test harness units:: + + # Build executable and produce the corresponding list of ALI files. Pass + # -A to gnatbind through gprbuild -bargs then filter out the test units: + gprbuild -p --target=powerpc-elf --RTS=light-mpc8641 -Ptests.gpr + -cargs -fdump-scos -g -fpreserve-control-flow -bargs -A=all.alis + + # Run and analyse all units except the test harness, filtering out + # the correspond ALI files from the list: + grep -v 'test_[^/]*.ali' all.alis > nontest.alis + gnatcov run --level=stmt+mcdc --scos=@nontest.alis + gnatcov coverage --level=stmt+mcdc --annotate=xcov --scos=@nontest.alis + +Going Further +------------- + +As the source and binary trace based workflows share commonalities, +a lot of information from the main documentation also applies to the +use binary traces, such as + +- The use of project files to specify command switches or designate + units of interest at analysis time, + +- Using coverage checkpoints or traces for consolidation, + +- Defining exemptions regions with pragmas for Ada. The support + for other languages is not available for binary traces. + +Then this appendix holds separate chapters dedicated to binary trace +specific considerations: + +- :ref:`bin_traces` + +- :ref:`ocov` + +- :ref:`osmetrics` + +- :ref:`bin_convert` diff --git a/doc/gnatcov/bin_limitations.rst b/doc/gnatcov/bin_limitations.rst new file mode 100644 index 000000000..caa3e16d7 --- /dev/null +++ b/doc/gnatcov/bin_limitations.rst @@ -0,0 +1,103 @@ + +.. _target_specific_notes: + +Target specific points of note with Binary traces +================================================= + +The following list summarizes points of note for each target where some +aspects of the build/execution/analysis process depart from the general +instructions. + +For **cross** configurations in general: + +- Need to convey the target to |gcvrun|, either with a :cmd-option:`--target` + switch or a ``Target`` project file attribute; + +- Need to convey the target and Ada runtime when using project files + to state units of interest, for |gcvcov|, |gcvins| or |gcvrun|. See + :ref:`sunits`, :ref:`gpr_context`. + +For **powerpc-vxworks6**: + +- Need to compile with -gno-strict-dwarf -mlongcall for source coverage + analysis; + +- Need to add a --kernel argument on |gcvrun|; + +- The provided kernel has to be augmented with a specific module + for gnatcov purposes. Please refer to the |gem| documentation for this + part of the process; + +- Support for the ``kernel`` Ada RTS and Downloadable Kernel Modules only. + +.. _known_limitations: + +Known Limitations with Binary traces +==================================== + +Incomplete statement coverage on lines with multiple statements +--------------------------------------------------------------- + +On lines with multiple statements, the tool may not be able to infer +accurate statement coverage results for each individual statement. The +tool emits explicit diagnostics in this case. + +In :cmd-option:`=report` outputs (with :cmd-option:`--annotate=report`), this +translates as a statement coverage violation like:: + + : multiple statements on line, unable to establish full statement coverage + +where is a source-filename:line:column source location of the +problematic line. + +In annotated sources kinds of outputs, this materializes as '!' note indicating +partial coverage on the affected lines, with the :cmd-option:`=report` violation +text quoted above available as part of the line extra-details expanded on demand +(:cmd-option:`=html` and :cmd-option:`xcov+` output formats). + +.. _mcdc-limitations: + +MCDC inaccuracies with interrupts and multi-threaded applications +----------------------------------------------------------------- + +There is one limitation in |gcp| with respect to MCDC assessments from binary +traces: potential inaccuracies in results reported for particular decisions +when these decisions are evaluated concurrently by different threads or mixed +with interrupt processing in bareboard configurations. + +Technically, the decisions of concern are those for which the associated +binary decision diagram is not a tree, that is, those with at least one +condition node joining several possible evaluation paths. + +The code sample below illustrates the simplest possible problematic decision +and the following figure depicts the corresponding Binary Decision Diagram +(commonly abbreviated as *BDD*), which states how sequence of operand +evaluations, starting from the left, eventually lead to the expression +outcome, here on the right: + +.. code-block:: ada + + function Mp (A, B, C : Boolean) return Boolean is + begin + return (A or else B) and then C; + end; + +.. figure:: fig_multipath-bdd.* + :align: center + + BDD for ``(A or else B) and then C``, not a tree + +The expression BDD is indeed not a tree, as the node representing the +evaluation of C is reachable either directly from A, when A is True, or +via B when A is False. + +According to measures performed on a few large real code bases, occurrences of +such decisions are statistically rare. |gcv| can report about them on demand, +thanks to the :command:`scan-decisions` command together with the the set of +coverage obligations to examine. Below is an excerpt of a an execution for a +project which encompasses this function, where we see that |gcv| provides the +source location of conditions reachable through multiple paths:: + + gnatcov scan-decisions -Pmytest.gpr + ... + *** mp.adb:4:33: warning: condition is reachable through multiple paths diff --git a/doc/gnatcov/bin_traces_convert.rst b/doc/gnatcov/bin_traces_convert.rst deleted file mode 100644 index c63a56f1a..000000000 --- a/doc/gnatcov/bin_traces_convert.rst +++ /dev/null @@ -1,14 +0,0 @@ -##################################### -Importing binary traces with |gcvcnv| -##################################### - -Traces generated from external sources (other than by using |gcvrun|) -can be imported into |gcp| by converting them to the |gcp| format -using |gcvcnv|. - -.. toctree:: - :maxdepth: 2 - - convert_commandline - nexus_5634 - trace32 diff --git a/doc/gnatcov/cons_checkpoints.rst b/doc/gnatcov/cons_checkpoints.rst index cd77856c0..20140de14 100644 --- a/doc/gnatcov/cons_checkpoints.rst +++ b/doc/gnatcov/cons_checkpoints.rst @@ -39,8 +39,8 @@ latter case, if the contribution comes from an intermediate checkpoint, the command which produced the checkpoint is displayed. For example, a sequence of commands such as:: - gnatcov run obj/pgm1 -o trace1 - gnatcov run obj/pgm2 -o trace2 + obj/pgm1 # producing trace1 + obj/pgm2 # producing trace2 gnatcov coverage --level=<> trace1 --save-checkpoint=t1.ckpt gnatcov coverage --level=<> trace2 --checkpoint=t1.ckpt --annotate=report @@ -51,13 +51,13 @@ Would produce a report with this kind of information in the header:: Trace files: trace2 - kind : binary + kind : source program : obj/pgm2 date : 2020-09-22 16:32:52 tag : trace1 - kind : binary + kind : source program : obj/pgm1 date : 2020-09-22 16:32:47 tag : @@ -91,9 +91,11 @@ discuss compatibility issues regarding consolidation. Efficient storage of test results ================================= -Binary trace files can be large and their processing requires access to the -executable file that was used to produce the trace. Preserving collections of -traces and executables to allow consolidation can be problematic, space-wise. +Trace files can be large and often need to be kept together with the +executable files that were used to produce the traces, for traceability +reasons for example, or for specific processing operations in some +circumstances. Preserving collections of traces and executables to allow +consolidation can be problematic, space-wise. In some situations (depending on the overall size of programs, number of units of interest, assessed coverage criteria, number and structure of decisions, @@ -162,22 +164,21 @@ sequence of commands such as:: # Process test1.trace, saving the resulting coverage state in a newly # created checkpoint: - gnatcov coverage --level=<> --scos=@alis test1.trace \ + gnatcov coverage --level=<> -P test1.srctrace \ --save-checkpoint=testsuite.ckpt - # Process subsequent test traces test2.trace .. testN.trace, each time + # Process subsequent test traces test2.srctrace .. testN.srctrace, each time # starting with the coverage state reached at the previous iteration, # and saving the resulting coverage state in the same checkpoint file # (overwriting it): - gnatcov coverage --level=<> --scos=@alis test2.trace \ + gnatcov coverage --level=<> -P test2.srctrace \ --checkpoint=testsuite.ckpt --save-checkpoint=testsuite.ckpt ... - gnatcov coverage --level=<> --scos=@alis testN.trace \ + gnatcov coverage --level=<> -P testN.srctrace \ --checkpoint=testsuite.ckpt --save-checkpoint=testsuite.ckpt # Now produce a report from the cumulated results: - gnatcov coverage --level=<> --scos=@alis \ - --checkpoint=testsuite.ckpt --annotate=<> + gnatcov coverage --level=<> --checkpoint=testsuite.ckpt --annotate=<> The big advantage of this approach is that it stores everything in a single @@ -209,9 +210,9 @@ Now suppose that you want to assess the global coverage for a system comprising both unit A and unit B. If the two sets of trace files are consolidated using a single execution of |gcvcov| as in:: - gnatcov coverage --level=stmt --scos=a.ali --scos=b.ali --annotate=report \ - testA1.trace ... testAN.trace \ - testB1.trace ... testBN.trace + gnatcov coverage --level=stmt --units=A --units=B --annotate=report \ + testA1.srctrace ... testAN.srctrace \ + testB1.srctrace ... testBN.srctrace then calls to B made by A while running testsuite A will contribute to discharging coverage obligations for unit B, and the other way round. @@ -227,17 +228,17 @@ interest for that run. A consolidated coverage report can thus be constructed using a two pass analysis:: - # Discharge the coverage obligations for unit A (--scos=a.ali) using + # Discharge the coverage obligations for unit A (--units=A) using # trace files from testsuite A. - gnatcov coverage --level=stmt --scos=a.ali \ - testA1.trace ... testAN.trace \ + gnatcov coverage --level=stmt --units=A \ + testA1.srctrace ... testAN.srctrace \ --save-checkpoint=testsuiteA.ckpt - # Discharge the coverage obligations for unit B (--scos=b.ali) using + # Discharge the coverage obligations for unit B (--units=B) using # trace files from testsuite B, consolidate with previous results from # testsuite A (--checkpoint), and produce a report (--annotate). - gnatcov coverage --level=stmt --scos=b.ali \ - testB1.trace ... testBN.trace --checkpoint=testsuiteA.ckpt \ + gnatcov coverage --level=stmt --units=B \ + testB1.srctrace ... testBN.srctrace --checkpoint=testsuiteA.ckpt \ --annotate=report In a consolidated report produced following this procedure, each set of trace diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index 7be5fdba3..d9f1256c9 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -13,16 +13,15 @@ The set of traces involved in a computation, with some details about each trace in the *Assessment Context* section of :cmd-option:`=report` outputs, where the command line is quoted. -Trace consolidation works the same for source or binary traces. Mixing -binary and source traces is not supported, however, so all the traces -provided for a consolidation must be of the same kind (all source or -all binary). - The following subsections provide examples of possible use cases of this facility. Single unit tested by different programs ======================================== +The sources for the following example can be found under the +`share/examples/gnatcoverage/doc/cons_traces` directory of the GNAT DAS +disctribution. + We will first consider achieving statement coverage of the following example Ada unit, which implements part of a robot controller able to send actuator commands depending on what a front sensor perceives is ahead of the robot: @@ -119,8 +118,8 @@ the symmetric results:: 12 .: end if; 13 .: end Stat; -Then a report obtained by combining traces, binary or source, will show -achievement of complete statement coverage like so:: +Then a report obtained by combining traces will show achievement of +complete statement coverage like so:: 6 .: procedure Stat (Safe : Boolean) is 7 .: begin @@ -131,12 +130,11 @@ achievement of complete statement coverage like so:: 12 .: end if; 13 .: end Stat; -Assuming you have obtained one trace for the execution of each test, both -traces either source or binary, the command to produce the combined report -would be something like:: +Assuming you have obtained one trace for the execution of each test, +the command to produce the combined report would be something like:: gnatcov coverage --level=stmt --annotate=xcov - test_cmd_safe.trace test_cmd_unsafe.trace + test_cmd_safe.srctrace test_cmd_unsafe.srctrace The means to obtain the traces and the :cmd-option:`` switches would depend on how the functional and testing code has been @@ -248,7 +246,7 @@ Multiple executions of a single program ======================================= Consider the example C program below, offering a simple command line interface -to perform very basic math operations. This is splitted in two main source +to perform very basic math operations. This is split in two main source files: ``process.c`` doing the computation and displaying the result, and ``main.c`` for the main entry point and basic usage control: @@ -383,55 +381,3 @@ visible on lines 7, 14, and 15 of ``main.c``, and attempt to compute an unsupported operation, visible on lines 21 and 22 of ``process.c``. These two scenarios, exercised through ``div.srctrace`` and ``misuse.srctrace`` were indeed not included in the consolidation scope. - -Special care needed with binary traces -====================================== - -Control of inlining in test programs ------------------------------------- - -With binary traces, the program is not itself instrumented to collect coverage -information on its own and the object files used to assess coverage are more -likely (than with source traces) to be used directly in operational -conditions. In such cases, we want to make sure that the binary code from -those object files is indeed exercised during the testing campaign. - -While this would automatically be the case for integration testing campaigns, -campaigns based on the use of explicit testing code, such as unit tests, need -to make sure that calls into the code-under-test by the testing code are not -inlined by the compiler. - -With GCC based toolchains such as GNAT Pro, this can be achieved by adding -:cmd-option:`-fno-inline` to the compilation options of the testing code. - - -Object code overlap in executables ----------------------------------- - -For object or source level criteria, |gcv| computes the coverage achieved for -the full set of routines or source units declared to be of interest amongst -those exposed by the union of the exercised executables, as designated by the -set of consolidated traces; - -For the purpose of computing combined coverage achievements, two symbols are -considered overlapping when all the following conditions are met: - -* Both symbols have identical names at the object level, - -* Both symbols have DWARF debug information attached to them, - -* According to this debug information, both symbols originate from the same - compilation unit, denoted by the full path of the corresponding source file. - -By this construction, a symbol missing debug information is never considered -overlapping with any other symbol. Whatever coverage is achieved on such a -symbol never gets combined with anything else and the only kind of report where -the symbol coverage is exposed is the :cmd-option:`=asm` assembly output for -object level criteria. - -Moreover, for object level coverage criteria, |gcvcov| will issue a -consolidation error when two symbols are found to overlap but have -structurally different machine code, which happens for example when the same -unit is compiled with different different optimization levels for -different executables. - diff --git a/doc/gnatcov/consolidation.rst b/doc/gnatcov/consolidation.rst index ce91d93b0..656ba0c76 100644 --- a/doc/gnatcov/consolidation.rst +++ b/doc/gnatcov/consolidation.rst @@ -22,7 +22,7 @@ tested separately (e.g. the different subprograms of a library unit or different scenarios of a given subprogram). The production of consolidated coverage reports can proceed either directly -from a set of source or binary traces produced by the executions, or from a +from a set of traces produced by the executions, or from a set of pre-computed partial results latched in what we refer to as :term:`coverage checkpoints `, which offer a lot of advanced capabilities. The following sections illustrate various combinations diff --git a/doc/gnatcov/cov_common_switches.rst b/doc/gnatcov/cov_common_switches.rst index 1bd6c8a27..76d295d7b 100644 --- a/doc/gnatcov/cov_common_switches.rst +++ b/doc/gnatcov/cov_common_switches.rst @@ -4,20 +4,20 @@ is used by default. :cmd-option:`--output-dir` : - Request that the report files (index and annotated sources for the - ``xcov``, ``html`` and ``dhtml`` output formats) be output in the provided - directory. If not specified, the default is the root project's object - directory if using projects, and the current directory if not. - If more than one of the above annotation formats is requested, then each - report will be placed in a subdirectory named accordingly. + Request that the report files (index and annotated sources for the ``xcov`` + and ``html`` output formats) be output in the provided directory. If not + specified, the default is the root project's object directory if using + projects, and the current directory if not. If more than one of the above + annotation formats is requested, then each report will be placed in a + subdirectory named accordingly. :cmd-option:`--report-title` : - Request that generated HTML documents (index and annotated sources for the - ``html`` and ``dhtml`` output formats) are assigned a customized title. For - instance, passing ``--report-title="Project ABC"`` will yield titles such - as: ``Project ABC - GNATcoverage Report``. If passed multiple times, passing - an empty string last will restore the default behavior. This option is - ignored is the selected output format does not support titles. + Request that generated HTML documents (index for the ``html`` output format) + are assigned a customized title. For instance, passing + ``--report-title="Project ABC"`` will yield titles such as: ``Project ABC - + GNATcoverage Report``. If passed multiple times, passing an empty string last + will restore the default behavior. This option is ignored is the selected + output format does not support titles. :cmd-option:`-T`, :cmd-option:`--trace` |marg|, |rarg| : Provide the set of execution traces for which a report is to be diff --git a/doc/gnatcov/cov_metrics.rst b/doc/gnatcov/cov_metrics.rst index 2a5041e6b..9def98075 100644 --- a/doc/gnatcov/cov_metrics.rst +++ b/doc/gnatcov/cov_metrics.rst @@ -172,5 +172,4 @@ assessments of distinct source and object criteria here, actually based on solid theoretical grounds established as part of the *Couverture* research project from which |gcp| originates. The core particularity allowing full branch coverage without mcdc is the presence of decisions with BDDs which -are not trees, as we have in this specfic case, - +are not trees, as we have in this specific case, diff --git a/doc/gnatcov/cov_object.rst b/doc/gnatcov/cov_object.rst index 87106f6ec..76fe42660 100644 --- a/doc/gnatcov/cov_object.rst +++ b/doc/gnatcov/cov_object.rst @@ -30,7 +30,7 @@ analyzed. The :ref:`bin_traces` chapter of this document provides details on the trace production interface. The remainder of this chapter explains the -use of |gcvcov| in particular, to analyse traces once they have been +use of |gcvcov| in particular, to analyze traces once they have been produced. The general command line structure is always like:: gnatcov coverage --level= --annotate= @@ -71,13 +71,12 @@ The available options are as follows: explained later in this chapter. :cmd-option:`-a`, :cmd-option:`--annotate` |marg|: - Request a specific output report format. The two possible criteria support - ``xcov[+]``, ``html[+]``, ``dhtml`` and ``asm``, with interpretations that - vary depending on the assessed criteria. See the corresponding - documentation later in this chapter for more details. - This option accepts comma separated values and/or can be specified multiple - times on the command line, in which case there will be one report produced - for each of the requested annotation formats. + Request a specific output report format. The two possible criteria support + ``xcov[+]``, ``html``, and ``asm``, with interpretations that vary depending + on the assessed criteria. See the corresponding documentation later in this + chapter for more details. This option accepts comma separated values and/or + can be specified multiple times on the command line, in which case there will + be one report produced for each of the requested annotation formats. .. include:: cov_common_switches.rst @@ -118,11 +117,11 @@ The :cmd-option:`asm` format produces an annotated assembly output, with a coverage indication attached to every single instruction. This is the base information of interest to object coverage analysis, simply presented in different manners through the other possible output formats. The -:cmd-option:`xcov`, :cmd-option:`html`, and :cmd-option:`dhtml` formats produce -a set of annotated source files, in the directory where |gcv| is launched -unless overriden with a :cmd-option:`--output-dir` option. Even though -presented on sources, the annotations remain representative of object coverage -metrics, synthesized for all the instructions associated with each source line. +:cmd-option:`xcov` and :cmd-option:`html` formats produce a set of annotated +source files, in the directory where |gcv| is launched unless overridden with a +:cmd-option:`--output-dir` option. Even though presented on sources, the +annotations remain representative of object coverage metrics, synthesized for +all the instructions associated with each source line. Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate` on the command line. For example, we use "the @@ -257,37 +256,24 @@ With :cmd-option:`--annotate=xcov+` (extra ``+`` at the end), the machine instructions and their individual coverage status are printed next to their associated source line. -Annotated sources, html (:cmd-option:`=html[+]`) or dynamic html (:cmd-option:`=dhtml`) +Annotated sources, html (:cmd-option:`=html`) --------------------------------------------------------------------------------------- -For object coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces -an annotated version of each source file, in html format, named after the -original source with an extra ``.html`` extension at the end. Each annotated -source page contains a summary of the assessment results followed by the -original source lines, all numbered and marked with a coverage annotation as in -the :cmd-option:`--annotate=xcov` case. In addition, lines with obligations are +For object coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces an +annotated version of each source file. Each annotated source page contains a +summary of the assessment results followed by the original source lines, all +numbered and marked with a coverage annotation as in the +:cmd-option:`--annotate=xcov` case. In addition, lines with obligations are colorized in green, orange or red for ``+``, ``!`` or ``-`` coverage respectively. An `index.html` page is also produced, which contains a description of the assessment context (assessed criteria, set of trace files involved, ...) and a summary of the coverage results for all the units, with links to their annotated sources. -Similarily to the :cmd-option:`xcov` format case, -:cmd-option:`--annotate=html+` (with a trailing +) attaches to each line -details about the coverage status of all the individual instructions generated -for the line. These are folded within the line and expanded when a mouse click -hits it. - -The page style is governed by a set of Cascading Style Sheet (CSS) parameters, -fetched from a ``xcov.css`` file in the directory where |gcv| is launched. If -this file is available when |gcv| starts, |gcv| uses it so users may setup a -customized version if needed. If the file is not available, |gcv| creates a -default one. - -As for source coverage criteria, the :cmd-option:`dhtml` variant produces a -more elaborate kind of report, with sortable columns and per-project indexes on -the root page when the units of interest were specified using the -:cmd-option:`-P` option. +Similarly to the :cmd-option:`xcov` format case, :cmd-option:`--annotate=html` +attaches to each line details about the coverage status of all the individual +instructions generated for the line. These are folded within the line and +expanded when a mouse click hits it. .. _ocov-insn: @@ -517,8 +503,8 @@ Inlining & Ada Generic units The generated code for an inlined subprogram call or a generic instantiation materializes two distinct source entities: the expanded source (of the inlined -subprogram or of the instanciated generic body) and the expansion request (the -subprogram call or the generic instanciation). While this is of no consequence +subprogram or of the instantiated generic body) and the expansion request (the +subprogram call or the generic instantiation). While this is of no consequence for :cmd-option:`=asm` outputs, which just report coverage of raw machine instructions within their object level subprograms, regardless of the object code origin, this raises a few points of note for in-source outputs. @@ -656,7 +642,7 @@ the corresponding source line in the :cmd-option:`=xcov` output (``!`` on line 12 +: end Count; 13 .: end Genpos; -And the :cmd-option:`=xcov+` (or :cmd-option:`=html+`) output gathers +And the :cmd-option:`=xcov+` (or :cmd-option:`=html`) output gathers everything together, with the blocks of instructions coming from different instances identifiable by the associated object symbol names:: diff --git a/doc/gnatcov/cov_rust.rst b/doc/gnatcov/cov_rust.rst new file mode 100644 index 000000000..7e3122461 --- /dev/null +++ b/doc/gnatcov/cov_rust.rst @@ -0,0 +1,130 @@ +.. _rust_cov: + +************************************ +Rust coverage analysis with |gcvcov| +************************************ + +Source coverage analysis for the Rust language is an unstable feature of +|gcv|. It relies on the internal coverage instrumentation of the rustc +compiler, which is itself leaning on the code coverage framework of the +LLVM project. + +.. note:: + This feature is made to be compatible with the **GNATPro For Rust** + tool suite, compatibility with other rust toolchains is not guaranteed. + +.. _rust_cov_workflow: + +Rust coverage workflow +====================== + +The workflow consists in 3 steps. First, build the program while instrumenting +it for coverage analysis. The instrumentation is delegated to ``rustc``. +Then, run the program, which produces trace files. Finally, use |gcvcov| to +generate a coverage report. + +An example project demonstrating Rust instrumentation can be found at +``share/examples/gnatcoverage/doc/rust_cov``. + +.. _rust_cov_workflow_1: + +Instrument and build the project +-------------------------------- + +Unlike source coverage analysis for Ada, C and C++ which rely on |gcv| to +instrument the source code *before* compiling it, the Rust workflow delegates +instrumentation to the ``rustc`` compiler. + +To instrument the code, pass the :cmd-option:`-Cinstrument-coverage` argument +to the compiler. If instrumenting for the ``stmt+decision`` or ``stmt+mcdc`` +coverage levels, pass the :cmd-option:`-Ccoverage-options=mcdc` additionally. + +Decision coverage as defined by |gcv| does not exist in the rust compiler, +thus |gcv| will infer the decision coverage from MC/DC coverage. + +The example showcases using the ``Cargo`` build system to instrument a project +for ``stmt+mcdc`` analysis analysis. + +:: + + RUSTFLAGS="-Cinstrument-coverage -Ccoverage-options=mcdc" cargo build + +.. _rust_cov_workflow_2: + +Run the executed binary +----------------------- + +Once again, the example showcases running the compiled program through +``Cargo``. At the end of execution, a trace file ending with ``.profraw`` is +created. + +The name of the file can be customized with the ``LLVM_PROFILE_FILE`` +environment variable. +See `LLVM_PROFILE_FILE format `_. + +:: + + LLVM_PROFILE_FILE="trace-%p.profraw" cargo run -- ARGS... + +The program may be run several times with different inputs to improve final +coverage. + +.. _rust_cov_workflow_3: + +Produce a coverage report +------------------------- + +To produce the coverage analysis from the obtained ``.profraw`` files, proceed +as follow: + +:: + + gnatcov coverage --level=stmt+mcdc -a xcov --exec EXEC_BIN PROFRAW_FILES... + +The important part is that the program binary needs to be passed with the +:cmd-option:`--exec` argument. In a ``Cargo`` project, the binary usually lives +under ``target/debug`` or ``target/release``. + +Note that aside of producing a report, the rust coverage report can be saved +as a :ref:`checkpoint` and reused for consolidation. + +.. _rust_cov_limitations: + +Rust coverage limitations +========================= + +This feature being relatively new, there are known limitations that we shall +mention hereafter. + +MC/DC false-negatives related to instrumentation level +-------------------------------------------------------- + +While the |gcvins| workflow controls and tracks the instrumentation level +of artifacts, making it possible to raise an error when trying to perform +MC/DC analysis on an artifact that was not instrumented for MC/DC, the Rust +workflow does not have such a safety feature yet. + +It means that if the project is instrumented without MC/DC support, and +the analysis is done with :cmd-option:`--level=stmt+mcdc`, no MC/DC violation +will be raised, even though there could have been some if the program had been +instrumented adequately. + +Approximative source location ranges +------------------------------------ + +Currently, you may witness that some SCOs have a source location range that +can overlap or merge with its neighbours. This is due to bugs in the +compiler's instrumentation logic and will be fixed in coming releases. + +Unsupported constructs +---------------------- + +Some constructs are not yet supported: + +- MC/DC instrumentation of pattern matching. Pattern matching can be viewed + as a decision with multiple conditions. However, it can lead to more than + just 2 outcomes. + +- Rust ``macros by example`` and procedural macros are not yet instrumented. + diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index d9861b79c..a4b65f084 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -7,13 +7,14 @@ Source coverage analysis with |gcvcov| .. _scov-principles: Source coverage analysis computes metrics focused on source programming -language entities such as high level *statements* or *decisions* (DO178 +language entities such as high level *statements* or *decisions* (|do| parlance for boolean expressions), which translate as :term:`Source Coverage Obligations `, or SCOs, in |gcp| terms. -Once you have produced source or binary traces, actual analysis is then -performed with |gcvcov| to generate coverage reports. *Source* coverage is -queried by passing a specific :cmd-option:`--level` argument to |gcvcov|. +Once you have produced coverage traces, actual analysis is performed +with |gcvcov| to generate coverage reports. *Source* coverage is +queried by passing a specific :cmd-option:`--level` argument to +|gcvcov|. The general structure of this command line is always like:: @@ -50,13 +51,13 @@ The available options are as follows: :cmd-option:`stmt+uc_mcdc`, all explained later in this chapter. :cmd-option:`-a`, :cmd-option:`--annotate` |marg|: - Request one or more output report formats. All the criteria support - ``xcov[+]``, ``html[+]``, ``dhtml`` and ``report`` formats, with + Request one or more output report formats. All the criteria support + ``cobertura``, ``html,``, ``report``, ``xcov[+]``, ``xml`` formats, with interpretations that vary depending on the assessed criteria. See the - corresponding documentation later in this chapter for more details. - This option accepts comma separated values and/or can be specified - mulitple times on the command line, in which case there will be one - report produced for each of the requested formats. + corresponding documentation later in this chapter for more details. This + option accepts comma separated values and/or can be specified multiple times + on the command line, in which case there will be one report produced for each + of the requested formats. :cmd-option:`-o` : Request that the synthetic report produced by ``--annotate=report`` be @@ -70,7 +71,7 @@ The available options are as follows: :cmd-option:`--non-coverable`: Report about language statements for which no object code could be found in - the surrounding suprogram (typically out of optimization). + the surrounding subprogram (typically out of optimization). :cmd-option:`-P`: Use the indicated project file as the root project to select the units of @@ -147,8 +148,8 @@ The available options are as follows: analysis from that initial state. :cmd-option:`--source-rebase`, |rarg|: - Specify alternate absolute path prefixes to locate missing source files - when producing annotated source outputs. See :ref:`rebase_opts` + Specify alternate absolute path prefixes to locate source files when + producing annotated source outputs. See :ref:`rebase_opts` :cmd-option:`--source-search`, |rarg|: Specify a directory in which missing source files will be searched when @@ -174,18 +175,18 @@ considered as trace file arguments. At least one trace file is required for the command lines to illustrate. Other examples will be exposed along the course of the following sections:: - gnatcov coverage --level=stmt --scos=@alis --annotate=report --trace=prog.trace - # (a) (b) (c) (d) + gnatcov coverage --level=stmt -P ut.gpr --annotate=report --trace=prog.srctrace + # (a) (b) (c) (d) # (a) Request Statement coverage assessment, - # (b) for units associated with the ALI files listed in the "alis" text file, + # (b) for units belonging to the "ut.gpr" project, # (c) producing a synthetic text report on standard output (no -o option), # (d) out of a single execution trace "prog.trace". - gnatcov coverage --level=stmt+decision --scos=@alis --annotate=html t1 t2 + gnatcov coverage --level=stmt+decision -P ut.gpr --annotate=html t1 t2 # Statement and Decision coverage assessments for two traces "t1" and "t2", - # producing html report files in the current directory. + # producing an html report in the current directory. - gnatcov coverage --level=stmt+decision --scos=@alis --annotate=html @mytraces + gnatcov coverage --level=stmt+decision -P ut.gpr --annotate=html @mytraces # Same report, with t1 and t2 listed in the "mytraces" text file gnatcov coverage --level=stmt -Papp.gpr --annotate=html @mytraces @@ -204,13 +205,15 @@ Output report formats (:cmd-option:`--annotate`) Source coverage reports may be produced in various formats, as requested with the :cmd-option:`--annotate` command line argument of |gcvcov|. The -:cmd-option:`xcov`, :cmd-option:`html` and :cmd-option:`dhtml` formats produce -a set of annotated source files, in the directory where |gcv| is launched -unless overriden with a :cmd-option:`--output-dir` option. The -:cmd-option:`report` output consists in a synthetic text report of -:term:`coverage violations ` with respect to the requested -criteria, produced on standard output by default or in the file specified by -the :cmd-option:`-o` command line option. +:cmd-option:`xcov` and :cmd-option:`html` formats produce a set of annotated +source files, in the directory where |gcv| is launched unless overriden with a +:cmd-option:`--output-dir` option. The :cmd-option:`report` output consists in a +synthetic text report of :term:`coverage violations ` with +respect to the requested criteria, produced on standard output by default or in +the file specified by the :cmd-option:`-o` command line option. The +:cmd-option:`cobertura` produce a single xml file containing a coverage report +in the Cobertura format. Its name is by default `cobertura.xml` and can be +altered using the :cmd-option:`-o` command line option. Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate` on the command line. For example, we use "the @@ -218,7 +221,7 @@ Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate=report`". We will illustrate the various formats with samples extracted from outputs -obtained by perfoming coverage analysis of the following example Ada +obtained by performing coverage analysis of the following example Ada application unit: .. code-block:: ada @@ -236,115 +239,86 @@ application unit: end Between; -Annotated sources, text (:cmd-option:`=xcov[+]`) ------------------------------------------------- +Cobertura report (:cmd-option:`=cobertura`) +------------------------------------------- -For source coverage criteria, |gcvcov| :cmd-option:`--annotate=xcov` produces -an annotated version of each source file, in text format, named after the -original source with an extra ``.xcov`` extension at the end (``x.ext.xcov`` -for a source named ``x.ext``). +:cmd-option:`--annotate=cobertura` produces a coverage report in the Cobertura +format, as specified per the cobertura.dtd (document type description) that is +generated alongside. -Each annotated source contains a global summary of the assessment results -followed by the original source lines, all numbered and marked with a coverage -annotation next to the line number. The annotation on a line always consists -in a single character, which may be one of the following: +This format specification is not maintained by gnatcov, and it does not thus +provide all of the information that other report formats do, notably MC/DC +coverage information, violation messages. Decision violations are output using +the "branch" terminology of Cobertura (one decision being two branches, and +either 0, 1 or 2 of those branches are covered). -.. tabularcolumns:: cl -.. csv-table:: - :delim: | - :widths: 10, 80 - :header: Annotation, Meaning +It is mainly provided for integration with external tools, such as continuous +integration systems, e.g. gitlab, which supports integration of coverage reports +into merge requests using this format. - ``.`` | No coverage obligation is attached to the line - ``-`` | Coverage obligations attached to the line, none satisfied - ``!`` | Coverage obligations attached to the line, some satisfied - ``+`` | Coverage obligations attached to the line, all satisfied +File names in this coverage report are absolute. Depending on the use context of +this coverage report, it can also make sense to strip a given prefix from the +absolute paths to make them relative to, e.g. a project root. The +:cmd-option:`--source-root` command line option accepts a string prefix that +will be removed from absolute path references in the report. -Here is, to illustrate, the full statement coverage report produced for our -example unit when the ``Between`` function was called so that the ``if`` -control evaluated True only. The function is actually part of an Ada package, -called Ranges, with an original body source file named ``ranges.adb``: -.. code-block:: +Annotated sources, html (:cmd-option:`=html`) +--------------------------------------------- - examples/src/ranges.adb: - 67% of 3 lines covered - Coverage level: stmt - 1 .: package body Ranges is - 2 .: function Between (X1, X2, V : Integer) return Boolean is - 3 .: begin - 4 +: if X1 < X2 then - 5 +: return V >= X1 and then V <= X2; - 6 .: else - 7 -: return V >= X2 and then V <= X1; - 8 .: end if; - 9 .: end; - 10 .: end; +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces an +index-based report under the HTML format (the other command names are aliases +for backward compatibility). -:cmd-option:`--annotate=xcov+` (with a trailing +) works the same, only -providing extra details below lines with improperly satisfied obligations. The -available details consists in the list of :term:`coverage violations ` diagnosed for the line, which depends on the coverage criteria -involved. Here is an excerpt for our previous example, where the only -improperly satisfied obligation is an uncovered statement on line 7:: +To navigate the report, open the index.html file using the browser of your +choice. This index file contains a summary of the assessment context (assessed +criteria, trace files involved, ...) and of the coverage results for all the +units, with links to their annotated sources. If the :cmd-option:`-P` was used +to designate the source units of interest, sources are indexed per-project. - 7 -: return V >= X2 and then V <= X1; - STATEMENT "return V ..." at 7:10 not executed +Note that some dynamic filtering / sorting can be applied: -Annotated sources, html (:cmd-option:`=html[+]`) ------------------------------------------------- +* Filter by kind of coverage obligations: either reporting on lines, or on + statement / decision / MCDC (one or several) obligations, depending on the + coverage level. See :ref:`synthetic-metrics` for more information. + +* Sort indexes by clicking on column headers, allowing for example sorts keyed + on unit names or on relative coverage achievement. -For source coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces -an annotated version of each source file, in html format, named after the -original source with an extra ``.html`` extension at the end. Each annotated -source page contains a summary of the assessment results followed by the -original source lines, all numbered and marked with a coverage annotation as in -the :cmd-option:`--annotate=xcov` case. Lines with obligations are colorized in -green, orange or red for ``+``, ``!`` or ``-`` coverage respectively. - -An `index.html` page is also produced, which contains a summary of the -assessment context (assessed criteria, trace files involved, ...) and of the -coverage results for all the units, with links to their annotated sources. See our :ref:`sample html index ` appendix for an example index page, which embeds a self-description of all the items it -contains. See the :ref:`sample annotated source ` -appendix for a sample of html annotated source. - -The page style is governed by a set of Cascading Style Sheet (CSS) parameters, -fetched from a ``xcov.css`` file in the directory where |gcv| is launched. If -this file is available when |gcv| starts, |gcv| uses it so users may setup a -customized version if needed. If the file is not available, |gcv| creates a -default one. +contains. -Similarily to the :cmd-option:`xcov` format case, -:cmd-option:`--annotate=html+` (with a trailing +) adds details about -improperly satisfied obligations. In the html version, these extra details are -initially folded within their associated line and expanded by a mouse click on -the line. +The user can browse through an annotated version of the sources from the index. +Each annotated source page contains a summary of the assessment results. This +summary can be expanded to print subprogram metrics: the user can click on a +subprogram's metrics to access it in the annotated source immediately. This +summary is followed by the original source lines, all numbered and marked with a +coverage annotation as in the :cmd-option:`--annotate=xcov` case. Lines with +obligations are colorized in green, orange or red for ``+``, ``!`` or ``-`` +coverage respectively. -Annotated sources, dynamic html (:cmd-option:`=dhtml`) ------------------------------------------------------- +See the :ref:`sample annotated source ` appendix for a +sample of html annotated source. -:cmd-option:`--annotate=dhtml` produces a *dynamic html* output, which -essentially features: -* A more modern look & feel compared to the :cmd-option:`html` formats - described earlier, +SARIF report (:cmd-option:`=sarif`) +----------------------------------- -* The ability to sort indexes by clicking on column headers, allowing for - example sorts keyed on unit names or on relative coverage achievement, +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=sarif` produces +a JSON-based report under the Static Analysis Results Interchange Format +(SARIF). -* Per-project indexes on the root page when :cmd-option:`-P` was used to - designate the source units of interest. - -The option produces a set of `.js` javascript files implementing most of the -report displays and interactions, as well as an `index.html` root page which -users should open as an entry point to the report contents. - -The per-line details that differentiates :cmd-option:`html+` from -:cmd-option:`html` are always produced, initially folded and available on line -clicks as well. +The generation of SARIF reports is mainly provided to allow viewing gnatcov +coverage reports with external IDEs that supports viewing them (for example, +Visual Studio Code with Microsoft's SARIF Viewer extension). To navigate this +report, open the ``coverage.sarif`` file using an integrated development +environment which supports viewing SARIF results. +The reports contain information on the violations observed by gnatcov as +"Results" and the enabled coverage levels as "Rules". Each violation is +registered as "error". Exempted violations are reported as "note" and +undetermined coverage results as "warning". Violations summary, text (:cmd-option:`=report`) ------------------------------------------------ @@ -356,9 +330,13 @@ assessed criteria. The report features explicit start/end of report notifications and at least three sections in between: Assessment Context, Coverage Violations, and -Analysis Summary. A few variations are introduced when :term:`exemption -regions ` are in scope. See the :ref:`exemptions` section -for more details on their use and effect on the output reports. +Analysis Summary. Should |gcv| be unable to determine the coverage state of +some coverage obligations, those will be reported in a dedicated Undetermined +Coverage Items section, with a description of why the tool was unable to +determine the coverage state for each obligation. A few variations are +introduced when :term:`exemption regions ` are in scope. +See the :ref:`exemptions` section for more details on their use and effect on +the output reports. If :cmd-option:`--dump-units-to -` is also on the command line, a *UNITS OF INTEREST* section is produced, which contains the list of units considered @@ -366,7 +344,6 @@ of-interest for the reported assessment, as well as the list of source files individually ignored with the ``Ignored_Source_Files`` project attribute and corresponding command-line option. - Assessment Context ^^^^^^^^^^^^^^^^^^ @@ -382,9 +359,9 @@ items: * Coverage level requested to be analyzed -* Details on the input trace files: path to binary program exercised (as - recorded in the trace header), production time stamp and tag string - (:cmd-option:`--tag` command line argument value). +* Details on the input trace files, such as the path to the binary + program exercised (as recorded in the trace header) or the trace + production time stamp. Here is a example excerpt:: @@ -510,6 +487,77 @@ level is fully satisfied, with details available from the per criterion sections that precede. +Annotated sources, text (:cmd-option:`=xcov[+]`) +------------------------------------------------ + +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=xcov` produces +an annotated version of each source file, in text format, named after the +original source with an extra ``.xcov`` extension at the end (``x.ext.xcov`` +for a source named ``x.ext``). + +Each annotated source contains a global summary of the assessment results +followed by the original source lines, all numbered and marked with a coverage +annotation next to the line number. The annotation on a line always consists +in a single character, which may be one of the following: + +.. tabularcolumns:: cl +.. csv-table:: + :delim: | + :widths: 10, 80 + :header: Annotation, Meaning + + ``.`` | No coverage obligation is attached to the line + ``-`` | Coverage obligations attached to the line, none satisfied + ``!`` | Coverage obligations attached to the line, some satisfied + ``?`` | Coverage obligations attached to the line, undetermined coverage state (*) + ``+`` | Coverage obligations attached to the line, all satisfied + +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + +Here is, to illustrate, the full statement coverage report produced for our +example unit when the ``Between`` function was called so that the ``if`` +control evaluated True only. The function is actually part of an Ada package, +called Ranges, with an original body source file named ``ranges.adb``: + +.. code-block:: + + examples/src/ranges.adb: + 67% of 3 lines covered + Coverage level: stmt + 1 .: package body Ranges is + 2 .: function Between (X1, X2, V : Integer) return Boolean is + 3 .: begin + 4 +: if X1 < X2 then + 5 +: return V >= X1 and then V <= X2; + 6 .: else + 7 -: return V >= X2 and then V <= X1; + 8 .: end if; + 9 .: end; + 10 .: end; + +:cmd-option:`--annotate=xcov+` (with a trailing +) works the same, only +providing extra details below lines with improperly satisfied obligations. The +available details consists in the list of :term:`coverage violations ` diagnosed for the line, which depends on the coverage criteria +involved. Here is an excerpt for our previous example, where the only +improperly satisfied obligation is an uncovered statement on line 7:: + + 7 -: return V >= X2 and then V <= X1; + STATEMENT "return V ..." at 7:10 not executed + + +XML report, xml (:cmd-option:`=xml`) +------------------------------------ + +:cmd-option:`--annotate=xml` produces a coverage report in the XML format, as +specified per the ``gnatcov-xml-report.xsd`` (XML schema description) that is +generated alongside. + +This report format is on par with the HTML report in terms of features, and it +is the preferred choice for programmatically accessing the coverage results. + + .. _scov-stmt: Statement Coverage analysis @@ -551,8 +599,12 @@ indications: ``-`` | At least one statement on the line, none covered ``!`` | More than one statement on the line, some covered + ``?`` | At least one statement on this line, some with undetermined coverage state (*) ``+`` | At least one statement on the line, all covered +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + When a single statement spans multiple lines, the coverage annotation is present on all the lines, as the two ``+`` signs for the single assignment in the following excerpt:: @@ -617,10 +669,11 @@ driver ` in ``test_div1.adb``: Assert (Div_With_Check (X, 1) = X); end; -From a ``test_div1.trace`` obtained with |gcvrun|, we analyze for the -Statement Coverage criterion using the following |gcvcov| invocation:: +From a ``test_div1.srctrace`` obtained by building the instrumented source +produced with |gcvins|, we analyze for the Statement Coverage criterion using +the following |gcvcov| invocation:: - gnatcov coverage --level=stmt --scos=div_with_check.ali --annotate=xcov test_div1.trace + gnatcov coverage --level=stmt -P ut.gpr --annotate=xcov test_div1.srctrace We get an :cmd-option:`=xcov` annotated source result in text format for the functional unit on which the analysis is focused, in @@ -645,7 +698,7 @@ We can observe that: - The inner ``raise`` and ``return`` statements are marked uncovered and covered respectively, as expected since the function was only called with - arguments for which the ``if`` controling decision evaluates False. + arguments for which the ``if`` controlling decision evaluates False. As a second experiment, we exercise the function for Y = 0 only, using: @@ -753,6 +806,10 @@ performs Statement and Decision Coverage assessments combined together. * The iteration predicate of Ada quantified expressions, in the same contexts as for if-expressions. +* The iterator filter predicate optionally present in a loop parameter + specification or in an iterator specification, in the same context as + if-expressions. + The expression may be of essentially any type in C. In Ada, this may be the standard Boolean type, or subtypes of it, or derived types thereof. Here are a few examples show-casing decisions in a variety of @@ -769,6 +826,9 @@ contexts:: Z := (for all X of Container => P(X)); -- "P(X)", quantified-expression predicate T := (for some X of Container => P(X)); + for I in 1 .. 10 when (I mod 2) = 0 loop ... -- "(I mod 2) = 0", iterator filter predicate + F := (for Elt of Container when Pred (Elt) => Elt); -- "Pred (Elt)", iterator filter predicate + The coverage status of a decision obligation is determined as follows: @@ -807,12 +867,16 @@ following table summarizes the meaning of the possible annotations: ``-`` | At least one statement on the line, none executed. ``!`` | Unless multiple statements are involved, decision partially covered on the line. + ``?`` | At least one statement or decision on the line with undetermined coverage state. (*) ``+`` | All the statements and decisions on the line are covered. +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. When a trailing `+` is added to the format passed to :cmd-option:`--annotate` -(:cmd-option:`=xcov+` or :cmd-option:`=html+`), a precise description of the -actual violations is available for each line in addition to the annotation. +(:cmd-option:`=xcov+`), a precise description of the actual violations is +available for each line in addition to the annotation. The :cmd-option:`=html` +provides it by default. Example program and assessments ------------------------------- @@ -987,8 +1051,8 @@ commands. :dfn:`Decisions` in this context are defined as: Then for all the decisions in the sources of interest: * Testing shall exercise both the True and False outcomes of the expression as - a whole and demonstrate the :dfn:`independant influence` of :dfn:`conditions` - in DO-178 parlance, where ... + a whole and demonstrate the :dfn:`independent influence` of :dfn:`conditions` + in |do| parlance, where ... * Separate conditions in a decision are identified as the operands of *short-circuit* operators. @@ -996,7 +1060,7 @@ Then for all the decisions in the sources of interest: Regarding coverage status definitions: * A condition is :dfn:`covered`, and the obligation discharged, when - the independant effect on the enclosing decision was demonstrated by + the independent effect on the enclosing decision was demonstrated by the tests, * A condition is said :dfn:`uncovered` otherwise. @@ -1005,7 +1069,7 @@ The :ref:`mcdc-decisions` section that follows provides a few examples to illustrate the identification of decisions and conditions. :ref:`non-short-circuit` focuses on the handling of computational Boolean operators, then :ref:`mcdc-variants` expands on the notion of -:dfn:`independant influence` and on possible variations of the MCDC criterion +:dfn:`independent influence` and on possible variations of the MCDC criterion definition. Output-wise, the source annotations for the :cmd-option:`=xcov` or @@ -1020,12 +1084,16 @@ condition specific cases marked with a ``!`` as well: ``-`` | At least one statement associated with this line, none executed. ``!`` | For a single statement line, decision partially covered or condition not covered on the line. + ``?`` | At least one statment or decision on the line with undetermined coverage state. (*) ``+`` | All the statements, decisions and conditions on the line are covered. +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + The :cmd-option:`=report` outputs feature an extra MCDC section in the Coverage Violations segment, which holds: -- The condition specific diagnosics (``independent influence not +- The condition specific diagnostics (``independent influence not demonstrated``), as well as - Decision level diagnostics (such as ``decision outcome True not covered`` @@ -1178,7 +1246,7 @@ Compared to Decision Coverage, achieving MCDC requires tests that demonstrate the independent influence of conditions in decisions. Several variants of the criterion exist. -:dfn:`Unique Cause MCDC` is the original criterion described in the DO178B +:dfn:`Unique Cause MCDC` is the original criterion described in the |do| reference guidelines, where independent influence of a specific condition must be demonstrated by a pair of tests where only that condition changes and the decision value toggles. @@ -1200,7 +1268,7 @@ short-circuited: Each line in such a table is called an :term:`evaluation vector `, and the pairs that demonstrate the independant effect of conditions +Vector>`, and the pairs that demonstrate the independent effect of conditions are known as :term:`independence pairs `. Evaluations 1 + 3 constitute a Unique Cause independence pair for A, where A @@ -1261,16 +1329,11 @@ single case where X1 < V < X2: Assert (Between (X1 => 2, X2 => 5, V => 3)); -- X1 < V < X2 end Test_X1VX2; -Performing MCDC analysis with binary traces requires telling the execution step -about it, by providing both the :cmd-option:`--level` and a list of units for -which analysis is to be performed to |gcvrun|:: - - gnatcov run --level=stmt+mcdc -Pmytest.gpr test_x1vx2 - -We can then request, say, an :cmd-option:`=xcov+` report to get a first set of -results in the ``ranges.adb.xcov`` annotated source:: +After instrumentation for MCDC and execution, we can then request, +say, an :cmd-option:`=xcov+` report to get a first set of results in +the ``ranges.adb.xcov`` annotated source:: - gnatcov coverage --level=stmt+mcdc -Pmytest.gpr --annotate=xcov+ test_x1vx2.trace + gnatcov coverage --level=stmt+mcdc -Pmytest.gpr --annotate=xcov+ test_x1vx2.srctrace ... 8 .: function Between (X1, X2, V : Integer) return Boolean is @@ -1370,6 +1433,218 @@ condition expressions are such that running vector 4 is not possible, however, since we can't have V both < X1 (condition 1 False) and V > X2 (condition 2 False) at the same time when X1 < X2. +.. _scov-atc: + +Assertion True Coverage (ATC) analysis (experimental) +===================================================== + +Along with the previous coverage levels, |gcv| can provide different strictness +levels of assertion coverage for source traces for Ada. + +Assertion coverage warrants defining separate criteria to perform coverage +analysis since contrary to all other regular decisions, those contained in +assertions are expected to never be evaluated to False. Assertion decisions and +conditions are defined the same way as for Decision and MCDC but, the coverage +is computed differently. + +If such coverage analysis is needed, it should always be activated along one of +the previously described coverage levels, as an "addition". In the following +sections on assertion coverage, their associated command line options will be +written as `--level=...+` where `...` is one of +`stmt`, `stmt+decision`, `stmt+mcdc` and `stmt+uc_mcdc`. + +Using assertion coverage levels allows to compute the coverage of the pragma +statements `Assert`, `Assert_And_Cut`, `Assume`, `Check`, `Loop_Invariant`, and +the aspects `Type_Invariant`, `Precondition` and `Postcondition`. + +Core notions and Reporting (:cmd-option:`--level=...+atc`) +---------------------------------------------------------- + +|gcv| performs Assertion True Coverage assessments with the +:cmd-option:`--level=...+atc` command line option. The assessment determines +the status of assertion true coverage obligations out of the tests execution, +considering that: + +* An assertion is :dfn:`covered`, and the obligation :dfn:`discharged`, + as soon as the assertion's decision has been evaluated once to True. + +* An assertion is :dfn:`uncovered` otherwise. + +In synthetic :cmd-option:`=report` outputs, uncovered source assertions are +listed as ATC Coverage violations in the report section dedicated to these. + +In annotated source outputs, the coverage annotations convey the following +indications: + +.. tabularcolumns:: cl +.. csv-table:: + :delim: | + :widths: 10, 80 + :header: Annotation, Meaning + + ``-`` | At least one assertion on the line, none covered + ``!`` | More than one assertion on the line, some covered + ``?`` | At least one assertion on this line, some with undetermined coverage state (*) + ``+`` | At least one assertion on the line, all covered + +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + +.. _scov-atcc: + +Assertion True Condition Coverage (ATCC) analysis (experimental) +================================================================ + +Core notions and Reporting (:cmd-option:`--level=...+atcc`) +----------------------------------------------------------- + +The coverage status of an "ATCC" obligation is determined as follows: + +* An assertion is said :dfn:`fully covered`, or just :dfn:`covered`, and the + obligation discharged, as soon as all conditions have been evaluated to True + or False at least once accross all evaluations to True of the whole decision. + +* An assertion is said :dfn:`uncovered` when the decision was never + evaluated to True, either because the enclosing assertion statement was not + executed at all or when all the attempted evaluations were interrupted e.g. + because of exceptions. + +* An assertion is said :dfn:`partially covered` when at least one of the + conditions of the assertion's decision was never evaluated to either True or + False in the context of an evaluation to True of the whole decision. In this + case, the obligation is partially discharged. + +The :cmd-option:`=report` synthetic output lists the ATC and ATCC coverage +violations in the ``ATC`` and ``ATCC`` coverage report section respectively. +For the :cmd-option:`=xcov` and :cmd-option:`=html` annotated-source oriented +formats, the single annotation produced on each source line combines the +statement and ATC coverage indications. The following table summarizes the +meaning of the possible annotations: + +.. tabularcolumns:: cl +.. csv-table:: + :delim: | + :widths: 10, 80 + :header: Annotation, Meaning + + ``-`` | At least one statement on the line, none executed. + ``!`` | Unless multiple statements are involved, assertion partially covered on the line. + ``?`` | At least one statement or assertion on the line with undetermined coverage state. (*) + ``+`` | All the statements and assertions on the line are covered. + +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + +When a trailing `+` is added to the format passed to :cmd-option:`--annotate` +(:cmd-option:`=xcov+`), a precise description of the actual violations is +available for each line in addition to the annotation. The :cmd-option:`=html` +provides it by default. + +.. _scov-fun_call: + +Function and Call Coverage (FUN_CALL) analysis (experimental) +============================================================= + +|gcv| can also provide an analysis of the coverage of subprograms and calls for +Ada, C, and C++ source traces. + +If such coverage analysis is needed, it should always be activated along one of +the non-assertion coverage levels previously described. In this section on +function and call coverage, the associated command line option will be written +as `--level=...+fun_call` where `...` is one of `stmt`, `stmt+decision`, +`stmt+mcdc` and `stmt+uc_mcdc`. Assertion coverage can also be activated at the +same time. + +Core notions and Reporting (:cmd-option:`--level=...+fun_call`) +--------------------------------------------------------------- + +|gcv| performs Function and Call Coverage assessments with the +:cmd-option:`--level=...+fun_call` command line option. The assessment +determines the status of subprograms and call coverage obligations out of the +tests execution, considering that: + +* A subprogram is :dfn:`covered`, and the obligation :dfn:`discharged`, + as soon as the execution as entered it at least once. + +* A subprogram is :dfn:`uncovered` otherwise. + +* A call is :dfn:`covered`, and the obligation :dfn:`discharged`, if it has + been executed at least once. + +* A call is :dfn:`uncovered` otherwise. + +In synthetic :cmd-option:`=report` outputs, uncovered source subprograms and +calls are listed as FUN_CALL Coverage violations in the dedicated report +section. + +It is important to note that for an :dfn:`uncovered` statement which happens +to be a call statement, only a statement violation will be emitted in +coverage reports. + +The limitations of this coverage level are detailed in the +:ref:`instr-limitations` section. + +.. _scov-gexpr: + +Guarded Expression Coverage (GEXPR) analysis (experimental) +============================================================ + +For the Ada language, |gcv| can provide an analysis on coverage of guarded +expressions. + +Core notions and Reporting (:cmd-option:`--level=...+gexpr`) +------------------------------------------------------------ + +|gcv| the following syntaxes to be :dfn:`guarded expressions`: + +* Then and Else dependent expressions of :dfn:`if expressions` + +.. code-block:: ada + + procedure Foo (A : Boolean) is + Var : constant String := + (if A + then "True expression" + else "False expression"); + begin + null; + end Foo; + +* Dependent expressions of :dfn:`case expressions` + +.. code-block:: ada + + type Animal is (Cat, Dog, Cow); + + procedure Foo (A : Animal) is + Var : constant String := + (case A + when Cat => "Expression Cat", + when Dog => "Expression Dog", + when others => "Expression other"); + begin + null; + end Foo; + +* Predicate expression of :dfn:`quantified expressions` + +.. code-block:: ada + + function Prime_In_Range (L, R : Natural) return Boolean is + begin + + -- Is_Prime (I) is the child expression that will be analysized. + + return (for some I in (L .. R) => Is_Prime (I)); + end Foo; + +For each of these, we consider the expression to be :dfn:`covered` and the +obligation to be :dfn:`discharged` if the execution flow evaluated it at least +once. + +The limitations of this coverage level are detailed in the +:ref:`instr-limitations` section. + .. _synthetic-metrics: Synthetic metrics @@ -1429,14 +1704,14 @@ kind involved in the assessed level (here, for total number of obligations of the given kind and the ratio of such obligations which have been fully discharged. The ``xcov`` obligation metrics don't distinguish partially covered from uncovered items. This -information is available from the ``dhtml`` reports. +information is available from the ``html`` report. -For the ``dhtml`` output, synthetic metrics for all the units are +For the ``html`` output, synthetic metrics for all the units are first displayed on the index page, together with metrics for the entire analysis and for sets of units grouped by GPR project. Initially, the line count based metrics are displayed, as illustrated -by :numref:`dhtml-index-lines`. The main procedure source used in our ``xcov`` +by :numref:`html-index-lines`. The main procedure source used in our ``xcov`` report example is the ``main.adb`` source here, single source encompassed by the ``main.gpr`` project: @@ -1446,25 +1721,25 @@ names ("Stmt", "Decision" or "Mcdc"). Each kind of obligation can be selected alone. Selecting multiple kinds is also allowed and just sums the individual counts. -:numref:`dhtml-index-obligations` illustrates the results we get with +:numref:`html-index-obligations` illustrates the results we get with the ``Stmt`` and ``Decision`` kinds selected together for our previous example: -.. _dhtml-index-lines: +.. _html-index-lines: -.. figure:: dhtml-index-lines.* +.. figure:: html-index-lines.* :scale: 42% :align: center - Dhtml index with line count based synthetic metrics + Html index with line count based synthetic metrics -.. _dhtml-index-obligations: +.. _html-index-obligations: -.. figure:: dhtml-index-obligations.* +.. figure:: html-index-obligations.* :scale: 42% :align: center - Dhtml index with obligations count based synthetic metrics (stmt+decision) + Html index with obligations count based synthetic metrics (stmt+decision) .. _rebase_opts: @@ -1473,25 +1748,20 @@ Handling source relocation for annotated sources output formats =============================================================== For all annotated sources output formats -(:cmd-option:`--annotate=xcov[+]|html[+]|dhtml)`, |gcv| needs access to the -sources of the :term:`units of interest ` to generate the -output. By default, the sources will be searched in the location where they -were compiled, for binary traces, or where they were instrumented for source -traces. This is generally going to be the case if the whole coverage analysis -process is done on the same machine, but in some cases it may be preferable to -generate the coverage report on a different machine than the one where the -coverage run was done, or the sources may have been moved. - -For instance, a project with a large number of unit tests may be run on -multiple machines in parallel to speed up the test runs, and then a single -report will be generated from all the traces/checkpoints. In such case, |gcv| -will not be able to automatically find the source files. |gcv| offers two -options to help in those situations: +(:cmd-option:`--annotate=xcov[+]|html)`, |gcv| needs access to the sources of +the :term:`units of interest ` to generate the output. The +tool searches for sources in some default locations which are usually correct +when the whole coverage analysis process is done on the same machine. + +When coverage reports are produced on a different machine than the one +where the coverage run was done, or when sources are moved in the +interim, |gcv| will likely not be able to automatically find the +source files. The tool offers two options to help in those situations: * The option :cmd-option:`--source-rebase=\=\` This option allows the specification of alternate path prefixes for source - files that were not found in there build_1234/instrumentation location. + files. If the location of a source file, when built on a first machine, was ``/work/build_1234/src/main.adb`` but on the machine where the report is to @@ -1519,18 +1789,17 @@ options to help in those situations: This option allows the specification of directories in which to search for missing source files. - If the location of a source file, when built on a first machine, was - ``/work/build_1234/src/main.adb`` but its location on the machine where the - report is generated is ``/some/path/project/src/main.adb`` then passing + If the location of a source file, when built on a first machine, + was ``/work/build_1234/src/main.adb`` but its location on the machine where + the report is generated is ``/some/path/project/src/main.adb`` then passing :cmd-option:`--source-search=/some/path/project/src` will enable |gcv| to find the missing source file. This option also accepts response files. - This option can appear multiple times on the command line, and when trying to - locate a missing source file, |gcv| will first try the - :cmd-option:`--source-rebase` prefix pairs, if any, and if the source file - was not found, it will then look for the file in all the directories passed - with :cmd-option:`--source-search` in the order in which they appear on the - command line. + This option can appear multiple times on the command line. Note that |gcv| + will first try the :cmd-option:`--source-rebase` prefix pairs, if any, and + if the source file was not found, it will then look for the file in all + the directories passed with :cmd-option:`--source-search` in the order in + which they appear on the command line. These two options perform very similar functions and can sometimes be used interchangeably, however the second option is less selective and can lead to @@ -1577,12 +1846,14 @@ where the generic source is considered as the entity of interest, to which all the instances contribute, and one where each instance is considered as a separate entity of interest. -Combined coverage on generics (default behavior) ------------------------------------------------- +.. _generics_cov: + +Combined coverage on generics +----------------------------- -By default, Ada generic units are also uniformly treated as single source -entities, with the coverage achieved by all the instances combined and -reported against the generic source only, not for each individual instance. +Ada generic units are also uniformly treated as single source entities, with +the coverage achieved by all the instances combined and reported against the +generic source only, not for each individual instance. Consider the following functional Ada generic unit for example. It provides a simple vector type abstraction on which two operations are available; ``Inc`` @@ -1664,100 +1935,6 @@ fully covered by default:: 15 .: end; 16 .: end; -Per instance analysis is possible though, as part of what we refer to as -:dfn:`separated coverage` facilities. - -Separated coverage on generics ------------------------------- - -As described above, a single coverage analysis of any source construct is -performed by default, consolidating all code copies generated by this -construct. For subprograms, this means consolidation over all inlined -copies. For generic units, consolidation over all instances. - -A finer-grained analysis is possible, where distinct copies of the code coming -from a given source construct are identified according to some criterion, and -a separate coverage assessment is made for each of these copies. - -In this case, coverage violations carry an additional indication of which code -copy the violation is reported for, available in all but the non-extended -``xcov`` and ``html`` output formats. The non-extended ``xcov`` and ``html`` -formats simply convey partial coverage achievement on a line as soon one -violation get reported for an obligation on that line, regardless of which -copy the violation originates from. - -|gcv| supports different modes for such analyses, detailed in the following -subsections. - - -Separation by instance (:cmd-option:`-S instance`) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this mode, two code regions coming from the same source construct will -undergo separate coverage analyses if they come from different generic -instances, identified by the instanciation source location. - -For our ``Vops`` example, selecting an output format where the -violations detailed are exposed, this translates as:: - - gnatcov coverage -Pvops.gpr --annotate=report -S instance [...] - ... - vops.adb:5:11: statement not executed (from v8.ads:2:1) - vops.adb:6:10: statement not executed (from v8.ads:2:1) - vops.adb:12:11: statement not executed (from v5.ads:2:1) - vops.adb:13:10: statement not executed (from v5.ads:2:1) - - -We do observe violations on the ``Vops`` generic body, fully covered without -:cmd-option:`-S instance`. This is the outcome of an analysis conducted on the -two generic instances separately, each designated by a ``(from )`` indication. - -|gcv| needs to see the coverage obligations correponding to each instance in -this mode. This is achieved transparently by the use of a project file in the -example command lines we quoted and needs particular care when the Library -Information files are provided manually with :cmd-option:`--scos` instead. - -Indeed, even if we aim at getting coverage results for the ``vops.adb`` source, -passing :cmd-option:`--scos=vops.ali` alone isn't enough when per instance -separate analysis is desired. Separate coverage analysis for the instances -entails coverage obligations for the instances, and this requires the units -where the instantiations occur to be declared of interest as well. In our -example, this means passing :cmd-option:`--scos=v5.ali` and -:cmd-option:`--scos=v8.ali` in addition. - -Separation by instance relies on specific compiler support available in the -GNAT Pro toolchain since the 7.2 release. For older toolchains, another mode -is available which reports separate coverage statuses for copies associated -with distinct symbols of the executable file. As we will describe, this -provides a good approximation of per-instance analysis in absence of inlining, -and becomes inaccurate when inlining comes into play. - -Separation by routine (:cmd-option:`-S routine`, *obsolete*) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this mode, two code regions coming from the same source construct will -undergo separate coverage analyses if they occur in different symbols of the -executable file. This scheme is obsolete, unreliable in presence of inlining. - -When a given subprogram is inlined in two different calling routines, each -inlined copy thus undergoes a separate coverage assessment. In the absence of -inlining, this will also ensure that different instances of the same generic -unit will have separated coverage analyses, since the compiler generates -different symbol names for different program units. For our ``Vops`` example, -this would be:: - - gnatcov coverage -Pvops.gpr --annotate=report -S routine [...] - ... - vops.adb:5:11: statement not executed (from v8__inc) - vops.adb:6:10: statement not executed (from v8__inc) - vops.adb:12:11: statement not executed (from v5__mult) - vops.adb:13:10: statement not executed (from v5__mult) - - -On the other hand, if two distinct instances of a generic subprogram are -inlined within a single calling routine, they will undergo a single coverage -analysis since they now occur in the same symbol. Handling Ada assertions and contracts ===================================== diff --git a/doc/gnatcov/disable_cov.rst b/doc/gnatcov/disable_cov.rst new file mode 100644 index 000000000..37a5941bd --- /dev/null +++ b/doc/gnatcov/disable_cov.rst @@ -0,0 +1,133 @@ +.. _disable_cov: + +************************* +Disable coverage analysis +************************* + +It is possible to fully disable coverage analysis over a specific region. In +contrast to exemption regions, gnatcov skips over disabled coverage region and +treats them similarly as a no code region, e.g. with no source coverage +obligations. + +Such a mechanism can typically be used to disable coverage for a code region +that may or may not expand according to the build configuration at use. + +This mechanism only works when using source traces. + +Defining Disabled Coverage Regions +================================== + +:dfn:`Disabled Coverage Regions` are lexical sections of sources in which +coverage analysis is fully disabled. + +For Ada with the |gnat| compilers, regions are defined by the insertion of +dedicated pragmas in the sources: + +- ``pragma Annotate (Xcov, Cov_Off, "justification text");`` starts a region, + providing some justification text that will be recalled in coverage reports. + +- ``pragma Annotate (Xcov, Cov_On);`` closes the current disabled coverage + region. + +There may be no overlap between disabled coverage regions. + +To illustrate, let us consider a common assertion control procedure in Ada: + +.. code-block:: ada + + procedure Eassert (T : Boolean) is + begin + pragma Annotate (Xcov, Cov_Off, "my justification"); + if not T then + raise Program_Error; + end if; + pragma Annotate (Xcov, Cov_On); + end Eassert; + +For C code, disabled coverage regions are defined using comment markers to +delimit the region + +- Any comment containing the string ``GNATCOV_COV_OFF`` followed by a string in + double quotes starts a region, the string within the double quotes being used + as justification text that will be recalled in coverage reports. + +- Any comment containing the string ``GNATCOV_COV_ON`` closes the current + region. + +The following assert function illustrates the definition of a disabled coverage +region: + +.. code-block:: C + + void + assert (bool x){ + // GNATCOV_COV_OFF "my justification" + if (!x) + abort(); + // GNATCOV_COV_ON + } + +It is also possible to define disabled coverage regions from external annotation +files, see :ref:`ext_annot` for more information. + +Consolidating traces with varying disabled coverage regions +=========================================================== + +As stated, there can be a varying set of disabled coverage regions according +to the build configuration and when considering C/C++ preprocessing. If you +lie in that case, read thoroughly the information below. + +It is not allowed to consolidate traces originating from instrumentations with +mismatching disabled coverage regions. If doing so, gnatcov will warn with +``traces for (from ) are inconsistent with the corresponding Source Instrumentation Data``. + +To circumvent this, it is mandatory to produce checkpoints using the +instrumentation artifacts the source trace originates from. GNATcov then allows +consolidation of checkpoints with mismatching disabled coverage regions. See +:ref:`consolidation` for more information. + + +Reporting about disabled coverage regions +========================================= + +Exempted regions are reported as blocks in both the annotated source and the +synthetic text reports, for both source and object coverage metrics. In +annotated source reports, a ``D`` annotates all the lines of a disabled coverage +region. + +For our ``Eassert`` above, a typical :cmd-option:`=xcov` output for +:cmd-option:`stmt+decision` coverage for would be:: + + 6 .: procedure Eassert (T : Boolean) is + 7 .: begin + 8 D: pragma Annotate (Xcov, Cov_Off, "my justification"); + 9 D: if not T then + 10 D: raise Program_Error; + 11 D: end if; + 12 D: pragma Annotate (Xcov, Cov_On); + 13 .: end Eassert; + + +In synthetic text reports, a single indication is emitted for each disabled +coverage region as a whole, and the indications for all the regions are grouped +in a separate *Disabled Coverage Regions* report section, only present if there +are disabled coverage regions in the analysis scope. + +The corresponding :cmd-option:`=report` excerpt below illustrates this for the +``Eassert`` example:: + + ... + ================================== + == 3. DISABLED COVERAGE REGIONS == + ================================== + + eassert.adb:8:4-12:4: justification: + "my justification" + + 1 region with disabled coverage. + + ========================= + == 4. ANALYSIS SUMMARY == + ========================= + + 1 region with disabled coverage. diff --git a/doc/gnatcov/examples/Makefile b/doc/gnatcov/examples/Makefile index 2c322e407..f608639af 100644 --- a/doc/gnatcov/examples/Makefile +++ b/doc/gnatcov/examples/Makefile @@ -1,12 +1,9 @@ -TARGET=powerpc-elf -RTS=zfp-prep - XCOVLEVEL=stmt ANNOTATE=xcov # unit test name and gpr file -UT= +UT= #test_... GPR=ut.gpr TDIR=_$(UT:test_%=%) OSUBDIR=obj @@ -20,14 +17,12 @@ build: @echo ' for Source_Dirs use ("../src");' >> $(GPR) @echo ' for Object_Dir use "$(OSUBDIR)";' >> $(GPR) @echo 'end UT;' >> $(GPR) - gprbuild -p -f --target=$(TARGET) --RTS=$(TARGET)/$(RTS) -P$(GPR) $(UT).adb \ - -cargs:Ada -gnateS -gnaty -gnatwe -cargs -g -fpreserve-control-flow \ - -bargs -A=$(UT).alis + gnatcov instrument -P$(GPR) --level=$(XCOVLEVEL) --dump-filename-simple \ + --units=$(UT) $(UT).adb + gprbuild -p -f -P$(GPR) $(UT).adb --src-subdirs=gnatcov-instr \ + --implicit-with=gnatcov_rts.gpr run: - gnatcov run $(OSUBDIR)/$(UT) - grep -v xxsupport.ali $(OSUBDIR)/$(UT).alis > alis - gnatcov coverage --level=$(XCOVLEVEL) --scos=@alis \ - --annotate=$(ANNOTATE) $(UT).trace - - + $(OSUBDIR)/$(UT) + gnatcov coverage --level=$(XCOVLEVEL) -P$(GPR) \ + --annotate=$(ANNOTATE) --units=$(UT) $(UT).srctrace diff --git a/doc/gnatcov/examples/starter/ops.gpr b/doc/gnatcov/examples/starter/ops.gpr deleted file mode 100644 index 0b776942f..000000000 --- a/doc/gnatcov/examples/starter/ops.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project Ops is - for Languages use ("Ada"); - for Source_Dirs use ("src"); - for Object_Dir use "obj"; -end Ops; \ No newline at end of file diff --git a/doc/gnatcov/examples/starter/src/ops.adb b/doc/gnatcov/examples/starter/src/ops.adb deleted file mode 100644 index 74f5f6b9a..000000000 --- a/doc/gnatcov/examples/starter/src/ops.adb +++ /dev/null @@ -1,14 +0,0 @@ ------------------------------------------------------------------------------- --- GNATcoverage -- --- Copyright (C) 2012-2021, AdaCore -- ------------------------------------------------------------------------------- - -package body Ops is - procedure Apply (Op : Op_Kind; X : in out Integer) is - begin - case Op is - when Increment => X := X + 1; - when Decrement => X := X - 1; - end case; - end Apply; -end Ops; diff --git a/doc/gnatcov/examples/starter/src/ops.ads b/doc/gnatcov/examples/starter/src/ops.ads deleted file mode 100644 index 104eaf65a..000000000 --- a/doc/gnatcov/examples/starter/src/ops.ads +++ /dev/null @@ -1,9 +0,0 @@ ------------------------------------------------------------------------------- --- GNATcoverage -- --- Copyright (C) 2012-2021, AdaCore -- ------------------------------------------------------------------------------- - -package Ops is - type Op_Kind is (Increment, Decrement); - procedure Apply (Op : Op_Kind; X : in out Integer); -end Ops; diff --git a/doc/gnatcov/examples/starter/src/test_inc.adb b/doc/gnatcov/examples/starter/src/test_inc.adb deleted file mode 100644 index cd4a45acd..000000000 --- a/doc/gnatcov/examples/starter/src/test_inc.adb +++ /dev/null @@ -1,13 +0,0 @@ ------------------------------------------------------------------------------- --- GNATcoverage -- --- Copyright (C) 2012-2021, AdaCore -- ------------------------------------------------------------------------------- - -with Ops; - -procedure Test_Inc is - X : Integer := 4; -begin - Ops.Apply (Ops.Increment, X); - pragma Assert (X = 5); -end Test_Inc; diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index ee871b93c..478826dfd 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -13,9 +13,10 @@ Defining :term:`Exemption Regions ` ===================================================== :dfn:`Exemption regions` are lexical sections of sources in which coverage -violations are expected and can be justified. For Ada with the |gnat| -compilers, regions are defined by the insertion of dedicated pragmas in the -sources: +violations are expected and can be justified. + +For Ada with the |gnat| compilers, regions are defined by the insertion of +dedicated pragmas in the sources: - ``pragma Annotate (Xcov, Exempt_On, "justification text");`` starts a region, providing some justification text that will be recalled in coverage @@ -31,7 +32,7 @@ To illustrate, let us consider a common assertion control procedure in Ada: procedure Eassert (T : Boolean) is begin - pragma Annotate (Xcov, Exempt_On, "assert condition is never False"); + pragma Annotate (Xcov, Exempt_On, "assert condition never to be False"); if not T then raise Program_Error; end if; @@ -42,13 +43,55 @@ We expect never to reach here with ``T`` False, so we declare an exemption region to state that coverage violations across this region are expected and not a testing campaign deficiency. +For C code, exemptions are only supported with +:term:`source traces` and are defined using comment markers to +delimit the exempted regions: + +- Any comment containing the string ``GNATCOV_EXEMPT_ON`` followed by a string + in double quotes starts a region, the string within the double quotes being + used as justification text that will be recalled in coverage reports. + +- Any comment containing the string ``GNATCOV_EXEMPT_OFF`` closes the current + exemption region. + +The following assert function illustrates the definition of an exemption +block: + +.. code-block:: C + + void + assert (bool x){ + // GNATCOV_EXEMPT_ON "assert condition never to be False" + if (!x) + abort(); + // GNATCOV_EXEMPT_OFF + } + +As in the first example, we never expect to reach this function with x false, +so an exemption region is declared to state that all coverage violations +within the region are expected. + +An exemption comment marker may not intersect any coverage obligation, +such as a statement or a decision, as in the following example attempting +to exempt a decision only partially: + +.. code-block:: C + + if(a && /*GNATCOV_EXEMPT_ON "justification"*/ b /*GNATCOV_EXEMPT_OFF*/){ + ... + } + +Such markers are ignored by |gcvins|, after emitting a warning. + +It is also possible to define exemption regions trough external annotation +files, see :ref:`ext_annot` for more information. Reporting about coverage exemptions =================================== Exempted regions are reported as blocks in both the annotated source and the synthetic text reports, for both source and object coverage metrics. In -annotated source reports, a ``#`` or ``*`` caracter annotates all the exempted +annotated source reports, a ``#`` or ``*`` character annotates all the exempted lines, depending on whether 0 or at least 1 violation was exempted over the whole section, respectively. For our ``Eassert`` example above, a typical :cmd-option:`=xcov` output for :cmd-option:`stmt+decision` coverage for would @@ -70,11 +113,13 @@ control. In synthetic text reports, a single indication is emitted for each exempted region as a whole, and the indications for all the regions are grouped in a -separate *Exempted Regions* report section, only present if there are -exemption regions in the analysis scope. This section lists the exempted -regions, displaying for each the source location span, the number of actually -exempted violations in the region, and the exemption justification text. It -also includes a total count of the number of exempted regions at the end. +separate *Exempted Regions* report section, only present if there are exemption +regions in the analysis scope. This section lists the exempted regions, +displaying for each the source location span, the number of actually exempted +violations in the region, the exemption justification text and the observed +exempted violations per regions. It also includes a total count of the number +of exempted regions and another for exempted violations across all sections at +the end. The corresponding :cmd-option:`=report` excerpt below illustrates this for the ``Eassert`` example:: @@ -85,9 +130,13 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the ========================= eassert.adb:8:4-12:4: 2 exempted violations, justification: - assert condition never to be False + "assert condition never to be False" - 1 exempted region. + Exempted violations: + eassert.adb:8:4: decision outcome TRUE never exercised + eassert.adb:9:8: statement not executed + + 1 exempted region, 2 exempted violations. ========================= == 4. ANALYSIS SUMMARY == @@ -95,7 +144,7 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the No non-exempted STMT violation. No non-exempted DECISION violation. - 1 exempted region. + 1 exempted region, 2 exempted violations. The *Coverage Violations* section is renamed to convey that it contains "NON-EXEMPTED" violations only, and the *Analysis Summary* counters are @@ -129,6 +178,19 @@ In synthetic reports, the count of exempted violations is 0, like:: 1 exempted region. +Undetermined Coverage state and Exemptions +------------------------------------------ + +For each exemption region in which there are obligations with undetermined +coverage state, the synthetic text report will indicate the count of +undetermined coverage obligations in the region, in addition to the number +of violations. + +In the annotated sources, exemption regions with *only* undetermined coverage +items are annotated with ``@`` signs instead of ``*``. If there are both +undetermined coverage obligations as well as violations in the exemption +region, the corresponding lines is still annotated with ``#``. + .. _ocov_exemptions: Object coverage exemptions diff --git a/doc/gnatcov/external_annotations.rst b/doc/gnatcov/external_annotations.rst new file mode 100644 index 000000000..0c83b984c --- /dev/null +++ b/doc/gnatcov/external_annotations.rst @@ -0,0 +1,406 @@ +.. _ext_annot: + +########################### +External source annotations +########################### + +In case modifying the sources is not possible or desirable, it is possible to +generate annotations in separate files, which can be passed to |gcvins| or +|gcvcov| to modify the behavior of the instrumenter or of the coverage +analysis. + +Annotations loaded from an external file can be used along in-source +annotations, however in case of conflicts, the annotations defined in the +sources will always be prioritized. + +External annotations are stored in TOML files, which can be manipulated through +three |gcv| commands, |gcvaddan|, |gcvdelan| and |gcvshoan|, to respectively +add a new annotations, delete an existing annotation from the files, or show +the annotations that are stored in the files. + +Once generated, annotation files should be passed to the |gcvins| or |gcvcov| +commands with the :cmd-option:`--external-annotations` switch for them to be +taken into account by |gcv|. + +.. _gen_ext: + +Generating external annotations +############################### + +The |gcvaddan| command can be used to create an annotation, tied to a specific +source location. + +The help section for the |gcvaddan| command can be displayed by running +``gnatcov add-annotation --help``. Its synopsis is:: + + gnatcov add-annotation --kind=KIND [--external-annotations=FILENAME] --output=OUTPUT_FILENAME [OPTIONS] FILENAME + +Some notable command line options are: + +:cmd-option:`--output` + Name of the file to the newly created annotation will be written. If there + already is a file, it will be overwritten. + +:cmd-option:`--external-annotations`, |rarg| + Loads pre-existing annotations from `FILENAME`. They are used to check that + the new annotation does not conflict with any pre-existing one. The loaded + annotations are all written to the output file specified through + :cmd-option:`--output`. + +:cmd-option:`FILENAME`, positional + Filename to which the new annotation should apply. There are special + considerations to keep in mind when specifying the name of the file to be + annotated, see :ref:`ext_annot_relocs` + +:cmd-option:`--annotation-id=IDENTIFIER`, optional + Unique identifier for the new annotation. If not specified, |gcv| will + generate one based on the kind of annotation and the designated location. + + This identifier must be unique across all external annotation files passed to + any |gcv| invocation, and is used in diagnostics, or in the other annotation + manipulation commands, |gcvdelan| and |gcvshoan| to uniquely designate an + annotation. + +:cmd-option:`--force`, optional + Force overwriting of a pre-existing annotation for the same location, or + with the same identifier. If not specified, gnatcov will emit an error and + abort the annotation generation. The output file will not be modified. + +The required command line switches depend on the value of the +:cmd-option:`--kind`, conveying the kind annotation to be generated, which +correspond to the annotations kinds supported in +``pragma Annotate (Xcov, KIND, ..)``. The required switches are detailed in the +help text for the |gcvaddan| command, and are detailed bellow. A switch in +brackets signifies that the switch is optional, otherwise the switch is required +and |gcvaddan| will emit an error if not found on the command line. + +* :cmd-option:`--kind=Exempt_On` + Generate an annotation symbolizing the beginning of an + :ref:`exempted region `. + + :cmd-option:`--location=LINE:COL` + Source location for the beginning of the exempted region. + + :cmd-option:`--justification=MESSAGE` + Justification message to be displayed in the coverage reports for the + exempted region. + +* :cmd-option:`--kind=Exempt_Off` + Generate an annotation symbolizing the end of an exempted region. + + :cmd-option:`--location=LINE:COL` + Source location for the end of the exempted region. + +* :cmd-option:`--kind=Exempt_Region` + Generate an annotation symbolizing an entire exempted region. + + :cmd-option:`--start-location=LINE:COL` + Source location for the beginning of the exempted region. + + :cmd-option:`--end-location=LINE:COL` + Source location for the end of the exempted region. + + :cmd-option:`--justification=MESSAGE` + Justification message to be displayed in the coverage reports for the + exempted region. + +* :cmd-option:`--kind=Cov_Off` + Generate an annotation symbolizing the beginning of a :ref:`disabled + coverage region `. + + :cmd-option:`--location=LINE:COL` + Source location for the beginning of the disabled coverage region. + + :cmd-option:`--justification=MESSAGE` + Justification message for the disabled coverage region, to be displayed + in the coverage reports. + +* :cmd-option:`--kind=Cov_On` + Generate an annotation symbolizing the end of a disabled coverage region. + + :cmd-option:`--location=LINE:COL` + Location for the end of the disabled coverage region. + +* :cmd-option:`--kind=Dump_Buffers` + Generate an annotation instructing |gcv| to insert a + :ref:`buffer dump procedure call ` at the specified location. + This is only taken into account when the selected dump trigger is + ``manual``, see :ref:`Dump_Triggers` for more information concerning the + dump triggers. + + :cmd-option:`--location=LINE:COL` + Source location at which the buffer dump procedure call should be + inserted. + + :cmd-option:`[--dump-filename-prefix=TEXT]` + Optional trace filename prefix to be passed to the buffer dump procedure + call. This will be textually passed as argument to the buffer dump, and + must be an expression evaluating to a null-terminated ``char *``. As + such, if the prefix to be used is a literal string, the argument passed + to ``--dump-filename-prefix`` must contain quotes + (e.g. ``--dump-filename-prefix='"my_trace"'``). + + :cmd-option:`[--annotate-after]` + If specified, instruct |gcv| to insert the buffer dump procedure + **after** the statement designated by the annotation. See + :ref:`buf_semantics` for more details on the meaning of this option. + +* :cmd-option:`--kind=Reset_Buffers` + Generate an annotation instructing gnatcov to insert a :ref:`coverage buffer + reset procedure call ` at the specified location. This is only + taken into account when the selected dump trigger is ``manual``, see + :ref:`Dump_Triggers` for more information concerning the dump triggers. + + :cmd-option:`--location=LINE:COL` + Location at which the buffer reset procedure call should be inserted. + + :cmd-option:`[--annotate-after]` + If specified, instruct |gcv| to insert the buffer reset procedure + **after** the statement designated by the annotation. See + :ref:`buf_semantics` for more details on the meaning of this option. + +.. _buf_semantics: + +Semantics of buffer manipulation annotations +-------------------------------------------- + +Due to the differences in instrumentation technology used by |gcv| for C/C++ and +Ada, the external annotations concerning buffer dump/reset have different +semantics that need to be taken into account when first annotation sources. + +For C and C++ sources, |gcv| will insert the buffer dump/reset call at the exact +location designated by the annotation, without validating if the resulting code +is legal. It is thus recommended to choose a location corresponding to a +whitespace character, immediately before or after a statement. + +For instance, starting from the following source file: + +.. code-block:: C + :linenos: + + int main(){ + // Execute the core program + do_stuff(); + + // Cleanup temp files + cleanup(); + } + +Creating an annotation as follows:: + + gnatcov add-annotation --kind=Dump_Buffers -o annotations.toml --location=6:3 main.c + +would result in the following invalid code to be generated: + +.. code-block:: C + :linenos: + :emphasize-lines: 6 + + int main(){ + //Execute the core program + do_stuff(); + + // Cleanup temp files + cgnatcov_dump_buffers();leanup(); + } + +Instead, it is better to target any whitespace character before the statement, +as in ``--location=6:2``. + +For Ada sources, |gcv| will locate the inner-most statement list that encloses +the designated location, and insert the procedure call immediately **before** +this statement by default. The ``--annotate-after`` switch can be used to +instruct gnatcov to instead insert the procedure call **after** the designated +statement. This in particular is necessary to add a buffer dump annotation after +the last statement of a list. + +If gnatcov cannot locate a statement list enclosing the designated location, a +warning will be emitted and the annotations will be ignored. + +For instance, starting from the following source file: + +.. code-block:: Ada + :linenos: + + procedure Main is + begin + -- Run the actual program + + Do_Processing; + + -- Cleanup temp files + + Do_Cleanup; + end Main; + +Generating an annotation with:: + + gnatcov add-annotation --kind=Dump_Buffers -o annotations.toml --location=9:15 main.adb + +results in the following source, despite the source location pointing at the end +of the Do_Cleanup procedure call: + +.. code-block:: Ada + :linenos: + :emphasize-lines: 9 + + procedure Main is + begin + -- Run the actual program + + Do_Processing; + + -- Cleanup temp files + + GNATCov_RTS_Dump_Buffers; Do_Cleanup; + end Main; + +To ensure the buffer dump procedure is inserted after the Do_Cleanup call, it is +necessary to pass the ``--annotate-after`` command line switch. + + +.. _ext_annot_relocs: + +File relocation considerations +------------------------------ + +The external file annotation mechanism stores the filename passed to the +|gcvaddan| command in the generated annotation file. When the annotations are +loaded by a |gcvins| or |gcvcov| command invocation, to determine if an +annotation is relevant for any of the processed files, |gcv| checks whether the +full filename of the file being processed ends with the annotation target +filename. It is thus important to only store in the annotation the part of the +filename that will not change between the different |gcv| command invocations. + +This means that relative paths components (e.g. ``./`` or ``../``), and absolute +paths are likely to not be properly recognized. + +The |gcvaddan| command accepts a ``--source-root=PREFIX`` option that will strip +``PREFIX`` from the target filename when generating the annotations. As such, it +is possible to generate an annotation for a file located in a parent directory, +while ensuring the generated annotation will correctly be taken into account in +subsequent |gcv| invocations with the following command line:: + + gnatcov add-annotation [OPTIONS] --source-root="../" ../src/file.adb + +|gcv| can also automatically deduce the appropriate prefix to be stripped from +the filename if a project file is passed to |gcvaddan| with the ``-P`` option. +Note that this only works if the file is unique in the project tree, or if the +file is located in a sub-directory of its project root directory. + + +Deleting a pre-existing annotation +################################## + +The |gcvdelan| command can be used to remove a pre-existing annotation from an +external annotation file. + +The help section for the |gcvaddan| command can be displayed by running +``gnatcov delete-annotation --help``. Its synopsis is:: + + gnatcov delete-annotation --external-annotations=FILENAME --output=OUTPUT_FILENAME --annotation-id=IDENTIFIER + +The semantics of each command line switch is: + +:cmd-option:`--annotation-id=IDENTIFIER`: + Unique IDENTIFIER of the annotation to be deleted.`` + +:cmd-option:`--external-annotations=FILENAME`, |rarg|: + External annotation files from which the annotation will be loaded. + If multiple files are passed to |gcv|, the annotations will be consolidated + together and all written to the output file. + +:cmd-option:`--output=OUTPUT_FILENAME`: + Name of the file where the annotations will be written back after deletion + of the designated annotation. This will overwrite any pre-existing file with + the same OUTPUT_FILENAME. + +Displaying the annotations contained in annotation files +######################################################## + +The command |gcvshoan| can be used to display the annotations contained in +annotation files in a more user-friendly manner. + +The help section for the |gcvaddan| command can be displayed by running +``gnatcov show-annotations --help``. Its synopsis is:: + + gnatcov show-annotations --external-annotations=FILENAME [--kind=KIND] [-P PROJECT] [FILENAMES] + +The semantics of the command line switches are as follow: + +:cmd-option:`--external-annotations=FILENAME`, |rarg|: + External annotation files from which annotations will be loaded + +:cmd-option:`--kind=KIND`, optional: + Only display the annotations of kind KIND. + +:cmd-option:`-P PROJECT`, optional: + Show all annotations applicable to all source files of the project tree + rooted at PROJECT. + +:cmd-option:`FILENAMES`, positional: + Only show the annotations applicable to the listed files. + +Either the ``-P`` command line option or positional filenames must be specified. + +The output format is as follows: + +.. code-block:: + + BASENAME_1: + - START_LOCATION - END_LOCATION; id: IDENTIFIER; kind: KIND; [EXTRA_FIELDS] + - ... + + BASENAME_2: + - ... + +``BASENAME_i`` corresponds to the basename of each file for which there is an +annotation. The each annotation is displayed on each line, starting by the +location range for the annotation. If the annotation only concerns a single +location, the ``END_LOCATION`` field will be identical to the +``START_LOCATION``. The unique identifier of the annotation is then displayed in +place of ``IDENTIFIER``, and the annotation kind is displayed in place of +``KIND``. The ``EXTRA_FIELDS`` concerns options specific to each annotation +kind, and are displayed as a semi-column separated list. See :ref:`gen_ext` for +more details on the extra fields that each annotation kind supports. + +Annotation stability through file modifications +############################################### + +The external annotations generated by the |gcvaddan| command embed varying +levels of information so that the source location designated on the command +line option can be remapped when possible, or invalidated otherwise. + +This depends mainly on the language of the file to be annotated: + +- For Ada sources, the annotation is tied to the inner-most enclosing named + construct, such as a subprogram or a package. If the file is modified outside + of that construct the annotation will be remapped properly. If the enclosing + construct is modified, the annotation will be invalidated. + +- For Cor C++ sources, the annotations are tied to the inner-most enclosing + named declaration, such as a function declaration for C, or any of a + namespace declaration, a class declaration or function/method declaration for + C++. + +Note that in both cases, if no enclosing named construct can be found, the +|gcvaddan| command will emit a warning and fall back to an absolute annotation, +which is invalidated as soon as the file is modified. + +If an annotation is invalidated gnatcov will emit a warning stating that the +annotation was ignored, along with its unique identifier. + +The output of the |gcvshoan| command will also display stale annotations, the +format for those annotations will be: + +.. code-block:: + + - STALE ANNOTATION; id: IDENTIFIER; kind: KIND; [EXTRA_FIELDS]; diagnostic: DIAGNOSTIC + +where ``DIAGNOSTIC`` will contain a short explanation of why the entry is stale. + +To fix this, simply replace the entry with an invocation of |gcvaddan|, +specifying the annotation identifier to be replaced, and forcing the +replacement:: + + gnatcov add-annotation --annotation-id=IDENTIFIER --force [OPTIONS] diff --git a/doc/gnatcov/fig_flow0.dot b/doc/gnatcov/fig_flow0.dot deleted file mode 100644 index fdc744c37..000000000 --- a/doc/gnatcov/fig_flow0.dot +++ /dev/null @@ -1,131 +0,0 @@ -digraph { - node [fontsize = 9] - src [shape = box, label = "Original Sources"]; - - scos [shape = ellipse, label = "SCOS", color=blue]; - units [shape = ellipse, label = "Units Of\nInterest", color=blue]; - - edge [fontsize = 9, arrowsize=0.7] - - /*------------------- - Using Source traces - -------------------*/ - { - /* processes */ - node [shape = box]; - - node [color = green]; - instrument [label = "Instrument\nOriginal Sources"]; - build_instr [label = "Build from\nInstrumented Sources"]; - regular_execution [label = "Regular Execution\n(Instrumented Executable)"]; - - node [color = blue]; - srct_coverage [label = "Analyze/Consolidate"]; - - /* products or inputs */ - node [shape = ellipse, color = green]; - st1 [label = "strace1"]; - stdots [label = "..."]; - st2 [label = "strace2"]; - - node [shape = ellipse, color = blue]; - srct_report [label = "Report"]; - srct_checkpoint [label = "Checkpoint"]; - } - - /*------------------- - Using Binary traces - -------------------*/ - { - /* processes */ - node [shape = box]; - node [color = red]; - build_orig [label = "Build from\nOriginal Sources"]; - instr_execution [label = "Instrumented Execution\n(Regular Executable)"]; - - node [color = blue]; - bint_coverage [label = "Analyze/Consolidate"]; - - /* products or inputs */ - node [shape = ellipse, color = red]; - bt1 [label = "btrace1"]; - btdots [label = "..."]; - bt2 [label = "btrace2"]; - - node [shape = ellipse, color = blue]; - bint_report [label = "Report"]; - bint_checkpoint [label = "Checkpoint"]; - } - - src; - src -> instrument; - src -> build_orig; - scos; - - /*=================== Using Source traces ================*/ - - subgraph "cluster_src_traces" { - label = "Using Source Traces\n(Source coverage criteria only)"; - fontsize = 10; - labeljust = l; - color = green; - - instrument -> build_instr; - build_instr -> regular_execution; - - {rank = same; - st1; stdots; st2; - } - - regular_execution -> st1 [style = dotted]; - regular_execution -> stdots [style = dotted]; - regular_execution -> st2 [style = dotted]; - - st1 -> srct_coverage; - stdots -> srct_coverage; - st2 -> srct_coverage; - - srct_coverage -> srct_report [style = dotted]; - srct_coverage -> srct_checkpoint [style = dotted]; - srct_checkpoint -> srct_coverage; - } - - /*=================== Using Binary traces ================*/ - - subgraph "cluster_bin_traces" { - label = "Using Binary Traces\n(Source or Object Coverage Criteria)"; - fontsize = 10; - labeljust = r; - color = red; - - build_orig [rank=2]; - build_orig -> instr_execution; - - {rank = same; - bt1; btdots; bt2; - } - - instr_execution -> bt1 [style = dotted]; - instr_execution -> btdots [style = dotted]; - instr_execution -> bt2 [style = dotted]; - - bt1 -> bint_coverage; - btdots -> bint_coverage; - bt2 -> bint_coverage; - - bint_coverage -> bint_report [style = dotted]; - bint_coverage -> bint_checkpoint [style = dotted]; - bint_checkpoint -> bint_coverage; - } - - instrument -> scos [style = invis]; - build_orig -> scos [style = invis]; - - scos -> units [dir=both, arrowhead=curve, arrowtail=curve]; - - units -> instrument; - units -> instr_execution; - units:s -> bint_coverage; - units:s -> srct_coverage; - -} diff --git a/doc/gnatcov/fig_flow0.pdf b/doc/gnatcov/fig_flow0.pdf deleted file mode 100644 index 0f5fc3f35..000000000 Binary files a/doc/gnatcov/fig_flow0.pdf and /dev/null differ diff --git a/doc/gnatcov/fig_flow0.png b/doc/gnatcov/fig_flow0.png deleted file mode 100644 index d560ed3b7..000000000 Binary files a/doc/gnatcov/fig_flow0.png and /dev/null differ diff --git a/doc/gnatcov/fig_flow_compare.dot b/doc/gnatcov/fig_flow_compare.dot new file mode 100644 index 000000000..698438dda --- /dev/null +++ b/doc/gnatcov/fig_flow_compare.dot @@ -0,0 +1,135 @@ +digraph { + node [fontsize = 9] + src [shape = box, label = "Original Sources"]; + + scos [shape = ellipse, label = "SCOS", color=blue]; + units [shape = ellipse, label = "Units Of\nInterest", color=blue]; + + edge [fontsize = 9, arrowsize=0.7] + + /*------------------- + Using Source traces + -------------------*/ + { + /* processes */ + node [shape = box]; + + node [color = green]; + instrument [label = "Instrument Original Sources\n(gnatcov instrument)"]; + build_instr [label = "Build from Instrumented Sources\n(gprbuild --src-subdirs ...)"]; + regular_execution [label = "Regular Execution\n(instrumented executable)"]; + + node [color = blue]; + srct_coverage [label = "Analyze/Consolidate\n(gnatcov coverage)"]; + + /* products or inputs */ + node [shape = ellipse, color = green]; + st1 [label = "strace1"]; + stdots [label = "..."]; + st2 [label = "strace2"]; + + node [shape = ellipse, color = blue]; + srct_report [label = "Report"]; + srct_checkpoint [label = "Checkpoint"]; + } + + /*------------------- + Using Binary traces + -------------------*/ + { + /* processes */ + node [shape = box]; + node [color = red]; + build_orig [label = "Build from Original Sources\n(gprbuild -cargs ...)"]; + instr_execution [label = "Instrumented Execution\n(gnatcov run)"]; + + node [color = blue]; + bint_coverage [label = "Analyze/Consolidate\n(gnatcov coverage)"]; + + /* products or inputs */ + node [shape = ellipse, color = red]; + bt1 [label = "btrace1"]; + btdots [label = "..."]; + bt2 [label = "btrace2"]; + + node [shape = ellipse, color = blue]; + bint_report [label = "Report"]; + bint_checkpoint [label = "Checkpoint"]; + } + + src; + src -> instrument; + src -> build_orig; + scos; + + /*=================== Using Source traces ================*/ + + subgraph "cluster_src_traces" { + label = "Using Source Traces\n(Source coverage criteria only)"; + fontsize = 10; + labeljust = l; + color = green; + + instrument -> build_instr; + build_instr -> regular_execution; + + {rank = same; + st1; stdots; st2; + } + + regular_execution -> st1 [style = dotted]; + regular_execution -> stdots [style = dotted]; + regular_execution -> st2 [style = dotted]; + + st1 -> srct_coverage; + stdots -> srct_coverage; + st2 -> srct_coverage; + + srct_coverage -> srct_report [style = dotted]; + srct_coverage -> srct_checkpoint [style = dotted]; + srct_checkpoint -> srct_coverage; + } + + /*=================== Using Binary traces ================*/ + + subgraph "cluster_bin_traces" { + label = "Using Binary Traces\n(Source or Object Coverage Criteria)"; + fontsize = 10; + labeljust = r; + color = red; + + build_orig [rank=2]; + build_orig -> instr_execution; + + pad1 [style=invis]; + build_orig:e -> pad1 [style=invis]; + pad1 -> instr_execution:e [style=invis]; + + {rank = same; + bt1; btdots; bt2; + } + + instr_execution -> bt1 [style = dotted]; + instr_execution -> btdots [style = dotted]; + instr_execution -> bt2 [style = dotted]; + + bt1 -> bint_coverage; + btdots -> bint_coverage; + bt2 -> bint_coverage; + + bint_coverage -> bint_report [style = dotted]; + bint_coverage -> bint_checkpoint [style = dotted]; + bint_checkpoint -> bint_coverage; + } + + instrument -> scos [style = invis]; + build_orig -> scos [style = invis]; + + scos -> units [dir=both, arrowhead=curve, arrowtail=curve]; + + units -> instrument; + units -> instr_execution; + units:s -> bint_coverage; + units:s -> srct_coverage; + +} diff --git a/doc/gnatcov/fig_flow_compare.pdf b/doc/gnatcov/fig_flow_compare.pdf new file mode 100644 index 000000000..2e188dfb7 Binary files /dev/null and b/doc/gnatcov/fig_flow_compare.pdf differ diff --git a/doc/gnatcov/fig_flow_compare.png b/doc/gnatcov/fig_flow_compare.png new file mode 100644 index 000000000..186f098ba Binary files /dev/null and b/doc/gnatcov/fig_flow_compare.png differ diff --git a/doc/gnatcov/fig_flow_integrated_instr.dot b/doc/gnatcov/fig_flow_integrated_instr.dot new file mode 100644 index 000000000..45f81b2be --- /dev/null +++ b/doc/gnatcov/fig_flow_integrated_instr.dot @@ -0,0 +1,61 @@ +digraph { + node [fontsize = 9] + + edge [fontsize = 9, arrowsize=0.7] + + setup [shape=box, label="gnatcov setup"] + + /*------------------- + Using Source traces + -------------------*/ + subgraph "cluster_src_traces" { + label = "Setup / Build / Execute / Analyze"; + fontsize = 10; + labeljust = l; + + /* processes */ + node [shape = box]; + + node [color = green]; + instrument [label = "Setup integrated instrumentation\n(gnatcov setup-integration -P)"]; + build_instr [label = "Regular build\n(using the generated compiler wrapper)"]; + regular_execution [label = "Regular Execution\n(instrumented executable)"]; + + node [color = blue]; + srct_coverage [label = "Analyze/Consolidate\n(gnatcov coverage -P...)"]; + + /* products or inputs */ + node [shape = ellipse, color = green]; + st1 [label = "strace1"]; + stdots [label = "..."]; + st2 [label = "strace2"]; + + node [shape = ellipse, color = blue]; + srct_report [label = "Report"]; + srct_checkpoint [label = "Checkpoint"]; + + src [shape = ellipse, label = "Original Sources"]; + + /* Links */ + src -> instrument; + instrument -> build_instr; + build_instr -> regular_execution; + + {rank = same; + st1; stdots; st2; + } + + regular_execution -> st1 [style = dotted]; + regular_execution -> stdots [style = dotted]; + regular_execution -> st2 [style = dotted]; + + st1 -> srct_coverage; + stdots -> srct_coverage; + st2 -> srct_coverage; + + srct_coverage -> srct_report [style = dotted]; + srct_coverage -> srct_checkpoint [style = dotted]; + srct_checkpoint -> srct_coverage; + + } +} diff --git a/doc/gnatcov/fig_flow_integrated_instr.pdf b/doc/gnatcov/fig_flow_integrated_instr.pdf new file mode 100644 index 000000000..e3ad76457 Binary files /dev/null and b/doc/gnatcov/fig_flow_integrated_instr.pdf differ diff --git a/doc/gnatcov/fig_flow_integrated_instr.png b/doc/gnatcov/fig_flow_integrated_instr.png new file mode 100644 index 000000000..fbaf58684 Binary files /dev/null and b/doc/gnatcov/fig_flow_integrated_instr.png differ diff --git a/doc/gnatcov/fig_flow_srctraces.dot b/doc/gnatcov/fig_flow_srctraces.dot new file mode 100644 index 000000000..d4c9e9b8e --- /dev/null +++ b/doc/gnatcov/fig_flow_srctraces.dot @@ -0,0 +1,61 @@ +digraph { + node [fontsize = 9] + + edge [fontsize = 9, arrowsize=0.7] + + setup [shape=box, label="gnatcov setup"] + + /*------------------- + Using Source traces + -------------------*/ + subgraph "cluster_src_traces" { + label = "Instrument / Build / Execute / Analyze"; + fontsize = 10; + labeljust = l; + + /* processes */ + node [shape = box]; + + node [color = green]; + instrument [label = "Instrument Original Sources\n(gnatcov instrument -P)"]; + build_instr [label = "Build from Instrumented Sources\n(gprbuild -P... --src-subdirs ...)"]; + regular_execution [label = "Regular Execution\n(instrumented executable)"]; + + node [color = blue]; + srct_coverage [label = "Analyze/Consolidate\n(gnatcov coverage -P...)"]; + + /* products or inputs */ + node [shape = ellipse, color = green]; + st1 [label = "strace1"]; + stdots [label = "..."]; + st2 [label = "strace2"]; + + node [shape = ellipse, color = blue]; + srct_report [label = "Report"]; + srct_checkpoint [label = "Checkpoint"]; + + src [shape = ellipse, label = "Original Sources"]; + + /* Links */ + src -> instrument; + instrument -> build_instr; + build_instr -> regular_execution; + + {rank = same; + st1; stdots; st2; + } + + regular_execution -> st1 [style = dotted]; + regular_execution -> stdots [style = dotted]; + regular_execution -> st2 [style = dotted]; + + st1 -> srct_coverage; + stdots -> srct_coverage; + st2 -> srct_coverage; + + srct_coverage -> srct_report [style = dotted]; + srct_coverage -> srct_checkpoint [style = dotted]; + srct_checkpoint -> srct_coverage; + + } +} diff --git a/doc/gnatcov/fig_flow_srctraces.pdf b/doc/gnatcov/fig_flow_srctraces.pdf new file mode 100644 index 000000000..0d6a5b808 Binary files /dev/null and b/doc/gnatcov/fig_flow_srctraces.pdf differ diff --git a/doc/gnatcov/fig_flow_srctraces.png b/doc/gnatcov/fig_flow_srctraces.png new file mode 100644 index 000000000..80d57f7ae Binary files /dev/null and b/doc/gnatcov/fig_flow_srctraces.png differ diff --git a/doc/gnatcov/gen_prjtrees.py b/doc/gnatcov/gen_prjtrees.py index 52b037d40..3579af24e 100644 --- a/doc/gnatcov/gen_prjtrees.py +++ b/doc/gnatcov/gen_prjtrees.py @@ -1,19 +1,21 @@ import re import subprocess +import os def render(tree): - subprocess.call(["dot", "-Tpng", "-o"+tree+".png", tree+".dot"]) - subprocess.call(["dot", "-Tpdf", "-o"+tree+".pdf", tree+".dot"]) + subprocess.call(["dot", "-Tpng", "-o" + tree + ".png", tree + ".dot"]) + subprocess.call(["dot", "-Tpdf", "-o" + tree + ".pdf", tree + ".dot"]) def gen_tree(tmpl, outfile, selected): for line in tmpl: - m = re.search(r'([a-z_0-9]*) \[(.*)\];', line) + m = re.search(r"([a-z_0-9]*) \[(.*)\];", line) if m and m.group(1) in selected: outfile.write( - "\t\t%s [%s,color=darkslateblue, fontcolor=white ];\n" % - (m.group(1), m.group(2))) + "\t\t%s [%s,color=darkslateblue, fontcolor=white ];\n" + % (m.group(1), m.group(2)) + ) else: outfile.write(line) @@ -21,13 +23,14 @@ def gen_tree(tmpl, outfile, selected): tmpl = open("prjtree.dot").readlines() trees = { - 'Proot-nosub': ['root'], - 'Proot-ss_a-nosub': ['ss_a'], - 'Proot-root-ss_a-nosub': ['root', 'ss_a'], - 'Proot-ss_a': ['ss_a', 'sa1', 'sa2', 'sa3', 'common'] + "Proot-nosub": ["root"], + "Proot-ss_a-nosub": ["ss_a"], + "Proot-root-ss_a-nosub": ["root", "ss_a"], + "Proot-ss_a": ["ss_a", "sa1", "sa2", "sa3", "common"], } for k in trees: gen_tree(tmpl, open(k + ".dot", "w"), trees[k]) render(k) + os.remove(f"{k}.dot") -render('prjtree') +render("prjtree") diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 8450914c6..0c76a0afd 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -2,149 +2,126 @@ Getting Started *************** -Framework concepts and process overview -======================================= - -|gcp| provides a range of coverage analysis facilities with support -notably for - -- A variety of measurement methods, coverage criteria and output - formats; - -- Powerful consolidation features to report about the combined - achievements of multiple program executions. - -Actual coverage is always first computed out of *trace files* conveying what -test programs have achieved. |gcp| works with two possible kinds of traces: - -- :dfn:`Binary traces`, produced by an instrumented execution environment - while running an unmodifed version of the program. Such traces contain low - level information about executed blocks of machine instructions. - -- :dfn:`Source traces`, produced by an alternative version of the program, - built from sources instrumented to feed coverage dedicated datastructures. - -Both kinds of traces can be used to assess so called :dfn:`source coverage` -criteria, where the entities subject to coverage assessment are defined in -terms of source level constructs. The specific criteria that |gcp| supports -are those defined by the DO-178B certification standard for civil avionics: - -- :dfn:`Statement Coverage`, where the coverage metrics are respective to source - level statements such as a variable assignment or a subprogram calls; - -- :dfn:`Decision Coverage`, which, in addition to statement coverage, requires - evaluating Boolean expressions (*decisions* in DO178B parlance) both True - and False, then +General notions +=============== + +|gcp| is a code coverage analysis tool offering support for a range of +coverage metrics and output formats associated with powerful +:dfn:`consolidation` features letting users assess the combined +coverage achievements of multiple program executions. It supports Ada, C +and C++. + +The set of compilation units for which a user needs to assess coverage +is commonly designated as the set of :dfn:`units of interest`. This is a +central notion to many of the tool's operations, conveyed by the user +through command line switches or GPR project file attributes. Units of +interest typically include the code under test in a campaign, as +opposed to the sources of the test harness infrastructure. + +After one or several program executions, the tool computes +:dfn:`coverage metrics` for a given set of units out of :dfn:`coverage +trace` data produced by the executions with the assistance of an +*instrumentation* mechanism. The primary mode offered by |gcp| +performs :dfn:`source instrumentation`, where the tool produces a +modified version of the program sources to keep track of coverage +relevant facts along with the program control flow, and output +the coverage data when the program terminates. We call :dfn:`source +traces` the coverage traces produced by programs instrumented this +way. + +The set of metrics that the tool can assess from source traces +corresponds to the set defined by the |do| certification standard +for civil avionics, that is: + +- :dfn:`Statement Coverage`, where the tools assesses the coverage + status (executed or not) of source statements such as a variable + assignment or a subprogram call; + +- :dfn:`Decision Coverage`, which, in addition to statement coverage, + evaluates whether Boolean expressions (*decisions* in |do| + parlance) have been exercised both True and False, then + +- :dfn:`Modified Condition/Decision Coverage`, commonly known as + *MCDC*, which requires testing particular variations of individual + Boolean operands (*conditions* in |do| parlance) within decisions. + +All these metrics are defined with respect to source level entities +(statements, decisions, conditions), and we commonly refer to such +assessments as :dfn:`source coverage analysis`. Individual statements, +decisions, or conditions within the scope of an analysis are referred +to as :dfn:`Source Coverage Obligations` or :dfn:`SCOs`. + +Workflow overview +================= + +Figure :numref:`fig-flow_srctraces` depicts the workflow involved in +computing coverage based on source instrumentation. + +A setup step is first needed to install a tiny runtime library used by +the instrumented sources to register coverage facts and output them +eventually. This runtime is parameterized for the project at hand, +depending on the set of languages involved (Ada, C, C++) and on the +kind of target for which the code will be compiled (native, cross with +OS, or bareboard). Once the setup is done, users proceed with +instrument / build / execute / analyze cycles to produce traces and +compute coverage results. + +The setup, instrumentation and analysis steps are all driven by a +|gcv| command line tool which exposes a subcommand for each kind of +operation; hence |gcvstp| for the setup step, |gcvins| to instrument +and |gcvcov| to compute metrics from traces. + +GPR project files and associated command line switches are used to let +the tool know about the project sources and to convey the units of +interest. Consolidation can be performed by aggregating multiple traces +directly, or internal representations of partial coverage results +stored in files that we call :dfn:`Coverage Checkpoints`. + +.. _fig-flow_srctraces: +.. figure:: fig_flow_srctraces.* + :align: center -- :dfn:`Modified Condition/Decision Coverage`, commonly known as *MCDC*, which - requires testing particular variations of individual Boolean operands - (*conditions* in DO178B parlance) within decisions. + Source instrumentation based Coverage analysis overview +|gcv| also provides an alternate workflow that consists in integrating +seamlessly into an existing build process possibly not involving the use of +gprbuild. This is provided as an experimental feature and is available for +C/C++, compiling with gcc/g++ on a linux host. The figure +:numref:`fig-flow_integrated_instr` depicts this workflow that is more +thoroughly detailed in the section :ref:`integrated_instr`. -From binary traces, |gcp| is also able to produce :dfn:`object -coverage` reports, measuring the coverage of machine level -instructions produced by the compilation toolchain out of the original -sources. |gcp| supports two criteria of this kind: +.. _fig-flow_integrated_instr: +.. figure:: fig_flow_integrated_instr.* + :align: center -- :dfn:`Instruction Coverage`, where we evaluate for each machine instruction - whether it has been executed at least once or not; and + Integrated instrumentation based Coverage analysis overview -- :dfn:`Branch Coverage`, where, in addition, we evaluate for each conditional - branch instruction whether it was only taken, or went fallthrough or both. +A simple example +================ -A central notion to all the assessments performed with |gcp| is that of -:dfn:`units of interest`, which simply designates the set of compilation units -of which we are aiming to assess the coverage. These typically include the -code under test in a campaign, as opposed to, for example, the sources of the -test harness infrastructure when one is used. The individual statements, -decisions, or conditions of relevance within units of interest are referred to -as :dfn:`Source Coverage Obligations` or :dfn:`SCOs`. +Here we first introduce a very simple example software project +structure then demonstrate one basic analysis workflow for this +project with actual commands. -Consolidation can be performed by aggregating multiple traces -directly, or so called :dfn:`Coverage Checkpoints`, which are just an -internal representation of partial coverage results. +The examples provided in most of this manual assume a native +configuration and the process is similar cross environments. Typical +variations would touch switches controlling where and when coverage +trace data is output by the instrumented programs, and default values +for such switches are selected by the tool based on +:cmd-option:`--target` and :cmd-option:`--RTS` arguments at setup +time. -The high level processes involved in using binary or source traces are -sketched on :numref:`fig-flow0`. We don't support mixing the two kinds -of traces together and have depicted a separate analysis/consolidation -step to emphasize this. -We have however strived to maximize the commonalities between the two -schemes, as hinted by the use of the same blue color for the common -notions and analysis steps. Indeed, the command line interfaces -involved are the same, they use inputs of similar general nature -(traces or checkpoints) and share common definitions of available -output formats for source coverage criteria. This is intended to -facilitate transitions from one scheme to the other and ensure that -the widest possible range of improvements benefit both modes in a -consistent manner. +Sample project +-------------- -.. _fig-flow0: -.. figure:: fig_flow0.* - :align: center +The sources for this examples are provided under the +`share/examples/gnatcoverage/doc/getting_started/` directory of the GNAT DAS +distribution. - Coverage analysis processes overview - -.. _selecting_trace_kind: - -Selecting a trace mode; supported features and environments -=========================================================== - -The source and binary trace modes each have specific strengths, the -relative importance of which depends on the project context. The -matrix below summarizes the main characteristics of each mode, as a -first key to help select one scheme or the other for a given software -development project: - -.. list-table:: - :widths: 20 20 20 - :header-rows: 1 - :stub-columns: 1 - - * - - - **With Source Traces** - - **With Binary Traces** - * - *Tracing mechanism* - - Program instrumentation - - Execution environment - * - ~ - - ~ - - ~ - * - *Native applications* - - Yes (including shared-libraries) - - No - * - *Cross configurations with RTOS* - - Yes - - No - * - *Bareboard configurations* - - Yes - - Selectively (specific CPUs only, through GNATemulator or - hardware probes) - * - ~ - - ~ - - ~ - * - *Object coverage analysis (language agnostic)* - - No - - Yes - * - *Source coverage analysis for Ada (up to Ada 2012)* - - Yes - - Yes - * - *Source coverage analysis for C* - - Beta in release 22 - - Yes - -The source trace based workflow also has a few other limitations that -are outlined in section :ref:`instr-limitations`. - -A brief introduction to the main process steps -============================================== - -This section is intended to illustrate the basics of the process on a -very simple example, without getting into details. - -We start from a very simple Ada package exposing a set of elementary -operations over ``Integer`` objects, with a spec and body in source files -named ``ops.ads`` and ``ops.adb``: +We consider an Ada package providing a set of elementary operations +over ``Integer`` objects, with a spec and body in source files named +``ops.ads`` and ``ops.adb``: .. code-block:: ada @@ -168,7 +145,7 @@ named ``ops.ads`` and ``ops.adb``: end; end; -We will analyse the statement coverage achieved by the sample unit :term:`test +We will analyze the coverage achieved by the sample unit :term:`test driver ` below, in ``test_inc.adb``, which exercises the ``Increment`` operation only: @@ -184,13 +161,9 @@ driver ` below, in ``test_inc.adb``, which exercises the end; -We will illustrate two basic use cases, one using binary traces produced by -GNATemulator for a cross target, and one using source traces for a native -environment. -Assuming we start from a temporary working directory, with the *ops* sources -in an ``opslib`` subdirectory and the *test* sources in a ``tests`` -subdirectory, we will rely for both cases on a couple of project files in the -common working directory: +Assuming a working directory, with the *ops* sources in an ``opslib`` +subdirectory and the *test* sources in a ``tests`` subdirectory, we +will use a couple of project files in the common working directory: .. code-block:: ada @@ -213,122 +186,96 @@ common working directory: end Tests; -If you wish to experiment with both trace modes, you should start from -separate working directories (one for each mode) to prevent possible -intereferences of artifacts from one mode on the other. +Setup, Instrument, Build, Execute, Analyze +------------------------------------------ +The instrumentation step that follows assumes that the original program +is well formed. A simple way to verify this is to build the non instrumented +version first. For our example, this would be:: -Example production of a binary trace for a bareboard environment ----------------------------------------------------------------- + gprbuild -f -p -Ptests.gpr -For binary traces, |gcv| relies on an instrumented execution environment to -produce the traces instead of having to instrument the program itself with -extra code and data structures. For cross configurations, |gem| provides such -an environment. Hardware probes may also be used, provided trace data is -converted to the format |gcv| expects. +We then first set up the instrumentation context, providing a local +*prefix* location where the runtime and default parameters for future +commands are going to be installed:: -Programs are built from their original sources, only requiring the use of -:cmd-option:`-g -fpreserve-control-flow -fdump-scos` compilation options to -generate coverage obligation lists and let us associate execution traces to -these obligations afterwards. + gnatcov setup --prefix=/path/to/gnatcov-rts -For our example use case here, we first use the GNAT Pro toolset for -``powerpc-elf`` to build, using :command:`gprbuild` as follows:: +Letting further commands know about the *prefix* location is achieved +by adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` +variable. In a Unix like environment, this would be: - gprbuild --target=powerpc-elf --RTS=light-mpc8641 -Ptests.gpr \ - -cargs -g -fpreserve-control-flow -fdump-scos +.. code-block:: sh -We pass the project file with ``-P``, the required compilation flags -with ``-cargs`` and request the use of a ``light`` runtime library tailored -for the ``mpc8641`` board. + export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/path/to/gnatcov-rts/share/gpr -The build command produces a ``test_inc`` executable in the object -subdirectory. To automate the execution of this program within |gem| -to produce a trace, we provide the |gcvrun| command. For the use case -at hand, we would simply do:: +This will both let the ``gprbuild`` command below locate the +``gnatcov_rts.gpr`` project file, and the |gcvins| command find +default parameter values. - gnatcov run --target=powerpc-elf obj-tests/test_inc +In addition, when using shared libraries, it is necessary to let the +environment know about the coverage runtime's own shared libraries. The +following command achieves this in a Unix like environment: +.. code-block:: sh -... which would produce a ``test_inc.trace`` binary trace file in the current -directory. By default, such a trace is amenable to statement and decision -coverage at most. If MCDC analysis is needed, ``--level=stmt+mcdc`` must be -passed to |gcvrun| as well and we recommand also providing source coverage -obligations in this case. + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/gnatcov-rts/lib -Example production of a source trace for a native environment -------------------------------------------------------------- +The following command performs the corresponding action on Windows systems: -The production of source traces is performed by an instrumented version of the -program running in its regular execution environment. The coverage data is -collected and output by the program itself. The output step is performed by a -specific instrumentation of the program main unit, according to a user -selectable policy. +.. code-block:: bat -The whole scheme requires the use of GPR project files. The code inserted by -the instrumentation process relies on common types and subprograms provided by -a :dfn:`coverage runtime` library, distributed in source form with |gcp|. The -first thing to do for a given project is then to setup this coverage runtime -so it becomes available to the instrumented sources afterwards. This step is -documented in the :ref:`instr-rts` section of this manual. + set PATH=%PATH%;C:\path\to\gnatcov-rts\bin\ -Instrumenting a test main program together with its "code" dependency is then -achieved by a |gcvins| command. For our example use case, this would be:: +Instrumentation is performed by a simple |gcvins| command:: - gnatcov instrument -Ptests.gpr --level=stmt \ - --dump-trigger=atexit --dump-channel=bin-file + gnatcov instrument -Ptests.gpr --level=stmt -The ``--dump-channel=bin-file`` switch requests outputing coverage data -directly to a trace file and ``--dump-trigger=atexit`` instructs to perform -this operation as part of an execution termination handler, the simplest -option in native environments. ``--level=stmt`` states that we will want to -perform statement coverage analysis afterwards and ``-Ptests.gpr`` specifies -the root project for coverage obligations and the main unit(s) to instrument. +The use of ``tests.gpr``, not ``code.gpr``, at this step is important +as it lets the instrumenter know about the main subprogram, which +needs to be processed specially to dump coverage data. -After setting ``GPR_PROJECT_PATH`` to designate the directory where the -coverage runtime has been installed, building the instrumented program then -goes like:: +Building the instrumented program then goes like:: - gprbuild -f -p -Ptests.gpr \ - --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts + gprbuild -f -p -Ptests.gpr \ + --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr +This is the same command as for the regular build, with a couple +of additional switches to: -The ``--src-subdirs`` and ``--implicit-with`` options respectively instruct -the builder to use the alternative sources produced by the instrumenter and to -automatically provide visiblity over the coverage runtime. This allows -building the instrumented version of the program without requiring any change -to the GPR project files. + * Instruct the builder to search for the instrumented versions of the sources + (``--src-subdirs``). Note that, due to the way ``--src-subdirs`` works in + ``gprbuild``, even though |gcvins| creates directories with names derived + from ``*-gnatcov-instr``, the argument to pass to GPRbuild must always be + exactly ``--src-subdirs=gnatcov-instr``. -Then simply executing the test program in its native environment, as in:: + * Provide visibility to the builder over the coverage runtime + referenced by the instrumented sources (``--implicit-with``). + +Executing the test program in its native environment, as in:: obj-tests/test_inc -produces a ``test_inc-.srctrace`` source trace file in the +then produces a ``test_inc-.srctrace`` source trace file in the current directory. The ``-`` suffix is intended to prevent clashes in case of concurrent executions of the program in the same directory. It can be controlled in a variety of ways from the instrumentation command line, documented in the :ref:`instr-tracename` section of this manual. +Analysis of the coverage achieved by previous executions is done with +|gcvcov| commands. For our example use case, this could for instance be:: -Example production of a coverage report ---------------------------------------- - -Analysis of the coverage achieved by previous executions is done with |gcvcov| -commands. For our example use case, this could for example be:: + gnatcov coverage --level=stmt --annotate=xcov test_inc*.srctrace -Ptests.gpr - gnatcov coverage --level=stmt --annotate=xcov -Ptests.gpr - -... where ```` would be either the source or the binary trace produced -by the commands introduced in the previous example sections. Here, we request: +Here, we request: - A source *statement coverage* assessment with :cmd-option:`--level=stmt`, - An annotated source report in text format with :cmd-option:`--annotate=xcov`, -- For the complete set of units involved in the executable, per - :cmd-option:`-Ptests.gpr` and no specification otherwise in the project - files. +- For the complete set of units involved in the executable with + :cmd-option:`-Ptests.gpr`. This produces annotated sources in the project's object directory, with ``ops.adb.xcov`` quoted below: @@ -354,20 +301,19 @@ all the statements except the one dealing with a ``Decrement`` operation, indeed never exercised by our driver. The command actually also produces reports for ``ops.ads`` and -``test_inc.adb``, even though the latter is not really relevant. Focus on -specific units can be achieved by providing a more precise set of units of -interest at this stage. For source traces, this could also be incorporated as -part of the instrumentation step, as there is no point in instrumenting the -test units for their own coverage achievements. +``test_inc.adb``, even though the latter is not really relevant. Focus +on specific units can be achieved by providing a more precise set of +units of interest at this step, for example by adding +``--projects=code.gpr`` to the command line, or setting dedicated attributes +in the project files themselves. See the :ref:`sunits` chapter for +details on this aspect of the procedure. Going Further ============= Each of the steps involved in the process overview presented previously -is described in detail in a specific chapter of this manual, the most -important ones referenced hereafter: - -- :ref:`bin_traces` +is described in detail in a specific chapter of this manual. The most +important ones are: - :ref:`src_traces` @@ -375,13 +321,14 @@ important ones referenced hereafter: - :ref:`scov` -- :ref:`ocov` - - :ref:`consolidation` :ref:`exemptions` is also worth noting here, a mechanism allowing users to define code regions for which coverage violations are -expected and legitimate (Ada only at this stage). +expected and legitimate. + +The known limitations of the tool are outlined in section +:ref:`instr-limitations`. Conventions used in the rest of this manual diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst new file mode 100644 index 000000000..e9c3a9e8c --- /dev/null +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -0,0 +1,14 @@ +############################################# +Appendix A. Using GNATcoverage Binary Traces +############################################# + +.. toctree:: + :maxdepth: 3 + + bin_intro + bin_traces + cov_object + cov_metrics + bin_gps + bin_convert + bin_limitations diff --git a/doc/gnatcov/gnatcov_part.rst b/doc/gnatcov/gnatcov_part.rst index 841d4f80f..1f55498ba 100644 --- a/doc/gnatcov/gnatcov_part.rst +++ b/doc/gnatcov/gnatcov_part.rst @@ -7,15 +7,15 @@ GNATcoverage User's Guide getting_started units_of_interest - bin_traces src_traces + integrated_instr cov_source - cov_object - cov_metrics + cov_rust consolidation exemptions + disable_cov + external_annotations gpr - bin_traces_convert gps - appendix glossary + appendix diff --git a/doc/gnatcov/gpr.rst b/doc/gnatcov/gpr.rst index f93f029bb..4351389f5 100644 --- a/doc/gnatcov/gpr.rst +++ b/doc/gnatcov/gpr.rst @@ -30,6 +30,11 @@ coverage perspectives. In the root project, a ``Coverage`` package may be used to specify the arguments for |gcv| commands and the target/runtime profile may be set using toplevel attributes. +Please note that **non-library aggregate project files are currently not +supported** and will be rejected by |gcv|. The aggregated projects will have +to be processed individually and coverage reports consolidated +:ref:`through checkpoints`, when this makes sense. + .. _switches_attr: Specifying |gcv| command Switches @@ -63,7 +68,7 @@ re-written as:: The ``*`` arguments are always inserted first with respect to the final command line interpretation. In the example above, ``--level`` from the ``*`` -list cumulates before ``--annotate`` for |gcvcov|. Similarily, switches from +list cumulates before ``--annotate`` for |gcvcov|. Similarly, switches from the project file are always processed as if appearing before the others on the command line. diff --git a/doc/gnatcov/gps.rst b/doc/gnatcov/gps.rst index d180e1d8b..43487b378 100644 --- a/doc/gnatcov/gps.rst +++ b/doc/gnatcov/gps.rst @@ -5,20 +5,20 @@ Using |gcp| from |gps| GNATcoverage is integrated in |gps| so that it is possible to analyze code coverage without leaving your favorite editor. -Basic usage -=========== - -As a first step, indicate which coverage criterion GNATcoverage should use. -The default is stmt. -For this, go to the project properties (:menuselection:`Edit --> -Project Properties...`). +Basic scenario +============== + +As a first step, indicate which coverage criterion GNATcoverage should use +through the :ref:`project file`. If no coverage level is set +in the project file, gnatcov will default to ``stmt``, and emit a warning +indicating that the coverage level is not set. +You can specify the coverage level by by editing directly the project file: |gps| +provides completion, tooltips, outline and other common IDE features for project +files through LSP and the `Ada Language Server `_, +helping you to customize your project more easily. .. image:: gps_screenshots/3-cov-level.png -In the GNATcov entry, you can change the coverage level passed to |gcv| commands -in the corresponding *Coverage level* combo boxes. Change both to -``stmt+decision``. - This is all for the setup part. Then you just need to click on the *Run GNATcoverage* toolbar button as shown in the following screenshot. @@ -36,7 +36,7 @@ respective menu items under the Also Note that you can select a prebuilt gnatcov runtime under the same menu. This will skip the "build the gnatcov runtime" step, and will be especially -useful if you bring modifications to this runtime. By default, GNATstudio will +useful if you bring modifications to this runtime. By default, GNAT Studio will rebuild the runtime that is shipped with GNATcoverage and reinstall it in a temporary directory every time. @@ -55,31 +55,41 @@ file with annotations that represent the coverage state: Note that the Locations view reports all non-covered lines. It makes navigation easy as you only have to click on a diagnostic to go to the corresponding line. -Binary traces usage -=================== +Viewing a coverage report produced outside of GNAT Studio +========================================================= + +If the workflow is not adapted to your process, GNAT Studio also supports +displaying a coverage report produced externally, by first loading the coverage +data using any of the actionable `Load Data` item under +:menuselection:`Analyze --> Coverage`. -Starting from GNATcoverage version 22.0, binary traces (using gnatcov run) are -no longer supported in native profiles. This mode is still supported for cross -configurations so the same steps performed above for source traces can be done -for binary traces IF you are in a supported configuration (otherwise, the menu -items won't show up). +GNAT Studio expects a coverage report under the xcov+ format, under the object +directory of the project (), or under /xcov+. -Go to the menu -:menuselection:`Analyze --> Coverage --> GNATcoverage Binary Traces`. -to perform each step individually, or use the ``Run All Actions`` item. +Then you can visualize the report by clicking on +:menuselection:`Analyze --> Coverage --> Show coverage report`. -You can also replace the toolbar button (dedicated to the instrumentation-based -scheme) with an alike button, but for binary traces. Go to GNATstudio -Preferences in :menuselection:`Edit --> Preferences`. +Using GNATtest's coverage integration makefile +============================================== -Then, go to the ``Build Targets`` section, and find the ``Run GNATcoverage`` -workflow: add it to the toolbar as shown below. +When using individual test drivers, it is not possible to use the regular +GNATcoverage integration. This is true when GNATtest is called with +:cmd-option:`--separate-drivers` or :cmd-option:`--stub` (as it implies +:cmd-option:`--separate-drivers`), as described in :ref:`Individual Test +Drivers`. In this case, the integration of +GNATcoverage is done through the use of the generated integration makefile. For +details on how to use this makefile, see :ref:`Integration with +GNATcoverage`. -.. image:: gps_screenshots/7-binary-traces.png +Producing coverage reports through GNATtest's coverage integration makefile +generates the coverage reports under the test driver's object director by +default. However, these reports contain coverage information not for the test +harness project, but for the project being tested with gnattest. -Remove from the toolbar the ``Run GNATcoverage with instrumentation`` in the -same fashion. +If the harness project is opened in GNAT Studio, the coverage data should be +loaded using the actionable `Load Data for All Projects` item. +Visualization of the reports is then done as previously described. GNATtest scenario ================= diff --git a/doc/gnatcov/gps_screenshots/3-cov-level.png b/doc/gnatcov/gps_screenshots/3-cov-level.png index 5e2bb3a64..ea5765fd5 100644 Binary files a/doc/gnatcov/gps_screenshots/3-cov-level.png and b/doc/gnatcov/gps_screenshots/3-cov-level.png differ diff --git a/doc/gnatcov/dhtml-index-lines.png b/doc/gnatcov/html-index-lines.png similarity index 100% rename from doc/gnatcov/dhtml-index-lines.png rename to doc/gnatcov/html-index-lines.png diff --git a/doc/gnatcov/dhtml-index-obligations.png b/doc/gnatcov/html-index-obligations.png similarity index 100% rename from doc/gnatcov/dhtml-index-obligations.png rename to doc/gnatcov/html-index-obligations.png diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst new file mode 100644 index 000000000..f6b2781a8 --- /dev/null +++ b/doc/gnatcov/integrated_instr.rst @@ -0,0 +1,189 @@ +.. _integrated_instr: + +###################################################################### +Producing source traces with integrated instrumentation (experimental) +###################################################################### + +|gcv| provides an alternate way of instrumenting sources, available for C/C++ +under linux and when using gcc or g++ as a compiler. Theoretically, any build +system should be supported, but it has only been tested for the Makefile / CMake +build systems so far. + +As with the workflow involving a separate instrumentation, a :term:`coverage +runtime ` to be used by the instrumented code needs to be +setup as a required prerequisite. Refer to the :ref:`instr-rts` section of this +manual for a description of this step. The installed coverage runtime must be +visible on the ``GPR_PROJECT_PATH``. Note that, by default, |gcvstp| sets up +the coverage runtime for Ada and C/C++. If no Ada toolchain is available, its +support should be explicitly disabled. For instance: + +.. code-block:: sh + + gnatcov setup --restricted-to-languages=C,C++ --prefix=/usr/custom + export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/usr/custom/share/gpr + +Then the process essentially goes like: + +#. Setup the integrated instrumentation process, specifying the instrumentation + parameters (units of interest, coverage level etc.) and the compilers of use. +#. Build the instrumented code using the generated compiler wrapper(s); +#. Execute the program to produce a trace. + +The compiler wrapper embeds knowledge through the ``gnatcov_config.json`` +configuration file that is generated alongside it. It is thus necessary to +re-run the setup step it if the closure of sources of interest, or if the build +environment (e.g. the path for the original compiler) changes. + + +Specifying instrumentation switches +=================================== + +The user specifies the switches through the |gcvsti| command, which accepts any +option accepted by |gcvins|, except the ones using project mechanisms to filter +out units of interest: :cmd-option:`--units` and :cmd-option:`--projects`. Refer +to :ref:`src_traces` for more information regarding the source instrumentation +specific switches. + +As there is no project acting as a units of interest provider, every file that +is not a system header is considered as a file of interest. The user can +explicitly specify files of interest through the :cmd-option:`--files` switch, +which expects a list of full filenames that can be passed through the command +line, or using a response file. + +To generate a compiler wrapper, use the :cmd-option:`--compilers` switch. The +list of supported compilers is ``gcc`` and ``g++``. + +This will generate in the current directory, or in the directory specified by +the :cmd-option:`--output-dir` switch an executable compiler wrapper and a +``gnatcov_config.json`` file along. Note that this configuration file is used to +configure various instrumentation options: it is thus very important that it +resides in the same directory as the compiler wrapper. Note that all of the +instrumentation artifacts, notably SID files that must be passed later to +|gcvcov|, are also generated in the current or specified output directory. + + +Building an instrumented executable +=================================== + +The build process can be run unchanged after it has been configured to use the +generated compiler wrapper instead of the original compiler. + + +Generating a coverage report +============================ + +The coverage generation report is as documented under the section :ref:`scov`. +The coverage obligations are specified through the :cmd-option:`--sid` by +passing the list of files with a sid extension generated by the build of the +instrumented executable, under the output directory that was specified or +implicitly assumed, when running the |gcvsti| command. + + +A simple Makefile example +========================= + +The sources for the following example can be found under the +``share/examples/gnatcoverage/doc/integrated`` directory of the GNAT DAS +distribution. + +The following considers that the coverage runtime was previously installed with +|gcvstp|, and that the ``GPR_PROJECT_PATH`` variable contains its installed +location. See :ref:`instr-rts`. + +Let's consider a simple ``main.cpp`` file: + +.. code-block:: c++ + + #include + + int main(int argc, char **argv){ + std::cout << "Hello World" << std::endl; + return 0; + } + +and the following Makefile: + +.. code-block:: makefile + + CC=g++ + OBJ = main.o + + %.o: %.c + $(CC) -c -o $@ $< + + test: $(OBJ) + $(CC) -o $@ $^ + +We start by configuring the instrumentation process: + +.. code-block:: sh + + cd + gnatcov setup-integration --files=/main.cpp --compilers=g++ + +Then, we launch the build processed unchanged, with the compiler wrapper first +on the path: + +.. code-block:: sh + + export PATH=:$PATH + make + +This will produce an instrumented executable, that will produce a source trace +when run, that can be analyzed with |gcvstp|. + +A simple CMake example +====================== + +The sources for the following example can be found under the +``share/examples/gnatcoverage/doc/integrated`` directory of the GNAT DAS +distribution. To ensure that the Makefile provided with the example sources +uses CMake as a build system, specify ``BUILD_SYSTEM=CMake`` on the `make` +invocation. + +The following considers that the coverage runtime was installed through the use +of |gcvstp|. + +Let's consider a simple ``main.cpp`` file + +.. code-block:: c++ + + #include + + int main(int argc, char **argv){ + std::cout << "Hello World" << std::endl; + return 0; + } + +The CMakeLists.txt file to be used to compile the main.cpp file is : + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.5) + project(HelloWorld) + + add_executable(hello_world main.cpp) + +We start by creating the build directory, and configuring the instrumentation +process there: + +.. code-block:: sh + + cd + mkdir build + cd build + gnatcov setup-integration --files=/main.cpp --compilers=g++ + +This creates a ``g++`` compiler wrapper in the build directory, along with a +``gnatcov_config.json`` file that we intend to use as a proxy for compilation. +To do that, we have to configure the CMake build process accordingly, using the +``CMAKE_CXX_COMPILER`` variable. We run the configuration command in the build +directory: + +.. code-block:: sh + + cmake .. -DCMAKE_CXX_COMPILER=/build/g++ + +The default generator for CMake is "Unix Makefiles", so we can then run the +build process with ``make``, and our executable which will produce a source trace +that can be analyzed by |gcvcov|. diff --git a/doc/gnatcov/run_prereq.rst b/doc/gnatcov/run_prereq.rst index f82797f22..0ebcf524c 100644 --- a/doc/gnatcov/run_prereq.rst +++ b/doc/gnatcov/run_prereq.rst @@ -3,13 +3,24 @@ Compilation prerequisites ========================= +General rules +------------- + If the traces are intended to be used for :ref:`source coverage analysis `, regardless of the actual criteria to be assessed afterwards, sources must be compiled with :cmd-option:`-g -fpreserve-control-flow -fdump-scos` to control optimizations and allow mapping trace info to source constructs. :cmd-option:`-gno-strict-dwarf` is required in addition for VxWorks targets, together with :cmd-option:`-mlongcall` for PowerPC configurations. -Optimization is supported up to :cmd-option:`-O1`, with inlining allowed. + +Optimization is supported up to :cmd-option:`-O1`, with inlining +allowed. However, if the binary version of the code under test during +the coverage campaign is intended to be used directly in operational +conditions, care is needed to prevent inlining of the code under test +within the testing code at compilation time in unit-testing campaigns. +With GCC based toolchains such as GNAT Pro, this can be achieved by +adding :cmd-option:`-fno-inline` to the compilation options of the +testing code. The :cmd-option:`-fprofile-arcs` or :cmd-option:`--coverage` compilation switches, intended for analysis with the gcov tool, are incompatible with the @@ -26,3 +37,33 @@ process might turn simpler if the same compilation options are used for both kinds of analysis. There is no incompatibility with object coverage analysis incurred by compiling the code compiled with options required for source coverage. + +Consolidation related rules +--------------------------- + +For object or source level criteria, |gcv| computes the coverage achieved for +the full set of routines or source units declared to be of interest amongst +those exposed by the union of the exercised executables, as designated by the +set of consolidated traces; + +For the purpose of computing combined coverage achievements, two symbols are +considered overlapping when all the following conditions are met: + +* Both symbols have identical names at the object level, + +* Both symbols have DWARF debug information attached to them, + +* According to this debug information, both symbols originate from the same + compilation unit, denoted by the full path of the corresponding source file. + +By this construction, a symbol missing debug information is never considered +overlapping with any other symbol. Whatever coverage is achieved on such a +symbol never gets combined with anything else and the only kind of report where +the symbol coverage is exposed is the :cmd-option:`=asm` assembly output for +object level criteria. + +Moreover, for object level coverage criteria, |gcvcov| will issue a +consolidation error when two symbols are found to overlap but have +structurally different machine code, which happens for example when the same +unit is compiled with different different optimization levels for +different executables. diff --git a/doc/gnatcov/sample_sc_html_index.png b/doc/gnatcov/sample_sc_html_index.png index a4a7720d8..d9ad654dd 100644 Binary files a/doc/gnatcov/sample_sc_html_index.png and b/doc/gnatcov/sample_sc_html_index.png differ diff --git a/doc/gnatcov/sample_sc_html_unit.png b/doc/gnatcov/sample_sc_html_unit.png index 5a84d68d6..e4f5ad5a0 100644 Binary files a/doc/gnatcov/sample_sc_html_unit.png and b/doc/gnatcov/sample_sc_html_unit.png differ diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 91cfa0e16..0ef0b28f9 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -67,7 +67,9 @@ of this project. Just like :command:`gprbuild`, |gcvstp| accept the :cmd-option:`--RTS`, :cmd-option:`--config` and :cmd-option:`--target` command line options: you need to build the coverage runtime with the same toolchain and runtime as the -ones used to build the application code. For instance: +ones used to build the application code. It also supports a +:cmd-option:`--gargs` option to pass arguments to the :command:`gprbuild` +invocation. For instance: .. code-block:: sh @@ -83,8 +85,30 @@ another location, pass the :cmd-option:`--prefix` option: .. code-block:: sh - gnatcov setup --prefix=/usr/local + gnatcov setup --prefix=/usr/custom +When installing the coverage runtime to a non-default location, tools that +process project files must be instructed how to find the coverage runtime +project file that is installed. To achieve this, update the +``GPR_PROJECT_PATH`` environment variable: + +.. code-block:: sh + + export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/usr/custom/share/gpr + +In addition, when using shared libraries, the environment needs to be updated +so that instrumented programs can load the coverage runtime's own shared +libraries. The following command achieves this in a Unix like environment: + +.. code-block:: sh + + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/gnatcov-rts/lib + +The following command performs the corresponding action on Windows systems: + +.. code-block:: bat + + set PATH=%PATH%;C:\path\to\gnatcov-rts\bin\ Multiple runtimes in the same prefix ------------------------------------ @@ -185,11 +209,66 @@ the options passed to the latter take precedence. For instance: Note that the defaults that |gcvstp| uses for each target platform may change between versions of |gcp|. -.. TODO (U211-014): Document: +Coverage runtime setup for configurations with no Ada runtime +------------------------------------------------------------- + +If the application is not linked against the Ada runtime library (but contains +Ada code), the coverage runtime needs to be setup accordingly, so as not to +rely on any features from the Ada runtime. + +This can be achieved with the :cmd-option:`--no-stdlib` |gcvstp| command line +switch. The resulting coverage runtime only supports a ``manual`` or +``main-end`` dump trigger, and will use a special implementation of the +``base64-stdout`` dump channel, relying on a user-provided function to output +the coverage data. - * the project positional argument (to install an extending coverage runtime - project). +The output function expected by the coverage runtime should have the same +signature as the stdlib's ``putchar`` function: +.. code-block:: C + + extern int gnatcov_rts_putchar(int __c); + +Note that the coverage runtime will ignore the return value. + +In all cases the coverage runtime still requires an implementation of +``memset`` and ``memcpy`` to be provided, either from the C standard library, +or provided by the user. + +.. note:: + This method of providing a function name upon which the coverage library + depends, without adding this information in the project file means that + gprbuild will produce a link command with the assumption that the coverage + runtime does not depend on the instrumented project. This may result in + the executable link failing due to an undefined reference to the output + function symbol name, if the object file is not already pulled in the + executable in a non-instrumented build. + + To work around this, either ensure the output function is defined in a + compilation unit that is part of the executable in a non-coverage build, + or use an extending project to add your own sources to provide the + ``gnatcov_rts_putchar`` symbol, as detailed in the + :ref:`section dedicated to coverage runtime customization`. + +.. note:: + While the coverage runtime does not explicitly depend on any object or function + from the Ada runtime, runtime checks added by the compiler will produce a + reference to the ``__gnat_last_chance_handler`` symbol on configurations that + do not support exception propagation. This in turn means that for + configurations that provide a default implementation of the last chance handler, + such as light runtimes, the runtime checks will implicitly depend on some Ada + runtime symbols. + + If this dependency is a problem, it can be avoided by either providing a user + defined last chance handler, as detailed in the + `GNAT's users guide supplement for cross platforms `_, or by disabling runtime checks during the coverage runtime + setup: + + .. code-block:: + + gnatcov setup --no-stdlib -gargs -gnatp Instrumenting programs ====================== @@ -214,7 +293,7 @@ kinds of operations: --------------------- As for other commands, help on the command line interface is displayed -by ``gnatcov instrument --help``. The general sysopsis is as follows:: +by ``gnatcov instrument --help``. The general synopsis is as follows:: gnatcov instrument --level=<> [OPTIONS] @@ -230,9 +309,9 @@ units, if any are designated by the root project: :cmd-option:`--dump-trigger` selects the execution point at which the output of coverage data should be - injected in main units. This is ``manual`` by default, leaving to users the - responsibility to emit the coverage data as they see fit. Other possible - choices are ``atexit``, ``main-end`` and ``ravenscar-task-termination``. + injected in main units. The default is inferred from the installed + instrumentation runtime. The possible choices are ``manual``, ``atexit``, + ``main-end`` and ``ravenscar-task-termination``. :cmd-option:`--dump-channel` selects the mechanism used to output coverage data at the selected @@ -250,12 +329,17 @@ dump-channel, the ``--dump-filename-<>`` family of switches provides control over the name of trace files. See :ref:`instr-tracename` for more details on the default behavior and possibilities to alter it. +The instrumentation process can be parallelized using the ``-j`` (shorthand for +``--jobs``) switch. ``-j0`` can be used for maximal parallelism, and ``-jN`` +with N > 0 to specify the desired level of concurrency. -Output strategies for main units --------------------------------- +.. _Dump_Triggers: -The choice of a ``--dump-trigger``/``--dump-channel`` pair for main units -depends on the runtime environment available to your program. +Output strategies for coverage information +------------------------------------------ + +The choice of a ``--dump-trigger``/``--dump-channel`` pair for coverage +information dump depends on the runtime environment available to your program. For a native program with access to a full Ada runtime and the associated coverage runtime, ``--dump-channel=bin-file`` is the recommended choice as it @@ -278,12 +362,142 @@ For more restricted environments where, say, there is limited file IO available to the program, a ``--dump-channel=base64-stdout`` kind of output is needed in association with the restricted coverage runtime. -If none of the available automatic triggering option works out well, full +.. _manual_dump: + +If none of the available automatic triggering option work out well, full control is offered by the ``--dump-trigger=manual`` policy where the instrumenter doesn't actually add any code to main units for emitting the -collected coverage data. You will have to emit this data somehow to allow -analysing coverage afterwards, still, and can of course experiment with other -possibilities just to get examples of possible ways to proceed. +collected coverage data. You will have to indicate the point at which you wish +to emit this data by inserting: + +- a ``pragma Annotate (Xcov, Dump_Buffers);`` pragma statement in Ada code; +- a ``/* GNATCOV_DUMP_BUFFERS */`` comment on its own line in C and C++ code + +where necessary in your code. During instrumentation, |gcv| will replace them +with a call to the procedure responsible for dumping the coverage buffers, at +which point the source traces will be created during the execution of the +program. Therefore, the pragma or comment should be placed at a location at +which such a function call would be appropriate. + +By default, gnatcov will look into all the files of the project. Alternatively, +the user can specify the list of files containing manual indications using +``--manual-dump-files=@FILES.list`` or ``--manual-dump-files=FILE1,FILE2`` +where the files are specified as full / relative names. Note that for C / C++ +files, the user shall specify the files where the +``/* GNATCOV_DUMP_BUFFERS */`` indication is ultimately expanded by the +preprocessor. Note that the ``--manual-dump-files`` option requires +``--dump-trigger=manual``, and that the option may be given more than once, +appending to the list of files to look at. + +A dump procedure is only able to dump the buffers of the project tree which +root is the project it is called from. A dump procedure call done in a +subproject will result in a trace containing all code of projects higher in the +project tree marked as not covered. + +One source trace is dumped per call to the dump buffers procedure. For the +``bin-file`` dump configuration, each trace is written in a file which name +depends on the selected trace file naming scheme. For the ``base64-stdout`` +dump configuration the traces are sequentially dumped in the same output file, +from which the |gcv| command ``extrace-base64-trace`` will be able to produce a +source trace file. + +It is also possible to configure the prefix of the trace filename +(see :ref:`instr-tracename` for more details) through these indications: + +- ``pragma Annotate (Xcov, Dump_Buffers, Prefix);`` in Ada code, where + ``Prefix`` resolves to type ``String``; +- ``/* GNATCOV_DUMP_BUFFERS (Prefix) */`` in C or C++ code, where ``Prefix`` + resolves to a null-terminated ``char *`` type. + +No type checking will be done during instrumentation, the values passed as +prefix indications are used as parameters to the buffer dump procedure call. +The Ada procedure call expects a ``String`` parameter, and the C or C++ +functions expect a null-terminated ``const char *``, so in both cases +specifying a string literal is allowed. If the prefix indication does not +resolve to the correct type, the instrumented code will fail to build. + +This can be used in case multiple traces are dumped in rapid succession, to +distinguish between each trace: + +.. code-block:: Ada + + procedure Dump is + Prefix : constant String := "variable"; + begin + -- Ok, Prefix is of type String + -- Trace filename will be "variable-.srctrace" + + pragma Annotate (Xcov, Dump_Buffers, Prefix); + + -- Ok, String literal + -- Trace filename will be "literal-.srctrace" + + pragma Annotate (Xcov, Dump_Buffers, "literal"); + + -- Not ok, Undefined does not resolve to a variable of type String + -- This will fail to compile. + + pragma Annotate (Xcov, Dump_Buffers, Undefined); + end Dump; + +.. code-block:: c + + void dump(void){ + + /* Ok, prefix if type char * and null-terminated. + Trace filename will be "variable-.srctrace" */ + char *prefix = "variable"; + /* GNATCOV_DUMP_BUFFERS (prefix) */ + + /* Ok, string literal. + Trace filename will be "literal-.srctrace" */ + /* GNATCOV_DUMP_BUFFERS ("literal") */ + + /* Not ok, Undefined does not resolve to a null terminated string. + This will not compile. */ + /* GNATCOV_DUMP_BUFFERS (Undefined) */ + } + +.. _buff_reset: + +Resetting coverage information during the execution +--------------------------------------------------- + +|gcvins| offers the possibility to indicate, in the program sources, one or +multiple locations at which the buffers used to track the execution of the +program should be cleared. This can be used in various situations where a finer +grain control of the traces generated by the instrumented program is required. +For instance, this can be used to ignore some initialization phase in the +coverage report, or to emit multiple coverage traces from a single execution of +the instrumented program, each trace containing the coverage information for a +specific part of the execution, such as in a unit test driver. + +This fine grain control of the coverage buffers mandates the use of a manual +dump of the coverage buffers, thus requiring passing the +``--dump-trigger=manual`` command line option to |gcvins| +invocations, as described in :ref:`Dump_Triggers`. + +The buffer reset location indications follow a similar convention as the manual +dump of the traces. Indicating the point at which coverage buffers must be +cleared is done by inserting: + +- a ``pragma Annotate (Xcov, Reset_Buffers);`` pragma statement in Ada code; +- a ``/* GNATCOV_RESET_BUFFERS */`` comment on its own line in C and C++ code + +where necessary. During instrumentation, |gcv| will replace them +with a call to the procedure responsible for clearing the coverage buffers. +Therefore, the pragmas or comments should be placed at locations at which such +a procedure call would be legal and appropriate. + +For performance reasons, no synchronization mechanisms are used to protect the +buffer clear procedure call against concurrent writes in the coverage buffers +(by regular program execution). **It is up to the user to ensure that no other +section of the instrumented code runs concurrently to the buffer clear +procedure, otherwise the correctness of the corresponding coverage report +cannot be guaranteed.** + +Both buffer dump indications and buffer reset indications can be specified in +external annotation files, see :ref:`ext_annot` for more information. .. _instr-tracename: @@ -343,55 +557,202 @@ within the same environment, the variable name for a program can actually be tailored by passing a :cmd-option:`--dump-filename-env-var` switch to |gcvins|, providing the variable name to use. +Support for preprocessing +------------------------- + +|gcvins| automatically detects preprocessor configuration from the compiler +switches present in project files (``-gnatep`` and ``-gnateD`` for Ada sources, +``-D`` and the like for C/C++ sources). It then runs preprocessing on the +source code *before* the instrumentation itself happens. This allows gnatcov +to compute the code coverage only for code that is left "enabled" by +preprocessing directives: disabled code (for instance what follows ``#if Debug +then`` in Ada when the preprocessing symbol ``Debug`` is set to ``False``) is +ignored and thus creates no coverage obligation. Note that consolidation will +not help including code from all "preprocessing branches" in coverage reports, +as gnatcov requires (and checks) that coverage obligations are the same for two +units to consolidate. + +Ada pecularities +^^^^^^^^^^^^^^^^ + +The coverage obligations for code that comes from symbol expansion (for +example, ``$Foo = 42`` expanded into ``My_Variable = 42`` with +``-Dfoo=My_Variable``) designate expanded code. Even though line numbers are +preserved during preprocessing, column numbers may be different between the +original code and the preprocessed code and thus the coverage report. + + +C/C++ pecularities +^^^^^^^^^^^^^^^^^^ + +As a wide variety of compiler switches impacts the preprocessing configuration, +gnatcov supports passing compiler switches to the compiler preprocessor +invocation through the :cmd-option:`-c-opts` and :cmd-option:`-c++-opts`. +Generally speaking, any switch that could impact the preprocessing of the source +(e.g. macro definitions / undefinitions, explicit include paths ...) must be +added to the |gcvins| command line. + +Coverage obligations resulting from macro expansions are designated as such in +detailed (e.g. HTML and XML) coverage reports and their expansions chain is +reported. Note that contrarily to Ada, line and column numbers are preserved in +the coverage report. + .. _instr-limitations: |gcvins| limitations -------------------- -There are situations and code patterns not handeled correctly by |gcvins|. +There are situations and code patterns not handled correctly by |gcvins|. Below are listed the limitations associated with general Ada sources. Coverage of SPARK sources require additional considerations, detailed in section :ref:`spark_instr`. +|gcvins| limitations are inherently bound to the version of the Ada language +used. The version is indicated to the tool via the ``--ada`` command line +switch, which is set to ``2012`` by default. Additionally, |gcvins| can also +retrieve the langage version for a specific source file which contains a +``pragma Ada_nnnn;`` directive. The pragma prevails on the command line +argument. + Unsupported source constructs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -There are a few language constructs that |gcvins| doesn't handle properly. +There are a few language constructs that |gcvins| doesn't support. The tool emits a warning when it encounters such cases and the corresponding -code is not instrumented. Source coverage obligations are still emitted, so -the unsupported constructs will appear as ``not covered`` in the report. +code is not instrumented. Source coverage obligations are still emitted, and +the unsupported constructs will be reported in a separate +``Undetermined_Coverage`` category, to differentiate them from actual coverage +violations. The list of unsupported constructs is as follows: -* Generic expression functions, * Generic null procedures, +* Protected bodies entry guards when the ``Simple_Barriers`` restriction or + the ``Pure_Barriers`` one apply. +* Decisions in default expressions of subprogram formals (for all + decision-related coverage criteria). +* Decisions in default expressions of record component declarations (for MC/DC + coverage criteria). + +Additionally, if the Ada language version in use, is less or equal to Ada 2012, +the following constructs are also unsupported: + +* Generic expression functions, * Recursive expression functions which are primitives of some tagged type, * Expression functions which are primitives of their return type, when it is a tagged type. The simplest way to work around the limitation concerning expression functions -is to turn them into regular funtions, by giving them a proper body, -containing a single return statment with the original expression. +is to turn them into regular functions, by giving them a proper body, +containing a single return statement with the original expression. Otherwise it is possible to exempt those constructs (see :ref:`exemptions`) and/or perform a manual coverage analysis for these special cases. -Global source traces limitations -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The MC/DC instrumentation of decisions with many conditions may require more +memory than available (during instrumentation and/or at run-time) to enumerate +the possible paths through the decision. To avoid this, |gcv| will not +instrument such decisions for MC/DC, emitting a warning in the process, and the +MC/DC coverage for each decision will be reported as ``Undetermined_Coverage`` +state. Should the default limit not be satisfactory, it can be tuned with the +option :cmd-option:`--path-count-limit`. + +Other source-traces limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In Ada, variable or type declarations at the package level can yield elaboration +code. Such code constructs are thus considered to have corresponding coverage +obligations. + +In the case where a ``pragma Preelaborate`` restriction affects the +instrumented unit, variable and type declarations at the package level are not +considered as coverage obligations, although some elaboration code may still be +emitted in rare instances. Note that declarations within a unit constrained by +a ``No_Elaboration_Code`` pragma don't produce coverage obligation either, +which is always correct as no executable code can be emitted by the compiler +for them. There are also a few limitations concerning the source trace workflow as a whole: -- Separate analysis of generic package instances is not supported, -- Preprocessing directives are ignored by the source instrumenter. +- Separate analysis of generic package instances is not supported. + +Additionally, the detected Ada language version can also alter the way some +constructs are instrumented, to use new language features and make the +instrumentation more robust. + +This limitation happens on the decision coverage level, which makes use of +if-expressions to instrument ``elsif`` decisions when the language version is +2012 or above. Toolchain-specific limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ With GNAT versions from 7.1 to 7.3, compiling with optimization will result in coverage violations on all statement obligations associated with expression -functions. Explicitely disabling optimization (with ``-O0`` for instance) will +functions. Explicitly disabling optimization (with ``-O0`` for instance) will resolve this issue. +C/C++ limitations +^^^^^^^^^^^^^^^^^ + +The instrumentation process yields preprocessed versions of the sources. Thus, +it is required to remove any :cmd-option:`-include` switch that is passed to +the compiler invocation, by having a dedicated scenario variable for a coverage +build for instance. + +To support annotations such as :ref:`exemptions` or :ref:`buffer +output indications`, the |gcvins| attempts to preserve comments +when preprocessing the sources. If this is not possible (e.g. due to illegal +concatenation of a comment with another token), the tool will emit a warning +and ignore any in-source annotation for the mentioned file, as well as any +other transitively included file. + +Function and call coverage limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Function and call coverage supports all three Ada, C and C++ languages, +with language-specific limitations. + +For the Ada language, gnatcov is currently unable to provided coverage +information for: + +* Call expressions part of the prefix of a dotted name + +The coverage state of these cases will be reported as undetermined. + +For the C++ language, gnatcov will currently not instrument nor provide +coverage information for: + +* Constructor and Destructor functions + +* Constructor and Destructor calls + +Guarded expression coverage limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Guarded expression coverage is only available for the Ada language. +For implementation reasons, it is only available starting from version 2022 of +the language. + +.. _instr-opti: + +Optimizing the execution of instrumented programs +================================================= + +To monitor the execution of statement obligations, gnatcov instruments the code +which results in an execution overhead. + +To mitigate the performance impact, one can use the +:cmd-option:`--instrument-block switch`. Instead of instrumenting for the +execution of one statement, gnatcov instrument the code for the execution of a +block of statements, greatly reducing the execution overhead. The coverage +report is left unchanged, only the way coverage obligation are discarded is. + +It is important to note that this could result in *false negatives* (i.e. +covered code reported as uncovered) when exceptions are used as a control flow +mechanism, and do not necessarily signal an abnormal termination of the program. +The tool will never report false positives (uncovered code reported as covered). + .. _instr-build: Building instrumented components @@ -411,10 +772,12 @@ reuse of a project hierarchy without replication of the directory structure, not even modification of the project files. For each project in the closure of-interest, the instrumentation generates the -alternative sources in the ``gnatcov-instr`` subdirectory of the project's -object directory. Giving priority to this subdir when it exists is achieved by -passing a :cmd-option:`--src-subdirs` switch to :command:`gprbuild`, naming -that particular relative subdirectory. +alternative sources in the ``PROJECT-gnatcov-instr`` subdirectory of the +project's object directory (replace ``PROJECT`` with the lower cased actual +name of the project: e.g. ``mylib-gnatcov-instr`` for ``mylib.gpr``). Giving +priority to this subdir when it exists is achieved by passing a +:cmd-option:`--src-subdirs` switch to :command:`gprbuild`, naming that +particular relative subdirectory. Then :command:`gprbuild` now supports a :cmd-option:`--implicit-with` option which requests processing every project as if it started with a ``with`` @@ -437,6 +800,22 @@ absolutely require :command:`gprbuild` to build the instrumented programs, even though we have augmented that builder with a few features to make that process very efficient and straightforward. +.. note:: + + The variety of supported compilers/compiler versions/optional warnings makes + it an irrealistic goal for |gcvins| (and source code generators in general) to + produce warning-free code. For instance, a hypothetical compiler is + perfectly allowed to warn when functions have more than X statements; yet it + would not be reasonable for |gcvins| to accomodate this restriction. + + It is important to note that these are warnings (notes that the compiler can + emit on code deemed suspicious, but which do not abort compilation), as + opposed to errors, which do abort compilation. + + For these reasons, the most reasonable thing to do with automatically + generated code is to disable “warnings-as-error†(``-gnatwn`` for GNAT, + ``-Wno-error`` for GCC) when building instrumented code. + Extracting a trace from standard output ======================================= @@ -512,7 +891,7 @@ And to instrument Ada, C and C++ units: Instrumentation and coverage of SPARK code ========================================== -The instrumentation of a SPARK project requires an additionnal step in order +The instrumentation of a SPARK project requires an additional step in order to make the compiler accept the instrumented code. Additionally, some parts of SPARK sources are not processed by the instrumenter, and thus will not have any coverage obligation attached to them. @@ -520,8 +899,8 @@ any coverage obligation attached to them. Inhibiting SPARK related pragmas --------------------------------- -SPARK introduces a certain number of pragmas and aspects to aid the developper -in writting program contracts and guiding the automatic provers. These are only +SPARK introduces a certain number of pragmas and aspects to aid the developer +in writing program contracts and guiding the automatic provers. These are only useful for static proof purposes, and are not used when assessing the coverage of a project during testing. As such, the instrumenter ignores those pragmas/aspects, and the compiler must be instructed to disregard them when @@ -551,12 +930,16 @@ Its contents are: pragma Ignore_Pragma (Refined_Global); pragma Ignore_Pragma (Refined_Depends); +The source for the following example can be found under the +`share/examples/gnatcoverage/spark_instrumentation/` directory of the GNAT DAS +distribution. + The configuration pragma file can be passed to the compiler either by specifying it on the gprbuild command line with the ``-gnatec`` switch:: gprbuild -Pproject --src-subdirs=gnatcov-instr --implicit-with= -cargs:Ada -gnatec=instrument-spark.adc -or by way of a ``Global_Configuration_File`` project file attribute, +or by way of a ``Global_Configuration_Pragmas`` project file attribute, possibly controlled by a scenario variable as in: .. code-block:: ada @@ -564,9 +947,9 @@ possibly controlled by a scenario variable as in: type mode is ("prod", "coverage"); BUILD_MODE : mode := external ("BUILD_MODE", "prod") - package Compiler is + package Builder is case BUILD_MODE is - when "coverage" => for Global_Configuration_File use "instrument-spark.adc"; + when "coverage" => for Global_Configuration_Pragmas use "instrument-spark.adc"; when "prod" => null; end case; end Compiler; @@ -586,7 +969,8 @@ Some parts of SPARK sources do not necessarily generate executable code when compiled, and are mainly used to aid the proof of the program. Computing coverage for such source regions isn't meaningful and are thus ignored by the instrumenter. This means that those regions will not have any -coverage obligation attached to them in the coverage reports. +coverage obligation attached to them in the coverage reports, unless +explicitly requested by enabling the coverage of assertions. The concerned pieces of code are notably: @@ -597,6 +981,11 @@ Note that since no coverage obligations are emitted for such source constructs, they will not appear in the coverage reports even if assertions are enabled and the assertion policy enables the compilation of ghost code. +It is however possible to request coverage information for some contracts that +generate executable code with assertion coverage levels, as described in +:ref:`scov-atc` and :ref:`scov-atcc`. Note that any ghost code that is not +part of a contract will never be instrumented. + .. _examples_src_traces: Example use cases @@ -609,6 +998,10 @@ Here we will consider examining the coverage achieved by the execution of the very basic sample program below, assuming the existence of a ``Sensors`` source unit providing access to some sensor values. +The sources for this example can be found under the +`share/examples/gnatcoverage/doc/cross_example` directory of the GNAT DAS +disctribution. + .. code-block:: ada with Sensors; use Sensors; @@ -637,24 +1030,13 @@ of trace data to standard output. Setting up the coverage runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -We just "build" the runtime library project as we would build a regular -program for our target configuration, specifying the target name and the -intended base Ada runtime library. +As seen in the :ref:`instr-rts` section, we use the ``gnatcov setup`` command to +build and install the :term:`coverage runtime `. For our intended target environment, this would be something like:: - # Copy the sources into a fresh local place for the build: - cp -rp /share/gnatcoverage/gnatcov_rts - - # Build and install the library to a place of our choice. Pick gnatcov_rts.gpr as - # we won't be emitting source trace files directly: - - cd - gprbuild -Pgnatcov_rts.gpr --target=powerpc-wrs-vxworks7r2 --RTS=rtp -f -p - - rm -rf - gprinstall -Pgnatcov_rts.gpr --target=powerpc-wrs-vxworks7r2 --RTS=rtp \ - -p --prefix= + gnatcov setup --target=powerpc-wrs-vxworks7r2 --RTS=rtp \ + --prefix= # Allow references to the coverage runtime project from other project files: export GPR_PROJECT_PATH=/share/gpr @@ -742,23 +1124,17 @@ For the sake of the example, we will consider that by each new test individually or for the current set of tests at a given point in time. +The sources for this example can be found under the +`share/examples/gnatcoverage/doc/library_instr/` directory of the GNAT DAS +distribution. + Setting up the coverage runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -On a native system such as Linux or Windows, the simplest is to pick a -*gnatcov_rts_full.gpr* variant, thanks to which we will be able to produce -trace files directly. We go for a straightforward setup assuming we will use -the default full Ada runtime (no specific :cmd-option:`--RTS` option):: - - # Copy the sources into a fresh local place for the build: - cp -rp /share/gnatcoverage/gnatcov_rts +As seen in the :ref:`instr-rts` section, we use the ``gnatcov setup`` command to +build and install the :term:`coverage runtime `:: - # Build and install the library to a place of our choice. - cd - gprbuild -Pgnatcov_rts_full.gpr -f -p - - rm -rf - gprinstall -Pgnatcov_rts_full.gpr -p --prefix= + gnatcov setup --prefix= # Allow references to the coverage runtime project from other project files: export GPR_PROJECT_PATH=/share/gpr @@ -840,7 +1216,7 @@ such as:: gnatcov instrument -Pcode.gpr -XCODE_LIBMODE=instrument --level=stmt+decision gprbuild -f -Pcode.gpr -XCODE_LIBMODE=build -p - --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full.gpr + --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr Both commands proceed with ``Externally_Built`` ``"False"``. There is no main unit attached to the library per se, so no need for @@ -868,7 +1244,322 @@ the trace file. The build of instrumented tests then proceeds as follows:: gprbuild -Ptests.gpr -p - --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full.gpr + --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr And a regular execution in the host environment would produce a source trace in addition to performing the original functional operations. + + +Coverage runtime customization +============================== + +.. _basic_rts_custom: + +Basics +------ + +Some configurations have constraints that make the default coverage runtime +inadequate. For instance, targeting a board that has no serial port, making the +default implementation for ``--dump-channel=base64-stdout`` ineffective. In +order to accomodate for such special needs, it is possible to extend the +coverage runtime project and add/override some of its sources. + +First, build and install the default coverage runtime (``gnatcov_rts``): + +.. code-block:: sh + + # Add --target / --RTS / --no-stdlib if needed according to the toolchain to use + gnatcov setup + +Then create the project extension. The integration with the |gcvstp| workflow +requires the project file and the sources to be in a dedicated directory: + +.. code-block:: sh + + mkdir my_rts + cat > my_rts/my_rts.gpr < Put, External_Name => "gnatcov_rts_put_string"); + end GNATcov_RTS.Base_IO; + + -- gnatcov_rts-strings.ads + + with Interfaces.C; use Interfaces.C; + + package GNATcov_RTS.Strings is + pragma Pure; + type GNATcov_RTS_String is record + Str : System.Address; + Length : size_t; + end record; + pragma Convention (C_Pass_By_Copy, GNATcov_RTS_String); + end GNATcov_RTS.Strings; + +When Ada support is disabled, override the ``gnatcov_rts_c-base_io.c`` source +file so that it implements the interface described in the (unmodified) +``gnatcov_rts_c-base_io.h`` source file. + +.. code-block:: c + + /* gnatcov_rts_c-base_io.h */ + + #include "gnatcov_rts_c_strings.h" + extern int gnatcov_rts_put_string (struct gnatcov_rts_string str); + + /* gnatcov_rts_c_strings.h */ + + #include + struct gnatcov_rts_string + { + const char *str; + size_t length; + }; + +When the customized runtime needs elaboration +--------------------------------------------- + +Ada units in the coverage runtime are all required to be either pure or +preelaborated (``pragma Pure;`` or ``pragma Preelaborate;``). This requirement +is essential for the instrumenter to generate compilable code for manual +reset/dump of coverage buffers in instrumented Ada units that are themselves +preelaborated: these units will need to have the coverage runtime in their +closure, and it is illegal for a preelaborated unit to have in its closure a +unit that is not either preelaborated or pure. + +This requirement is however impractical in some cases: for instance, on some +targets, coverage buffers may need to be dumped on a custom stream that needs +to be initialized at elaboration time: running initialization code during the +elaboration of the coverage runtime would be handy, but it unfortunately +violates the preelaborated requirement mentionned above. + +Ultimately, it is necessary for this case to work around compiler-enforced +elaboration constraints using interfacing pragmas (``pragma Import``/``pragma +Export``). Assuming that the IO handling code is self-contained and is already +present in the closure of the project to analyze, the following example +demonstrates how to handle this case. The sources can be found under the +`share/examples/gnatcoverage/custom_rt/` directory of the GNAT DAS distribution. + + +First, move the IO handling code to an independent library project: + +.. code-block:: ada + + -- stateful_io.gpr + library project Stateful_IO is + type Any_Library_Type is ("static", "relocatable", "static-pic"); + Library_Type : Any_Library_Type := external ("LIBRARY_TYPE", "static"); + + for Library_Name use "stateful_io"; + for Library_Kind use Library_Type; + for Library_Dir use "lib." & Library_Type; + for Object_Dir use "obj." & Library_Type; + end Stateful_IO; + + -- stateful_io.ads + package Stateful_IO is + procedure Put (S : String); + pragma Export (Ada, Put, "stateful_io_put"); + end Stateful_IO; + + -- stateful_io.adb + with GNAT.IO; + + package body Stateful_IO is + + -- Since we are short-circuiting the Ada compiler's elaboration checks, + -- preserve a manual guard to detect attempts to send data to the IO + -- channel before elaboration has occurred. + + Initialized : Boolean := False; + + procedure Put (S : String) is + begin + if not Initialized then + raise Program_Error with + "attempt to call Stateful_IO.Put before elaboration"; + end if; + + -- Replace the following with the actual code to send data to the IO + -- stream used by coverage data. + + GNAT.IO.Put (S); + end Put; + + begin + -- Here, do whatever necessary to initialize the IO stream + + Initialized := True; + end Stateful_IO; + +Then, bind this code (non preelaborated) to the customized coverage runtime +(``my_rts.gpr`` as in the previous section, preelaborated) using the +interfacing pragmas: + +.. code-block:: ada + + -- gnatcov_rts-base_io.adb + package body GNATcov_RTS.Base_IO is + + procedure Stateful_IO_Put (S : String); + pragma Import (Ada, Stateful_IO_Put, "stateful_io_put"); + + procedure Put (S : GNATcov_RTS_String) is + Str : String (1 .. Integer (S.Length)); + for Str'Address use S.Str; + pragma Import (Ada, Str); + begin + Stateful_IO_Put (Str); + end Put; + + end GNATcov_RTS.Base_IO; + +Finally, make sure that the project file for the instrumented codebase contains +a ``with "stateful_io";`` clause and that at least one of its unit has a ``with +Stateful_IO;`` clause, so that the ``Stateful_IO`` library gets included during +the build of the instrumented project. + + +Building instrumented programs with CCG +======================================= + +Programs instrumented with |gcvins| can be built using the +`GNAT Pro Common Code Generator `_ +provided a few modifications are made to the coverage runtime, and +respecting some limitations in terms of dump-trigger and dump-channel choice. + +Customizing the runtime +----------------------- + +Given the workflow associated with CCG, it is not possible to use the |gcvstp| +command to setup the coverage runtime. Instead, it must be prepared manually. + +The coverage runtime contains both Ada and C sources. When using CCG through +GPRbuild, projects containing C sources are not well handled and some steps of +the build procedure won't be executed. There thus is an external variable to +remove all C sources from the project. This means that C sources must be +manually managed during the executable compilation later on. + +The first step is to copy the runtime sources in a dedicated directory. For the +remainder of this section, it will be denoted by ``ccg_gnatcov_rts``. + +.. code-block:: sh + + mkdir ccg_gnatcov_rts + cp -r /share/gnatcoverage/gnatcov_rts ccg_gnatcov_rts + +Then, C sources not relevant to the coverage runtime for the CCG configuration +must be deleted: + +.. code-block:: sh + + rm ccg_gnatcov_rts/gnatcov_rts_c-base-io.c + rm ccg_gnatcov_rts/gnatcov_rts_c-trace-output-files.* + rm ccg_gnatcov_rts/gnatcov_rts_c-os_interface.* + +Finally, it is necessary to modify the contents of +``ccg_gnatcov_rts/gnatcov_rts-base_io.adb`` to use an alternate medium on which +the execution trace will be output. By default this relies on ``GNAT.IO``, +which is not available in the CCG runtime. One way to modify it is to implement it on top of the ``putchar`` libc function: + +.. code-block:: ada + + declare + function Putchar (C : Integer) return Integer; + pragma Import (C, Putchar); + Ignored : Integer; + begin + for C of Str loop + Ignored := Putchar (Character'Pos (C)); + end loop; + end; + +Otherwise, see :ref:`custom_base_64` for more details on the expected interface +to dump the coverage trace information. + +Building an instrumented program with CCG +----------------------------------------- + +Building an instrumented program with CCG is done in the same manner as with +any other target, with the exception that GPRbuild must be instructed to use +the custom coverage runtime prepared in the previous step, and by setting an +external variable to configure the coverage runtime project for a build with +CCG: + +.. code-block:: sh + + gprbuild -P --src-subdirs=gnatcov-instr \ + --implicit-with=ccg_gnatcov_rts/gnatcov_rts.gpr \ + -XGNATCOV_RTS_FOR_CCG=true \ + + +After the generation of C sources is complete, all the coverage runtime C sources +must be included in the build process of the executable. These can be found +under ``ccg_gnatcov_rts/`` for the sources already present before the gprbuild +invocation, and under ``ccg_gnatcov_rts/obj-gnatcov_rts.static`` for the sources +generated by CCG. The C sources generated from the instrumented Ada sources will +be available in the object directory of their corresponding project. + +Common instrumentation errors +============================= + +Linker error when building instrumented application +--------------------------------------------------- + +If the build of the instrumented programs fails with an undefined reference to a +gnatcov defined symbol (e.g. "xcov_buf_stmt_"), it usually means that the +list of coverage buffers that contain coverage data is not in the closure of the +main. This is typically the case when the main was not instrumented as such, or +when using the manual dump-trigger and inserting a dump buffer annotation in +a source that is not in the main closure. Refer to :ref:`Dump_Triggers` for more +information. diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index 748a59f55..cb1286a3c 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -3,87 +3,61 @@ Specifying *Units Of Interest* ============================== -This chapter describes the means available to convey the set of units on which +This chapter describes the means to convey the set of units on which coverage should be assessed, which we commonly refer to as the :dfn:`units of -interest`, and which are relevant to |gcvins|, |gcvrun| and |gcvcov|. +interest`. + +The first opportunity to do so is at |gcvins| time, with GPR project file +oriented command line switches possibly associated with coverage specific +attributes within project files. This step controls which units are +instrumented to track coverage to begin with. It also needs visibility +over the main subprogram(s) as they require special processing to trigger +the calls dumping coverage data when a program terminates. + +The use of such GPR based mechanisms is also allowed at |gcvcov| time to +further refine the focus of reports or coverage checkpoints. Another mechanism +is available at this point, with lower level command line switches letting +users provide lists of files holding SCO definitions for the units of +interest, where one such file is produced per unit by the |gcvins| command. +When both obligation files and project file options are on the command line, +the former prevail and the project files are only used for switches or the +determination of the target and runtime configuration. + +Regardless of how units of interest were requested, the actual list of units +for which a report is produced can be displayed with the +:cmd-option:`--dump-units-to` option of the |gcvcov| command. This also +displays the list of individually ignored source files for each unit, +controlled by the :cmd-option:`--ignore-source-files` switch. -There are two main families of such means: users would either provide the set -of files which hold the coverage obligations for the units of interest, or -rely on project files facilities to designate the set of units. At analysis -time, the actual list of unit names for which a report or checkpoint is -produced as well as the list of individually ignored source files for each unit -can be displayed with the :cmd-option:`--dump-units-to` option of the -|gcvcov| command. -.. _passing_scos: - -Providing coverage obligation files (:cmd-option:`--scos|--sid`) ----------------------------------------------------------------- - -With the :cmd-option:`--scos` or :cmd-option:`--sid` command line arguments, -users convey the set of units of interest by directly providing the set of -files which contain the coverage obligations for those units. - -The :cmd-option:`--scos` switch is for binary trace based analysis and the -files to provide are the *Library Information* files produced by the compiler -(``.ali`` files for Ada, ``.gli`` files for C). The :cmd-option:`--sid` switch -is for source trace based analysis and the files to provide are the ``.sid`` -*Source Instrumentation Data* files produced by ``gnatcov instrument``. In all -cases, the files are located at the same place as where the object file for a -unit is produced. - -The following paragraphs provide details and examples on the use of -:cmd-option:`--scos` with ``.gli`` or ``.ali`` files. The same principles apply -to :cmd-option:`--sid` with ``.sid`` files. - -Each occurrence of :cmd-option:`--scos` on the command line expects a single -argument which specifies a set of units of interest. Multiple occurrences are -allowed and the sets accumulate. The argument might be either the name of a -single Library Information file for a unit, or a :term:`@listfile arguments -<@listfile argument>` expected to contain a list of such file names. - -For example, focusing on Ada units ``u1``, ``u2`` and ``u3`` can be achieved -with either ``--scos=u1.ali --scos=u2.ali --scos=u3.ali``, with ``--scos=u3.ali ---scos=@lst12`` where ``lst12`` is a text file containing the first two ALI -file names, or with other combinations alike. - -The GNAT toolchain provides a useful device for list computations: the -:cmd-option:`-A` command line argument to :command:`gnatbind` which produces a -list of all the ``.ali`` files involved in an executable construction. By -default, the list goes to standard output. It may be directed to a file on -request with :cmd-option:`-A=`, and users may of course filter -this list as they see fit depending on their analysis purposes. +.. _passing_gpr: -Below is an example sequence of commands to illustrate, using the standard Unix -``grep`` tool to filter out test harness units, assuming a basic naming -convention:: +Using project files (:cmd-option:`-P`, :cmd-option:`--projects`, :cmd-option:`--units`) +--------------------------------------------------------------------------------------- - # Build executable and produce the corresponding list of ALI files. Pass - # -A to gnatbind through gprbuild -bargs then filter out the test units: - gprbuild -p --target=powerpc-elf --RTS=zfp-prep -Pmy.gpr - test_divmod0.adb -fdump-scos -g -fpreserve-control-flow -bargs -A=all.alis +The simplest possible form of units of interest specification with GPR +facilities is a lone:: - # Run and analyse all units except the test harness, filtering out - # the correspond ALI files from the list: - grep -v 'test_[^/]*.ali' all.alis > divmod0.alis - gnatcov run --level=stmt+mcdc --scos=@divmod0.alis - gnatcov coverage --level=stmt+mcdc --annotate=xcov --scos=@divmod0.alis + -P.gpr +provided to both |gcvins| and |gcvcov|. In the absence of coverage related +attributes within the project file(s), this requests considering *of interest* +all the units of ** and its project dependency closure. -.. _passing_gpr: +For |gcvins|, the source files containing main subprograms need to be +encompassed by ``myproject.gpr`` and specified either by a ``Main`` +project file attribute or provided on the command line, as for ``gprbuild`` +commands. -Using project files (:cmd-option:`-P`, :cmd-option:`--projects`, :cmd-option:`--units`) ---------------------------------------------------------------------------------------- +Finer grain control is possible with additional switches and attributes, +letting users first specify the set of :dfn:`projects of interest` where the +units of interest reside, then may filter the *units* of interest therein. -As an alternative to providing the complete list of coverage obligation files -with :cmd-option:`--scos` or :cmd-option:`--sid`, you can use project files to -specify units of interest. When both obligation files and project file options -are on the command line, the former prevail and the project files are only used -for switches or the determination of the target and runtime configuration. +Please note that **non-library aggregate project files are currently not +supported** and will be rejected by |gcv|. The aggregated projects will have +to be processed individually and coverage reports consolidated +:ref:`through checkpoints`, when this makes sense. -The units of interest designation with project files incurs two levels of -selection: first, specify the set of :dfn:`projects of interest` where the -units of interest reside, then specify units of interest therein. Conveying *projects* of interest ******************************** @@ -213,7 +187,7 @@ considered of interest within a project are as follows: attributes are removed from the initial set to yield the set to consider. Finally, the list of units of interest for a given execution of |gcv| can also -be overriden from the command line using the :cmd-option:`--units` switch. +be overridden from the command line using the :cmd-option:`--units` switch. When this option is used, the project files attributes are ignored. The switch may appear multiple times. Each occurrence indicates one @@ -235,6 +209,29 @@ and then executing:: gnatcov --units=@units.list +Conveying *subprograms* of interest (experimental) +************************************************** + +|gcv| enables even finer grain control through the use of ``--subprograms`` +switch, which restricts coverage analysis to the specified list of subprograms +of interest. + +The ``--subprograms`` switch expects a ``:`` argument, where +```` is a source file name path, absolute or relative to the current +directory, pointing to the subprogram source and ``line`` is the first line of +the subprogram specification in Ada, and the first line of the function +definition in C/C++. + +Every coverage obligation from non subprograms of interest is discarded and +reported as *no code* in the various output formats, and the associated coverage +data is ignored. This means that checkpoints will hold coverage data for +subprograms of interest only. + +The ``--subprograms`` switch acts only on subprograms within units of interest. +If a unit was ignored for coverage analysis through a project attribute (e.g. +``Excluded_Units``) or through a command line switch (e.g. ``--units``), the +designated subprogram will be ignored for coverage analysis as well. + .. _gpr_context: Other switches or attributes of importance @@ -254,7 +251,7 @@ as the ``-X`` series setting scenarii variables. In some cases, such as ``--target`` or ``--RTS``, the effect of the command line switch can be achieved with a project file attribute, which |gcp| knows -how to interepret as well. +how to interpret as well. .. _ignore_source_files: @@ -269,6 +266,10 @@ unit of interest encompass some of its testing sources, for example when parts of the testing code is implemented with ``separate`` subunits in Ada. +The sources for the following example can be found under the +`share/examples/gnatcoverage/doc/subunits/` directory of the GNAT DAS +distribution. + The dummy example below shows a possible organization of this kind, with a ``Data_Processing`` package to be tested which contains a ``Test`` procedure declared as a ``separate`` entity:: @@ -315,10 +316,23 @@ one or the other based on a scenario variable:: pragma Assert (Internal_Data < 0); end; + -- run_all.adb; main file to run the test + + with Data_Processing; + procedure Run_All is + begin + Data_Processing.Test; + end; + -- Project file with a Body source file name selection in a -- Naming project package: project P is + + for Object_Dir use "obj"; + for Source_Dirs use ("src"); + for Main use ("run_all.adb"); + TEST := external ("TEST"); package Naming is for Body ("data_processing.test") use "data_processing-" & TEST & ".adb"; @@ -327,16 +341,8 @@ one or the other based on a scenario variable:: Then we can build one variant or the other with:: - -- run_all.adb - - with Data_Processing; - procedure Run_All is - begin - Data_Processing.Test; - end; - - $ gprbuild -Pp.gpr -XTEST=test1 run_all.adb - $ gprbuild -Pp.gpr -XTEST=test2 run_all.adb + $ gprbuild -Pp.gpr -XTEST=test1 + $ gprbuild -Pp.gpr -XTEST=test2 ... As any testing code, such subunits usually need to be excluded from @@ -414,7 +420,7 @@ attributes or :cmd-option:`--units` arguments to elaborate the set of This offers a simple and consistent naming basis to users, orthogonal to the unit/source name mapping. Consider, for example, a project file with the set -of declarations below, which parameterizes the source file name to use for the +of declarations below, which parametrizes the source file name to use for the body of a ``Logger`` package depending on the kind of build performed:: type Build_Mode_Type is ("Production", "Debug"); @@ -465,10 +471,33 @@ Typically, from a sample ``foo.c`` source like: { ... } -``gcc -c foo.c -fdump-scos ...`` would produce a ``foo.o`` object file, a -``foo.c.gli`` companion Library Information file, and excluding it from the -analysis scope can be achieved with:: +excluding ``foo.c`` from the analysis scope can be achieved with:: package Coverage is for Excluded_Units use ("foo.c"); /* source file name here */ end Coverage; + +.. _passing_scos: + +Providing coverage obligation files (:cmd-option:`--sid`) +--------------------------------------------------------- + +With the :cmd-option:`--sid` command line option, users can convey the set of +units of interest by directly providing the set of files which contain the +coverage obligations for those units. + +One such file is produced for each unit instrumented by the |gcvins| command, +next to the object file for a unit, with a `.sid` extension which stands for +*Source Instrumentation Data*. + +Each occurrence of :cmd-option:`--sid` on the command line expects a +single argument which specifies a set of units of interest. Multiple +occurrences are allowed and the sets accumulate. The argument might be +either the name of a single `.sid` file for a unit, or a +:term:`@listfile arguments <@listfile argument>` expected to contain a +list of such file names. + +For example, focusing on Ada units ``u1``, ``u2`` and ``u3`` can be achieved +with either ``--sid=u1.sid --sid=u2.sid --sid=u3.sid``, with ``--sid=u3.sid +--sid=@lst12`` where ``lst12`` is a text file containing the first two SID +file names, or with other combinations alike. diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 22a1056d3..0ae9f618b 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -73,6 +73,9 @@ where specifies the project defining the location of source files. When no file names are provided on the command line, all sources in the project are used as input. This switch is required. + + For the semantics of aggregate project processing by gnattest, see the + :ref:`aggregate_projects` section. * :switch:`{filename}` is the name of the source file containing the library unit package *declaration* @@ -247,6 +250,13 @@ Switches for ``gnattest`` in framework generation mode code under test. + .. index:: --recursive-stub (gnattest) + +:switch:`--recursive-stub` + Used along --stub, indicates gnattest to generate stubs for all the packages + that are withed by the stubbed units, recursively. + + .. index:: --harness-dir (gnattest) :switch:`--harness-dir={dirname}` @@ -307,9 +317,9 @@ Switches for ``gnattest`` in framework generation mode corresponding spec files, one per line. -:switch:`--exclude-from-stubbing:{unit}={filename}` +:switch:`--exclude-from-stubbing:{spec}={filename}` Same as above, but corresponding units will not be stubbed only when testing - specified ``unit``. + unit whose specification is declared in specified ``spec`` file. .. index:: --validate-type-extensions (gnattest) @@ -357,7 +367,9 @@ Switches for ``gnattest`` in framework generation mode :switch:`--exit-status={val}` Specifies whether or not generated test driver should return failure exit status if at least one test fails or crashes. ``val`` can be either - "on" or "off", "off" being the default. + "on" or "off", "off" being the default. If ``--exit-status=on`` is used to + generate the test harness, it should also be used if running the test + drivers via the ``gnattest test_drivers.list`` command. .. index:: --omit-sloc (gnattest) @@ -382,6 +394,14 @@ Switches for ``gnattest`` in framework generation mode Adds time measurements for each test in generated test driver. + .. index:: --reporter (gnattest) + +:switch:`--reporter={val}` + Use specified reporter in the test driver. ``val`` is expected to be a name + of child package of AUnit.Reporter. Test drivers generated with non-default + reporter specified cannot be properly processed by test execution mode of ``gnattest``. + + :switch:`--tests-root`, :switch:`--subdirs` and :switch:`--tests-dir` switches are mutually exclusive. @@ -397,6 +417,12 @@ Switches for ``gnattest`` in test execution mode Specifies whether or not passed tests should be shown. ``val`` can be either "show" or "hide", "show" being the default. +:switch:`--exit-status={val}` + Specifies whether or not generated test driver should return failure exit + status if at least one test fails or crashes. ``val`` can be either + "on" or "off", "off" being the default. The switch ``--exit-status=on`` + should be used both when generating the test harness and when running the + test drivers via the ``gnattest test_drivers.list`` command. .. index:: --queues (gnattest) .. index:: -j (gnattest) @@ -460,10 +486,10 @@ package ``Gnattest``. Here is the list of attributes: is used to specify the file with list of units whose bodies should not be stubbed, otherwise specified by ``--exclude-from-stubbing=filename``. -* ``Stub_Exclusion_List ("unit")`` +* ``Stub_Exclusion_List ("spec")`` is used to specify the file with list of units whose bodies should not - be stubbed when testing "unit", otherwise specified by - ``--exclude-from-stubbing:unit=filename``. + be stubbed when testing "spec", otherwise specified by + ``--exclude-from-stubbing:spec=filename``. Each of those attributes can be overridden from the command line if needed. Other ``gnattest`` switches can also be passed via the project @@ -904,6 +930,35 @@ put under version control. Option ``--omit-sloc`` may be useful when putting test packages under version control. +.. _aggregate_projects: + +Aggregate project handling +-------------------------- + +If the project passed to ``gnattest`` with the ``-P`` switch is an aggregate +project, the aggregated projects will be processed sequentially and +independently. This will result in one harness directory being generated by +default, in the object directories of each of the aggregated projects. + +``gnattest`` will not generate any project file or makefile to automate the +build of the harnesses of each of the aggregated project. + +Artifact directories and aggregate projects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, all artifacts generated by ``gnattest`` are located in +subdirectories of the object directory of each of the aggregated projects. This +in particular means that tests or stubs for a common dependency of two +aggregated projects will be duplicated. In order to avoid this, options such as +``--stubs-dir``., ``--tests-dir`` or ``--subdirs`` can be used, with **relative +paths** so that the artifacts for the common dependencies are generated in the +same location, and re-used across each test harness. + +On the contrary, using ``--harness-dir`` or ``--tests-dir`` with an absolute +path will result in the harness and/or files of a first aggregated project being +overwritten by the generation of the test harness for subsequent aggregated +projects, and should thus be avoided. + .. _Current_Limitations: Current Limitations @@ -923,3 +978,111 @@ The tool currently has the following limitations: may result in elaboration circularities in the generated harness; * heavy usage of preprocessor that affects constructs like subprogram profiles or tagged type hierarchies may result in improper test driver generation. + +.. _Automatic_testcase_generation: + +Automatically generating test cases (experimental) +-------------------------------------------------- + +Please note that all the features described bellow are experimental, and the +interface is subject to change. + +GNATtest has the capability to generate test inputs for subprograms under test. +This test generation feature is also useable in conjunction with GNATfuzz, in +order to use GNATtest harnesses (generated or manually written) as a starting +corpus for a fuzzing session, and to integrate inputs of interest found by +GNATfuzz back into the test harness. For more details, see section +:ref:`Gnattest_Gnatfuzz`. + +.. _Tgen_Env: + +Setting up the test generation runtime +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Generation of values for Ada cannot be fully done statically, as the bounds of +some types may only be defined at runtime. As such, the test generation feature +requires the compilation and installation of a runtime project. + +The sources for that project are located at +``/share/tgen/tgen_rts /tmp/tgen_rts_src + + # Build the project + cd /tmp/tgen_rts_src + gprbuild -P tgen_rts.gpr + + # Install the project (removing the previous one if needed) + gprinstall --uninstall -P tgen_rts.gpr --prefix=/tmp/tgen_rts_install + gprinstall -p -P tgen_rts.gpr --prefix=/tmp/tgen_rts_install + + # Make it available to other tools + export GPR_PROJECT_PATH=/tmp/tgen_rts_install/share/gpr:$GPR_PROJECT_PATH + +Generating test inputs +^^^^^^^^^^^^^^^^^^^^^^ + +``gnattest`` provides a ``--gen-test-vectors`` switch that can be used to +automatically generate test cases for all of the supported subprogram profiles. +The number of generated test cases can be configured through the +``--gen-test-num`` switch. + +``gnattest`` can automatically generate test cases unless any of the following +are true: + +1. Any of the subprogram's "in" or "in out" mode parameters are of an + Access type or contain a sub-component of an Access type. +2. Any of the subprogram's "in" or "in out" mode parameters are Subprogram + Access Types. +3. Any of the subprogram's "in" or "in out" mode parameters are Limited types. +4. Any of the subprogram's "in" or "out" mode parameters are tagged types. +5. Any of the subprogram's "in" or "out" mode parameters is a private type of + a nested package. + +Input value generation currently follows a simple strategy for each input +parameter of the subprogram under test. Parameters of scalar types, and scalar +components of composite types have their values uniformly generated. For +unconstrained array types, a length is randomly chosen between 0 and 10 +elements, then the low bound is randomly chosen and the high bound computed +accordingly to those two first points. + +For record discriminants, different strategies are chosen depending on the use +of the discriminant within the record: If the discriminant constraints a array +component, then the array strategy described above is used. If the discriminant +is used in a variant part, generation will be biased in order to generated all +possible shapes of the record (i.e. explore all variants). Otherwise, these are +generated as any other scalar component. + + +The generated test cases are then stored in a ad-hoc (and yet to be specified) +JSON format, in files under the ``/gnattest/tests/JSON_Tests`` directory. +The generated JSON files are preserved through a ``gnattest`` rerun. The user is +thus free to modify them, to e.g. fill in expected return values, though +backward compatibility of the format is not guaranteed at this stage. + +``gnattest`` also generates Ada files to actually execute the test cases. Each test vector +has its own AUnit test case, and all test cases for a specific subprogram are all +stored in a dedicated file, namely +``-test_data-test__.ad[bs]``, where +```` is the name of the unit in which the subprogram is declared, +```` is the name of the subprogram, and is a hash based +on the profile of the subprogram, in order to differentiate overloads. + +The content of these files are re-generated each time ``gnattest`` is invoked, +independently of the presence of the ``--gen-test-vectors`` switch on the +command line. It is thus not necessary to re-invoke ``gnattest`` with that +switch more than once, unless the goal is to generate additional test inputs. + +.. + TODO: document the --unparse switch diff --git a/doc/index.rst b/doc/index.rst index ad35eb865..552703095 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -8,4 +8,12 @@ gnatcov/gnatcov_part gnattest/gnattest_part + +.. Optional GNATfuzz part + integration/integration_part + +.. Appendix part - manual numbering + +.. toctree:: + gnatcov/gnatcov_bin_part diff --git a/doc/integration/gs_menu.png b/doc/integration/gs_menu.png new file mode 100644 index 000000000..c261b4fef Binary files /dev/null and b/doc/integration/gs_menu.png differ diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 64be188a6..be5f87335 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -34,7 +34,7 @@ consists of two files: The makefile also assumes that the |gcp| runtime is already built and installed, and that the path to its project file is in the environment variable -``GPR_PROJECT_PATH`` so it can be automaticaly located by GPRbuild. +``GPR_PROJECT_PATH`` so it can be automatically located by GPRbuild. It is also possible to specify the path to the project file in the ``GNATCOV_RTS`` variable in the ``coverage_settings.mk`` file. See :ref:`instr-rts` for instructions on building and installing the runtime. @@ -49,11 +49,10 @@ If all the switches that need to be passed to |gcp| are correctly defined in will build and run all the harness projects and then generate a coverage report for all the units under test. -By default, the trace kind (binary or source, see :ref:`selecting_trace_kind`) -used to produce the coverage report will be chosen based on the target of the -root project. Coverage data for a native project will be obtained using -:ref:`source traces `, and coverage for projects targeting a cross -environment will be assessed using :ref:`binary traces `. +By default, coverage data for a native project is obtained using +:ref:`source traces ` and coverage for projects targeting +a cross environment is assessed using :ref:`binary traces +`. For cases where the default behavior isn't appropriate for the project under test, the rules for producing a coverage report from both kind of traces are @@ -75,7 +74,7 @@ the ``Board`` attribute in the package ``Emulator`` needs to be specified in the root project file, or alternatively the ``GNATEMU_BOARD`` variable must be set in the ``coverage_settings.mk`` secondary makefile. -For source traces, the instrumented program will be run using GNATemuator +For source traces, the instrumented program will be run using GNATemulator directly, and assumes that the standard package Ada.GNAT_IO allows data to be output on a serial port. The instrumentation process overrides the two switches :cmd-option:`--dump-trigger` and :cmd-option:`--dump-channel` to the values @@ -211,7 +210,7 @@ example, this would be like: gnatcov instrument -PPkg1.Test_Data.Tests/test_driver.gpr --dump-trigger=main-end --level=stmt --projects=Prj --units=@Pkg1.Test_Data.Tests/units.list Building Pkg1.Test_Data.Tests/test_driver.gpr: - gprbuild -PPkg1.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full + gprbuild -PPkg1.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts ... Running Pkg1.Test_Data.Tests/test_driver.gpr: @@ -227,7 +226,7 @@ example, this would be like: gnatcov instrument -PPkg2.Test_Data.Tests/test_driver.gpr --dump-trigger=main-end --level=stmt --projects=Prj --units=@Pkg2.Test_Data.Tests/units.list Building Pkg2.Test_Data.Tests/test_driver.gpr: - gprbuild -PPkg2.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full + gprbuild -PPkg2.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts ... Running Pkg2.Test_Data.Tests/test_driver.gpr: @@ -292,7 +291,7 @@ example, this would be like: ** END OF REPORT ** The log shows all the steps necessary to obtain coverage results from the -mutliple test drivers, and end with the report. +multiple test drivers, and end with the report. From the coverage report, we see that the only lines not covered are in ``pkg1.adb``, which is expected as the tests corresponding to that unit are @@ -314,7 +313,7 @@ which outputs: gnatcov instrument -Ptest_driver.gpr --dump-trigger=main-end --level=stmt --projects=Prj Building test_driver.gpr: - gprbuild -Ptest_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full + gprbuild -Ptest_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts ... Running test_driver.gpr: GNATCOV_TRACE_FILE=test_driver-gnattest_td.srctrace ./test_driver @@ -462,3 +461,68 @@ created in the same directory as each ``test_driver.gpr`` file. This file contains the name of the unit tested by the driver, and can be used to specify to |gcv| to only process the unit under test, by adding the switch :cmd-option:`--units=@units.list`. + +.. _Gnattest_Gnatfuzz: + +########################################### +Using GNATtest with GNATfuzz (experimental) +########################################### + +This section presents how a pre-existing GNATtest test harness can be used as +a starting corpus for a GNATfuzz fuzzing campaign, and how inputs of interest +found by GNATfuzz can be imported back into a GNATtest harness. These features +are still experimental; the workflow and command line interface may change in +the future. + +************************** +Setting up the environment +************************** + +To ensure the entire workflow functions properly, it's crucial to configure +the various tools by setting specific environment variables. + +The first step is to setup the value generation runtime library. For detailed +instructions on how to do so, see :ref:`Tgen_Env`. + +******************************************* +Using GNATStudio to perform the integration +******************************************* + +The simplest way to sequence the invocations of the two tools is to use the +GNATstudio integration plugin. + +First, create a GNATtest harness project if it doesn't already exist, using the +``Analyze -> GNATtest -> Generate harness project`` entries in the menu bar. +Note that in the dialog box opening there is an option to generate tests inputs +if needed. + +Then, exporting tests inputs from GNATtest to GNATfuzz and running a fuzzing +campaign on a specific subprogram can be done by right-clicking on the +declaration of the target subprogram, then selecting +``GNATtest -> Start/Stop fuzzing subprogram``, as illustrated bellow. + +.. Image:: gs_menu.png + +This will first instrument sources and re-generate the GNATtest harness in order +to be able to intercept the inputs passed to the subprogram, then run the test +harness, dumping the inputs in a binary format that can be used by GNATfuzz. +GNATstudio will then setup a fuzzing session on the subprogram, for which the +parameters can be controlled through the various pop-up windows that will be +displayed during the process. + +``gnatfuzz`` will periodically export newly found inputs in a human readable +JSON format under ``/gnattest/test/JSON_Tests``, where ```` designates +the object directory of the project. + +The fuzzing session will stop once all the stopping criteria have been met. The +fuzzing session can also be stopped early by right clicking on the subprogram +declaration, then selecting ``GNATtest => Start/Stop fuzzing subprogram``. + +After the fuzzing sessions has ended, a new GNATtest harness will be +regenerated, including the tests exported by the GNATfuzz session. These will +appear in +``/gnattest/tests/-test_data-test__.adb``, +where ```` is the name of the unit in which the subprogram is +declared, ```` is the name of the subprogram, and is a +hash based on the profile of the subprogram, in order to differentiate +overloads. diff --git a/doc/latex_preamble.inc b/doc/latex_preamble.inc index 9d2f7249e..bbf4720f1 100644 --- a/doc/latex_preamble.inc +++ b/doc/latex_preamble.inc @@ -3,6 +3,12 @@ \let\oldpart\part \renewcommand{\part}[1]{\oldpart{#1}\gdef\parttitle{#1}} +% Arrange to reset chapter numbering at the start of each "part" +\makeatletter +\@addtoreset{chapter}{part} +\makeatother + +% Setup page headers and footers \makeatletter \fancypagestyle{normal}{ \fancyhf{} diff --git a/env/env.yaml b/env/env.yaml new file mode 100644 index 000000000..3ec3c3591 --- /dev/null +++ b/env/env.yaml @@ -0,0 +1,10 @@ +coding_standard: adacore +ada_version: '2012' + +target_exec: '' +runtime: '' + +version_number: 0.00 (YYYYMMDD) + +tags: [] + diff --git a/examples/integration/prj.gpr b/examples/integration/prj.gpr index 03ca6e950..97dfbe728 100644 --- a/examples/integration/prj.gpr +++ b/examples/integration/prj.gpr @@ -2,7 +2,7 @@ project Prj is for Source_Dirs use ("src"); for Object_Dir use "obj"; - + package Coverage is Cov_Level := ("--level=stmt"); for Switches ("instrument") use ("--dump-trigger=main-end") & Cov_Level; diff --git a/qualification/qm/LRM/lrm_ref.txt b/qualification/LRM/lrm_ref.txt similarity index 100% rename from qualification/qm/LRM/lrm_ref.txt rename to qualification/LRM/lrm_ref.txt diff --git a/qualification/LRM/lrm_ref_.txt b/qualification/LRM/lrm_ref_.txt new file mode 100644 index 000000000..cb5bda93d --- /dev/null +++ b/qualification/LRM/lrm_ref_.txt @@ -0,0 +1,252 @@ +# secnum # Ada revs # sectitle # applicable? # comment # +# ---------#----------#--------------------------------------------------------- #------------ #--------------------------# +# # # # # # +1 # 95,05,12 # General # no # General overview material +1.1 # 95,05,12 # Scope # no # Not relevant to SCA +1.1.1 # 95,05,12 # Extent # no # Not relevant to SCA +1.1.2 # 95,05,12 # Structure # no # Not relevant to SCA +1.1.3 # 95,05,12 # Conformity of an Implementation with the Standard # no # Not relevant to SCA +1.1.4 # 95,05,12 # Method of Description and Syntax Notation # no # Not relevant to SCA +1.1.5 # 95,05,12 # Classification of Errors # no # Not relevant to SCA +1.2 # 95,05,12 # Normative References # no # Not relevant to SCA +1.3 # 95,05 # Definitiona # no # Not relevant to SCA +1.3 # 12 # Terms and Definitions # no # Not relevant to SCA + +2 # 95,05,12 # Lexical Elements # no # General overview material +2.1 # 95,05,12 # Character Set # no # Not relevant to SCA +2.2 # 95,05,12 # Lexical Elements, Separators, and Delimiters # no # Not relevant to SCA +2.3 # 95,05,12 # Identifiers # no # Not relevant to SCA +2.4 # 95,05,12 # Numeric Literals # no # Not relevant to SCA +2.4.1 # 95,05,12 # Decimal Literals # no # Not relevant to SCA +2.4.2 # 95,05,12 # Based Literals # no # Not relevant to SCA +2.5 # 95,05,12 # Character Literals # no # Not relevant to SCA +2.6 # 95,05,12 # String Literals # no # Not relevant to SCA +2.7 # 95,05,12 # Comments # no # Not relevant to SCA +2.8 # 95,05,12 # Pragmas # yes # +2.9 # 95,05,12 # Reserved Words # no # Not relevant to SCA + +3 # 95,05,12 # Declarations and Types # no # General overview material +3.1 # 95,05,12 # Declarations # no # This is a general overview section; TOR references are supplied for the associated specific sections. Only declarations that result in generated code are considered to have SCA obligations. +3.2 # 95,05,12 # Types and Subtypes # no # General overview material +3.2.1 # 95,05,12 # Type Declarations # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +3.2.2 # 95,05,12 # Subtype Declarations # yes # +3.2.3 # 95,05,12 # Classification of Operations # no # Not relevant to SCA +3.2.4 # 12 # Subtype Predicates # yes # +3.3 # 95,05,12 # Objects and Named Numbers # no # General overview material +3.3.1 # 95,05,12 # Object Declarations # yes # +3.3.2 # 95,05,12 # Number Declarations # no # Not relevant to SCA +3.4 # 95,05,12 # Derived Types and Classes # no # Covered by 3.2.2 +3.4.1 # 95,05,12 # Derivation Classes # no # Not relevant to SCA +3.5 # 95,05,12 # Scalar Types # no # Covered by subsections +3.5.1 # 95,05,12 # Enumeration Types # yes # +3.5.2 # 95,05,12 # Character Types # yes # +3.5.3 # 95,05,12 # Boolean Types # yes # +3.5.4 # 95,05,12 # Integer Types # yes # +3.5.5 # 95,05,12 # Operations of Discrete Types # no # Not relevant to SCA +3.5.6 # 95,05,12 # Real Types # no # Deferred to 3.5.7 and 3.5.9 +3.5.7 # 95,05,12 # Floating Point Types # yes # +3.5.8 # 95,05,12 # Operations of Floating Point Types # no # Not relevant to SCA +3.5.9 # 95,05,12 # Fixed Point Types # yes # +3.5.10 # 95,05,12 # Operations of Fixed Point Types # no # Not relevant to SCA +3.6 # 95,05,12 # Array Types # yes # +3.6.1 # 95,05,12 # Index Constraints and Discrete Ranges # yes # +3.6.2 # 95,05,12 # Operations of Array Types # no # Not relevant to SCA +3.6.3 # 95,05,12 # String Types # no # Not relevant to SCA +3.7 # 95,05,12 # Discriminants # no # Not relevant to SCA +3.7.1 # 95,05,12 # Discriminant Constraints # no # Not relevant to SCA +3.7.2 # 95,05,12 # Operations of Discriminated Types # no # Covered by 4.1.4 +3.8 # 95,05,12 # Record Types # partial # SCA obligations are associated with default initializations for record components +3.8.1 # 95,05,12 # Variant Parts and Discrete Choices # yes # +3.9 # 95,05,12 # Tagged Types and Type Extensions # no # Covered by subsections +3.9.1 # 95,05,12 # Type Extensions # no # Not relevant to SCA +3.9.2 # 95,05,12 # Dispatching Operations of Tagged Types # yes # +3.9.3 # 95,05,12 # Abstract Types and Subprograms # no # Not relevant to SCA +3.9.4 # 05,12 # Interface Types # yes # +3.10 # 95,05,12 # Access Types # partial # SCA obligations are associated with default initializations for access values +3.10.1 # 95,05,12 # Incomplete Type Declarations # no # Not relevant to SCA +3.10.2 # 95,05,12 # Operations of Access Types # no # Not relevant to SCA +3.11 # 95,05,12 # Declarative Parts # no # SCA obligations for a declarative_part are covered in other sections: either for the unit in which the declarative_part occurs, or the constituent declarative_items in the declarative_part +3.11.1 # 95,05,12 # Completions of Declarations # no # Not relevant to SCA + +4 # 95,05,12 # Names and Expressions # no # General overview material +4.1 # 95,05,12 # Names # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +4.1.1 # 95,05,12 # Indexed Components # partial # This section applies when the indexed component is an element of a Boolean array and is used as a condition +4.1.2 # 95,05,12 # Slices # no # Not relevant to SCA +4.1.3 # 95,05,12 # Selected Components # partial # This section applies when the selected component is a Boolean value and is used as a condition +4.1.4 # 95,05,12 # Attributes # partial # This section applies when the attribute is a Boolean value and is used as a condition +4.1.5 # 12 # User-Defined References # yes # +4.1.6 # 12 # User-Defined Indexing # yes # +4.2 # 95,05,12 # Literals # no # Not relevant to SCA +4.3 # 95,05,12 # Aggregates # no # Not relevant to SCA +4.3.1 # 95,05,12 # Record Aggregates # no # Not relevant to SCA +4.3.2 # 95,05,12 # Extension Aggregates # no # Not relevant to SCA +4.3.3 # 95,05,12 # Array Aggregates # no # Not relevant to SCA +4.4 # 95,05,12 # Expressions # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +4.5 # 95,05,12 # Operators and Expression Evaluation # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +4.5.1 # 95,05,12 # Logical Operators and Short-circuit Control Forms # yes # +4.5.2 # 95,05,12 # Relational Operators and Membership Tests # yes # +4.5.3 # 95,05,12 # Binary Adding Operators # no # Not relevant to SCA +4.5.4 # 95,05,12 # Unary Adding Operators # no # Not relevant to SCA +4.5.5 # 95,05,12 # Multiplying Operators # no # Not relevant to SCA +4.5.6 # 95,05,12 # Highest Precedence Operators # partial # The "not" operator is the only highest_precedence_operator relevant to SCA +4.5.7 # 12 # Conditional Expressions # yes # +4.5.8 # 12 # Quantified Expressions # yes # +4.6 # 95,05,12 # Type Conversions # partial # This section applies when the type conversion is to type Boolean and is used as a condition +4.7 # 95,05,12 # Qualified Expressions # partial # This section applies when the type qualification is to type Boolean and is used as a condition +4.8 # 95,05,12 # Allocators # no # Not relevant to SCA +4.9 # 95,05,12 # Static Expressions and Static Subtypes # no # SCA-related requirements for static expressions are the same as for non-static expressions and are addressed in the corresponding sections +4.9.1 # 95,05,12 # Statically Matching Constraints and Subtypes # no # Not relevant to SCA + +5 # 95,05,12 # Statements # no # General overview material +5.1 # 95,05,12 # Simple and Compound Statements - Sequences of Statements # partial # This is a general syntax section; the null statement is specifically addressed here, all others covered elsewhere. +5.2 # 95,05,12 # Assignment Statements # yes # +5.3 # 95,05,12 # If Statements # yes # +5.4 # 95,05,12 # Case Statements # yes # +5.5 # 95,05,12 # Loop Statements # yes # +5.5.1 # 12 # User-Defined Iterator Types # yes # +5.5.2 # 12 # Generalized Loop Iteration # yes # +5.6 # 95,05,12 # Block Statements # yes # +5.7 # 95,05,12 # Exit Statements # yes # +5.8 # 95,05,12 # Goto Statements # yes # + +6 # 95,05,12 # Subprograms # no # General overview material +6.1 # 95,05,12 # Subprogram Declarations # no # Not relevant to SCA +6.1.1 # 12 # Preconditions and Postconditions # yes # +6.2 # 95,05,12 # Formal Parameter Modes # no # Not relevant to SCA +6.3 # 95,05,12 # Subprogram Bodies # no # SCA obligations are associated with the constituents of the subprogram body +6.3.1 # 95,05,12 # Conformance Rules # no # Not relevant to SCA +6.3.2 # 95,05,12 # Inline Expansion of Subprograms # yes # +6.4 # 95,05,12 # Subprogram Calls # yes # +6.4.1 # 95,05,12 # Parameter Associations # no # Covered by 6.4 +6.5 # 95,05,12 # Return Statements # yes # +6.5.1 # 05 # Pragma No_Return # yes # +6.5.1 # 12 # Nonreturning Procedures # yes # +6.6 # 95,05,12 # Overloading of Operators # no # Not relevant to SCA +6.7 # 05,12 # Null Procedures # yes # +6.8 # 12 # Expression Functions # yes # + +7 # 95,05,12 # Packages # no # General overview material +7.1 # 95,05,12 # Package Specifications and Declarations # no # SCA obligations are associated with the constituent basic_declarative_items in the package_specification +7.2 # 95,05,12 # Package Bodies # no # SCA obligations are associated with the constituent declarations and statements in the package_body +7.3 # 95,05,12 # Private Types and Private Extensions # no # Not relevant to SCA +7.3.1 # 95,05,12 # Private Operations # no # Not relevant to SCA +7.3.2 # 12 # Type Invariants # yes # +7.4 # 95,05,12 # Deferred Constants # yes # +7.5 # 95,05,12 # Limited Types # no # Not relevant to SCA +7.6 # 95,05 # User-Defined Assignment and Finalization # no # GNATcoverage is not qualified for controlled type definitions +7.6 # 12 # Assignment and Finalization # no # Only relevant to task types, protected types and controlled type definitions, for which GNATcoverage is not qualified +7.6.1 # 95,05,12 # Completion and Finalization # no # Only relevant to task types, protected types and controlled type definitions, for which GNATcoverage is not qualified + +8 # 95,05,12 # Visibility Rules # no # General overview material +8.1 # 95,05,12 # Declarative Region # no # Not relevant to SCA +8.2 # 95,05,12 # Scope of Declarations # no # Not relevant to SCA +8.3 # 95,05,12 # Visibility # no # Not relevant to SCA +8.3.1 # 05,12 # Overriding Indicators # yes # +8.4 # 95,05,12 # Use Clauses # no # Not relevant to SCA +8.5 # 95,05,12 # Renaming Declarations # no # Not relevant to SCA +8.5.1 # 95,05,12 # Object Renaming Declarations # no # Not relevant to SCA +8.5.2 # 95,05,12 # Exception Renaming Declarations # no # Not relevant to SCA +8.5.3 # 95,05,12 # Package Renaming Declarations # no # Not relevant to SCA +8.5.4 # 95,05,12 # Subprogram Renaming Declarations # no # Not relevant to SCA +8.5.5 # 95,05,12 # Generic Renaming Declarations # no # Not relevant to SCA +8.6 # 95,05,12 # The Context of Overload Resolution # no # Not relevant to SCA + +9 # 95,05,12 # Tasks and Synchronization # no # GNATcoverage is not qualified for tasking constructs +9.1 # 95,05,12 # Task Units and Task Objects # no # GNATcoverage is not qualified for tasking constructs +9.2 # 95,05,12 # Task Execution - Task Activation # no # GNATcoverage is not qualified for tasking constructs +9.3 # 95,05,12 # Task Dependence - Termination of Tasks # no # GNATcoverage is not qualified for tasking constructs +9.4 # 95,05,12 # Protected Units and Protected Objects # no # GNATcoverage is not qualified for tasking constructs +9.5 # 95,05,12 # Intertask Communication # no # GNATcoverage is not qualified for tasking constructs +9.5.1 # 95,05,12 # Protected Subprograms and Protected Actions # no # GNATcoverage is not qualified for tasking constructs +9.5.2 # 95,05,12 # Entries and Accept Statements # no # GNATcoverage is not qualified for tasking constructs +9.5.3 # 95,05,12 # Entry Calls # no # GNATcoverage is not qualified for tasking constructs +9.5.4 # 95,05,12 # Requeue Statements # no # GNATcoverage is not qualified for tasking constructs +9.6 # 95,05,12 # Delay Statements, Duration, and Time # no # GNATcoverage is not qualified for tasking constructs +9.6.1 # 05,12 # Formatting, Time Zones, and other operations for Time # no # GNATcoverage is not qualified for tasking constructs +9.7 # 95,05,12 # Select Statements # no # GNATcoverage is not qualified for tasking constructs +9.7.1 # 95,05,12 # Selective Accept # no # GNATcoverage is not qualified for tasking constructs +9.7.2 # 95,05,12 # Timed Entry Calls # no # GNATcoverage is not qualified for tasking constructs +9.7.3 # 95,05,12 # Conditional Entry Calls # no # GNATcoverage is not qualified for tasking constructs +9.7.4 # 95,05,12 # Asynchronous Transfer of Control # no # GNATcoverage is not qualified for tasking constructs +9.8 # 95,05,12 # Abort of a Task - Abort of a Sequence of Statements # no # GNATcoverage is not qualified for tasking constructs +9.9 # 95,05,12 # Task and Entry Attributes # no # GNATcoverage is not qualified for tasking constructs +9.10 # 95,05,12 # Shared Variables # no # GNATcoverage is not qualified for tasking constructs +9.11 # 95,05,12 # Example of Tasking and Synchronization # no # GNATcoverage is not qualified for tasking constructs + +10 # 95,05,12 # Program Structure and Compilation Issues # no # General overview material +10.1 # 95,05,12 # Separate Compilation # no # Not relevant to SCA +10.1.1 # 95,05,12 # Compilation Units - Library Units # no # Not relevant to SCA +10.1.2 # 95,05,12 # Context Clauses - With Clauses # no # Not relevant to SCA +10.1.3 # 95,05,12 # Subunits of Compilation Units # no # Not relevant to SCA +10.1.4 # 95,05,12 # The Compilation Process # no # Not relevant to SCA +10.1.5 # 95,05,12 # Pragmas and Program Units # no # Not relevant to SCA +10.1.6 # 95,05,12 # Environment-Level Visibility Rules # no # Not relevant to SCA +10.2 # 95,05,12 # Program Execution # no # SCA obligations are associated with the constituents of the units comprising the program's partitions +10.2.1 # 95,05,12 # Elaboration Control # no # SCA obligations are associated with the constituents of the units whose elaboration is controlled by the pragmas defined in this section + +11 # 95,05,12 # Exceptions # no # General overview material +11.1 # 95,05,12 # Exception Declarations # no # Not relevant to SCA +11.2 # 95,05,12 # Exception Handlers # yes # +11.3 # 95,05,12 # Raise Statements # yes # +11.4 # 95,05,12 # Exception Handling # partial # The semantics for control transferring to a local handler are described in 11.2. The more general propagation described in 11.4 is only partially supported, see the :ref:`operational-conditions` section of this document. +11.4.1 # 95,05,12 # The Package Exceptions # no # The only subprogram defined in Ada.Exceptions that has SCA obligations is Raise_Exception, and this has the same treatment as the raise statement (11.3) +11.4.2 # 95 # Example of Exception Handling # no # Not relevant to SCA +11.4.2 # 05,12 # Pragmas Assert and Assertion_Policy # yes # +11.4.3 # 05,12 # Example of Exception Handling # no # Not relevant to SCA +11.5 # 95,05,12 # Suppressing Checks # no # Not relevant to SCA +11.6 # 95,05,12 # Exceptions and Optimization # no # Not relevant to SCA + +12 # 95,05,12 # Generic Units # no # General overview material +12.1 # 95,05,12 # Generic Declarations # no # The SCA obligations of generic declarations are only manifest at instantiations (12.3) +12.2 # 95,05,12 # Generic Bodies # no # The SCA obligations of generic bodies are only manifest at instantiations (12.3) +12.3 # 95,05,12 # Generic Instantiation # yes # +12.4 # 95,05,12 # Formal Objects # no # Not relevant to SCA +12.5 # 95,05,12 # Formal Types # no # Not relevant to SCA +12.5.1 # 95,05,12 # Formal Private and Derived Types # no # Not relevant to SCA +12.5.2 # 95,05,12 # Formal Scalar Types # no # Not relevant to SCA +12.5.3 # 95,05,12 # Formal Array Types # no # Not relevant to SCA +12.5.4 # 95,05,12 # Formal Access Types # no # Not relevant to SCA +12.5.5 # 05,12 # Formal Interface Types # no # Not relevant to SCA +12.6 # 95,05,12 # Formal Subprograms # no # Not relevant to SCA +12.7 # 95,05,12 # Formal Packages # no # Not relevant to SCA +12.8 # 95,05,12 # Example of a Generic Package # no # Not relevant to SCA + +13 # 95,05,12 # Representation Issues # no # General overview material +13.1 # 95,05 # Operational and Representation Items # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +13.1 # 12 # Operational and Representation Aspects # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +13.1.1 # 12 # Aspect Specifications # no # Not relevant to SCA. Particular aspects are, e.g. Precondition, and these are handled as part of their specific section. +13.2 # 95,05 # Pragma Pack # partial # Use of packed component in decisions +13.2 # 12 # Packed Types # partial # Use of packed component in decisions +13.3 # 95 # Representation Attributes # partial # The only construct relevant to SCA is the address attribute definition +13.3 # 05,12 # Operational and Representation Attributes # partial # The only construct relevant to SCA is the address attribute definition +13.4 # 95,05,12 # Enumeration Representation Clauses # no # Not relevant to SCA +13.5 # 95,05,12 # Record Layout # no # General overview material +13.5.1 # 95,05,12 # Record Representation Clauses # yes # +13.5.2 # 95,05,12 # Storage Place Attributes # no # Not relevant to SCA +13.5.3 # 95,05,12 # Bit Ordering # yes # +13.6 # 95,05,12 # Change of Representation # no # Not relevant to SCA +13.7 # 95,05,12 # The Package System # partial # The only consitutents of package System that are relevant to SCA are the relational operators for type Address +13.7.1 # 95,05,12 # The Package System.Storage_Elements # no # Not relevant to SCA +13.7.2 # 95,05,12 # The Package System.Address_To_Access_Conversions # no # Not relevant to SCA +13.8 # 95,05,12 # Machine Code Insertions # yes # +13.9 # 95,05,12 # Unchecked Type Conversions # no # Not relevant to SCA +13.9.1 # 95,05,12 # Data Validity # no # General overview material +13.9.2 # 95,05,12 # The Valid Attribute # no # Covered by 4.1.4 +13.10 # 95,05,12 # Unchecked Access Value Creation # no # Not relevant to SCA +13.11 # 95,05,12 # Storage Management # no # Not relevant to SCA +13.11.1 # 95,05 # The Max_Size_In_Storage_Elements Attribute # no # Not relevant to SCA +13.11.1 # 12 # Storage Allocation Attributes # no # Not relevant to SCA +13.11.2 # 95,05,12 # Unchecked Storage Deallocation # no # Not relevant to SCA +13.11.3 # 95,05 # Pragma Controlled # no # Not relevant to SCA +13.11.3 # 12 # Default Storage Pools # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.11.4 # 12 # Storage Subpools # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.11.5 # 12 # Subpool Reclamation # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.11.6 # 12 # Storage Subpool Example # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.12 # 95,05 # Pragma Restrictions # no # Not relevant to SCA +13.12 # 12 # Pragma Restrictions and Pragma Profile # no # Not relevant to SCA +13.12.1 # 05 # Language-Defined Restrictions # no # Not relevant to applicable SCA +13.12.1 # 12 # Language-Defined Restrictions and Profiles # no # Not relevant to applicable SCA +13.13 # 95,05,12 # Streams # no # General overview material +13.13.1 # 95,05,12 # The Package Streams # no # Not relevant to SCA +13.13.2 # 95,05,12 # Stream-Oriented Attributes # no # Not relevant to SCA +13.14 # 95,05,12 # Freezing Rules # no # Not relevant to SCA diff --git a/qualification/Makefile.common b/qualification/Makefile.common new file mode 100644 index 000000000..9c9600817 --- /dev/null +++ b/qualification/Makefile.common @@ -0,0 +1,58 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +CONFDIR = ../../gnatcheck_qualkit_common +SOURCEDIR = .. +SPHINXOPTS = -c $(CONFDIR) +SPHINXBUILD = DOC_NAME=$(DOC) TOOL_DIR=$(TOOL) MASTER=$(MASTER_DOC) sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + + +pdf: + @echo "Copying adacore.png to $(BUILDDIR)/pdf" + @echo "Source: $(CONFDIR)/adacore.png" + @echo "Destination: $(BUILDDIR)/pdf" + @if [ -f $(CONFDIR)/adacore.png ]; then echo "Source file exists"; else echo "Source file does not exist"; fi + @if [ -d $(BUILDDIR)/pdf ]; then echo "Destination directory exists"; else echo "Creating destination directory"; mkdir -p $(BUILDDIR)/pdf; fi + cp $(CONFDIR)/adacore.png $(BUILDDIR)/pdf + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/pdf + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/pdf all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/pdf." + +.PHONY: all +all : html latexpdf diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/obj/.gitignore b/qualification/__init__.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/obj/.gitignore rename to qualification/__init__.py diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 68d06fba0..397f1efbf 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -158,7 +158,7 @@ # | # | (clone by genbundle.py) # v -# $work-dir/ gnatcoverage-git-clone/ +# $work-dir/ # qualification/qm/plans/ <- PLANS artifacts # testsuite/ <- TOR artifacts # @@ -192,44 +192,53 @@ # ***************************************************************************** from e3.os.process import Run -from e3.fs import cp, mv, rm, mkdir, ls, find +from e3.fs import cp, mv, rm, mkdir, ls, find, sync_tree from datetime import date -import optparse, sys, os.path, shutil, re, hashlib +import hashlib +import optparse +import os.path +import re +import sys -# This lets us access modules that the testuite +# This lets us access modules that the testsuite # code features: -MY_TESTSUITE_DIR=os.path.abspath("../testsuite") +MY_TESTSUITE_DIR = os.path.abspath("../testsuite") sys.path.append(MY_TESTSUITE_DIR) -from SUITE.qdata import CTXDATA_FILE, treeref_at -from SUITE.cutils import contents_of, output_of -from SUITE.dutils import jload_from +from SUITE.qdata import CTXDATA_FILE, treeref_at # noqa: E402 +from SUITE.cutils import contents_of, output_of # noqa: E402 +from SUITE.dutils import jload_from # noqa: E402 # ======================================================================= # == MISC UTILITY FUNCTIONS == # ======================================================================= -class Error (Exception): + +class Error(Exception): def __init__(self): pass -def fail_if (p, msg): + +def fail_if(p, msg): if p: print(msg) raise Error -def exit_if (p, msg): + +def exit_if(p, msg): if p: print(msg) sys.exit(1) -def warn_if (p, msg): + +def warn_if(p, msg): if p: print("\n!!! WARNING: %s !!!\n" % msg) -def run_list (cmd, dir=None, env=None): + +def run_list(cmd, dirname=None, env=None): """Execute the provided CMD command-list (command name + arguments), temporarily switching to the DIR directory unless None, dumping a .log file tracking the command output in the directory where the command @@ -240,28 +249,31 @@ def run_list (cmd, dir=None, env=None): oriwd = os.getcwd() print("from : %s" % oriwd) - if dir: - print("hopat : %s" % dir) - os.chdir (dir) + if dirname: + print("hopat : %s" % dirname) + os.chdir(dirname) + + print("run : %s" % " ".join(cmd)) - print("run : %s" % ' '.join(cmd)) + out = os.path.basename(cmd[0]) + ".log" + p = Run(cmd, output=out, env=env, ignore_environ=False) - out = os.path.basename(cmd[0])+".log" - p = Run (cmd, output=out, env=env, ignore_environ=False) + fail_if( + p.status != 0, "execution failed\n" + "log was:\n" + contents_of(out) + ) - fail_if ( - p.status != 0, "execution failed\n" - + "log was:\n" + contents_of(out)) + os.chdir(oriwd) - os.chdir (oriwd) -def run (s, dir=None, env=None): - run_list (s.split(), dir, env=env) +def run(s, dirname=None, env=None): + run_list(s.split(), dirname=dirname, env=env) -def announce (s): + +def announce(s): print("=========== " + s) -def remove (path): + +def remove(path): """Delete the file or directory subtree designated by PATH""" print("from : %s" % os.getcwd()) @@ -286,177 +298,211 @@ def remove (path): def isdir(path): return os.path.isdir(path) and not os.path.islink(path) - if os.path.exists (local_name): - rm (local_name, recursive=isdir(local_name)) + if os.path.exists(local_name): + rm(local_name, recursive=isdir(local_name)) + + if os.path.exists(path): + mv(path, local_name) + rm(local_name, recursive=isdir(local_name)) - if os.path.exists (path): - mv (path, local_name) - rm (local_name, recursive=isdir(local_name)) # testsuite dirs may include a [user@]remote-host: prefix -def raccess_in (path): - components = path.split(':') + +def raccess_in(path): + components = path.split(":") return components[0] if len(components) > 1 else None -def rdir_in (path): - components = path.split(':') + +def rdir_in(path): + components = path.split(":") return components[1] if len(components) > 1 else None + # current git branch name, used as kit identifier: -def current_gitbranch_at (dirname): +def current_gitbranch_at(dirname): cwd = os.getcwd() os.chdir(dirname) - this_branch = re.search ( - pattern="\* (?P\S*)", - string=output_of("git branch") - ).group('branchname') + this_branch = re.search( + pattern=r"\* (?P\S*)", string=output_of("git branch") + ).group("branchname") os.chdir(cwd) return this_branch + # ======================================================================= # == QUALIF MATERIAL GENERATION HELPER CLASS == # ======================================================================= -sphinx_target_for = { - "html": "html", - "pdf" : "latexpdf" - } +sphinx_target_for = {"html": "html", "pdf": "latexpdf"} # The master GIT repo where our source artifacts reside -GIT_MASTER = "ssh://git.adacore.com/gnatcoverage-qualification" +GIT_MASTER = os.environ.get("GIT_MASTER") -# The subdir name for this clone, relative to --root -GIT_CLONE_SUBDIR = "gnatcoverage-git-clone" +# The name of the subdir in the working directory where we'll fetch TOR +# artifacts from. This would be an image of a "gnatcoverage" repository, from +# either +# +# - the immediate result of a git clone command, or +# - an rsync from a cloned repo somewhere (--rsync ), +# - an rsync from a source package, typically prepared from a branch +# for a qualification project (--rsync ). -class QMAT: +REPO_IMAGE_SUBDIR = "gnatcoverage-git-clone" - def itemsdir (self): - return os.path.join (self.workdir, "%s" % self.this_docformat.upper()) - def __init__(self, options): +class QMAT: + def itemsdir(self): + return os.path.join(self.workdir, "%s" % self.this_docformat.upper()) + def __init__(self, options): self.o = options # Make sure we can designate the work dir easily from anywhere. # Latch repo dir location while we're at it: - self.workdir = os.path.abspath (options.workdir) - self.repodir = os.path.join (self.workdir, GIT_CLONE_SUBDIR) + self.workdir = os.path.abspath(options.workdir) + self.repodir = os.path.join(self.workdir, REPO_IMAGE_SUBDIR) + self.qualdir = os.path.join(self.repodir, "qualification", "qualkit") # A local place where the testsuite tree may be found, # possibly after remote syncing from testsuite_dir if that # is non-local: - self.local_testsuite_dir = None + self.local_testsuite_dir = "" # To be set prior to build_as_needed(): - self.this_docformat = None + self.this_docformat: str = "" # Sequence number of doc build pass we are processing: self.passno = 0 + # --------------------- + # -- prepare_content -- + # --------------------- + + def prepare_content(self, dirs, root): + """ + Prepare the content files by choosing the correct *_content.rst file + according to the qualification parameters. + """ + for dirname in dirs: + cp( + os.path.join( + root, dirname, f"{self.o.trace_mode}_content.rst" + ), + os.path.join(root, dirname, "content.rst"), + ) + # -------------------- # -- setup_workdir -- # -------------------- - def setup_workdir (self): - - announce ("setting up working dir at %s" % self.workdir) - - mkdir (self.workdir) + def setup_workdir(self): + announce("setting up working dir at %s" % self.workdir) + mkdir(self.workdir) # --------- # -- log -- # --------- - def log (self, line): - with open (os.path.join(self.workdir, "genbundle.log"), 'a') as f: - f.write (line + '\n') + def log(self, line): + with open(os.path.join(self.workdir, "genbundle.log"), "a") as f: + f.write(line + "\n") # ---------------- - # -- git_update -- + # -- rsync_from -- # ---------------- - def git_update (self): - - # If we're requested to rsync from an existing repo dir, do so + def rsync_from(self, rsync_source): + run_list( + [ + "rsync", + "-ar", + rsync_source + "/", + self.repodir + "/", + "--delete", + "--delete-excluded", + "--filter", + ". dev.rsync", + ] + ) - if self.o.gitrsync: - run_list ( - ["rsync", "-ar", self.o.gitrsync + '/', self.repodir + '/', - '--delete', '--delete-excluded', - '--filter', '. dev.rsync', - ] - ) - return + # ---------------- + # -- git_update -- + # ---------------- + def git_update(self): # If we're requested to pull/update only, do so if self.o.gitpull: - announce ("updating git clone from origin") + announce("updating git clone from origin") os.chdir(self.repodir) - run ("git pull --rebase origin") + run("git pull --rebase origin") return # If we're requested to reuse an existing clone, do so if self.o.gitreuse: - announce ("reusing existing git clone") + announce("reusing existing git clone") return # Otherwise, get a fresh clone. os.chdir(self.workdir) - gitref = ( - self.o.gitsource if self.o.gitsource - else GIT_MASTER - ) + gitref = self.o.gitsource if self.o.gitsource else GIT_MASTER + exit_if( + not gitref, + "set the repository source either through the --git-source option" + " or through the GIT_MASTER environment variable", + ) - announce ("cloning git repository from %s" % gitref) + announce("cloning git repository from %s" % gitref) - remove (GIT_CLONE_SUBDIR) - run ("git clone %s %s" % (gitref, GIT_CLONE_SUBDIR)) + remove(REPO_IMAGE_SUBDIR) + run("git clone %s %s" % (gitref, REPO_IMAGE_SUBDIR)) # ---------------------- # -- switch_to_branch -- # ---------------------- - def switch_to_branch (self): - announce ("switching to branch '%s'" % self.o.branchname) + def switch_to_branch(self): + announce("switching to branch '%s'" % self.o.branchname) os.chdir(self.repodir) - run ("git checkout %s" % self.o.branchname) + run("git checkout %s" % self.o.branchname) # ----------------- # -- kititem_for -- # ----------------- - def kititem_for (self, part): + def kititem_for(self, part): """The name of the filesystem entity which materializes PART in a kit distribution. This will be a subdirectory name for treeish formats a-la html (e.g. TOR, which will contain content.html etc), or a specific filename (e.g. PLANS.pdf) for other formats. This is what latch_into sets up eventually.""" - this_item_is_tree = (self.this_docformat == 'html') + this_item_is_tree = self.this_docformat == "html" this_item_suffix = ( - '' if this_item_is_tree else '.%s' % self.this_docformat) + "" if this_item_is_tree else ".%s" % self.this_docformat + ) return "%(part)s%(suffix)s" % { - "part": part.upper(), - "suffix": this_item_suffix } + "part": part.lower(), + "suffix": this_item_suffix, + } # ---------------- # -- latch_into -- @@ -494,17 +540,16 @@ def kititem_for (self, part): # # for the html versions. - def __latch_into (self, dir, part, toplevel, copy_from=None): - - this_target_is_tree = (self.this_docformat == 'html') + def __latch_into(self, dirname, part, toplevel, copy_from=None): + this_target_is_tree = self.this_docformat == "html" # Compute the target dir or file name for our copy: this_target = ( - dir if toplevel and this_target_is_tree - else os.path.join ( - dir, self.kititem_for(part=part)) - ) + dirname + if toplevel and this_target_is_tree + else os.path.join(dirname, self.kititem_for(part=part)) + ) # Compute the source dir or file name for our copy: @@ -513,245 +558,236 @@ def __latch_into (self, dir, part, toplevel, copy_from=None): # doc format. For file outputs, assume the builders are setup to # produce PART., e.g. TOR.pdf: - this_build_subdir = os.path.join ( + this_build_subdir = os.path.join( copy_from if copy_from is not None else "build", - sphinx_target_for[self.this_docformat] - ) + self.this_docformat, + ) this_source = ( - this_build_subdir if this_target_is_tree - else os.path.join(this_build_subdir, - part.upper() + ".%s" % self.this_docformat) + this_build_subdir + if this_target_is_tree + else os.path.join( + this_build_subdir, part.lower() + ".%s" % self.this_docformat ) - + ) # Delete an old version of latched results that might # already be there if we're running with --work-dir. - remove (this_target) + remove(this_target) # Now proceed with the latch operation per se: if not this_target_is_tree: - cp (this_source, this_target, recursive=False) + cp(this_source, this_target, recursive=False) elif copy_from: - cp (this_source, this_target, recursive=True) + cp(this_source, this_target, recursive=True) else: - mv (this_build_subdir, this_target) - - print("%s %s available in %s %s" % ( - self.this_docformat, part.upper(), - this_target, "(toplevel)" if toplevel else "" - )) - - # ------------------ - # -- gen_qm_model -- - # ------------------ - - def gen_qm_model (self): - """Generate model.xml that __qm_build will use.""" - - announce ("generating qm model") - - os.chdir ( - os.path.join (self.repodir, "qualification", "qm") - ) - - run (sys.executable + \ - " genmodel.py --dolevel=%s --languages=%s" % - (self.o.dolevel, self.o.languages)) - - # ---------------- - # -- __qm_build -- - # ---------------- - - def __qm_build (self, part): - """Build one PART of using the Qualifying Machine.""" - - announce ("building %s %s" % (self.this_docformat, part.upper())) - - os.chdir ( - os.path.join (self.repodir, "qualification", "qm") + mv(this_build_subdir, this_target) + + print( + "%s %s available in %s %s" + % ( + self.this_docformat, + part.upper(), + this_target, + "(toplevel)" if toplevel else "", ) - - # The qmachine model might use the "build" directory as - # a repository, and it has to preexist: - - mkdir ("build") - run ("qmachine model.xml -l scripts/generate_%s_%s.py" \ - % (part, self.this_docformat), - env={'GENBUNDLE_DOLEVEL': self.o.dolevel}) - - self.__latch_into ( - dir=self.itemsdir(), part=part, toplevel=False) + ) # --------------- # -- build_tor -- # --------------- - def build_tor (self): - + def build_tor(self): # If we have a local testsuite dir at hand and we haven't done so - # already, fetch the testsresults that the QM needs to check TOR/TC + # already, fetch the tests results that the QM needs to check TOR/TC # consistency: if self.local_testsuite_dir and self.passno == 1: - os.chdir (self.local_testsuite_dir) + os.chdir(self.local_testsuite_dir) def sync(tr): - target_dir = os.path.join ( - self.repodir, "testsuite", os.path.dirname (tr) - ) + target_dir = os.path.join( + self.repodir, "testsuite", os.path.dirname(tr) + ) if os.path.exists(target_dir): - cp (tr, target_dir) + cp(tr, target_dir) else: - print ("ERRRR !! inexistant target dir for %s" % tr) + print("ERROR !! inexistent target dir for %s" % tr) - [sync(tr) for tr in find (root=".", pattern="tc.dump")] + [sync(tr) for tr in find(root=".", pattern="tcs.dump")] - self.__qm_build (part="tor") + announce("building %s %s" % (self.this_docformat, "TOR")) + + tor_dir = os.path.join(self.repodir, "qualification", "qualkit", "tor") + run( + f"python genrest.py --dolevel {self.o.dolevel} --force" + f" --testsuite-dir {self.o.testsuite_dir}", + env={"PYTHONPATH": self.qualdir}, + dirname=tor_dir, + ) + run("make %s" % (self.this_docformat), dirname=tor_dir) + + self.__latch_into( + dirname=self.itemsdir(), + part="tor", + toplevel=False, + copy_from=os.path.join(tor_dir, "build"), + ) # ------------------------------ # -- dump_kit_consistency_log -- # ------------------------------ - def __dump_tree_consistency_info (self, log, suite_ctxdata): - - log.write ("\n-- TREE CONSISTENCY LOG:\n") + def __dump_tree_consistency_info(self, log, suite_ctxdata): + log.write("\n-- TREE CONSISTENCY LOG:\n") if not suite_ctxdata: - log.write ( + log.write( "suite context info unavailable, " - "tree consistency unchecked\n") + "tree consistency unchecked\n" + ) return - os.chdir (self.repodir) + os.chdir(self.repodir) local_treeref = treeref_at(self.repodir) - suite_treeref = suite_ctxdata['treeref'] + suite_treeref = suite_ctxdata["treeref"] if local_treeref == suite_treeref: - log.write ( - "artifact tree ref matches testsuite (%s)\n" % local_treeref) + log.write( + "artifact tree ref matches testsuite (%s)\n" % local_treeref + ) return - log.write ( - "local_treeref = %s , suite_treeref = %s\n" % \ - (local_treeref, suite_treeref) - ) + log.write( + "local_treeref = %s , suite_treeref = %s\n" + % (local_treeref, suite_treeref) + ) - merge_base = output_of ( + merge_base = output_of( "git merge-base %s %s" % (local_treeref, suite_treeref) - ).strip(' \n') + ).strip(" \n") - (first, next) = ( - (suite_treeref, local_treeref) if merge_base == suite_treeref - else (local_treeref, suite_treeref) if merge_base == local_treeref - else (None, None)) + (first, next_item) = ( + (suite_treeref, local_treeref) + if merge_base == suite_treeref + else ( + (local_treeref, suite_treeref) + if merge_base == local_treeref + else (None, None) + ) + ) - if first == None: - log.write ( - "!!! local and suite tree refs aren't sequential !!!\n") + if first is None: + log.write("!!! local and suite tree refs aren't sequential !!!\n") return - log.write ( - "%s tree is ahead\n" % \ - ('suite' if first == local_treeref else 'local') - ) - - gitlog_cmd = ( - "git rev-list --oneline %s ^%s" % (next, first)) - log.write ( - '\n'.join (['', gitlog_cmd, '--', output_of(gitlog_cmd), '']) - ) + log.write( + "%s tree is ahead\n" + % ("suite" if first == local_treeref else "local") + ) - def __dump_version_consistency_info (self, log, suite_ctxdata): + gitlog_cmd = "git rev-list --oneline %s ^%s" % (next_item, first) + log.write("\n".join(["", gitlog_cmd, "--", output_of(gitlog_cmd), ""])) - log.write ("\n-- VERSION CONSISTENCY LOG:\n") + def __dump_version_consistency_info(self, log, suite_ctxdata): + log.write("\n-- VERSION CONSISTENCY LOG:\n") if not suite_ctxdata: - log.write ( + log.write( "suite context info unavailable, " - "versions consistency unchecked\n") + "versions consistency unchecked\n" + ) return - def check_one (tool, actual, expected): - + def check_one(tool, actual, expected): if not expected: - log.write ( - "expected %s version NOT specified\n" % tool) + log.write("expected %s version NOT specified\n" % tool) return note = ( - "matches" if re.search (pattern=expected, string=actual) - else "doesn't match") - - log.write ( - '%(tool)s version "%(actual)s" %(note)s ' \ - 'expectation \"%(expected)s"\n' % { - 'tool' : tool, - 'note' : note, - 'expected': expected, - 'actual' : actual - } - ) - # + "matches" + if re.search(pattern=expected, string=actual) + else "doesn't match" + ) - check_one ( - tool = "gnatpro", - actual = suite_ctxdata['gnatpro']['version'], - expected = self.o.xgnatpro) + log.write( + '%(tool)s version "%(actual)s" %(note)s ' + 'expectation "%(expected)s"\n' + % { + "tool": tool, + "note": note, + "expected": expected, + "actual": actual, + } + ) - check_one ( - tool = "gnatcov", - actual = suite_ctxdata['gnatcov']['version'], - expected = self.o.xgnatcov) + # - def __dump_tr_consistency_info (self, log): + check_one( + tool="gnatpro", + actual=suite_ctxdata["gnatpro"]["version"], + expected=self.o.xgnatpro, + ) - log.write ("\n-- TOR/TR CONSISTENCY LOG:\n") + check_one( + tool="gnatcov", + actual=suite_ctxdata["gnatcov"]["version"], + expected=self.o.xgnatcov, + ) - tor_tr_logfile = os.path.join ( - self.repodir, "qualification", "qm", "missing_tr_log.txt") + def __dump_tr_consistency_info(self, log): + log.write("\n-- TOR/TR CONSISTENCY LOG:\n") - if not os.path.exists (tor_tr_logfile): - log.write ("QM log NOT available\n") + tor_tr_logfile = os.path.join( + self.repodir, + "qualification", + "qualkit", + "tor", + "missing_tr_log.txt", + ) + + if not os.path.exists(tor_tr_logfile): + log.write("QM log NOT available\n") return - log.write ( - "%s TOR/TR consistency log from QM @ %s :\n" % \ - ("FRESH" if self.do_tor() else "OLD", tor_tr_logfile) - ) - log.write (contents_of (tor_tr_logfile)) - log.write ("--\n") + log.write( + "%s TOR/TR consistency log from QM @ %s :\n" + % ("FRESH" if self.do_tor() else "OLD", tor_tr_logfile) + ) + log.write(contents_of(tor_tr_logfile)) + log.write("--\n") - def dump_kit_consistency_log (self): - announce ("dumping consistency log - format agnostic") + def dump_kit_consistency_log(self): + announce("dumping consistency log - format agnostic") logfile = os.path.join(self.workdir, "consistency.log") - log = open (logfile, 'w') + log = open(logfile, "w") - log.write ( - "artifact tree at %s (%s)\n" % ( - self.repodir, treeref_at(self.repodir)) - ) - log.write ( - "designated testsuite tree at %s (%s)\n" % \ - (self.o.testsuite_dir, - "REMOTE" if raccess_in(self.o.testsuite_dir) - else "local") + log.write( + "artifact tree at %s (%s)\n" + % (self.repodir, treeref_at(self.repodir)) + ) + log.write( + "designated testsuite tree at %s (%s)\n" + % ( + self.o.testsuite_dir, + "REMOTE" if raccess_in(self.o.testsuite_dir) else "local", ) - log.write ( - "local testsuite tree at %s\n" % self.local_testsuite_dir) + ) + log.write("local testsuite tree at %s\n" % self.local_testsuite_dir) - suite_ctxdata = jload_from ( - os.path.join (self.local_testsuite_dir, CTXDATA_FILE)) + suite_ctxdata = jload_from( + os.path.join(self.local_testsuite_dir, CTXDATA_FILE) + ) - self.__dump_tree_consistency_info (log, suite_ctxdata) - self.__dump_version_consistency_info (log, suite_ctxdata) - self.__dump_tr_consistency_info (log) + self.__dump_tree_consistency_info(log, suite_ctxdata) + self.__dump_version_consistency_info(log, suite_ctxdata) + self.__dump_tr_consistency_info(log) log.close() @@ -761,14 +797,15 @@ def dump_kit_consistency_log (self): # -- localize_testsuite_dir -- # ---------------------------- - def __localize_testsuite_dir (self): + def __localize_testsuite_dir(self): """If testsuite_dir is remote, fetch a local copy. Memorize the local location always.""" - os.chdir (self.workdir) + os.chdir(self.workdir) - self.local_testsuite_dir = \ - hashlib.sha1(self.o.testsuite_dir.encode()).hexdigest() + self.local_testsuite_dir = hashlib.sha1( + self.o.testsuite_dir.encode() + ).hexdigest() # Exclude non qualification tests and internal reports aimed at our # intranet from the transfer. All useless and potentially confusing. @@ -780,180 +817,220 @@ def __localize_testsuite_dir (self): # STR subdir contents entirely. There's no binary there, and artifacts # we all need to produce the STR after the copy (e.g. Makefile). - run ("rsync -arz --delete --delete-excluded %s/ %s %s" % ( - self.o.testsuite_dir, self.local_testsuite_dir, - ' '.join (("--exclude=/tests", - "--exclude=/output", - "--exclude=/rep_gnatcov*", - "--exclude=*.o", - "--exclude=*.obj", - "--exclude=*.exe", - "--exclude=*.trace", - "--exclude=*.dmap", - "--include=*.*", - "--include=*/", - "--include=/STR/**", - "--exclude=*")))) - - self.log ( - "testsuite-dir %s fetched as %s" % ( - self.o.testsuite_dir, self.local_testsuite_dir) + run( + "rsync -arz --delete --delete-excluded %s/ %s %s" + % ( + self.o.testsuite_dir, + self.local_testsuite_dir, + " ".join( + ( + "--exclude=/tests", + "--exclude=/output", + "--exclude=/rep_gnatcov*", + "--exclude=*.o", + "--exclude=*.obj", + "--exclude=*.exe", + "--exclude=*.trace", + "--exclude=*.dmap", + "--include=*.*", + "--include=*/", + "--include=/STR/**", + "--exclude=*", + ) + ), ) + ) - self.local_testsuite_dir = \ - os.path.abspath (self.local_testsuite_dir) + self.log( + "testsuite-dir %s fetched as %s" + % (self.o.testsuite_dir, self.local_testsuite_dir) + ) + + self.local_testsuite_dir = os.path.abspath(self.local_testsuite_dir) # --------------------- # -- prepare_str_dir -- # --------------------- - def __prepare_str_dir (self): + def __prepare_str_dir(self): """Helper for build_str. If we haven't done it already, arrange to generate the STR REST for the designated testsuite-dir, possibly remote. Fetch this dir back as needed then and remember where the corresponding STR subdir (with REST generated) is located.""" - announce ("preparing STR dir @ %s" % self.o.testsuite_dir) + announce("preparing STR dir @ %s" % self.o.testsuite_dir) # Produce REST from the tests results dropped by testsuite run. If we # did not launch one just above, expect results to be available from a # previous run, possibly remote: - raccess = raccess_in (self.o.testsuite_dir) - rdir = rdir_in (self.o.testsuite_dir) + raccess = raccess_in(self.o.testsuite_dir) + rdir = rdir_in(self.o.testsuite_dir) + + mkstr_cmd = "(cd %(dir)s/STR && sh ./mkrest.sh %(level)s)" % { + "dir": self.o.testsuite_dir if not rdir else rdir, + "level": self.o.dolevel, + } - mkstr_cmd = ( - "(cd %(dir)s/STR && ./mkrest.sh %(level)s)" - % {"dir" : self.o.testsuite_dir if not rdir else rdir, - "level" : self.o.dolevel} - ) prefix = ["sh", "-c"] if not raccess else ["ssh", raccess] - run_list (prefix + [mkstr_cmd]) + run_list(prefix + [mkstr_cmd]) # --------------- # -- build_str -- # --------------- - def build_str (self): - announce ("building %s STR" % self.this_docformat) + def build_str(self): + announce("building %s STR" % self.this_docformat) - os.chdir (os.path.join (self.local_testsuite_dir, "STR")) + str_dir = os.path.join(self.qualdir, "str") - run ("make %s" % sphinx_target_for[self.this_docformat]) + source_str_dir = os.path.join( + self.local_testsuite_dir, "STR", "source" + ) + dest_str_dir = os.path.join(str_dir, "source") + + # Copy the sources from the testsuite into the work dir + sync_tree(source_str_dir, dest_str_dir, delete=True) - self.__latch_into ( - dir=self.itemsdir(), part='str', toplevel=False) + run("make %s" % self.this_docformat, dirname=str_dir) + + self.__latch_into( + dirname=self.itemsdir(), + part="str", + toplevel=False, + copy_from=os.path.join(str_dir, "build"), + ) # ----------------- # -- build_plans -- # ----------------- - def build_plans (self): - self.__qm_build (part="plans") + def build_plans(self): + plans_root = os.path.join( + self.repodir, + "qualification", + "qualkit", + "plans", + ) + trace_specific_content = [ + os.path.join( + plans_root, "Tool_Qualification_Plan", "Qualified_Interface" + ) + ] + self.prepare_content(trace_specific_content, root=plans_root) + + run(f"make {self.this_docformat}", dirname=plans_root) + + self.__latch_into( + dirname=self.itemsdir(), + part="plans", + toplevel=False, + copy_from=os.path.join(plans_root, "build"), + ) # --------------- # -- build_kit -- # --------------- - def __relocate_into(self, dir, part): - + def __relocate_into(self, dirname, part): the_item = self.kititem_for(part=part) - item_source_path = os.path.join (self.itemsdir(), the_item) - item_target_path = os.path.join (dir, the_item) + item_source_path = os.path.join(self.itemsdir(), the_item) + item_target_path = os.path.join(dirname, the_item) - remove (item_target_path) + remove(item_target_path) print("move : %s" % item_source_path) - print("into : %s" % dir) + print("into : %s" % dirname) - mv (item_source_path, dir) + mv(item_source_path, dirname) - def build_kit (self): - announce ("building %s kit" % self.this_docformat) + def build_kit(self): + announce("building %s kit" % self.this_docformat) - os.chdir (self.workdir) + os.chdir(self.workdir) # The kit name is computed as: # # gnatcov-qualkit-- # - # where is the kit production stamp (now), and is - # computed from the git branch off which the artifacts are taken. The - # git branch name might contain the "qualkit" indication already. + # is the kit production stamp (now), + # is the kit identifier, typically -. today = date.today() - gitbranch = current_gitbranch_at(self.repodir) - kitprefix = ( - "gnatcov-qualkit" if "qualkit" not in gitbranch - else "gnatcov" - ) + # If the kitid is not provided, assume the artifacts repo image holds + # a git clone and compute the id from the current branch there: + + if self.o.kitid: + kitid = self.o.kitid + else: + gitbranch = current_gitbranch_at(self.repodir) - kitid = gitbranch - kitid = kitid.replace('/', '-') - kitid = kitid.replace('.', '_') + kitid = gitbranch.replace("qualkit-", "") + kitid = kitid.replace("/", "-") + kitid = kitid.replace(".", "_") # If we are re-constructing a kit with some parts just rebuilt, target # the specified version (stamp) and arrange to keep the old elements # in place: kitstamp = ( - self.o.rekit if self.o.rekit + self.o.rekit + if self.o.rekit else "%4d%02d%02d" % (today.year, today.month, today.day) - ) - kitname = "%s-%s-%s" % (kitprefix, kitid, kitstamp) + ) + kitname = "gnatcov-qualkit-%s-%s" % (kitid, kitstamp) kitdir = "%s-%s" % (kitname, self.this_docformat) - mkdir (kitdir) + mkdir(kitdir) - [self.__relocate_into (dir=kitdir, part=part) for part in self.o.parts] + for part in self.o.parts: + self.__relocate_into(dirname=kitdir, part=part) - run ("zip -q -r %(kitdir)s.zip %(kitdir)s" % {"kitdir": kitdir}) + run("zip -q -r %(kitdir)s.zip %(kitdir)s" % {"kitdir": kitdir}) # ----------------------- # -- zip_testsuite_dir -- # ----------------------- def zip_testsuite_dir(self): + os.chdir(self.workdir) - os.chdir (self.workdir) - - relative_testsuite_dir = os.path.basename (self.local_testsuite_dir) + relative_testsuite_dir = os.path.basename(self.local_testsuite_dir) zipname = "%s.zip" % relative_testsuite_dir - remove (zipname) - run ("zip -q -r %s %s" % (zipname, relative_testsuite_dir)) + remove(zipname) + run("zip -q -r %s %s" % (zipname, relative_testsuite_dir)) # --------------------- # -- build_as_needed -- # --------------------- - def do_str (self): - return 'str' in self.o.parts + def do_str(self): + return "str" in self.o.parts - def do_tor (self): - return 'tor' in self.o.parts + def do_tor(self): + return "tor" in self.o.parts - def do_plans (self): - return 'plans' in self.o.parts + def do_plans(self): + return "plans" in self.o.parts - def do_kit (self): + def do_kit(self): return self.o.kitp - def build_as_needed (self, docformat): - + def build_as_needed(self, docformat): self.passno += 1 self.this_docformat = docformat - mkdir (self.itemsdir()) + mkdir(self.itemsdir()) if self.do_str() and self.passno == 1: self.__prepare_str_dir() if self.o.testsuite_dir and not self.local_testsuite_dir: - self.__localize_testsuite_dir () + self.__localize_testsuite_dir() # Build the STR as needed, using the REST generated # by prepare_str_dir above: @@ -977,155 +1054,204 @@ def build_as_needed (self, docformat): if self.do_kit(): qmat.build_kit() + # ======================================================================= # == MAIN SCRIPT BODY == # ======================================================================= -valid_docformats = ('html', 'pdf') -valid_parts = ('tor', 'plans', 'str') -valid_dolevels = ('doA', 'doB', 'doC') -valid_xada = ('95', '2005', '2012') -valid_languages = ["Ada%s" % version for version in valid_xada] +valid_docformats = ("html", "pdf") +valid_parts = ("tor", "plans", "str") +valid_dolevels = ("doA", "doB", "doC") +valid_xada = ("95", "2005", "2012") +valid_languages = ["Ada%s" % version for version in valid_xada] +valid_trace_modes = ("src", "bin") + def commandline(): """Build and return an OptionParser instance for this script.""" op = optparse.OptionParser(usage="%prog ") - op.add_option ( - "--work-dir", dest="workdir", + op.add_option( + "--work-dir", + dest="workdir", help=( "Name of a directory from where a previous kit construction " - "will resume. Must exist already.") - ) - - op.add_option ( - "--git-source", dest="gitsource", default=None, + "will resume. Must exist already." + ), + ) + + op.add_option( + "--git-source", + dest="gitsource", + default=None, help=( "Git repo we should be cloning to get our source artifacts. " "!! This overrides whatever is in a --work-dir already !!" - ) - ) - op.add_option ( - "--git-pull", dest="gitpull", action="store_true", default=False, + ), + ) + op.add_option( + "--git-pull", + dest="gitpull", + action="store_true", + default=False, help=( "Pull commits from current origin in the git clone setup " "in work-dir." - ) - ) - op.add_option ( - "--git-reuse", dest="gitreuse", action="store_true", default=False, - help=( - "Reuse current git clone setup in work-dir, as-is. " - ) - ) - op.add_option ( - "--git-rsync", dest="gitrsync", default=False, + ), + ) + op.add_option( + "--git-reuse", + dest="gitreuse", + action="store_true", + default=False, + help=("Reuse current git clone setup in work-dir, as-is. "), + ) + op.add_option( + "--rsync-from", + dest="rsync_from", + default=False, + help=("Rsync an existing repo image into our local image dir."), + ) + op.add_option( + "--branch", + dest="branchname", + default=None, + help=("The git branch we shall produce the material from."), + ) + op.add_option( + "--kitid", + dest="kitid", + default=False, + help=("Use the provided argument as the kit identifier."), + ) + + op.add_option( + "--docformat", + dest="docformat", + type="string", # choices=valid_docformats, help=( - "Rsync an existing git repo into our git clone dir." - ) - ) - op.add_option ( - "--branch", dest="branchname", default=None, - help = ( - "The git branch we shall produce the material from.") - ) - - op.add_option ( - "--docformat", dest="docformat", - type='string', # choices=valid_docformats, - help = ( "The format we need to produce for each document. " - "At least one of %s. Multiple values separated by ','." \ - % valid_docformats.__str__()) - ) - op.add_option ( - "--parts", dest="parts", default=None, - help = ( + "At least one of %s. Multiple values separated by ','." + % valid_docformats.__str__() + ), + ) + op.add_option( + "--parts", + dest="parts", + default=None, + help=( "A comma separated list of the parts of the qualkit that " - "are to be generated, subset of %s." % valid_parts.__str__()) - ) - - op.add_option ( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, - help = ( - "Target DO178 qualification level. One of %s." \ - % valid_dolevels.__str__()) - ) - - op.add_option ( - "--languages", dest="languages", default=None, - help = ( + "are to be generated, subset of %s." % valid_parts.__str__() + ), + ) + + op.add_option( + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, + help=( + "Target DO178 qualification level. One of %s." + % valid_dolevels.__str__() + ), + ) + + op.add_option( + "--languages", + dest="languages", + default=None, + help=( "Comma separated list of languages, for traceability matrix " - "purposes. Amongst %s." % valid_languages.__str__()) - ) - - op.add_option ( - "--testsuite-dir", dest="testsuite_dir", default=None, - help = ( - "Name of a directory where the testsuite was run") - ) - - op.add_option ( - "--rekit", dest="rekit", default=None, - help = ( + "purposes. Amongst %s." % valid_languages.__str__() + ), + ) + + op.add_option( + "--testsuite-dir", + dest="testsuite_dir", + default=None, + help=("Name of a directory where the testsuite was run"), + ) + + op.add_option( + "--rekit", + dest="rekit", + default=None, + help=( "rebuild the specified --parts and re-package them in the " - "kit stamped according to this option's value (YYYYMMDD)") - ) - - op.add_option ( - "--xgnatpro", dest="xgnatpro", default=None, - help = ( + "kit stamped according to this option's value (YYYYMMDD)" + ), + ) + + op.add_option( + "--xgnatpro", + dest="xgnatpro", + default=None, + help=( "Version we expect -gcc -v to match. " - "Mandatory when producing a kit") - ) - op.add_option ( - "--xgnatcov", dest="xgnatcov", default=None, - help = ( + "Mandatory when producing a kit" + ), + ) + op.add_option( + "--xgnatcov", + dest="xgnatcov", + default=None, + help=( "Version we expect gnatcov --version to match. " - "Mandatory when producing a kit") - ) - op.add_option ( - "--xgnatemu", dest="xgnatemu", default=None, - help = ( - "Version we expect -gnatcov --version to match.") - ) - - op.add_option ( - "--xada", dest="xada", default=None, choices=valid_xada, - help = ( - "Version of the Ada language we are qualifying for (%s)" % \ - '|'.join(valid_xada) - ) - ) + "Mandatory when producing a kit" + ), + ) + op.add_option( + "--xgnatemu", + dest="xgnatemu", + default=None, + help=("Version we expect -gnatcov --version to match."), + ) + + op.add_option( + "--xada", + dest="xada", + default=None, + choices=valid_xada, + help=( + "Version of the Ada language we are qualifying for (%s)" + % "|".join(valid_xada) + ), + ) + + op.add_option( + "--trace-mode", + dest="trace_mode", + default=None, + choices=valid_trace_modes, + help="Trace kind we are qualifying gnatcov for. One of 'src' or 'bin'", + ) return op -def check_valid(options, args): +def check_valid(options, args): # We are producing qualification material. Better know what we're # aiming at, always: - exit_if ( - not options.dolevel, - "Please specify an explicit dolevel (--dolevel)." - ) + exit_if( + not options.dolevel, "Please specify an explicit dolevel (--dolevel)." + ) + + exit_if( + not options.trace_mode, + "Please specify an explicit trace-mode (--trace-mode).", + ) # Generating docs can be pretty long. Better make sure the output format # was intentionally stated: - exit_if ( + exit_if( not options.docformat, - ("Please specify the desired output format (--docformat).") - ) - - # Likewise for the git branch name: - - exit_if ( - not options.branchname, - ("Please specify the git branch name (--branch).") - ) + ("Please specify the desired output format (--docformat)."), + ) # Convey whether we are requested to produce a kit: @@ -1134,50 +1260,50 @@ def check_valid(options, args): # Settle on the set of documents we are to produce: options.parts = ( - valid_parts if not options.parts - else options.parts.split(',') - ) + valid_parts if not options.parts else options.parts.split(",") + ) - [exit_if ( + [ + exit_if( part not in valid_parts, - "Requested part '%s' is invalid, none of %s" \ - % (part, valid_parts.__str__()) - ) - for part in options.parts] + "Requested part '%s' is invalid, none of %s" + % (part, valid_parts.__str__()), + ) + for part in options.parts + ] # work dir - exit_if ( - not options.workdir, - "A work dir must be specified (--work-dir)" - ) + exit_if(not options.workdir, "A work dir must be specified (--work-dir)") - warn_if ( - options.kitp and os.path.exists (options.workdir) + warn_if( + options.kitp + and os.path.exists(options.workdir) and ls("%s/*" % options.workdir), - "producing kit within non empty workdir") + "producing kit within non empty workdir", + ) # Producing a STR requires a testsuite dir - exit_if ( - 'str' in options.parts and not options.testsuite_dir, - "--testsuite-dir required when producing a STR" - ) + exit_if( + "str" in options.parts and not options.testsuite_dir, + "--testsuite-dir required when producing a STR", + ) # GIT aspects: - exit_if ( + exit_if( options.gitpull and options.gitsource, "Specifying git source is incompatible with " - "request to pull from current origin" - ) + "request to pull from current origin", + ) # In case we produce TOR/LRM traceability matrixes ... - exit_if ( + exit_if( not options.languages, - "Please specify the qualified languages (--languages)" - ) + "Please specify the qualified languages (--languages)", + ) # -xada, -xgnatcov etc @@ -1188,33 +1314,33 @@ def check_valid(options, args): if __name__ == "__main__": - (options, args) = commandline().parse_args() - check_valid (options, args) + check_valid(options, args) # Make sure that directory options are absolute dirs, to # facilitate switching back and forth from one to the other: - if options.testsuite_dir and not raccess_in (options.testsuite_dir): - options.testsuite_dir = os.path.abspath (options.testsuite_dir) + if options.testsuite_dir and not raccess_in(options.testsuite_dir): + options.testsuite_dir = os.path.abspath(options.testsuite_dir) # Instanciate our helper and proceed with the base directory setup: - qmat = QMAT (options=options) + qmat = QMAT(options=options) qmat.setup_workdir() - qmat.git_update() - qmat.switch_to_branch() - # Produce each part we are requested to produce, with a tailored - # QM model: + if options.rsync_from: + qmat.rsync_from(options.rsync_from) + else: + qmat.git_update() - qmat.gen_qm_model() + if options.branchname: + qmat.switch_to_branch() # Build the various parts and maybe the kit for each requested format: - [qmat.build_as_needed (docformat=f) for f in options.docformat.split(',')] + [qmat.build_as_needed(docformat=f) for f in options.docformat.split(",")] if options.kitp: qmat.zip_testsuite_dir() diff --git a/qualification/qm/.qm/cnt_env.py/artifactstamp.json b/qualification/qm/.qm/cnt_env.py/artifactstamp.json deleted file mode 100644 index 467e491c5..000000000 --- a/qualification/qm/.qm/cnt_env.py/artifactstamp.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "content-kind": "content", - "signature": "5358c2c895991794a84246b9834b39dba9149e85", - "location": "default:///env.py", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/README_FIRST b/qualification/qm/README_FIRST deleted file mode 100644 index 539562898..000000000 --- a/qualification/qm/README_FIRST +++ /dev/null @@ -1,25 +0,0 @@ -To run the QM: - -* Download a recent wavefront (synchronize with the QM team for that) -* Unzip it (if on Windows) or untar it (on Unix). The created directory will be - denoted by . You can safely move it to any convenient - location. -* Make sure the bin directory is in your PATH: - on unix: export PATH=/bin:$PATH - on windows: right click on start menu->computer, select properties, - select advanced properties, environment variables, update the PATH definition - or define it to \bin;%PATH% -* In the directory containing this README file, using the command line: - - To run the qmachine with the GUI (requires gnatpython): - - ./genmodel.py --dolevel=doB - qmachine model.xml - - - To generate the documentation (html and pdf) - - qmachine model.xml -l scripts/generate_[tor|plans]_[html|pdf].py - - The documentation will be generated in the release folder - -Important Note: -In order to generate the PDF, you will need make, and LaTeX installed. diff --git a/qualification/qm/common_conf.py b/qualification/qm/common_conf.py deleted file mode 100644 index 992ffd3ee..000000000 --- a/qualification/qm/common_conf.py +++ /dev/null @@ -1,52 +0,0 @@ -from collections import OrderedDict -from datetime import date - -project_name = 'GNATcoverage' -project_name_it = '*%s*' % project_name -owner = 'AdaCore' - -users = { - 'unassigned': {'name': 'Unassigned', - 'company': '', - 'email': '', - 'team': ''}, - - 'hainque': {'name': 'Olivier Hainque', - 'company': owner, - 'email': 'hainque@adacore.com', - 'team': 'Qualification'}, - - 'guitton': {'name': 'Jerome Guitton', - 'company': owner, - 'email': 'guitton@adacore.com', - 'team': 'Qualification'}, - - 'leguillou': {'name': 'Erwan Leguillou', - 'company': owner, - 'email': 'leguillou@adacore.com', - 'team': 'Qualification'}, - - 'fofanov': {'name': 'Vasily Fofanov', - 'company': owner, - 'email': 'fofanov@adacore.com', - 'team': 'Qualification'}} - -roles = OrderedDict( - [('authors', {'description': 'the authors of the document'}), - ('reviewers', {'description': 'the reviewers of the document'})]) - -assignments = { - 'authors': ['hainque'], - 'reviewers': ['unassigned'] -} - -release = 'DRAFT 0.0' -version = '(version %s)' % release - -copyright = '%s, %d' % (owner, date.today().year) - -extensions = ['sphinx.ext.ifconfig'] - -tor_doc_id = 'PE.' -str_doc_id = 'PE.' -plans_doc_id = 'PE.' diff --git a/qualification/qm/env/env.py b/qualification/qm/env/env.py deleted file mode 100644 index cb5ab894d..000000000 --- a/qualification/qm/env/env.py +++ /dev/null @@ -1,5 +0,0 @@ -{"gnat" : "powerpc-elf", - "version" : "7.0.3", - "switches" : ["-O1 -fpreserve-control-flow"], - "coding standard" : "", - "project_full" : "SomeProject"} diff --git a/qualification/qm/genmodel.py b/qualification/qm/genmodel.py deleted file mode 100755 index eb00b14c3..000000000 --- a/qualification/qm/genmodel.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python - -# Generate the "model.xml" file from which the qm driven document -# generators will work, with 2 specifities driven by info provided -# on the command line: -# -# * The target do-level, which lets us include level-specific -# directories that the QM will look into for e.g. TOR artifacts -# (typical example is the doB specific testcases for DC on non -# short-circuit operators) -# -# * The target Ada language version, so we can focus the LRM -# traceability matrix production (and maybe the set of TORs -# and testcases someday) - -import sys, optparse, re -from e3.os.process import Run - -def exit_if (p, msg): - if p: - print(msg) - sys.exit(1) - -def contents_of(filename): - with open(filename) as fd: - return fd.read() - -def __extra_block_for(dolevel): - """Allow level specific local subsets of testcases.""" - - return '\n'.join( - ('', - '', - ' ', - ' ', - ' ', - ' ', - '')) - -RE_LANG="([a-zA-Z]*)([0-9]*)" - -def __langdir_for(lang): - # Requirements for all the versions Ada are all under Ada/ etc; - # only keep the non-digital start of the language name as the subdir - # to search: - return re.match(RE_LANG, string=lang).group(1) - -def __langversion_for(lang): - return re.match(RE_LANG, string=lang).group(2) - -def __reqset_triggers_for (lang, chapter): - - return '\n'.join( - ('')) - -def __langlevel_triggers_for(dolevel, languages): - """Triggers so only the language/criterion sections of relevance - are included.""" - - chapters_for = { - 'doC': ['stmt'], - 'doB': ['stmt', 'decision'], - 'doA': ['stmt', 'decision', 'mcdc'] - } - - return '\n'+'\n'.join( - (__reqset_triggers_for(lang, chapter) - for lang in languages - for chapter in chapters_for[dolevel]) - ) - -def __gen_model_for(dolevel, languages): - """Generate model.xml from template.xml""" - - # We expect one version of Ada to be part of the language set - - ada_lang = [l for l in languages if "Ada" in l][0] - - with open('model.xml', 'w') as f: - f.write( - contents_of("template.xml") % { - 'langlevel_reqset_triggers': - __langlevel_triggers_for (dolevel=dolevel, - languages=languages), - 'ada_version': - __langversion_for(ada_lang), - - 'extra_block': - __extra_block_for(dolevel=dolevel) - } - ) - -def __gen_lrm_ref_for(lang): - """Generate lrm_ref_.txt from lrm_ref.txt, filtering - out the lines that don't apply to (extracted from the - input LANGuage name.""" - - lang_version = __langversion_for(lang) - - input = open ("LRM/lrm_ref.txt", mode='r') - output = open ("LRM/lrm_ref_%s.txt" % lang_version, mode='w') - - # The reference matrix lines with section numbers and corresponding - # language versions are of the form: - # - # # # # # - # - # language versions are shortened to their last two digits, - # for example: - # - # 13.8 # 95,05,12 # Machine Code # yes # - - # Produce an output file which has all the lines of the input one - # except those corresponding to sections not for the targeted language. - - short_version = lang_version[-2:] - - for line in input.readlines(): - - m = re.match(pattern="([0-9. ]*)#([0-9, ]*?)#", string=line) - if m and short_version not in m.group(2): - continue - - output.write(line) - - output.close() - input.close() - -# ======================================================================= -# == MAIN SCRIPT BODY == -# ======================================================================= - -valid_dolevels = ('doA', 'doB', 'doC') -valid_languages = ('Ada95', 'Ada2005', 'Ada2012') - -if __name__ == "__main__": - - op = optparse.OptionParser(usage="%prog ") - - op.add_option ( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, - help = ( - "Target DO178 qualification level. One of %s." \ - % valid_dolevels.__str__()) - ) - - op.add_option ( - "--languages", dest="languages", default=None, - help = ( - "comma separated list of languages amongst %s" \ - % valid_languages.__str__()) - ) - - (options, args) = op.parse_args() - - exit_if ( - not options.dolevel, - "Please specify a DO level (--dolevel)." - ) - - exit_if ( - not options.languages, - "Please specify languages (--languages)." - ) - - languages=options.languages.split(',') - - # should check that there is only one instance of a given - # language (e.g. only one Ada) - - __gen_model_for(dolevel=options.dolevel, languages=languages) - - [__gen_lrm_ref_for(lang=lang) - for lang in languages if "Ada" in lang] diff --git a/qualification/qm/plans/.qm/artifactstamp.json b/qualification/qm/plans/.qm/artifactstamp.json deleted file mode 100644 index 7d7d9d5e5..000000000 --- a/qualification/qm/plans/.qm/artifactstamp.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/content.rst": "ee5d37c85291ef70f198197d8277bf0031c4ba36", - "default:///plans/qmconf.py": "ef65551845c160016f1c6a064acf7eb377a9485a" - }, - "location": "default:///plans", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Introduction/.qm/artifactstamp.json b/qualification/qm/plans/Introduction/.qm/artifactstamp.json deleted file mode 100644 index fee95daa0..000000000 --- a/qualification/qm/plans/Introduction/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Documentation_Introduction/content.rst": "58c64e74ae5f2a14f8f80a4551dbd8399b1b30af" - }, - "location": "default:///plans/Documentation_Introduction", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Introduction/Definitions/content.rst b/qualification/qm/plans/Introduction/Definitions/content.rst deleted file mode 100644 index f71b18960..000000000 --- a/qualification/qm/plans/Introduction/Definitions/content.rst +++ /dev/null @@ -1,39 +0,0 @@ -Definitions -=========== - -General Definitions -------------------- - -The Annex B of [|tool_standard|] provides a list of acronyms and glossary of -common terms used throughout this qualification material. - -Project Specific Definitions ----------------------------- - -.. rubric:: GNATcoverage - -A tool performing structural coverage analysis of Ada programs. - -.. rubric:: Operational Environment - -The environment in which GNATcoverage is used. - -.. rubric:: Verification Environment - -The environment in which GNATcoverage is qualified. - -.. rubric:: Test - -A part of a testcase which exercises functional code in a precise manner, -aimed at obtaining precise expected coverage results. - -.. rubric:: Testcase - -A part of the testing strategy used to verify a given Tool Operational -Requirement. - -.. rubric:: Tool Operational Requirement (TOR) - -A TOR describes the expected behavior of a tool from the user point of view. - - diff --git a/qualification/qm/plans/Introduction/Organization_And_Roles/content.rst b/qualification/qm/plans/Introduction/Organization_And_Roles/content.rst deleted file mode 100644 index 6f57bd563..000000000 --- a/qualification/qm/plans/Introduction/Organization_And_Roles/content.rst +++ /dev/null @@ -1,27 +0,0 @@ -Organization And Roles -====================== - -Here is the list of parties involved in the development, verification and -qualification process for GNATcoverage, along with their responsibilities: - -* **GNATcoverage Development Team**: Developers contribute to the development - of GNATcoverage, including requirements specification, implementation, test - case development and test execution. This team is also in charge of the - configuration management of the artifacts it produces. - -* **GNATcoverage Qualification Team**: The Qualification Team is responsible - for the infrastructure supporting the qualification process of GNATcoverage. - The Qualification Team supports the Development Team. This team is also in - charge of the configuration management of the artifacts it produces. - -* **GNATcoverage Quality Assurance Team**: The Quality Assurance Team is - independent of the Development Team and Qualification Team and is - responsible for ascertaining that the expected processes have been put in - place. The Quality Assurance Team is granted the authority to require - specific activities to be performed by the GNATcoverage Development and - Qualification Teams. This team is also in charge of the configuration - management of the artifacts it produces (mostly Quality Assurance reports). - -* **GNATcoverage users**: GNATcoverage users are expected to perform the - activities identified in section - :qmref:`/PLANS/Tool_Qualification_Plan/User_Activities`. diff --git a/qualification/qm/plans/Introduction/Referenced_Documents/content.rst b/qualification/qm/plans/Introduction/Referenced_Documents/content.rst deleted file mode 100644 index b822f34e1..000000000 --- a/qualification/qm/plans/Introduction/Referenced_Documents/content.rst +++ /dev/null @@ -1,54 +0,0 @@ -Referenced Documents -==================== - -.. rubric:: AE09 - -Bordin et al.: *Couverture: An Innovative Open Framework for Coverage Analysis -of Safety Critical Applications* - Ada User Journal, December 2009. - -.. rubric:: |standard| - -RTCA DO-178C/EUROCAE ED-12C: -*Software Considerations in Airborne Systems and Equipment Certification*; -December 13, 2011 - -.. rubric:: |tool_standard| - -RTCA DO-330/EUROCAE ED-215: -*Software Tool Qualification Considerations*; -December 13, 2011 - -.. rubric:: ERTS2010 - -Bordin et al: *Couverture: An Innovative and Open Coverage Analysis Framework -for Safety-Critical Applications* - ERTS2 2010 - -.. rubric:: GNAT Pro UG - -AdaCore: *GNAT User's Guide for Native Platforms*, part of the GNAT Pro 7.4.3 -release documentation (file *share/doc/gnat/pdf/gnat_ugn.pdf*). - -.. rubric:: GNATcoverage UG - -AdaCore: *GNATcoverage User's Guide*, part of the GNATcoverage 1.4.3 release -documentation (file *share/doc/gnatdas/pdf/gnatdas.pdf*). - -.. rubric:: |plans_doc_title| - -AdaCore: |project_name_it| - |plans_doc_title|, |plans_doc_id|, this document. - -.. rubric:: |tor_doc_title| - -AdaCore: |project_name_it| - |tor_doc_title|, |tor_doc_id|, included in this -qualification package. - -.. rubric:: |str_doc_title| - -AdaCore: |project_name_it| - |str_doc_title|, |str_doc_id|, included in this -qualification package. - -.. rubric:: |tqa_doc_title| - -AdaCore: |project_name_it| - |tqa_doc_title|, accompanying this qualification -package. - diff --git a/qualification/qm/plans/Introduction/content.rst b/qualification/qm/plans/Introduction/content.rst deleted file mode 100644 index 81cfe7ebd..000000000 --- a/qualification/qm/plans/Introduction/content.rst +++ /dev/null @@ -1,11 +0,0 @@ -============ -Introduction -============ - -.. qmlink:: - - Document_Purpose - Referenced_Documents - Definitions - Organization_And_Roles - diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json deleted file mode 100644 index d510e8739..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Software_Configuration_Management_Plan/content.rst": "49090be777e8db68e6f42042cdc1b56921fed642" - }, - "location": "default:///plans/Software_Configuration_Management_Plan", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst deleted file mode 100644 index 6532580a1..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| - -.. csv-table:: Compliance matrix for Table 7-1 of |tool_standard| - :delim: & - :header: "Item", "Description", "Ref.", "Achieved", "Notes" - - 1 & Configuration Identification & 7.2.1 & Yes & See :ref:`adacore-configuration-items`. - 2 & Baselines & 7.2.2.a,b,c,d,e & N/A & Not required for CC2. - 3 & Traceability & 7.2.2.f,g & Yes & See :ref:`traceability`. - 4 & Problem Reporting & 7.2.3 & N/A & Not required for CC2. - 5 & Change Control - integrity and identification & 7.2.4.a,b & Yes & See :ref:`adacore-change-control`. - 6 & Change Control - tracking & 7.2.4.c,d,e & N/A & Not required for CC2. - 7 & Change Review & 7.2.5 & N/A & Not required for CC2. - 8 & Configuration Status Accounting & 7.2.6 & N/A & Not required for CC2. - 9 & Retrieval & 7.2.7.a & Yes & See :ref:`adacore-archive`. - 10 & Protection against Unauthorized Changes & 7.2.7.b.1 & Yes & See :ref:`adacore-archive`. - 11 & Media Selection, Refreshing, Duplication & 7.2.7.b.2,3,4, 7.2.7.c & N/A & Not required for CC2. - 12 & Release & 7.2.7.d & N/A & Not required for CC2. - 13 & Data Retention & 7.2.7.e & Yes & See :ref:`adacore-archive`. - -.. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| - -.. csv-table:: Compliance matrix for Table T-8 of |tool_standard| - :delim: & - :header: "Item", "Description", "Ref.", "Achieved", "Notes" - - 1 & Configuration items are identified. & 7.1.a & Yes & See :ref:`adacore-configuration-items`. - 2 & Baselines and traceability are established. & 7.1.b & N/A & Not required for TQL-5 tools. - 3 & Problem reporting, change control, change review, and configuration status accounting are established. & 7.1c,d,e,f & N/A & Not required for TQL-5 tools. - 4 & Archive, retrieval, and release are established. & 7.1.g & Yes & See :ref:`adacore-archive`. - 5 & Tool life cycle environment control is established & 7.1.h & N/A & Not required for TQL-5 tools. diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst deleted file mode 100644 index 1dd208291..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. _adacore-conf-methods: - -Configuration Management Methods and Activities -*********************************************** - -This section describes the internal configuration management process at -AdaCore. It is not related to the configuration management process deployed by -the applicant. - -Base technical support ----------------------- - -Configuration Management of artifacts is technically implemented via Git -repositories which track the life cycle of each artifact automatically. -E-mail-based discussions about each artifact are also tracked, using the -AdaCore ticket system deployed within the whole company since 1998. - -.. _adacore-change-control: - -Change control --------------- - -Integrity of configuration items is guaranteed by the Git -repositories where all configuration items are located. Only authorized -engineers can modify configuration items and all modifications are -recorded. In addition, all repositories and mail servers are mirrored with -machines physically located in Paris (France) and New York. This increases -confidence in the durability of qualification data (activity 7.2.4.a). - -Each change to a configuration item is associated to a unique -ID, which unambiguously identifies the version of a configuration item over -its history (activity 7.2.4.b). - -.. _adacore-archive: - -Archive, Retrieval and Release ------------------------------- - -Repositories are available for audit if necessary (activity 7.2.7.a). - -Only authorized engineers can change the configuration -items, thanks to the security mechanisms embedded in the Git -repositories (activity 7.2.7.b.1). - - -Detailed procedures are as follows. - -Customer/Project specific tracking -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For each specific customer/project qualification we assign an internal *kit -identifier*, referenced for example in QA reports. All the corresponding -verification related artifacts are managed on a dedicated *branch* within -AdaCore's version control systems. Releases of qualification kits for the -specific customer/project are produced off that branch, which also tracks the -QA cycles performed on the kit items (QA reports, corresponding corrections, -...). A typical kind of early change incorporated on the branch is the -adjustment of the targeted operational environment parameters, to be accounted -for when setting up the verification environment for kit production cycles. - - -Official baseline production -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Official baselines are generated for customer-specific deliveries aimed at a -precise operational environment and software level. Once the configuration -management branch dedicated to such deliveries is set up, a complete testsuite -run is performed in the corresponding verification environment. A kit version -number is then assigned and the qualification data documents are produced. -The resulting set of documents is packaged as a zip file which materializes -the kit as a whole. This kit then goes through QA as needed and all or part of -this cycle repeats until a positive agreement on the kit "acceptability" for -release is reached. - diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/content.rst deleted file mode 100644 index 09a65109c..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/content.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _dev-conf-management: - -Tool Developer Configuration Management Plan -============================================ - -GNATcoverage is a TQL-5 tool, and as such, its tool developer configuration -items are managed at Control Category 2 (CC2). The corresponding subset -of TCM process activities to -perform is defined by Tables 7-1 and T-8 of |tool_standard|. - -This section describes the processes in place at AdaCore, the Tool Developer. - -.. qmlink:: - - Compliance - Version_Control - Traceability - Methods_And_Activities diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst deleted file mode 100644 index be47a99f0..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst +++ /dev/null @@ -1,13 +0,0 @@ - -.. tabularcolumns:: |p{0.05\linewidth}|p{0.35\linewidth}|p{0.10\linewidth}|p{0.30\linewidth}| - -.. csv-table:: Compliance matrix for Table T-8 of |tool_standard| - :delim: | - :header: "Item", "Description", "Ref.", "Notes" - - 1 | Configuration items are identified. |7.1.a| Up to the applicant. - 2 | Baselines and traceability are established. |7.1.b| Not required for TQL-5 tools. - 3 | Problem reporting, change control, change review, and configuration status accounting are established.|7.1c,d,e,f| Not required for TQL-5 tools. - 4 | Archive, retrieval, and release are established. |7.1.g| Up to the applicant. - 5 | Tool life cycle environment control is established. |7.1.h| Not required for TQL-5 tools. - diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst deleted file mode 100644 index 8f5278232..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst +++ /dev/null @@ -1,17 +0,0 @@ - -What follows is a set of configuration management suggestions for the -items up to the applicant as per the compliance matrix above. - - * **Activity 7.2.1:** The suggested configuration items are: - - #. The .zip packages of this |project_name| qualification kit; - #. The |tqa_doc| document, output of the Quality Assurance activities described - in the :ref:`tqap` chapter of this document; - #. The GNAT Pro and GNATcoverage binary packages containing the executable - files as well as their accompanying infrastructure and - documentation. Likewise for GNATemulator in the case of cross - configurations. - - * **Activity 7.2.7:** with respect to these items, we let the user deploy the - most appropriate process depending on his own configuration management - process and tools. diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/User/content.rst deleted file mode 100644 index d6c5583dd..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/content.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _user-conf-management: - -Tool User Configuration Management Suggestions -============================================== - -.. qmlink:: - - Compliance - Suggested_Items diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/content.rst deleted file mode 100644 index ad80f0ae2..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/content.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _tcmp: - -================================== -Tool Configuration Management Plan -================================== - -.. qmlink:: - - Developer - User diff --git a/qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json deleted file mode 100644 index 9cee7f273..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/content.rst": "9107595cbe85926f695d71d01f3aa73b192ebe4c" - }, - "location": "default:///plans/Tool_Qualification_Plan", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst deleted file mode 100644 index 1f0923432..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _certification-credit: - -Sought Certification Credit -=========================== - -GNATcoverage aims at automating the Structural Coverage Analysis activities -required by the Software Verification Process of |standard|, in section -6.4.4.2 and table A-7, objectives 5, 6 and 7 depending on the software level. -Any coverage limitations are enumerated in section *Language Version and -Scope* of the |tor_doc_title| document; it is the user's responsibility to -assure that the code subject to analysis conforms to what this qualification -material encompasses. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst deleted file mode 100644 index c9d3a4eb3..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst +++ /dev/null @@ -1,31 +0,0 @@ -Compliance With Guidance -======================== - -This section contains the compliance matrices with the guidance contained in -section 12.2 of [|standard|] and section 11.3.2 of [|tool_standard|] from a -Tool Developer's perspective. - -.. tabularcolumns:: |p{0.15\linewidth}|p{0.10\linewidth}|p{0.65\linewidth}| - -.. csv-table:: Compliance with Section 12.2 of |standard| - :delim: # - :header: "Section", "Achieved", "Notes" - - 12.2.1 #Yes#GNATcoverage qualification is needed. See :ref:`certification-credit`. - 12.2.2 #Yes#GNATcoverage qualification level is **TQL-5** for all software levels. See :ref:`tql`. - - -.. tabularcolumns:: |p{0.15\linewidth}|p{0.18\linewidth}|p{0.60\linewidth}| - -.. csv-table:: Compliance with Table 11-1 of |tool_standard| - :delim: # - :header: "Section", "Achieved", "Notes" - - T-0, Objectives 1, 3, 6, 7 # Not applicable # Apply to Tool User, not to Tool Developer per section 11.3 of |tool_standard|. - T-0, Objective 2 # Yes # See the requirement description items in the |tor_doc| document. - T-0, Objective 4 # Not Applicable # Not required for TQL-5. See :ref:`tqap` for AdaCore's QA procedures nevertheless. - T-0, Objective 5 # Yes # See the test and test-cases description items in the |tor_doc| document. - T-1 to T-7 # Not Applicable # Not required for TQL-5. - T-8 # Up to the applicant # See :ref:`user-conf-management` for suggested configuration items. - T-9 # Yes # See the |tqa_doc| document accompanying this qualification package. - T-10 # Up to the applicant # Applies to Tool User, not to Tool Developer per section 11.3 of |tool_standard|. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Data_Production/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Data_Production/content.rst deleted file mode 100644 index a05a6e833..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Data_Production/content.rst +++ /dev/null @@ -1,102 +0,0 @@ -Production of Qualification Data -================================ - -For a given project, the production of qualification data proceeds in several -steps described hereafter: - -Settle on the |opcond_section_title| -************************************ - -As the Tool Developer, AdaCore first discusses with the Tool User to define -the use -that will be made of the tool, agreeing on items such as the tool interface, -the source language version, the runtime profile and language features, the -software level. -This eventually translates as specific indications in the -|opcond_section_title_ref| section of the |tor_doc| document and in the -:ref:`qualified-interface` section of the |plans_doc| document, then |tors| -and their Tests derivatives are refined to accommodate changes in the -scope for which the tool had been qualified so far. - -Produce TORs, Test Cases and Tests Artifacts -******************************************** - -The current set of TORs is organized very hierarchically along the following -major lines: - -* The coverage criteria associated with software levels, - -* The constructs allowed by the source language, influenced by the established - conditions of use, and - -* General coverage analysis facilities, such as the ability to perform coverage - consolidation. - -The general organization is described in the -|torintro_section_title_ref| of the |tor_doc| document. - -A TOR always comes with a Testing Strategy, to be implemented by Test Cases -and eventually Tests. The TOR expresses expected behavior of the tool and the -testing strategy introduces the set of Test Cases. It describes the general -ideas governing the choice of this specific set when needed, and explains how -the set of Tests is constructed for each Test Case when common guidelines were -used. - -Each Test Case addresses a part of what its parent TOR incurs, e.g. on a -particular instance of a language construct. For example, we have a general -core requirement regarding MCDC assessments and derive families of Test Cases -to validate the tool behavior on variations over forms and sizes of decisions, -over the context in which decisions may occur, over the possible forms of -expression operands. - -Then for a given Test Case (say, an *A and then B* Ada expression controlling -an *if* statement, with *A* and *B* both simple Boolean variables), several -tests verify the tool behavior across a set of execution scenarii. Each test -checks results for a specific sequence of calls into the code to analyze, -providing particular values for variables involved in a decision for -example. A single such valuation or several of them are performed with a -specific coverage objective purpose, for instance evaluating a decision both -True and False but demonstrating independent influence of only the first -condition. - -Section |testproc_section_title_ref| of the |tor_doc| document -provides more details on how Tests are composed, and in particular on how -expected results are stated. - -Additional TORs are introduced or existing TORs are adjusted on a case by case -basis when the scope of possible uses of the tool widens somehow, most -commonly when the set of source language constructs for which the tool needs -to be qualified expands. - -The adjustment of an existing TOR might incur a change in the TOR expression -itself and/or a refinement of its testing strategy to encompass what the -new scope requires. - - -Execute Tests to Produce Test-Results Artifacts -*********************************************** - -This is achieved in the Verification Environment by launching a script which -automatically selects the relevant set of tests for the target software level -and runs them with provided control parameters. The tests are taken from a -branch dedicated to the kit construction in AdaCore's repositories. - -This produces execution logs and data files that are later on gathered to -elaborate the |str_doc| report. The Qualification Team verifies at this point -that test results conform to expectations, making sure that the only failures, -if any, are understood and registered in AdaCore's tracking system. - -Produce the Qualification Kit -***************************** - -This is also achieved automatically by a collection of tools coordinated by a -top level script provided with the name of a branch in AdaCore's repositories -where the kit is maintained and the (possibly remote) location of the -directory where the testsuite execution took place. - -The script collects the artifacts, builds the PDF and HTML versions of the -documents and bundles everything together to constitute the kit per se. It -also performs consistency and traceability checks, producing a log of what -those checks find out. The Qualification Team reviews this log and verifies -the general consistency of the documents before handing them to the Quality -Assurance team. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json deleted file mode 100644 index 6ed03541b..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/Environment_Equivalence/content.rst": "4c4b3b0cb6ca7af7026dcd008f15bc6d022db0f0" - }, - "location": "default:///plans/Tool_Qualification_Plan/Environment_Equivalence", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst deleted file mode 100644 index 841ac1fb4..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst +++ /dev/null @@ -1,10 +0,0 @@ -============================= -|opcond_section_title| -============================= - -Beyond the Qualified Interface, qualified use of the tool requires following a -number of rules regarding the Operational Environment, the language revision, -the runtime library profile and the set of language constructs used in the -programs. These rules are described in the |opcond_section_title_ref| section of -the |tor_doc| document. - diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst deleted file mode 100644 index 8eb1b26c1..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst +++ /dev/null @@ -1,54 +0,0 @@ -.. _qualification-data: - -Qualification Data Overview -=========================== - -GNATcoverage is qualified as a COTS tool according to guidance of -section 11.3 of [DO-330/ED-215]. This qualification kit documents the -activities required for the Tool Developer, and provides -recommendations for the Tool User to fulfill his part of the required -activities. - -The qualification data that comes with the tool, composing the tool -*qualification kit*, consists of the following components: - -* **PDF documents package**, containing the following three documents: - - * The |plans_doc_title| document, |plans_pdf|, which is this document - and which we'll refer to as the |plans_doc| document. - - * The |tor_doc_title| document, |tor_pdf|, which contains the description of - the tool operational requirements together with the associated testing - strategy and test cases, and which we'll refer to as the |tor_doc| document. - - The *Document Purpose and Organization* section of the |tor_doc| document - includes a high level description of our overall testing strategy. The - *Overview of the test procedures organization* appendix explains how - expectations on coverage results for each test are stated and used to - produce a verification report out of a testsuite run. - - The test sources aren't included in this version of the document. They are - included in an HTML version, presented below. - - * The |str_doc_title| report, |str_pdf|, which contains a synthetic summary - of the testsuite run performed to assess the tool behavioral correctness - with respect to its intended use, and which we'll refer to as the |str_doc| - report. - -* **HTML documents package**, containing HTML versions of the PDF documents - described above, presented differently and including test sources for the - |tor_doc_title| item. The tests are organized in a very hierarchical manner - so much easier to present and browse in this format than in PDF. See the - :ref:`qa-activities` section of this document for a description of which - |QA| activities are performed on which document variant. - -* **Testsuite package**, archive of the testsuite directory where the - qualification testsuite run took place, filtered to include artifacts - of possible use for inspection (execution logs, coverage reports, ...), - not binary artifacts such as object and executable files, as they take - a huge amount of space, aren't so useful for inspection, and can easily - be re-generated on demand if really needed. - -* |tqa_doc| document, where all Quality Assurance cycles are tracked. - - diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst deleted file mode 100644 index 2788eafd4..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst +++ /dev/null @@ -1,82 +0,0 @@ -.. _qualified-interface: - -GNATcoverage Qualified Interface -================================ - -To obtain reports suitable for use as certification evidence, applicants shall -use GNATcoverage as follows: - -* Build the application with the GNAT Pro toolchain identified in the - *Operational Environment* section of the TOR document, obeying the - compilation options and coding standard rules documented there as well. - -* Build the test code and test harness and link it with the relevant - application objects if necessary to form one or several test - executables. The test code does not need to be compiled with the switches - described in the Operational Environment section, nor does it need to comply - to the coding standard. - -* Obtain as many execution trace files () as needed, by - running the test executables () within the instrumented - execution environment, as in the following example. - - is the coverage criterion level to be assessed and is - the target architecture. The :literal:`--target` switch is required - for cross configurations and shouldn't be stated in the native case. - - The part is required for mcdc analysis only and shall - designate at least the units of that will be of interest to - the analysis step. - - The form these switches should take is described below. - -.. code-block:: text - - gnatcov run [--target=] --level= -o [] - ... - gnatcov run [--target=] --level= -o [] - - -* Optionally, produce a single file (format documented in the - GNATcoverage User's Guide), consolidating the coverage outcome for the list - of execution traces stored in the file, and querying results - for the source units designated by the argument: - -.. code-block:: text - - gnatcov coverage --annotate=report --level= @ -o - - -In the sample commands above: - -* is a test executable; -* designates the coverage criteria to assess, depending on the software - level; - - * For level C, statement coverage data is obtained with :literal:`--level=stmt`; - - * For level B, statement *and* decision coverage data is obtained with - :literal:`--level=stmt+decision`; - - * For level A, statement *and* decision *and* mcdc coverage data is obtained - with :literal:`--level=stmt+mcdc`. - -* is the output file containing the GNATcoverage report; -* identifies the target platform (as in the GNAT Pro toolchain - prefixes, e.g. powerpc-elf); -* is the output file containing the execution trace -* is a specification of the units for which coverage is to be - assessed (so called *Units Of Interest*), with either - - * A :option:`--scos=@` switch, where is a text - file containing the list of GNAT Pro ALI file names associated with - the units of interest; *or* - - * GPR project file facilities, as documented in the tool User's Guide and - summarized in the |tor_doc| document. - -* is a text file containing the list of execution traces to - operate on. - -IO redirections, sometimes necessary for proper operation of the programs -within the execution environment, are allowed. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json deleted file mode 100644 index b772f14bb..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/Tool_Overview/content.rst": "62c9dd406c5253722e013bcfb4fc1919cef2d1fd" - }, - "location": "default:///plans/Tool_Qualification_Plan/Tool_Overview", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst deleted file mode 100644 index f2b250968..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _tql: - -Tool Qualification Level -======================== - -GNATcoverage is qualified as a COTS tool, with impact corresponding to -**Criteria 3** of |standard| section 12.2.2. From Table 12-1, the -GNATcoverage Tool Qualification Level is then **TQL-5** for all software -levels. - diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json deleted file mode 100644 index f6a8beb3d..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/User_Activities/content.rst": "7b61cda26525a947e1ec27e878d4110a3c6027d4" - }, - "location": "default:///plans/Tool_Qualification_Plan/User_Activities", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst deleted file mode 100644 index f9cfb502c..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst +++ /dev/null @@ -1,43 +0,0 @@ -|project_name| Qualification -============================ - -#. **Reference** |project_name_bold| **in the Plan for Software Aspects of - Certification (PSAC)**. The user needs to: - - * Identify |project_name| as a verification tool that needs to be - qualified; - - * Include references to the |project_name| qualification kit documents that - were received to support this particular use of the tool. - -#. **Delivery Acceptance.** On delivery of |project_name| and its - qualification kit, the user shall - - * Assess whether the qualified Operational Environment is - representative of the user's Operational Environment; - - * Assess whether the structural coverage analysis performed - by GNATcoverage satisfies the goals specified in the - :ref:`certification-credit` section; - - * Assess whether the Tool Operational Requirements include suitable - artifacts for specific language constructs expected to be of relevance - for a given coverage criterion. - -#. **Configuration management of qualification data**. The user needs to place - all qualification data under configuration management. - -#. **Obtain a tool qualification agreement**, see section 9.0.b of - |tool_standard|. - -#. **Update Environment Configuration Index (SECI).** Refer to the - |project_name| qualification kit for details associated with its - environment configuration. - -#. **Update the Software Accomplishment Summary (SAS).** The SAS needs to be - updated: - - * For Table A-7 of |standard|: achievement of the objectives 5, 6 and 7, - depending on the software level. - - * For qualification status of |project_name|: refer to |str_doc| report. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst deleted file mode 100644 index b74d75506..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst +++ /dev/null @@ -1,13 +0,0 @@ -|project_name| Usage -==================== - -#. **Install the tool in the Operational Environment.** The user needs - to install the tool in an Operational Environment deemed equivalent - to the one prescribed by the |opcond_section_title_ref| chapter of - the |tor_doc| document (*Operational Environment* section, item e1). - -#. **Check correct usage of the tool.** For the tool results to be - used in a certification context, users must comply with the - interface presented in the :ref:`qualified-interface` section of - this document, as well as with the rules and scope prescribed by - the |opcond_section_title_ref| chapter of the |tor_doc| document. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/content.rst deleted file mode 100644 index 12a3d647b..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/content.rst +++ /dev/null @@ -1,13 +0,0 @@ -=============== -User Activities -=============== - -To finalize the qualification of |project_name|, the Tool User needs to -perform a set of activities, described hereafter: - -.. qmlink:: - - Qualification - Usage - Archiving - diff --git a/qualification/qm/plans/Tool_Qualification_Plan/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/content.rst deleted file mode 100644 index 0a1832dc9..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/content.rst +++ /dev/null @@ -1,15 +0,0 @@ -======================= -Tool Qualification Plan -======================= - -.. qmlink:: - - Qualification_Data_Overview - Compliance - Tool_Overview - Certification_Credit - Tool_Qualification_Level - Data_Production - Qualified_Interface - Operational_Conditions - User_Activities diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Activities/content.rst b/qualification/qm/plans/Tool_Quality_Assurance_Plan/Activities/content.rst deleted file mode 100644 index 09cccdb57..000000000 --- a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Activities/content.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. _qa-activities: - -|QA| Activities -=============== - -This section provides the overview of objectives of distinct |QA| activities -applied to the documents composing a qualification kit. Output of |QA| -activities is recorded in the separate sections of the |tqa_doc| document. - -The PDF format offers a sequential layout of the material which allows -browsing from end to end in a reliable manner, so most of the QA operations -described here are performed on the PDF version of the documents. Only those -steps requiring access to test sources are performed with the help of the HTML -contents. - -Reading the |plans_doc| document -******************************** - -**Objectives:** - - * Assess the compliance with qualification objectives. - -Inspection of Tool Operational Requirements -******************************************* - -**Objectives:** - - * Check the accuracy, completeness and consistency with respect to the - qualification objectives. - -The inspection is conducted by sampling, according to the following -guidelines: - -The requirements are split into families corresponding to the major kind of -metrics to be assessed. For DAL C, there is only a "Statement Coverage" -family; for DAL B, there is an additional "Decision Coverage" family and for -DAL A, a "Modified Condition/Decision Coverage" family complements the other -two. Each metric family is further divided into groups and possibly subgroups, -as needed. - -This is all summarized in the *Document Purpose and Organization* chapter of -the |tor_doc| document, section *Organization Guidelines*, which the |QA| -reviewer reads first. - -The reviewer then selects a set of requirements for review and this set is -documented in the |QA| report. The set would include at least stmt/Exemptions, -Common/Report and some other requirement(s) at the discretion of the reviewer. - -Inspection of Test Cases -************************ - -**Objectives:** - - * Check the accuracy of test cases, in particular whether the tests exercise - their target Ada constructs. - -This activity is also performed by sampling by the |QA| reviewer, selecting -all or a subset of the test cases associated with the selected requirements, -also documented in the |QA| report. - -To help understanding the tests performed for a test case, the reviewer first -gets acquainted with the *Overview of the test Procedures Organization* -appendix of the |tor_doc| document, where we describe the specific syntax we -use to state expected coverage results. - -Inspection of test execution results -************************************ - -**Objectives:** - - * Check that the Verification Environment reported in the |str_doc| report - is equivalent to the Operational Environment described in the |tor_doc| - document. - - * Check the results of test execution. - - * In the case tests failed, it is necessary to investigate whether the - source of error is: - - * A misbehavior of the infrastructure used to run tests and compare actual - results to expected results: in this case, the |project_name| - Qualification Team is in charge of reporting and fixing the problem. - - * A bug in the |project_name| implementation: in this case, the - |project_name| Development Team is in charge of reporting and fixing the - problem. - - * A reasonable limitation of the tool: in this case, the |project_name| - Qualification Team is in charge of reporting and justifying the problem - as part of the known limitations of the tool. - diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst b/qualification/qm/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst deleted file mode 100644 index a7435574a..000000000 --- a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst +++ /dev/null @@ -1,15 +0,0 @@ -Compliance With Guidance -======================== - -|project_name| is qualified as a TQL-5 tool. - -.. tabularcolumns:: |p{0.05\linewidth}|p{0.20\linewidth}|p{0.15\linewidth}|p{0.45\linewidth}| - -.. csv-table:: Compliance matrix for Table T-9 of |tool_standard| - :delim: & - :header: "Item", "Ref.", "Achieved", "Notes" - - 1,3,4 & 8.1.a,b,c & Not applicable & Not required for TQL-5 tools - 2 & 8.1.b & Yes & See :ref:`qa-activities` - 5 & 8.1.d & Yes & See :ref:`tool-conformity-review` - diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst b/qualification/qm/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst deleted file mode 100644 index ae8f5897f..000000000 --- a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _tool-conformity-review: - -Tool Conformity Review -====================== - -These objectives are achieved in the scope of the tool conformity review: - - * **8.3.a**: Check that tool life cycle data is under configuration - management and managed as described - * **8.3.b**: Check that activities of the TQP, TCMP and TQAP are - completed and have produced the items described - at :ref:`tcmp` - * **8.3.c**: Check that problems have been reported and evaluated according to - the :ref:`tcmp`. - * **8.3.d**: Record and approve software requirements deviations arising from - two sources: (1) deviations exposed by test failures reported in the - |project_name| |str_doc| provided as part of the tool qualification data; - and (2) deviations due to issues recorded in the known-problems - file maintained by |adacore| for a given release of |project_name|. - * **8.3.e**: Check that the tool executable object code can be re-generated - from the tool source code. - * **8.3.f**: Check that problems from a previous Tool Conformity Review are - re-evaluated. - * **8.3.g**: Not applicable since no credit is sought for the use of - previously developed tools. - diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst b/qualification/qm/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst deleted file mode 100644 index 7b69d4b73..000000000 --- a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst +++ /dev/null @@ -1,52 +0,0 @@ -|QA| Cycles -=========== - -Each |QA| cycle consists of the following iterations: - -* The **Qualification Team** starts the cycle by adding the documents - submitted for review into the ``qa`` area. The **Quality Assurance Team** is - then notified. - -:raw-latex:`\begin{minipage}{\linewidth}` - -* The **Quality Assurance Team** identifies defects in the documents. For each - defect the **Quality Assurance Team** enters in the report a unique *defect - id*, its *location and scope*, *description*, as well as defect *severity - code*, which can be: - - * **EDIT** - minor editorial remark. - * **MINOR** - minor defect, i.e. one that is not blocking the document - release. - * **MAJOR** - major defect, i.e. one that is blocking the document release. - - **Qualification Team** is notified when the review is complete. - -:raw-latex:`\end{minipage}` - -:raw-latex:`\begin{minipage}{\linewidth}` - -* The **Qualification Team** reviews each defect, and either Accepts or - Rejects it. - - * If a defect is **Accepted**: *Corrective Action* is described and applied. - * If a defect is **Rejected**: *Reason* is provided. - -:raw-latex:`\end{minipage}` - -* If any defects have been **Accepted** and *Corrective Actions* applied: new - version of the document(s) is generated and added to the ``qa`` area. - -* The **Quality Assurance Team** reviews remarks for **Rejected** defects, - description and proper application of *Corrective Actions* for **Accepted** - defects. If the **Quality Assurance Team** agrees with the **Qualification - Team**'s response to a defect, it is marked as *Resolved*. - -* The **Qualification Team** and The **Quality Assurance Team** converge until - at least all **MAJOR** defects are *Resolved*. - - i.e.: The **Quality Assurance Team** agrees either with the given *Reason* - if a defect is **Rejected**, or with the proposed *Corrective Action* (and - its proper application has then been verified) if defect is **Accepted**. - -* The documents are then deemed ready for release. - diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/content.rst b/qualification/qm/plans/Tool_Quality_Assurance_Plan/content.rst deleted file mode 100644 index e98dc4141..000000000 --- a/qualification/qm/plans/Tool_Quality_Assurance_Plan/content.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _tqap: - -=========================== -Tool Quality Assurance Plan -=========================== - -|project_name| |QA| (QA) proceeds in cycles of activities. - -The QA outputs for a kit are stored in a "qa" directory dedicated to the -project for which the kit is produced. The most significant output is the -|tqa_doc| document, ``qa.doc``, where all the QA cycles are tracked. - -The responsibility for the |QA| process belongs to the |QA| team. - -.. qmlink:: - - Compliance - Cycles - Activities - Conformity_Review diff --git a/qualification/qm/plans/content.rst b/qualification/qm/plans/content.rst deleted file mode 100644 index 99f71ef39..000000000 --- a/qualification/qm/plans/content.rst +++ /dev/null @@ -1,18 +0,0 @@ -=================================================================== -GNATcoverage - |standard| Qualification Material: |plans_doc_title| -=================================================================== - -.. rubric:: Revision History - -.. csv-table:: - :delim: | - :header: "Version #", "Date", "Comment" - - |release| & |today| & Initial version - -.. qmlink:: - - Introduction - Tool_Qualification_Plan - Tool_Configuration_Management_Plan - Tool_Quality_Assurance_Plan diff --git a/qualification/qm/plans/qmconf.py b/qualification/qm/plans/qmconf.py deleted file mode 100644 index c53fc4612..000000000 --- a/qualification/qm/plans/qmconf.py +++ /dev/null @@ -1,24 +0,0 @@ -# This file gets copied by sphinx as something like: -# .../qualification/qm/.qm/PLANS/_sphinx/conf.py -# -# and the common configuration file is in qualification/qm ... - -common_file = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__))))), - "common_conf.py") - -if os.path.isfile(common_file): - execfile(common_file) - execfile(os.path.join( - os.path.dirname(common_file), - "qm_prolog.py")) -else: - print "Couldn't find common configuration file" - print common_file - print "from: %s" % __file__ - -doc_id = plans_doc_id diff --git a/qualification/qm/qm_plugins/generate_doc.py b/qualification/qm/qm_plugins/generate_doc.py deleted file mode 100644 index 39ae4085c..000000000 --- a/qualification/qm/qm_plugins/generate_doc.py +++ /dev/null @@ -1,51 +0,0 @@ -import os.path -import qm -import qm.rest.pdfgenerator - -def get_userconf(): - # retrieve the author from the environment data artifact - env = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'env.py') - with open(env,"r") as fd: - envdata = eval(fd.read()) - - author = "AdaCore for %s" % (envdata['project_full']) - - return author - -class GenPDF(qm.rest.pdfgenerator.SphinxGeneratePdf): - def userconf(self): - # use method from super just to retrieve the 'extras' field - [ author, version, extras ] = qm.rest.pdfgenerator.SphinxGeneratePdf.userconf (self) - author = get_userconf() - - return [author, version, extras] - -class GenHTML(qm.rest.pdfgenerator.SphinxGenerateHtml): - def userconf(self): - # use method from super just to retrieve the 'extras' field - [ author, version, extras ] = qm.rest.pdfgenerator.SphinxGenerateHtml.userconf (self) - author = get_userconf() - - return [author, version, extras] - - -def _generate(name, path, generator): - root = None - top = qm.get_toplevel_artifacts() - for artifact in top: - if artifact.name == name: - root = artifact - break - if root is None: - qm.log_error("Cannot find an artifact named " + name) - else: - full = os.path.abspath(path) - generator.execute(root, full) - - -def generate_pdf(name, path): - _generate(name, os.path.join(path, "%s.pdf" % name), GenPDF()) - - -def generate_html(name, path): - _generate(name, path, GenHTML()) diff --git a/qualification/qm/qm_plugins/importers.py b/qualification/qm/qm_plugins/importers.py deleted file mode 100644 index 50a787ae5..000000000 --- a/qualification/qm/qm_plugins/importers.py +++ /dev/null @@ -1,1155 +0,0 @@ -import qm -from qm.rest import ArtifactImporter, writer -from qm.rest.pdfgenerator import artifact_hash -from itertools import izip_longest -from collections import OrderedDict -import re -import os - - -MISSING_TR_LOG = os.path.join(qm.get_project_dir(), "missing_tr_log.txt") - - -def class_to_string(a): - """ - Returns the two or three letters string - refering to the class of the artifact 'a' if defined, - the name of the class otherwise. - - :param a: the artifact - :type a: artifact - """ - d = {'TORReq_Set': 'rqg', - 'TORReq': 'rq', - 'TC': 'tc', - 'TC_Set': 'tcg'} - - if 'Appendix' in a.full_name: - return 'app' - elif a.name == 'OpEnviron': - return 'env' - elif a.__class__.__name__ in d: - return d[a.__class__.__name__] - else: - return a.__class__.__name__ - - -def class_to_content_key(a): - """ - Returns key name for the main content of an artifact - which is a container. (defined in xml model). - - :param a: the artifact - :type a: artifact - """ - - # keys in the model are dependant of the artifact class - d = {'TORReq_Set': 'set_content', - 'TORReq': 'requirement', - 'TC': 'tc_content', - 'TC_Set': 'tc_set_content', - } - - if 'Appendix' in a.full_name: - return 'app' - elif a.name == 'OpEnviron': - # OpEnv only is content, not container - return None - elif a.__class__.__name__ in d: - return d[a.__class__.__name__] - else: - return None - - -########################### -# Tests on artifact class # -########################### - -def is_req(a): - from qm import TORReq - return isinstance(a, TORReq) - - -def is_reqset(a): - from qm import TORReq_Set - return isinstance(a, TORReq_Set) - - -def is_req_or_set(a): - return is_req(a) or is_reqset(a) - - -def is_tc(a): - from qm import TC - return isinstance(a, TC) - - -def is_tcset(a): - from qm import TC_Set - return isinstance(a, TC_Set) - - -def is_tc_or_set(a): - return is_tc(a) or is_tcset(a) - - -def is_test_result(a): - from qm import TR - return isinstance(a, TR) - - -def is_lrm_section(a): - from qm import LRM_Section - - return isinstance(a, LRM_Section) - - -def is_source(a): - from qm import Source_files - return isinstance(a, Source_files) - - -def is_consolidation(a): - from qm import Conso_Sources - return isinstance(a, Conso_Sources) - - -def is_helper(source_resource): - return not(is_driver(source_resource) or is_functional(source_resource)) - - -def is_driver(source_resource): - # a resource named with "test_" is necsseraly a 'driver' - return "test_" in source_resource.basename - - -def is_functional(source_resource): - # a resource whom content contains "-- #" is - # a functional source. In case of Ada Sources !! - - content = source_resource.get_content() - is_func = False - - for line in content.splitlines(): - if "-- #" in line: - is_func = True - break - return is_func - - -######### -# Utils # -######### - -def get_short_description(artifact): - """ - Get the first line of a file as the short description. - Layout elements are removed from the description. - - :param artifact: the artifact - :type artifact: artifact - """ - - for item in artifact.contents(class_to_content_key(artifact)): - content = item.get_content() - - for line in content.splitlines(): - line = line.strip() - if len(line) > 0: - # ** has to be removed - # from short_description when used in tables - first_line = line.replace('**', '') - break - - return first_line - - -def get_first_req_relative(artifact): - """ - Returns the first parent which is a req. - - :param artifact: the artifact - :type artifact: artifact - """ - parent = artifact.relative_to - return (parent if (parent is None or is_req(parent)) - else get_first_req_relative(parent)) - - -def write_artifact_ref(artifact_full_name, label=None): - """ - Returns a sphinx :ref: on 'artifact_full_name' - using as label: 'label' if declared, 'artifact_full_name' otherwise - - :param artifact_full_name: the full name of the artifact - :type artifact_full_name: string - :param label: the label to be used un the hyperlink - :type label: string - """ - - if label is None: - label = artifact_full_name - - return writer.role('ref', - '%s <%s>' % (label, - artifact_full_name.replace('/', '_')[1:])) - - -def kind_of(artifact): - """ - :param artifact: the artifact - :type artifact: artifact - """ - return ("Requirement Group" if is_reqset(artifact) - else "Requirement" if is_req(artifact) - else "Testcase Group" if is_tcset(artifact) - else "Testcase" if is_tc(artifact) - else "Chapter") - - -def short_kind_of(artifact): - """ - :param artifact: the artifact - :type artifact: artifact - """ - kind = kind_of(artifact) - return "Group" if "Group" in kind else kind - - -def relative_links_for(artifact): - """ - :param artifact: the artifact - :type artifact: artifact - """ - output = "" - - req = get_first_req_relative(artifact) - if req: - output += writer.paragraph( - "**Parent Requirement**: %s\n\n" % writer.qmref(req.full_name)) - - ancestor = artifact.relative_to - if ancestor and ancestor != req: - output += writer.paragraph( - "**Parent %s**: %s\n\n" % - (short_kind_of(ancestor), write_artifact_ref(ancestor.full_name))) - - return output - - -def default_importer(artifact): - """ - Returns the importer whom the to_rest() method - must be used for a given 'artifact' according to its class. - - :param artifact: the artifact - :type artifact: artifact - """ - if is_req(artifact): - return RequirementImporter() - elif is_tcset(artifact): - return TCSetImporter() - else: - return qm.rest.DefaultImporter() - -#################################################################### -# Importers - - -class LRMTableImporter(ArtifactImporter): - """ - The specific importer to generate the Traceability matrix - between reference manual and testcases and requirements - """ - - def qmlink_to_rest(self, parent, artifacts): - """ - Returns a matrix of traceability between - lrm section artifact and thi associated test cases - and requirements. - chosen format was dicussed in MB23-001. - - :param parent: the artifact calling the qmlink - :type parent: artifact - :param artifacts: the list of artifacts listed in qmlink - :type artifacts: list of artifacts - """ - REQ_NAME_PREFIX = "/TOR/Ada" - pdf_items = [] - html_items = [] - output = "" - language_version = None - - for a in artifacts: - if is_lrm_section(a): - - if not language_version: - language_version = a.attributes['language'].strip() - - ref = {} - for children in a.derived_to: - for child in children.all: - if is_tc(child): - parent = get_first_req_relative(child).full_name - - if parent not in ref.keys(): - ref[parent] = [] - - ref[parent].append([child.full_name, - child.full_name.replace( - parent, '')]) - - pdf_tc_list = "" - html_tc_list = "" - pdf_comment = "" - html_comment = "" - - for req in ref.keys(): - - pdf_other_tcs = "" - html_tcs = "" - - if len(ref[req]) > 1: - pdf_other_tcs = "%s + %d other tests" % \ - (writer.role("raw-latex", r'\newline'), - (len(ref[req]) - 1)) - - html_tcs = writer.role("raw-html", r'
').join( - [write_artifact_ref(k[0], - label=k[1]) for k in ref[req]]) - - requirement_str = "Req: %s" % \ - write_artifact_ref(req, - req.replace(REQ_NAME_PREFIX, - '')).strip() - first_tc_str = "* TC: %s" % \ - write_artifact_ref(ref[req][0][0], - label=ref[req][0][1]).strip() - - pdf_tc_list += "%s %s %s %s %s " % ( - requirement_str, - writer.role("raw-latex", r'\newline'), - first_tc_str, - pdf_other_tcs, - writer.role("raw-latex", r'\newline')) - - html_tc_list += "%s %s * TC: %s %s " % ( - requirement_str, - writer.role("raw-html", r'
'), - html_tcs, - writer.role("raw-html", r'
')) - - applicable = a.attributes['relevance'].strip() - if pdf_tc_list != "": - if applicable == "no" or applicable == "partial": - relevance = applicable - comment = a.attributes['comment'].strip() - - pdf_comment = comment + ' ' + \ - writer.role("raw-latex", r'\newline') + ' ' - html_comment = comment + ' ' + \ - writer.role("raw-html", r'
') + ' ' - - elif applicable == "yes": - relevance = "yes" - elif applicable == "no*": - relevance = "no" - comment = "Section does not require SCA-related " + \ - "tests, but some are supplied " - - pdf_comment = comment + \ - writer.role("raw-latex", r'\newline') + ' ' - html_comment = comment + \ - writer.role("raw-html", r'
') + ' ' - else: - relevance = "unexpected value %s" % applicable - - if relevance != "no": - # when applicable is set to no, the list of - # tc must be ommitted. - # otherwise it is added to the comment column - # see N102-011 Feb 8, 2014 - pdf_comment += pdf_tc_list - html_comment += html_tc_list - - else: - if applicable == "no": - relevance = "no" - comment = a.attributes['comment'].strip() - - pdf_comment = comment - html_comment = comment + ' ' + \ - writer.role("raw-html", r'
') + ' ' - - elif applicable == "partial": - relevance = "PARTIAL but not covered" - comment = a.attributes['comment'].strip() - - pdf_comment = comment - html_comment = comment + ' ' + \ - writer.role("raw-html", r'
') + ' ' - - elif applicable == "yes": - relevance = "YES but not covered" - elif applicable == "no*": - relevance = "NO but" - comment = "Indicated as no* in matrix." + \ - " Some test should be provided." - - pdf_comment = comment - html_comment = comment + ' ' - - else: - relevance = "unexpected value %s" % applicable - - pdf_items.append(["%s" % a.full_name.replace('/', ''), - a.attributes['title'].strip(), - relevance, - pdf_comment]) - - html_items.append(["%s" % a.full_name.replace('/', ''), - a.attributes['title'].strip(), - relevance, - html_comment]) - - pdf_table = writer.csv_table( - pdf_items, - title="TOR/LRM Traceability Matrix for Ada %s" % language_version, - headers=["Section", "Title", "Applicable", "Comment"], - latex_format='|p{0.08\linewidth}|p{0.20\linewidth}|' + - 'p{0.10\linewidth}|p{0.50\linewidth}|') - - html_table = writer.csv_table( - html_items, - headers=["Section", "Title", "Applicable", "Comment"], - widths=[8, 20, 10, 50]) - - output += writer.paragraph( - "This particular table is established for **Ada %s**." % - language_version + - "\n\The requirement identifiers in this table were shortened by " - "removing the *%s* common prefix.\n\n" % REQ_NAME_PREFIX) + \ - writer.only(pdf_table, "latex") + \ - writer.only(html_table, "html") - - output += "\n\n" - - return output, [] - - -class TCIndexImporter(ArtifactImporter): - - def get_recursive_relatives(self, artifact, depth): - """ - Returns the list of the tc or tc_set children of an artifact - and recurcively the children of its children until the - required depth - - :param artifact: - :type artifact: artifact - :param depth: - :type depth: positive integer - - """ - result = [] - - for child in artifact.relatives: - if is_tc_or_set(child): - result.append(child) - if depth > 1: - result += self.get_recursive_relatives(child, depth - 1) - - return result - - def qmlink_to_rest(self, parent, artifacts): - - html_items = [] - pdf_items = [] - output = "" - - for a in artifacts: - # Don't put sources in the tables - if is_source(a): - continue - - if is_tc_or_set(a): - reference = write_artifact_ref(a.full_name, - get_short_description(a)) - - html_items.append([writer.strong(class_to_string(a)), - writer.strong(a.name), - reference]) - pdf_items.append([class_to_string(a), - a.name, - reference]) - for suba in self.get_recursive_relatives(a, 1): - # We do include in the table children artifacts only - # in html format. - - if is_tc(suba): - subref = write_artifact_ref(suba.full_name, - get_short_description(suba)) - - if is_tcset(suba): - subref = writer.qmref(suba.full_name) - - html_items.append([class_to_string(suba), - "`..` %s" % suba.name, - subref]) - - html_table = writer.csv_table( - html_items, - headers=["", "TestCases", "Description"], - widths=[3, 25, 65]) - - pdf_table = writer.csv_table( - pdf_items, - headers=["", "TestCases", "Description"], - widths=[3, 25, 65]).strip() - - output += writer.only(html_table, "html") - output += writer.only(pdf_table, "latex").strip() - output += "\n\n" - - links = [] - for a in artifacts: - if is_tc(a): - links.append((a, TestCaseImporter())) - elif is_source(a): - pass - else: - links.append((a, default_importer(a))) - - output += writer.toctree( - ['/%s/content' % artifact_hash(*l) - for l in links - if not is_tc_or_set(l[0]) or is_tc_or_set(parent)], - hidden=True) - - return output, links - - -class AppIndexImporter(ArtifactImporter): - - def qmlink_to_rest(self, parent, artifacts): - return '', [] - - -class RequirementImporter(ArtifactImporter): - """ - The specific importer for requirements - """ - - def to_rest(self, artifact): - """ - Returns the 'rest' content of a requirement having the - macro %REQ_ID% replaced by the requirement fullname - """ - - reference = ".. _%s:\n\n" % artifact.full_name.replace('/', '_')[1:] - - result = qm.rest.DefaultImporter().to_rest(artifact) + '\n\n' - - result = (reference + re.sub(pattern="%REQ_ID%", - repl="**REQUIREMENT** %s" % - artifact.full_name, - string=result)) - - return result - - -class TCSetImporter(ArtifactImporter): - """ - The specific importer for TCSet - """ - - def to_rest(self, artifact): - """ - Returns the 'rest' content of a tc set having the - title and the links to parents included in the same 'minipage' - in order to keep them close in the final pdf generation - """ - - reference = ".. _%s:\n\n" % artifact.full_name.replace('/', '_')[1:] - result = "" - qmlink = "" - in_qmlink = False - content = qm.rest.DefaultImporter().to_rest(artifact) - - for line in content.splitlines(): - if line.startswith('.. qmlink:: TCIndexImporter'): - in_qmlink = True - - if in_qmlink: - qmlink += line + '\n' - else: - result += line + '\n' - - result = reference + result + '\n\n' - result += relative_links_for(artifact) - result = "|\n\n" + writer.minipage(result, r'\linewidth') + "\n\n" + \ - qmlink - - return result - - -class ToplevelIndexImporter(ArtifactImporter): - - def qmlink_to_rest(self, parent, artifacts): - - items = [] - html_top_index = "" - - for a in artifacts: - - items.append([writer.strong(a.name), - writer.qmref(a.full_name)]) - - if a.name == "Ada": - - def key(a): - d = {'stmt': 1, 'decision': 2, 'mcdc': 3} - for k in d: - if k in a.name: - return d[k] - - selected = [k for k in a.relatives if not is_source(k)] - selected.sort(key=key) - - else: - selected = a.relatives - - for suba in selected: - items.append(["`..` %s" % suba.name, - writer.qmref(suba.full_name)]) - - html_top_index += writer.csv_table( - items, - headers=["Chapter", "Description"], - widths=[30, 70]) - - output = writer.only(html_top_index, "html") - - links = [(a, qm.rest.DefaultImporter()) - for a in artifacts if "Index/.+" not in a.full_name] - - output += writer.toctree(['/%s/content' % artifact_hash(*l) - for l in links if not is_tc_or_set(l[0])], - hidden=True) - - return output, links - - -class SubsetIndexTable(ArtifactImporter): - - def qmlink_to_rest(self, parent, artifacts): - - items = [] - header = "" - - req = len([a for a in artifacts if class_to_string(a) == 'rq']) - reqg = len([a for a in artifacts if class_to_string(a) == 'rqg']) - tcg = len([a for a in artifacts if class_to_string(a) == 'tcg']) - tc = len([a for a in artifacts if class_to_string(a) == 'tc']) - - for a in artifacts: - - name = a.name - items.append([class_to_string(a), - name, - writer.qmref(a.full_name)]) - - # in the html, the title is adapted to the content of the table - header = ("Requirements and Groups" if (req > 0 and reqg > 0) else - ("Requirements Group" if (req == 0 and reqg == 1) else - ("Requirements Groups" if (req == 0 and reqg > 1) else - ("Requirement" if (req == 1 and reqg == 0) else - ("Requirements" if (req > 1 and reqg == 0) else - ("Testcases and Groups" if (tc > 0 and tcg > 0) else - ("Testcases" if (tc > 0 and tcg == 0) else - ("Testcases Groups" if (tc == 0 and tcg > 0) else - (""))))))))) - - output = writer.csv_table( - items, - headers=["", "%s" % header, "Description"], - widths=[3, 25, 65]) - - return output, [] - - -class SubsetIndexTocTree(ArtifactImporter): - - def qmlink_to_rest(self, parent, artifacts): - - links = [(a, default_importer(a)) for a in artifacts] - - output = writer.toctree(['/%s/content' % artifact_hash(*l) - for l in links if not is_tc_or_set(l[0])], - hidden=True) - - return output, links - - -class SubsetIndexImporter(SubsetIndexTable): - - def qmlink_to_rest(self, parent, artifacts): - - output, links = SubsetIndexTable.qmlink_to_rest(self, - parent, artifacts) - - links = [(a, default_importer(a)) for a in artifacts] - - output += writer.toctree(['/%s/content' % artifact_hash(*l) - for l in links if not is_tc_or_set(l[0])], - hidden=True) - return output, links - - -class TestCaseImporter(ArtifactImporter): - - def log_missing_TR(self, artifact): - """ - Logs in a specific files the test case - if it has no test results. - - :param artifact: the artifact to analyse - :type artifact: artifact - """ - - has_TR = False - - for child in artifact.relatives: - has_TR = is_test_result(child) - if has_TR: - break - - if not has_TR: - with open(MISSING_TR_LOG, 'a') as fd: - fd.write("No TR for artifact %s location: %s\n" % - (artifact.full_name, artifact.location)) - - def get_sources(self, artifact): - """ - Returns all the sources an artifact TC needs to - list. It means its own sources and all thoses - of its parents - - :param artifact: the artifact the sources are required from - :type artifact: artifact - """ - - result = [] - - for child in artifact.relatives: - if is_source(child): - result += [child] - - if artifact.relative_to is not None: - result += self.get_sources(artifact.relative_to) - - return result - - def to_rest(self, artifact): - - reference = "\n\n.. _%s:\n" % artifact.full_name.replace('/', '_')[1:] - - result_pdf = '**TEST CASE**: %s\n\n' % artifact.full_name - result_html = '%s\n%s\n' % (artifact.full_name, - '=' * len(artifact.full_name)) - - result_pdf += qm.rest.DefaultImporter().to_rest(artifact) + '\n\n' - result_html += qm.rest.DefaultImporter().to_rest(artifact) + '\n\n' - - result = reference + writer.only(result_pdf, "latex") - result += writer.only(result_html, "html") - - self.log_missing_TR(artifact) - - # Create a navigation links from this TC up to its requirement - # and group if any: - - result += relative_links_for(artifact) - - # Managing the list of the sources - - driver_list = [] - driver_list_qmref = [] - func_list = [] - func_list_qmref = [] - helper_list = [] - helper_list_qmref = [] - - consolidation_list = [] - consolidation_list_qmref = [] - - # Whether we will output sources for the PDF version - do_pdf = False - - for item in self.get_sources(artifact): - - if is_consolidation(item): - - consolidation_list += [item.name] - consolidation_list_qmref += [writer.qmref - (item.full_name, - item.name)] - - continue - - for key in item.contents_keys: - if len(item.contents(key)) > 0: - - for resource in item.contents(key): - - if is_driver(resource): - driver_list += [resource.basename] - driver_list_qmref += [writer.qmref - (item.full_name, - resource.basename)] - continue - - if is_functional(resource): - func_list += [resource.basename] - func_list_qmref += [writer.qmref - (item.full_name, - resource.basename)] - continue - - helper_list += [resource.basename] - helper_list_qmref += [writer.qmref - (item.full_name, - resource.basename)] - - driver_list.sort() - driver_list_qmref.sort() - func_list.sort() - func_list_qmref.sort() - helper_list.sort() - helper_list_qmref.sort() - - headers = ["Functional Sources", "Drivers Sources", "Helpers Sources"] - - if consolidation_list: - headers += ["Consolidation Sources"] - consolidation_list.sort() - consolidation_list_qmref.sort() - - for_table_qmref = izip_longest(func_list_qmref, - driver_list_qmref, - helper_list_qmref, - consolidation_list_qmref, - fillvalue="") - - for_table = izip_longest(func_list, - driver_list, - helper_list, - consolidation_list, - fillvalue="") - else: - for_table_qmref = izip_longest(func_list_qmref, - driver_list_qmref, - helper_list_qmref, - fillvalue="") - - for_table = izip_longest(func_list, - driver_list, - helper_list, - fillvalue="") - - html_content = writer.csv_table([k for k in for_table_qmref], - headers) - - result += writer.only(html_content, "html") - - if (do_pdf): - latex_content = writer.csv_table([k for k in for_table], - headers).strip() - result += writer.only(latex_content, "latex") - - output = '\n\n' + writer.minipage(result, r'\linewidth') + "|\n\n" - - return output - - -class SourceCodeImporter(ArtifactImporter): - - def to_rest(self, artifact): - - from qm import Ada_Sources, C_Sources, Conso_Sources - - result = "" - - if isinstance(artifact, Ada_Sources): - - for key in artifact.contents_keys: - for item in artifact.contents(key): - result += writer.paragraph_title(item.basename) - result += writer.code_block(item.get_content(), "ada") - - if isinstance(artifact, C_Sources): - - for key in artifact.contents_keys: - for item in artifact.contents(key): - result += writer.paragraph_title(item.basename) - result += writer.code_block(item.get_content(), "c") - - if isinstance(artifact, Conso_Sources): - - result += writer.paragraph_title(artifact.name) - result += writer.code_block(artifact.location.get_content(), - "bash") - - return result - - -class IndexImporter(ArtifactImporter): - - def append_to_items(self, art, depth): - - if is_req(art): - self.current_req = art - kind_text = writer.strong("(%s)" % class_to_string(art)) - id_text = writer.strong( - "%s" % art.full_name.replace("/TOR", "")) - - elif is_tc(art): - kind_text = "(%s)" % class_to_string(art) - - common_prefix_parent_req = os.path.commonprefix( - (art.full_name, - self.current_req.full_name)) - - id_text = \ - "[...]" + art.full_name.replace(common_prefix_parent_req, "") - - self.items.append( - [kind_text, id_text, - write_artifact_ref(art.full_name, get_short_description(art))]) - - def handle(self, art, depth): - - if is_req(art) or is_tc(art): - self.append_to_items(art, depth) - - for child in art.relatives: - self.handle(art=child, depth=depth+1) - - def qmlink_to_rest(self, parent, artifacts): - - self.items = [] - - def sortkey_for(art): - - # Arrange for stmt requirements to come first, before decision and - # mcdc. Work from locations, which contain the explicit ordering - # requests in the names (numeric prefixes like 1_). - - return str(art.location).replace("/stmt", "/a") - - artifacts.sort(key=sortkey_for) - - for art in artifacts: - self.handle(art=art, depth=0) - - pdf_table = writer.csv_table( - self.items, - headers=["Kind", "Identification", "Description"], - latex_format=( - '|p{0.05\linewidth}|p{0.47\linewidth}||p{0.37\linewidth}|')) - - html_table = writer.csv_table( - self.items, - headers=["Kind", "Ref"], - widths=[5, 47, 37]) - - output = "" - output += writer.only(pdf_table, "latex") - output += writer.only(html_table, "html") - - output += "\n\n" - - return output, [] - - -class TestCasesImporter(ArtifactImporter): - - def short_descs_of_main_ancestors(self, artifact, head): - """ - Get the first line of both itself and the ancestor - if the ancestor name is ended with 'head' - - :param artifact: the artifact - :type artifact: artifact - :param head: the prefix of the main group of artifacts - the description is required for - :type head: string - """ - - parent = artifact.relative_to - desc = None - main_desc = None - - if parent is not None: - if parent.full_name.endswith(head): - main_desc = get_short_description(parent) - desc = get_short_description(artifact) - else: - main_desc, desc = self.short_descs_of_main_ancestors(parent, - head) - - return main_desc, desc - - def get_testcases(self, artifact): - """ - Returns either itself if artifact is a tc or a tc_set - or the list of the test cases children of the artifact - - :param artifact: the artifact - :type artifact: artifact - """ - result = [] - - if is_tc_or_set(artifact): - return [artifact] - - for child in artifact.relatives: - result += self.get_testcases(child) - - return result - - def get_sources(self, artifact): - """ - Returns either itself if artifact is a source or - the list of the sources children of artifact - - :param artifact: the artifact - :type artifact: artifact - """ - result = [] - - if is_source(artifact): - return [artifact] - - for child in artifact.relatives: - result += self.get_sources(child) - - return result - - def tc_pdf_for(self, toplevel, subdirs, links): - """ - String to emit in the PDF output for testcases (or sets) - found in the ``links`` list underneath the list of candidate - ``subdirs`` of the ``toplevel`` directory within the Qualif - tree (eg. toplevel='Ada', subdirs=['stmt', 'decision', 'mcdc']). - - :param toplevel: Name of toplevel subdirectory within the - Qualif hierarchy, such as 'Ada' or 'Common'. - :type toplevel: string - - :param subdirs: List of immediate subdirectories of ``toplevel`` - where we should be searching for testcases, possiby through - intermediate sets. There may be no testcase in any of these. - :type subdirs: list[str] - - :param links: List of (artifact, importer) tuples for actual - tc_or_set artifacts to include in the document we're generating. - :type links: list[(artifact,importer)] - """ - - pdf_output = '' - - for subdir in subdirs: - subdir_output = self.tc_pdf_for_subdir( - toplevel=toplevel, subdir=subdir, links=links) - - if subdir_output: - if len(pdf_output) == 0: - pdf_output += writer.section( - '%s Testcases' % toplevel) + '\n' - else: - pdf_output += writer.role( - 'raw-latex', r'\newpage') + '\n\n' - - pdf_output += subdir_output - - return pdf_output - - def tc_pdf_for_subdir(self, toplevel, subdir, links): - """ - Helper for tc_pdf_for, doing the work for a single subdir. - """ - - subdir_links = [ - sdl for sdl in links - if sdl[0].full_name.startswith('/TOR/%s/%s' % (toplevel, subdir))] - - if not subdir_links: - return '' - - links_dict = OrderedDict() - for sdl in subdir_links: - main_desc, desc = self.short_descs_of_main_ancestors(sdl[0], - subdir) - if desc not in links_dict: - links_dict[desc] = [] - links_dict[desc].append(sdl) - - pdf_output = '' - pdf_output += writer.subsection('%s' % main_desc) + '\n' - - for desc in links_dict.keys(): - pdf_output += writer.subsubsection(desc) + '\n' - pdf_output += writer.toctree( - ['/%s/content' % artifact_hash(*l) - for l in links_dict[desc]], - hidden=True) - - return pdf_output - - def qmlink_to_rest(self, parent, artifacts): - - # cleanup missingTRfile - with open(MISSING_TR_LOG, 'w') as fd: - fd.write("") - - # Precompute sets of (artifact, importer) pairs of relevance - # to our outputs. - - tc_or_set_links = [] - src_links = [] - for a in artifacts: - for suba in self.get_testcases(a) + self.get_sources(a): - if is_tc(suba): - tc_or_set_links.append((suba, TestCaseImporter())) - elif is_tcset(suba): - tc_or_set_links.append((suba, TCSetImporter())) - elif is_source(suba): - src_links.append((suba, SourceCodeImporter())) - - mixed_links = src_links + tc_or_set_links - - # Build the html output - - html_output = writer.toctree( - ['/%s/content' % artifact_hash(*l) - for l in mixed_links], hidden=True) - - # Then the PDF variant. A bit more work as we need to output - # intermediate section titles ourselves and we don't want to - # include the sources there. - - pdf_output = '' - pdf_output += self.tc_pdf_for( - toplevel='Ada', - subdirs=['stmt', 'decision', 'mcdc'], - links=tc_or_set_links) - pdf_output += self.tc_pdf_for( - toplevel='Common', - subdirs=['Report', 'UnitsOfInterest', 'GprFacilities'], - links=tc_or_set_links) - - output = writer.only(html_output, "html") - output += writer.only(pdf_output, "latex") - - return output, mixed_links diff --git a/qualification/qm/qm_plugins/link_lrm.py b/qualification/qm/qm_plugins/link_lrm.py deleted file mode 100644 index 8a5f023a2..000000000 --- a/qualification/qm/qm_plugins/link_lrm.py +++ /dev/null @@ -1,20 +0,0 @@ - -LRMREF = "LRMREF:" - - -def parse_req(artifact): - """ - Parses the requirements to extract LRM Sections - that are bound "from" of links 'Lrm_Req' defined in model - """ - - loc = artifact.resources[0][0] - ref_list = [] - - for line in loc.get_content().splitlines(): - - if line.lstrip().startswith(LRMREF): - ref_list = ['/%s' % k.strip() - for k in line.split(LRMREF, 1)[1].split(',')] - - return ref_list diff --git a/qualification/qm/qm_prolog.py b/qualification/qm/qm_prolog.py deleted file mode 100644 index 7b3f1932d..000000000 --- a/qualification/qm/qm_prolog.py +++ /dev/null @@ -1,62 +0,0 @@ -import os - -opcond_section_title = "Operational Conditions of Use" -torintro_section_title = "Document Purpose and Organization" -testproc_section_title = "Overview of the Test Procedures Organization" - -rst_prolog = writer.macro('project_command', '``gnatcov``') \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemi}{$\bullet$}') + '\n\n' \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemii}{$\circ$}') + '\n\n' \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemiii}{$\cdots$}') + '\n\n' \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemiv}{$-$}') + '\n\n' \ - + writer.macro('adacore', 'AdaCore') \ - + writer.macro('gnatpro', 'GNAT Pro') \ - + writer.macro('gnatpro_it', '*GNAT Pro*') \ - + writer.macro('gnatpro_bold', '**GNAT Pro**') \ - + writer.macro('Ada83', '`Ada 83`') \ - + writer.macro('Ada95', '`Ada 95`') \ - + writer.macro('Ada05', '`Ada 2005`') \ - + writer.macro('Ada12', '`Ada 2012`') \ - + writer.macro('QA', 'Quality Assurance') \ - + writer.macro('plans_pdf', r'``PLANS.pdf``') \ - + writer.macro('tor_pdf', r'``TOR.pdf``') \ - + writer.macro('str_pdf', r'``STR.pdf``') \ - + writer.macro('tqa_file', r'``qa.doc``') \ - + writer.macro('tors', r'Tool Operational Requirements') \ - + writer.macro('plans_doc_title', r'*Qualification Plans*') \ - + writer.macro('tor_doc_title', r'*Tool Operational Requirements and V&V Cases and Procedures*') \ - + writer.macro('str_doc_title', r'*Tool Operational Verification and Validation Results*') \ - + writer.macro('tqa_doc_title', r'*Tool Quality Assurance Records*') \ - + writer.macro('plans_doc', r'*PLANS*') \ - + writer.macro('tor_doc', r'*TOR*') \ - + writer.macro('str_doc', r'*STR*') \ - + writer.macro('tqa_doc', '|tqa_doc_title|') \ - + writer.macro('plans_doc_id', r'*' + plans_doc_id + r'*') \ - + writer.macro('tor_doc_id', r'*' + tor_doc_id + r'*') \ - + writer.macro('str_doc_id', r'*' + str_doc_id + r'*') \ - + writer.macro('opcond_section_title', r'%s' % opcond_section_title) \ - + writer.macro('opcond_section_title_ref', r'*%s*' % opcond_section_title) \ - + writer.macro('torintro_section_title', r'%s' % torintro_section_title) \ - + writer.macro('torintro_section_title_ref', r'*%s*' % torintro_section_title) \ - + writer.macro('testproc_section_title', r'%s' % testproc_section_title) \ - + writer.macro('testproc_section_title_ref', r'*%s*' % testproc_section_title) \ - + writer.macro('DAL', 'Design Assurance Level') \ - + writer.macro('PSAC', 'Plan for Software Aspects of Certification') \ - + writer.macro('PSAC_bold', - '**Plan for Software Aspects of Certification**') \ - + writer.macro('V&V', 'Verification and Validation') \ - + writer.macro('RAMS', - 'Reliability, Availability, Maintainability and Safety') \ - + writer.macro('ARM', 'Ada Reference Manual') \ - + writer.macro('standard', 'DO-178C/ED-12C') \ - + writer.macro('tool_standard', 'DO-330/ED-215') \ - + writer.macro('client', '`GENERIC CLIENT`') - -# We expect to be called through genbundle.py, which should export an -# environment variable stating what --dolevel it was passed ('doA', 'doB', -# or 'doC'). Expose the significant letter to documents: -rst_prolog += writer.macro('dolevel', os.environ.get('GENBUNDLE_DOLEVEL')[-1]) diff --git a/qualification/qm/scripts/generate_plans_html.py b/qualification/qm/scripts/generate_plans_html.py deleted file mode 100644 index 87629cdfb..000000000 --- a/qualification/qm/scripts/generate_plans_html.py +++ /dev/null @@ -1,6 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_html('PLANS', 'build/html') diff --git a/qualification/qm/scripts/generate_plans_pdf.py b/qualification/qm/scripts/generate_plans_pdf.py deleted file mode 100644 index 04c5da3c7..000000000 --- a/qualification/qm/scripts/generate_plans_pdf.py +++ /dev/null @@ -1,7 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_pdf('PLANS', 'build/latexpdf') - diff --git a/qualification/qm/scripts/generate_tor_html.py b/qualification/qm/scripts/generate_tor_html.py deleted file mode 100644 index 6e63bb98e..000000000 --- a/qualification/qm/scripts/generate_tor_html.py +++ /dev/null @@ -1,6 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_html('TOR', 'build/html') diff --git a/qualification/qm/scripts/generate_tor_pdf.py b/qualification/qm/scripts/generate_tor_pdf.py deleted file mode 100644 index 921356f92..000000000 --- a/qualification/qm/scripts/generate_tor_pdf.py +++ /dev/null @@ -1,7 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_pdf('TOR', 'build/latexpdf') - diff --git a/qualification/qm/template.xml b/qualification/qm/template.xml deleted file mode 100644 index 3b86b5066..000000000 --- a/qualification/qm/template.xml +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(langlevel_reqset_triggers)s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(extra_block)s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qualification/qualification.md b/qualification/qualification.md new file mode 100644 index 000000000..37c01b12d --- /dev/null +++ b/qualification/qualification.md @@ -0,0 +1,211 @@ +# Producing a qualification kit for GNATcoverage + + +This documents describes how to produce the various documents that +comprise the DO-178C qualification kit for GNATcoverage, and provide +some details as to how each document is generated and about the scripts +used to generate them. + +## Prerequisites + +All documents require some common configuration that we pull from the +/eng/libadalang/gnatcheck-qualkit repository. +To set things up correctly clone the repository somewhere (later referenced +as ) and copy / make a symbolic link as follows + +```console +(gnatcov/qualification)$ ln -s /doc/_common gnatcheck_qualkit_common +``` + +or + +```console +(gnatcov/qualification)$ cp -r /doc/_common gnatcheck_qualkit_common +``` + +## General components and structure of a qualkit + +### Qualification kit contents + +A qualification kit (qualkit) is comprised of three main documents: +- The TORs, which stands for tool operational requirements, which describes + the coverage results gnatcov is expected to generate for the relevant Ada + language constructs, and how it is supposed to behave depending on the + various command line arguments that can be used in certification projects; + +- The STR, which stands for Software Test Results, which mostly contains the + results from a qualification testsuite run (qualrun), along with statistics + on the kind and numbers of verified coverage obligations in the tests; + +- The PLANs document, which describe all things procedure related. This + includes the tools developments practices, the tool testing procedure, the + qualkit verification procedure, and the tool interface users must adhere to + when using it in a certification project. + +### Source material for qualkit production + +To produce a qualkit we thus need: +- The sources for the various documents which are + * In the `qualification/qualkit/plans/` directory for the PLANS; + * In the testsuite all the `testsuite/Qualif/**/content.rst` for the TORs; + * Mostly generated for the STR, but some static bits are placed in + `testsuite/STR/` +- The testsuite tree after execution of the testsuite in qualification mode. + It will contain, in addition to the usual artifacts, some `.dump` files + containing some information about the test context and the amount of tested + obligations. + +The TOR production is a bit delicate as the source `content.rst` are not valid +ReST documents, but instead contain some custom directives that need to be +expanded by the `qualkit/tor/genrest.py` script. This script has a two pass +approach to compute the full view of the testcases and requirements: +- A top-down traversal of the testsuite to determine the hierarchy between + documents; +- A bottom-up approach to compute for a given test-case, which are the sources + that are actually part of the testcase. + +Once we have an in-memory representation of the various test-cases & +requirements, along with the sources that go with them, the contents of each +file are processed to replace the "importers" (custom directives) to generate +tables of links to the children and artifacts. + +The importers would gain to be inlined, we can't completely get rid of them yet +as we still need to compute the actual set of sources that belong to a testcase. + + +## Producing a qualification kit with anod + +The simplest way to generate a qualkit is to use the anod specs that will run +the qualification testsuite and produce the documents. +To do so, from a **linux** wavefront sandbox run + +```console +(wave)$ anod build gnatcov-qualkit +``` + +There are multiple qualifiers available to customize the qualification +parameters, a description of which is available through `anod help +gnatcov-qualkit`. + +One important caveat is that with this mechanism it is not possible to create +a qualkit for a Windows hosted testsuite run, unless it is scheduled in a +nightly run through the plans. This is because the production of the pdf +documents depend on texlive, which is not available on Windows hosts, the +`gnatcov-qualkit` spec thus expects the artifacts from the testsuite run to +be available through a cathod component. + +## Producing a kit from source + +To produce a qualkit from source, the first step is to obtain the artifacts +form a qualrun, either through anod, or by running the testsuite manually. + +### Producing a qualrun + +#### Through anod: + +From a wavefront sandbox simply run: + +``` +(wave)$ anod test gnatcov-qualrun +``` + +The qualrun artifacts will be available under +`//gnatcov-qualrun-/artifacts/`. + +#### Running the testsuite manually: + +The requirements to run a qualification testsuite are the same as those for a +"regular" testsuite run, so the environment produced by `gnatcov-dev.anod` is suitable. + +```console +(gnatcov/testsuite)$ ./testsuite.py --trace-mode=src --qualif-level=doA --cargs:ada="-gnatec=native-doA.adc -gnat12" +``` + +The artifacts are in the `testsuite` directory. + +### The genbundle script + +The main entrypoint to produce a qualkit is the `qualification/genbundle.py` +script. It will set the required environment to produce a qualification kit, +generate the sources for the TOR and STR documents, invoke the sphinx +invocations to produce the pdf or html documents, and zip everything together. + +A typical invocation for this script will look like: + +``` +(gnatcov/qualification)$ python genbundle.py --docformat=html,pdf --work-dir=$HOME/qualkit-dev/ \ +--dolevel=doA --languages=Ada2012 --testsuite-dir=$HOME/repos/gnatcoverage/testsuite \ +--rsync-from $HOME/repos/gnatcoverage --trace-mode=src +``` + +This invocation will produce kits in both HTML and pdf formats, in the +`$HOME/qualkit-dev/` directory, for a `doA` qualification level, targeting +`Ada2012`, assuming source traces using the testsuite artifacts from +`$HOME/repos/gnatcoverage/testsuite` and the qualification sources & scripts +from `$HOME/repos/gnatcoverage`. + +Parameters may of course be tweaked, see the help of `genbundle.py` for more +information. + +It is also possible not to produce a whole kit but only a single document using +the `--parts` option. + +### Producing the documents individually + +When working on the qualification source directly it may be faster to build the +documents directly. The only requirement is to install `doctools-e3` from a +wave sandbox and set its environment. Beware that the setenv primitive for this +spec will modify the locale, which will most certainly break your shell. You +can instead print the environment variables that would be set, and only export +`PATH` and `LD_LIBRARY_PATH`. + +For the TOR document it is necessary to add `/qualification/qualkit` +to the `PYTHONPATH`. This is done by `genbundle.py` so it not necessary when +using this wrapper. + +#### Producing the PLANS + +The plans are a "simple" ReST document, in order to build either the html or +pdf document go to `qualification/plans` and run: + +```console +(qualification/qualkit/plans)$ make [html|pdf] +``` + +### Producing the TORs + +To generate the TORs, the first step is to gather the required sources, using +the `qualification/tor/genrest.py` script: + +```console +(qualification/qualkit/tor)$ python genrest.py --dolevel=doA +``` + +You can then build the ReST document via make (this takes a while and generates +lots of warnings, it is expected): + +```console +(qualification/qualkit/tor)$ make [html|pdf] +``` + +### Producing the STR + +Similarly, the STR first needs to go through a source generations gathering +phase: + +```console +(testsuite/STR)$ python genrest.py --testsuite-dir=../ --dolevel=doA +``` + +The generated sources need to be copied into the `qualification/qualkit/str` +directory: + +```console +(qualification/qualkit/str)$ cp -r ../../../testsuite/STR/source . +``` + +then followed by + +```console +(qualification/qualkit/str)$ make [html|pdf] +``` diff --git a/qualification/qualkit/_common/project_settings.yaml b/qualification/qualkit/_common/project_settings.yaml new file mode 100644 index 000000000..863d962df --- /dev/null +++ b/qualification/qualkit/_common/project_settings.yaml @@ -0,0 +1,225 @@ +project: + subst: { + + # USER_ENTRIES + + # Project definitions + 'prj_title': 'GNATcoverage - DO-330/ED-215 QDP', + 'prj_toolset': 'GNATcoverage', + 'prj_toolset_bold': '**GNATcoverage**', + 'prj_switches': '', + 'prj_platform': 'TBD', + 'prj_host_platform': 'TBD', + 'prj_RTS': 'No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless.', + 'prj_dump_trigger': ':literal:`--dump-triger=atexit`', + 'prj_dump_channel': ':literal:`--dump-channel=bin-file`', + 'prj_ASIL': 'ASIL D', + 'prj_DAL': 'A', + 'prj_TCL': 'TCL 3', + 'prj_TQL': 'TQL-5', + 'tool_standard': 'DO-178C/ED-12C', + 'tool_supplement_standard': 'DO-330/ED-215', + 'prj_release_plan_repository': 'git@ssh.gitlab.adacore-it.com:eng/it/anod.git', + 'prj_release_process_database': 'TBD', + 'prj_new_features': 'TBD', + 'prj_known_problems': 'TBD', + 'prj_gpr_new_features': 'TBD', + 'prj_gpr_known_problems': 'TBD', + 'prj_known_problems_date': 'TBD', + + # Project assignments + + 'prj_pm': &prj_assignment_pm 'Vasiliy Fofanov', + 'prj_sm': &prj_assignment_sm 'TBD', + 'prj_ver': &prj_assignment_ver 'TBD', + 'prj_wri': &prj_assignment_wri 'TBD', + + # Document definitions + 'plans_doc': &prj_doc_plans 'Qualification Plans', + 'plans_id': &prj_docid_plans 'SE.DOC-TBD', + 'plans_abb': '*PLANS*', + + 'tor_doc': &prj_doc_tor 'Tool Operational Requirements and V\&V Cases and Procedures', + 'tor_id': &prj_docid_tor 'SE.DOC-TBD', + 'tor_abb': '*TOR*', + + 'str_doc': &prj_doc_str 'Tool Operational Verification and Validation Results', + 'str_id': &prj_docid_str 'SE.DOC-TBD', + 'str_abb': '*STR*', + + 'tqa_doc': &prj_doc_tqa 'Tool Quality Assurance Records', + 'tqa_id': &prj_docid_tqa 'SE.DOC-TBD', + + # Project tool versions + + 'gnatcov_version': 'TDB', + 'gnatpro_version': 'TDB', + 'gprbuild_version': 'TDB', + 'gnatemu_version': 'TDB', + + # END_OF_USER_ENTRIES + + # Project abbreviations + + 'TBD': &prj_abbr_tbd 'To Be Done', + 'QA': 'Quality Assurance', + 'adacore': 'AdaCore', + + # AdaCore QMS documents + + 'acqp_doc': 'AdaCore Quality Procedures', + 'acqp_ref': 'ACQP', + 'acqp_id': 'ENG.DOC-107', + 'acqp_version': 'Version 13', + + 'accm_doc': 'AdaCore ISO 9001:2015 Compliance Matrix', + 'accm_ref': 'ACCM', + 'accm_id': 'ENG.DOC-101', + 'accm_version': 'Version 3', + + 'acip_doc': 'AdaCore ISO 9001:2015 Procedures', + 'acip_ref': 'ACIP', + 'acip_id': 'ENG.DOC-102', + 'acip_version': 'Version 4', + + 'acp_doc': 'AdaCore Procedures', + 'acp_ref': 'ACP', + 'acp_id': 'SE.DOC-353', + 'acp_version': 'Version 10', + + 'acqm_doc': 'AdaCore Quality Manual', + 'acqm_ref': 'ACQM', + 'acqm_id': 'ENG.DOC-104', + 'acqm_version': 'Version 4', + + 'acrp_doc': 'AdaCore Release Procedures', + 'acrp_ref': 'ACRP', + 'acrp_id': 'SE.DOC-361', + 'acrp_version': 'Version 13', + + 'pep_doc': 'Product Engineering Procedures', + 'pep_ref': 'PEP', + 'pep_id': 'ENG.DOC-383', + 'pep_version': 'Version 6', + + # Technical documents + + 'acs_doc': 'Ada Coding Style', + 'acs_ref': 'ACS', + 'acs_id': 'SE.DOC-359', + 'acs_version': 'Version 6', + + 'alrm_doc': 'Ada Reference Manual - Language and Standard Libraries', + 'alrm_ref': 'ALRM', + 'alrm_id': 'N/A', + 'alrm_version': 'ISO/IEC 8652:2012(E) with COR.1:2016', + + 'atsug_doc': 'The Ada Conformity Assessment Test Suite (ACATS) User''s guide', + 'atsug_ref': 'ATSUG', + 'atsug_id': 'N/A', + 'atsug_version': 'Version 3.1, January 30, 2014', + + 'gaug_doc': 'Using as', + 'gaug_ref': 'GAUG', + 'gaug_id': 'N/A', + 'gaug_version': 'TBD', + + 'gbu_doc': 'GNU Binary Utilities', + 'gbu_ref': 'GBU', + 'gbu_id': 'N/A', + 'gbu_version': 'TBD', + + 'gbug_doc': 'GPR Tools User''s Guide', + 'gbug_ref': 'GPRUG', + 'gbug_id': 'N/A', + 'gbug_version': '19.8', + + 'gccug_doc': 'using gcc', + 'gccug_ref': 'GCCUG', + 'gccug_id': 'n/a', + 'gccug_version': 'TBD', + + 'glug_doc': 'The GNU linker', + 'glug_ref': 'GLUG', + 'glug_id': 'n/a', + 'glug_version': 'TBD', + + 'gprm_doc': 'GNAT Pro Reference Manual', + 'gprm_ref': 'GPRM', + 'gprm_id': 'N/A', + 'gprm_version': '19.8', + + 'gpug_doc': 'GNAT Pro User''s Guide for Native Platforms', + 'gpug_ref': 'GPUG', + 'gpug_id': 'N/A', + 'gpug_version': 'TBD', + + 'gpugc_doc': 'GNAT Pro User Guide Supplement for Cross Platforms', + 'gpugc_ref': 'GPUGC', + 'gpugc_id': 'N/A', + 'gpugc_version': 'TBD', + + 'spug_doc': 'SPARK 2014 Toolset User''s Guide', + 'spug_ref': 'SPUG', + 'spug_id': 'N/A', + 'spug_version': 'TBD', + + 'gcheck_doc': 'GNATcheck Reference Manual', + 'gcheck_ref': 'GCRM', + 'gcheck_id': 'N/A', + 'gcheck_version': '19.8', + + 'gsas_doc': 'GNAT SAS User''s Guide', + 'gsas_ref': 'GSASUG', + 'gsas_id': 'N/A', + 'gsas_version': 'TBD', + + # Standards + + 'guapl_doc': 'Information technology - Programming languages - Guide for the Use of the Ada Programming Language in High Integrity Systems', + 'guapl_ref': 'GUAPL', + 'guapl_id': 'N/A', + 'guapl_version': 'ISO/IEC TR 15942:2000(E)', + + 'iec_doc': 'Functional safety of electrical/electronic/programmable electronic safety-related systems', + 'iec_ref' : 'IEC-61508', + 'iec_id': 'N/A', + 'iec_version': 'IEC 61508:2010', + + 'iqms_doc': 'ISO 9001:2015(E) Quality Management Systems - Requirements', + 'iqms_ref': 'IQMS', + 'iqms_id': 'N/A', + 'iqms_version': 'ISO 9001:2015(E)', + + 'iso_doc': 'Road Vehicles - Functional Safety', + 'iso_ref' : 'ISO-26262', + 'iso_id': 'N/A', + 'iso_version': 'ISO 26262:2018', + + 'racsps_doc': 'Railway applications - Communications, signalling and processing systems - Software for railway control and protection systems', + 'racsps_ref': 'RACSPS', + 'racsps_id': 'N/A', + 'racsps_version': 'EN 50128:2001', + + 'racspsb_doc': 'Railway applications - Communications, signalling and processing systems - Software for railway control and protection systems', + 'racspsb_ref': 'RACSPSB', + 'racspsb_id': 'N/A', + 'racspsb_version': 'EN 50128:2011', + + 'spasb_doc': 'Space Product Assurance', + 'spasb_ref': 'SPASB', + 'spasb_id': 'N/A', + 'spasb_version': 'B', + + 'spasc_doc': 'Space Product Assurance', + 'spasc_ref': 'SPASC', + 'spasc_id': 'N/A', + 'spasc_version': 'C', + + 'do_doc': 'Software Considerations in Airborne Systems and Equipment Certification', + 'do_ref': 'DO-178', + 'do_id': 'N/A', + 'do_version': 'DO-178C', + + + } diff --git a/qualification/qualkit/plans/Introduction/Definitions/content.rst b/qualification/qualkit/plans/Introduction/Definitions/content.rst new file mode 100644 index 000000000..f47fa4476 --- /dev/null +++ b/qualification/qualkit/plans/Introduction/Definitions/content.rst @@ -0,0 +1,37 @@ +Definitions +=========== + +General Definitions +------------------- + +The Annex B of [|tool_supplement_standard|] provides a list of acronyms and glossary of +common terms used throughout this qualification material. + +Project Specific Definitions +---------------------------- + +.. rubric:: GNATcoverage + +A tool performing structural coverage analysis of Ada programs. + +.. rubric:: Operational Environment + +The environment in which GNATcoverage is used. + +.. rubric:: Verification Environment + +The environment in which GNATcoverage is qualified. + +.. rubric:: Test + +A part of a testcase which exercises functional code in a precise manner, +aimed at obtaining precise expected coverage results. + +.. rubric:: Testcase + +A part of the testing strategy used to verify a given Tool Operational +Requirement. + +.. rubric:: Tool Operational Requirement (TOR) + +A TOR describes the expected behavior of a tool from the user point of view. diff --git a/qualification/qm/plans/Introduction/Document_Purpose/content.rst b/qualification/qualkit/plans/Introduction/Document_Purpose/content.rst similarity index 100% rename from qualification/qm/plans/Introduction/Document_Purpose/content.rst rename to qualification/qualkit/plans/Introduction/Document_Purpose/content.rst diff --git a/qualification/qualkit/plans/Introduction/Organization_And_Roles/content.rst b/qualification/qualkit/plans/Introduction/Organization_And_Roles/content.rst new file mode 100644 index 000000000..4048cc127 --- /dev/null +++ b/qualification/qualkit/plans/Introduction/Organization_And_Roles/content.rst @@ -0,0 +1,26 @@ +Organization And Roles +====================== + +Here is the list of parties involved in the development, verification and +qualification process for GNATcoverage, along with their responsibilities: + +* **GNATcoverage Development Team**: Developers contribute to the development + of GNATcoverage, including requirements specification, implementation, test + case development and test execution. This team is also in charge of the + configuration management of the artifacts it produces. + +* **GNATcoverage Qualification Team**: The Qualification Team is responsible + for the infrastructure supporting the qualification process of GNATcoverage. + The Qualification Team supports the Development Team. This team is also in + charge of the configuration management of the artifacts it produces. + +* **GNATcoverage Quality Assurance Team**: The Quality Assurance Team is + independent of the Development Team and Qualification Team and is + responsible for ascertaining that the expected processes have been put in + place. The Quality Assurance Team is granted the authority to require + specific activities to be performed by the GNATcoverage Development and + Qualification Teams. This team is also in charge of the configuration + management of the artifacts it produces (mostly Quality Assurance reports). + +* **GNATcoverage users**: GNATcoverage users are expected to perform the + activities identified in section :ref:`tqp-user-activities`. diff --git a/qualification/qualkit/plans/Introduction/Referenced_Documents/content.rst b/qualification/qualkit/plans/Introduction/Referenced_Documents/content.rst new file mode 100644 index 000000000..0d55c4e0c --- /dev/null +++ b/qualification/qualkit/plans/Introduction/Referenced_Documents/content.rst @@ -0,0 +1,53 @@ +Referenced Documents +==================== + +.. rubric:: AE09 + +Bordin et al.: *Couverture: An Innovative Open Framework for Coverage Analysis +of Safety Critical Applications* - Ada User Journal, December 2009. + +.. rubric:: |tool_standard| + +RTCA DO-178C/EUROCAE ED-12C: +*Software Considerations in Airborne Systems and Equipment Certification*; +December 13, 2011 + +.. rubric:: |tool_supplement_standard| + +RTCA DO-330/EUROCAE ED-215: +*Software Tool Qualification Considerations*; +December 13, 2011 + +.. rubric:: ERTS2010 + +Bordin et al: *Couverture: An Innovative and Open Coverage Analysis Framework +for Safety-Critical Applications* - ERTS2 2010 + +.. rubric:: GNAT Pro UG + +|adacore|: *GNAT User's Guide for Native Platforms*, part of the GNAT Pro +|gnatpro_version| release documentation (file *share/doc/gnat/pdf/gnat_ugn.pdf*). + +.. rubric:: GNATcoverage UG + +|adacore|: *GNATcoverage User's Guide*, part of the GNATcoverage +|gnatcov_version| release documentation (file *share/doc/gnatdas/pdf/gnatdas.pdf*). + +.. rubric:: |plans_doc| + +|adacore|: |prj_toolset| - |plans_doc|, |plans_id|, this document. + +.. rubric:: |tor_doc| + +|adacore|: |prj_toolset| - |tor_doc|, |tor_id|, included in this +qualification package. + +.. rubric:: |str_doc| + +|adacore|: |prj_toolset| - |str_doc|, |str_id|, included in this +qualification package. + +.. rubric:: |tqa_doc| + +|adacore|: |prj_toolset| - |tqa_doc|, accompanying this qualification +package. diff --git a/qualification/qualkit/plans/Introduction/content.rst b/qualification/qualkit/plans/Introduction/content.rst new file mode 100644 index 000000000..09317a171 --- /dev/null +++ b/qualification/qualkit/plans/Introduction/content.rst @@ -0,0 +1,11 @@ +============ +Introduction +============ + +.. toctree:: + :maxdepth: 1 + + Document_Purpose/content + Referenced_Documents/content + Definitions/content + Organization_And_Roles/content diff --git a/qualification/qualkit/plans/Makefile b/qualification/qualkit/plans/Makefile new file mode 100644 index 000000000..f76f6230e --- /dev/null +++ b/qualification/qualkit/plans/Makefile @@ -0,0 +1,3 @@ +DOC=plans +TOOL?=$(realpath ../) +include ../../Makefile.common diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst new file mode 100644 index 000000000..d16c75b1c --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst @@ -0,0 +1,34 @@ +Compliance Matrices +******************* + +.. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| + +.. csv-table:: Compliance matrix for Table 7-1 of |tool_supplement_standard| + :delim: & + :header: "Item", "Description", "Ref.", "Achieved", "Notes" + + 1 & Configuration Identification & 7.2.1 & Yes & See :ref:`adacore-configuration-items`. + 2 & Baselines & 7.2.2.a,b,c,d,e & N/A & Not required for CC2. + 3 & Traceability & 7.2.2.f,g & Yes & See :ref:`traceability`. + 4 & Problem Reporting & 7.2.3 & N/A & Not required for CC2. + 5 & Change Control - integrity and identification & 7.2.4.a,b & Yes & See :ref:`adacore-change-control`. + 6 & Change Control - tracking & 7.2.4.c,d,e & N/A & Not required for CC2. + 7 & Change Review & 7.2.5 & N/A & Not required for CC2. + 8 & Configuration Status Accounting & 7.2.6 & N/A & Not required for CC2. + 9 & Retrieval & 7.2.7.a & Yes & See :ref:`adacore-archive`. + 10 & Protection against Unauthorized Changes & 7.2.7.b.1 & Yes & See :ref:`adacore-archive`. + 11 & Media Selection, Refreshing, Duplication & 7.2.7.b.2,3,4, 7.2.7.c & N/A & Not required for CC2. + 12 & Release & 7.2.7.d & N/A & Not required for CC2. + 13 & Data Retention & 7.2.7.e & Yes & See :ref:`adacore-archive`. + +.. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| + +.. csv-table:: Compliance matrix for Table T-8 of |tool_supplement_standard| + :delim: & + :header: "Item", "Description", "Ref.", "Achieved", "Notes" + + 1 & Configuration items are identified. & 7.1.a & Yes & See :ref:`adacore-configuration-items`. + 2 & Baselines and traceability are established. & 7.1.b & N/A & Not required for TQL-5 tools. + 3 & Problem reporting, change control, change review, and configuration status accounting are established. & 7.1c,d,e,f & N/A & Not required for TQL-5 tools. + 4 & Archive, retrieval, and release are established. & 7.1.g & Yes & See :ref:`adacore-archive`. + 5 & Tool life cycle environment control is established & 7.1.h & N/A & Not required for TQL-5 tools. diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst new file mode 100644 index 000000000..37028cf65 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst @@ -0,0 +1,76 @@ +.. _adacore-conf-methods: + +Configuration Management Methods and Activities +*********************************************** + +This section describes the internal configuration management process at +AdaCore. It is not related to the configuration management process deployed by +the applicant. + +Base technical support +---------------------- + +Configuration Management of artifacts is technically implemented via Git +repositories which track the life cycle of each artifact automatically. +E-mail-based discussions about each artifact are also tracked, using the +AdaCore ticket system deployed within the whole company since 1998. + +.. _adacore-change-control: + +Change control +-------------- + +Integrity of configuration items is guaranteed by Git repositories where all +configuration items are located. Only authorized engineers can modify +configuration items and all modifications are recorded. The sources and scripts +for the AdaCore products are maintained in Git repositories that are completely +backed up at least every 2 hours. All repositories are stored electronically +and are backed up to geographically isolated locations in AWS (in EU and US). +This increases AdaCore's confidence in the durability of qualification data +(activity 7.2.4.a). + +Each change to a configuration item is associated to a unique +ID, which unambiguously identifies the version of a configuration item over +its history (activity 7.2.4.b). + +.. _adacore-archive: + +Archive, Retrieval and Release +------------------------------ + +Repositories are available for audit if necessary (activity 7.2.7.a). + +Only authorized engineers can change the configuration +items, thanks to the security mechanisms embedded in the Git +repositories (activity 7.2.7.b.1). + + +Detailed procedures are as follows. + +Customer/Project specific tracking +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For each specific customer/project qualification we assign an internal *kit +identifier*, referenced for example in QA reports. All the corresponding +verification related artifacts are managed on a dedicated *branch* within +AdaCore's version control systems. Releases of qualification kits for the +specific customer/project are produced off that branch, which also tracks the +QA cycles performed on the kit items (QA reports, corresponding corrections, +...). A typical kind of early change incorporated on the branch is the +adjustment of the targeted operational environment parameters, to be accounted +for when setting up the verification environment for kit production cycles. + + +Official baseline production +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Official baselines are generated for customer-specific deliveries aimed at a +precise operational environment and software level. Once the configuration +management branch dedicated to such deliveries is set up, a complete testsuite +run is performed in the corresponding verification environment. A kit version +number is then assigned and the qualification data documents are produced. +The resulting set of documents is packaged as a zip file which materializes +the kit as a whole. This kit then goes through QA as needed and all or part of +this cycle repeats until a positive agreement on the kit "acceptability" for +release is reached. + diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/content.rst new file mode 100644 index 000000000..9fda75fc4 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/content.rst @@ -0,0 +1,19 @@ +.. _dev-conf-management: + +Tool Developer Configuration Management Plan +============================================ + +GNATcoverage is a TQL-5 tool, and as such, its tool developer configuration +items are managed at Control Category 2 (CC2). The corresponding subset +of TCM process activities to +perform is defined by Tables 7-1 and T-8 of |tool_supplement_standard|. + +This section describes the processes in place at AdaCore, the Tool Developer. + +.. toctree:: + :maxdepth: 1 + + Compliance/content + Version_Control/content + Traceability/content + Methods_And_Activities/content diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst new file mode 100644 index 000000000..96d2a5833 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst @@ -0,0 +1,14 @@ +Compliance Matrices +******************* + +.. tabularcolumns:: |p{0.05\linewidth}|p{0.35\linewidth}|p{0.10\linewidth}|p{0.30\linewidth}| + +.. csv-table:: Compliance matrix for Table T-8 of |tool_supplement_standard| + :delim: | + :header: "Item", "Description", "Ref.", "Notes" + + 1 | Configuration items are identified. |7.1.a| Up to the applicant. + 2 | Baselines and traceability are established. |7.1.b| Not required for TQL-5 tools. + 3 | Problem reporting, change control, change review, and configuration status accounting are established.|7.1c,d,e,f| Not required for TQL-5 tools. + 4 | Archive, retrieval, and release are established. |7.1.g| Up to the applicant. + 5 | Tool life cycle environment control is established. |7.1.h| Not required for TQL-5 tools. diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst new file mode 100644 index 000000000..78954f1be --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst @@ -0,0 +1,19 @@ +Configuration management suggestions +************************************ + +What follows is a set of configuration management suggestions for the +items up to the applicant as per the compliance matrix above. + + * **Activity 7.2.1:** The suggested configuration items are: + + #. The .zip packages of this |prj_toolset| qualification kit; + #. The |tqa_doc| document, output of the Quality Assurance activities described + in the :ref:`tqap` chapter of this document; + #. The GNAT Pro and GNATcoverage binary packages containing the executable + files as well as their accompanying infrastructure and + documentation. Likewise for GNATemulator in the case of cross + configurations. + + * **Activity 7.2.7:** with respect to these items, we let the user deploy the + most appropriate process depending on his own configuration management + process and tools. diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/content.rst new file mode 100644 index 000000000..d073b514c --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/content.rst @@ -0,0 +1,10 @@ +.. _user-conf-management: + +Tool User Configuration Management Suggestions +============================================== + +.. toctree:: + :maxdepth: 1 + + Compliance/content + Suggested_Items/content diff --git a/qualification/qualkit/plans/Tool_Configuration_Management_Plan/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/content.rst new file mode 100644 index 000000000..ee2d19640 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/content.rst @@ -0,0 +1,11 @@ +.. _tcmp: + +================================== +Tool Configuration Management Plan +================================== + +.. toctree:: + :maxdepth: 1 + + Developer/content + User/content diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Certification_Credit/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Certification_Credit/content.rst new file mode 100644 index 000000000..5860bdb17 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Certification_Credit/content.rst @@ -0,0 +1,16 @@ +.. _certification-credit: + +Sought Certification Credit +=========================== + +GNATcoverage aims at automating the Structural Coverage Analysis activities +required by the Software Verification Process of |tool_standard|, in section +6.4.4.2 and table A-7, objectives 5, 6 and 7 depending on the software level; +or Structural Coverage Analysis activities +required by the Tool Verification Process of |tool_supplement_standard|, in section +6.1.4.3 and table T-7, objectives 6, 7 and 8 depending on the qualification level. + +Any coverage limitations are enumerated in section *Language Version and +Scope* of the |tor_abb| document; it is the user's responsibility to +assure that the code subject to analysis conforms to what this qualification +material encompasses. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Compliance/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Compliance/content.rst new file mode 100644 index 000000000..27a2d8ff9 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Compliance/content.rst @@ -0,0 +1,31 @@ +Compliance With Guidance +======================== + +This section contains the compliance matrices with the guidance contained in +section 12.2 of [|tool_standard|] (or section 4.4(e) of [|tool_supplement_standard|], as appropriate) +and section 11.3.2 of [|tool_supplement_standard|]. + +.. tabularcolumns:: |p{0.15\linewidth}|p{0.10\linewidth}|p{0.65\linewidth}| + +.. csv-table:: Compliance with Section 12.2 of |tool_standard| or section 4.4(e) of |tool_supplement_standard|, as appropriate + :delim: # + :header: "Section", "Achieved", "Notes" + + 12.2.1 or 4.4(e) #Yes#GNATcoverage qualification is needed. See :ref:`certification-credit`. + 12.2.2 #Yes#GNATcoverage impact corresponds to **Criteria 3**. According to Table 12-1 Tool Qualification Level is **TQL-5** for all assurance levels. See :ref:`tql`. + 4.4(e) #Yes#GNATcoverage is a tool that cannot introduce an error in the output of the qualified tool, but may fail to detect an error in the tool life cycle data, hence the applicable TQL is **TQL-5**. See :ref:`tql` + +.. tabularcolumns:: |p{0.15\linewidth}|p{0.18\linewidth}|p{0.60\linewidth}| + +.. csv-table:: Compliance with Table 11-1 of |tool_supplement_standard| + :delim: # + :header: "Section", "Achieved", "Notes" + + T-0, Objectives 1, 3, 6, 7 # Not applicable # Apply to Tool User, not to Tool Developer per section 11.3 of |tool_supplement_standard|. + T-0, Objective 2 # Yes # See the requirement description items in the |tor_abb| document. + T-0, Objective 4 # Not Applicable # Not required for TQL-5. Nevertheless, see :ref:`tqap` for AdaCore's QA procedures. + T-0, Objective 5 # Yes # See the test and test-cases description items in the |tor_abb| document. + T-1 to T-7 # Not Applicable # Not required for TQL-5. + T-8 # Up to the applicant # See :ref:`user-conf-management` for suggested configuration items. + T-9 # Yes # See the |tqa_doc| document accompanying this qualification package. + T-10 # Up to the applicant # Applies to Tool User, not to Tool Developer per section 11.3 of |tool_supplement_standard|. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Data_Production/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Data_Production/content.rst new file mode 100644 index 000000000..8544d5e91 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Data_Production/content.rst @@ -0,0 +1,102 @@ +Production of Qualification Data +================================ + +For a given project, the production of qualification data proceeds in several +steps described hereafter: + +Settle on the Operational Conditions of Use +******************************************* + +As the Tool Developer, AdaCore first discusses with the Tool User to define +the use +that will be made of the tool, agreeing on items such as the tool interface, +the source language version, the runtime profile and language features, the +software level. +This eventually translates as specific indications in the +*Operational Conditions of Use* section of the |tor_abb| document and in the +:ref:`qualified-interface` section of the |plans_abb| document, then +Tool Operational Requirements and their Tests derivatives are refined to +accommodate changes in the scope for which the tool had been qualified so far. + +Produce TORs, Test Cases and Tests Artifacts +******************************************** + +The current set of TORs is organized very hierarchically along the following +major lines: + +* The coverage criteria associated with software levels, + +* The constructs allowed by the source language, influenced by the established + conditions of use, and + +* General coverage analysis facilities, such as the ability to perform coverage + consolidation. + +The general organization is described in the +*Document Purpose and Organization* of the |tor_abb| document. + +A TOR always comes with a Testing Strategy, to be implemented by Test Cases +and eventually Tests. The TOR expresses expected behavior of the tool and the +testing strategy introduces the set of Test Cases. It describes the general +ideas governing the choice of this specific set when needed, and explains how +the set of Tests is constructed for each Test Case when common guidelines were +used. + +Each Test Case addresses a part of what its parent TOR incurs, e.g. on a +particular instance of a language construct. For example, we have a general +core requirement regarding MCDC assessments and derive families of Test Cases +to validate the tool behavior on variations over forms and sizes of decisions, +over the context in which decisions may occur, over the possible forms of +expression operands. + +Then for a given Test Case (say, an *A and then B* Ada expression controlling +an *if* statement, with *A* and *B* both simple Boolean variables), several +tests verify the tool behavior across a set of execution scenarii. Each test +checks results for a specific sequence of calls into the code to analyze, +providing particular values for variables involved in a decision for +example. A single such valuation or several of them are performed with a +specific coverage objective purpose, for instance evaluating a decision both +True and False but demonstrating independent influence of only the first +condition. + +Section *Overview of the Test Procedures Organization* of the |tor_abb| document +provides more details on how Tests are composed, and in particular on how +expected results are stated. + +Additional TORs are introduced or existing TORs are adjusted on a case by case +basis when the scope of possible uses of the tool widens somehow, most +commonly when the set of source language constructs for which the tool needs +to be qualified expands. + +The adjustment of an existing TOR might incur a change in the TOR expression +itself and/or a refinement of its testing strategy to encompass what the +new scope requires. + + +Execute Tests to Produce Test-Results Artifacts +*********************************************** + +This is achieved in the Verification Environment by launching a script which +automatically selects the relevant set of tests for the target software level +and runs them with provided control parameters. The tests are taken from a +branch dedicated to the kit construction in AdaCore's repositories. + +This produces execution logs and data files that are later on gathered to +elaborate the |str_abb| report. The Qualification Team verifies at this point +that test results conform to expectations, making sure that the only failures, +if any, are understood and registered in AdaCore's tracking system. + +Produce the Qualification Kit +***************************** + +This is also achieved automatically by a collection of tools coordinated by a +top level script provided with the name of a branch in AdaCore's repositories +where the kit is maintained and the (possibly remote) location of the +directory where the testsuite execution took place. + +The script collects the artifacts, builds the PDF and HTML versions of the +documents and bundles everything together to constitute the kit per se. It +also performs consistency and traceability checks, producing a log of what +those checks find out. The Qualification Team reviews this log and verifies +the general consistency of the documents before handing them to the Quality +Assurance team. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst new file mode 100644 index 000000000..5b280571f --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst @@ -0,0 +1,9 @@ +============================= +Operational Conditions of Use +============================= + +Beyond the Qualified Interface, qualified use of the tool requires following a +number of rules regarding the Operational Environment, the language revision, +the runtime library profile and the set of language constructs used in the +programs. These rules are described in the *Operational Conditions of Use* +section of the |tor_abb| document. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst new file mode 100644 index 000000000..0a2f1d5e4 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst @@ -0,0 +1,53 @@ +.. _qualification-data: + +Qualification Data Overview +=========================== + +GNATcoverage is qualified as a COTS tool according to guidance of +section 11.3 of [DO-330/ED-215]. This qualification kit documents the +activities required for the Tool Developer, and provides +recommendations for the Tool User to fulfill his part of the required +activities. + +The qualification data that comes with the tool, composing the tool +*qualification kit*, consists of the following components: + +* **PDF documents package**, containing the following three documents: + + * The |doc_title| document, which is this document + and which we'll refer to as the |plans_abb| document. + + * The |tor_doc| document, which contains the description of + the tool operational requirements together with the associated testing + strategy and test cases, and which we'll refer to as the |tor_abb| document. + + The *Document Purpose and Organization* section of the |tor_abb| document + includes a high level description of our overall testing strategy. The + *Overview of the test procedures organization* appendix explains how + expectations on coverage results for each test are stated and used to + produce a verification report out of a testsuite run. + + The test sources aren't included in this version of the document. They are + included in an HTML version, presented below. + + * The |str_doc| report, which contains a synthetic summary + of the testsuite run performed to assess the tool behavioral correctness + with respect to its intended use, and which we'll refer to as the |str_abb| + report. + +* **HTML documents package**, containing HTML versions of the PDF documents + described above, presented differently and including test sources for the + |tor_doc| item. The tests are organized in a very hierarchical manner + so much easier to present and browse in this format than in PDF. See the + :ref:`qa-activities` section of this document for a description of which + |QA| activities are performed on which document variant. + +* **Testsuite package**, archive of the testsuite directory where the + qualification testsuite run took place, filtered to include artifacts + of possible use for inspection (execution logs, coverage reports, ...), + not binary artifacts such as object and executable files, as they take + a huge amount of space, aren't so useful for inspection, and can easily + be re-generated on demand if really needed. + +* |tqa_doc| document, where all Quality Assurance cycles are tracked. + diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst new file mode 100644 index 000000000..ea8f13931 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst @@ -0,0 +1,82 @@ +.. _qualified-interface: + +GNATcoverage Qualified Interface +================================ + +To obtain reports suitable for use as certification evidence, applicants shall +use GNATcoverage as follows: + +* Build the application with the GNAT Pro toolchain identified in the + *Operational Environment* section of the TOR document, obeying the + compilation options and coding standard rules documented there as well. + +* Build the test code and test harness and link it with the relevant + application objects if necessary to form one or several test + executables. The test code does not need to be compiled with the switches + described in the Operational Environment section, nor does it need to comply + to the coding standard. + +* Obtain as many execution trace files () as needed, by + running the test executables () within the instrumented + execution environment, as in the following example. + + is the coverage criterion level to be assessed and is + the target architecture. The :literal:`--target` switch is required + for cross configurations and shouldn't be stated in the native case. + + The part is required for mcdc analysis only and shall + designate at least the units of that will be of interest to + the analysis step. + + The form these switches should take is described below. + +.. code-block:: text + + gnatcov run [--target=] --level= -o [] + ... + gnatcov run [--target=] --level= -o [] + + +* Optionally, produce a single file (format documented in the + GNATcoverage User's Guide), consolidating the coverage outcome for the list + of execution traces stored in the file, and querying results + for the source units designated by the argument: + +.. code-block:: text + + gnatcov coverage --annotate=report --level= @ -o + + +In the sample commands above: + +* is a test executable; +* designates the coverage criteria to assess, depending on the software + level; + + * For level C, statement coverage data is obtained with :literal:`--level=stmt`; + + * For level B, statement *and* decision coverage data is obtained with + :literal:`--level=stmt+decision`; + + * For level A, statement *and* decision *and* mcdc coverage data is obtained + with :literal:`--level=stmt+mcdc`. + +* is the output file containing the GNATcoverage report; +* identifies the target platform (as in the GNAT Pro toolchain + prefixes, e.g. powerpc-elf); +* is the output file containing the execution trace +* is a specification of the units for which coverage is to be + assessed (so called *Units Of Interest*), with either + + * A :option:`--scos=@` switch, where is a text + file containing the list of GNAT Pro ALI file names associated with + the units of interest; *or* + + * GPR project file facilities, as documented in the tool User's Guide and + summarized in the |tor_abb| document. + +* is a text file containing the list of execution traces to + operate on. + +IO redirections, sometimes necessary for proper operation of the programs +within the execution environment, are allowed. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst new file mode 100644 index 000000000..e55200e66 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst @@ -0,0 +1,106 @@ +.. _qualified-interface: + +GNATcoverage Qualified Interface +================================ + +To obtain reports suitable for use as certification evidence, applicants shall +use GNATcoverage as follows: + +* Build and install the coverage runtime in a dedicated + directory. Use the GNAT Pro toolchain identified in the + *Operational Environment* section of the |tor_abb| document for this, + taking care to specify the and if the application is + not a native one. + + This would be achieved with a command such as: + + .. code-block:: text + + gnatcov setup [--target= --RTS=] --prefix= + + + This step needs only to be done once, provided that the *Operational + Environment* described in the |tor_abb| document has not changed as of + the previous coverage runtime setup. + + +* Instrument the application for coverage assessment and test harness main + units for coverage buffer dumping using the ``gnatcov instrument`` command; + Specify the coverage criterion level to be assessed as well as a trace + and as specified in the + *Operational Environment* section of the |tor_abb| document. Also specify the + set of units of interest for which coverage should be assessed trough + the arguments, which should at least include a + indication using the :literal:`-P` switch: + + .. code-block:: text + + gnatcov instrument [--target= --RTS=] --level= --dump-trigger= --dump-channel= -P + + +* Build the application and test executables with the GNAT Pro toolchain + identified in the *Operational Environment* section of the |tor_abb| document, + obeying the coding standard rules, and compilation switches documented there + as well. The gprbuild invocation to build the application shall contain the + ``--src-subdirs=gnatcov-instr`` argument on the command line, as well as a + ``--implicit-with=gnatcov_rts.gpr`` argument to link against the coverage + runtime. The coverage runtime project must be made available to gprbuild by + adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` environment + variable. + + +* Obtain as many execution trace files () as needed, by + running the test executables. + +* Optionally, produce a single file (format documented in the + GNATcoverage User's Guide), consolidating the coverage outcome for the list of + execution traces, produced in the previous step and stored in the + file, and querying results for the source units designated by + the argument: + + .. code-block:: text + + gnatcov coverage --annotate=report --level= -P @ -o + + +In the sample commands above: + +* designates the path to a directory in which the coverage + runtime will be installed. It shall be accessible for writing and reading by + the tool; +* identifies the trigger to produce execution traces, as + described in the tool User's Manual, and for which the value to be used + is defined in the |tor_abb| document; +* identifies the medium used by the instrumented executable to + output the execution traces, as described in the tool User's Manual and for + which the value to be used is defined in the |tor_abb| document; +* designates the coverage criteria to assess, depending on the software + level; + + * For level C, statement coverage data is obtained with :literal:`--level=stmt`; + + * For level B, statement *and* decision coverage data is obtained with + :literal:`--level=stmt+decision`; + + * For level A, statement *and* decision *and* mcdc coverage data is obtained + with :literal:`--level=stmt+mcdc`. + +* is the output file containing the GNATcoverage report; +* identifies the target platform (as in the GNAT Pro toolchain + prefixes, e.g. arm-elf); +* identifies the Ada runtime library to be used, (either a GNAT Pro + provided runtime, identified by its name, e.g. embedded-stm32f4, or the path + to a custom runtime project); +* is the name of an output file containing an execution trace; +* is the path to the GPR project file defining the main units for + the application testing; +* is a specification of the units for which coverage is to be + assessed (so called *Units Of Interest*), with GPR project file facilities, + as documented in the tool User's Guide and summarized in the |tor_doc| + document; + +* is a text file containing the list of execution traces to + operate on. + +IO redirections, sometimes necessary for proper operation of the programs +within the execution environment, are allowed. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst new file mode 100644 index 000000000..21b165424 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst @@ -0,0 +1,109 @@ +.. _qualified-interface: + +GNATcoverage Qualified Interface +================================ + +To obtain reports suitable for use as certification evidence, applicants shall +use GNATcoverage as follows: + +* Build and install the coverage runtime in a dedicated + directory. Use the GNAT Pro toolchain identified in the + *Operational Environment* section of the |tor_abb| document for this, + taking care to specify the and if the application is + not a native one. + + This would be achieved with a command such as: + + .. code-block:: text + + gnatcov setup [--target= --RTS=] --prefix= + + + This step needs only to be done once, provided that the *Operational + Environment* described in the |tor_abb| document has not changed as of + the previous coverage runtime setup. + + +* Instrument the application for coverage assessment and test harness main + units for coverage buffer dumping using the ``gnatcov instrument`` command; + Specify the coverage criterion level to be assessed as well as a trace + and as specified in the + *Operational Environment* section of the |tor_abb| document. Also specify the + set of units of interest for which coverage should be assessed trough + the arguments, which should at least include a + indication using the :literal:`-P` switch: + + .. code-block:: text + + gnatcov instrument [--target= --RTS=] + --dump-trigger= --dump-channel= + --level= -P + + +* Build the application and test executables with the GNAT Pro toolchain + identified in the *Operational Environment* section of the |tor_abb| document, + obeying the coding standard rules, and compilation switches documented there + as well. The gprbuild invocation to build the application shall contain the + ``--src-subdirs=gnatcov-instr`` argument on the command line, as well as a + ``--implicit-with=gnatcov_rts.gpr`` argument to link against the coverage + runtime. The coverage runtime project must be made available to gprbuild by + adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` environment + variable. + + +* Obtain as many execution trace files () as needed, by + running the test executables. + +* Optionally, produce a single file (format documented in the + GNATcoverage User's Guide), consolidating the coverage outcome for the list of + execution traces, produced in the previous step and stored in the + file, and querying results for the source units designated by + the argument: + + .. code-block:: text + + gnatcov coverage --annotate=report -o + --level= -P @ + + +In the sample commands above: + +* designates the path to a directory in which the coverage + runtime will be installed. It shall be accessible for writing and reading by + the tool; +* identifies the trigger to produce execution traces, as + described in the tool User's Manual, and for which the value to be used + is defined in the |tor_abb| document; +* identifies the medium used by the instrumented executable to + output the execution traces, as described in the tool User's Manual and for + which the value to be used is defined in the |tor_abb| document; +* designates the coverage criteria to assess, depending on the software + level; + + * For level C, statement coverage data is obtained with :literal:`--level=stmt`; + + * For level B, statement *and* decision coverage data is obtained with + :literal:`--level=stmt+decision`; + + * For level A, statement *and* decision *and* mcdc coverage data is obtained + with :literal:`--level=stmt+mcdc`. + +* is the output file containing the GNATcoverage report; +* identifies the target platform (as in the GNAT Pro toolchain + prefixes, e.g. arm-elf); +* identifies the Ada runtime library to be used, (either a GNAT Pro + provided runtime, identified by its name, e.g. embedded-stm32f4, or the path + to a custom runtime project); +* is the name of an output file containing an execution trace; +* is the path to the GPR project file defining the main units for + the application testing; +* is a specification of the units for which coverage is to be + assessed (so called *Units Of Interest*), with GPR project file facilities, + as documented in the tool User's Guide and summarized in the |tor_doc| + document; + +* is a text file containing the list of execution traces to + operate on. + +IO redirections, sometimes necessary for proper operation of the programs +within the execution environment, are allowed. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Overview/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Overview/content.rst diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst new file mode 100644 index 000000000..428cf70b9 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst @@ -0,0 +1,9 @@ +.. _tql: + +Tool Qualification Level +======================== + +GNATcoverage is qualified as a COTS tool, with impact corresponding to +**Criteria 3** of |tool_standard| section 12.2.2. From Table 12-1, the +GNATcoverage Tool Qualification Level is then **TQL-5** for all software +levels. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst new file mode 100644 index 000000000..098c747d4 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst @@ -0,0 +1,47 @@ +|prj_toolset| Qualification +============================ + +#. **Reference** |prj_toolset_bold| **in the Plan for Software Aspects of + Certification (PSAC) and, if appropriate, in Tool Qualification Plan**. + The user needs to: + + * identify |prj_toolset| as a TQL-5 tool with regard to software level + A, B, and C, or with regard to tool qualification level 1, 2, and 3, + whichever is appropriate, that needs to be qualified; + + * Include references to the |prj_toolset| qualification kit documents that + were received to support this particular use of the tool. + +#. **Delivery Acceptance.** On delivery of |prj_toolset| and its + qualification kit, the user shall: + + * Assess whether the qualified Operational Environment is + representative of the user's Operational Environment; + + * Assess whether the structural coverage analysis performed + by GNATcoverage satisfies the goals specified in the + :ref:`certification-credit` section; + + * Assess whether the Tool Operational Requirements include suitable + artifacts for specific language constructs expected to be of relevance + for a given coverage criterion. + +#. **Configuration management of qualification data**. The user needs to place + all qualification data under configuration management. + +#. **Obtain a tool qualification agreement**, see section 9.0.b of + |tool_supplement_standard|. + +#. **Update the Software or Tool Life Cycle Environment Configuration Index.** + Refer to the |prj_toolset| qualification kit for details associated with + its environment configuration. + +#. **Update the Software or Tool Accomplishment Summary (SAS or TAS).** + The SAS/TAS needs to be updated: + + * For Table A-7 of |tool_standard|: achievement of the objectives 5, 6 and 7, + depending on the software level; or for Table T-7 of |tool_supplement_standard|: + achievement of the objectives 6, 7 and 8, depending on the qualification + level (as appropriate). + + * For qualification status of |prj_toolset|: refer to |str_abb| report. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst new file mode 100644 index 000000000..19f5dd53b --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst @@ -0,0 +1,13 @@ +|prj_toolset| Usage +==================== + +#. **Install the tool in the Operational Environment.** The user needs + to install the tool in an Operational Environment deemed equivalent + to the one prescribed by the *Operational Conditions of Use* chapter of + the |tor_abb| document (*Operational Environment* section, item e1). + +#. **Check correct usage of the tool.** For the tool results to be + used in a certification context, users must comply with the + interface presented in the :ref:`qualified-interface` section of + this document, as well as with the rules and scope prescribed by + the *Operational Conditions of Use* chapter of the |tor_abb| document. diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/content.rst new file mode 100644 index 000000000..13864b621 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/content.rst @@ -0,0 +1,14 @@ +.. _tqp-user-activities: + +User Activities +=============== + +To finalize the qualification of |prj_toolset|, the Tool User needs to +perform a set of activities, described hereafter: + +.. toctree:: + :maxdepth: 1 + + Qualification/content + Usage/content + Archiving/content diff --git a/qualification/qualkit/plans/Tool_Qualification_Plan/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/content.rst new file mode 100644 index 000000000..64f6ab886 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/content.rst @@ -0,0 +1,16 @@ +======================= +Tool Qualification Plan +======================= + +.. toctree:: + :maxdepth: 1 + + Qualification_Data_Overview/content + Compliance/content + Tool_Overview/content + Certification_Credit/content + Tool_Qualification_Level/content + Data_Production/content + Qualified_Interface/content + Operational_Conditions/content + User_Activities/content diff --git a/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Activities/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Activities/content.rst new file mode 100644 index 000000000..7e48c8b89 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Activities/content.rst @@ -0,0 +1,90 @@ +.. _qa-activities: + +|QA| Activities +=============== + +This section provides the overview of objectives of distinct |QA| activities +applied to the documents composing a qualification kit. Output of |QA| +activities is recorded in the separate sections of the |tqa_doc| document. + +The PDF format offers a sequential layout of the material which allows +browsing from end to end in a reliable manner, so most of the QA operations +described here are performed on the PDF version of the documents. Only those +steps requiring access to test sources are performed with the help of the HTML +contents. + +Reading the |plans_abb| document +******************************** + +**Objectives:** + + * Assess the compliance with qualification objectives. + +Inspection of Tool Operational Requirements +******************************************* + +**Objectives:** + + * Check the accuracy, completeness and consistency with respect to the + qualification objectives. + +The inspection is conducted by sampling, according to the following +guidelines: + +The requirements are split into families corresponding to the major kind of +metrics to be assessed. For DAL C, there is only a "Statement Coverage" +family; for DAL B, there is an additional "Decision Coverage" family and for +DAL A, a "Modified Condition/Decision Coverage" family complements the other +two. Each metric family is further divided into groups and possibly subgroups, +as needed. + +This is all summarized in the *Document Purpose and Organization* chapter of +the |tor_abb| document, section *Organization Guidelines*, which the |QA| +reviewer reads first. + +The reviewer then selects a set of requirements for review and this set is +documented in the |QA| report. The set would include at least stmt/Exemptions, +Common/Report and some other requirement(s) at the discretion of the reviewer. + +Inspection of Test Cases +************************ + +**Objectives:** + + * Check the accuracy of test cases, in particular whether the tests exercise + their target Ada constructs. + +This activity is also performed by sampling by the |QA| reviewer, selecting +all or a subset of the test cases associated with the selected requirements, +also documented in the |QA| report. + +To help understanding the tests performed for a test case, the reviewer first +gets acquainted with the *Overview of the test Procedures Organization* +appendix of the |tor_abb| document, where we describe the specific syntax we +use to state expected coverage results. + +Inspection of test execution results +************************************ + +**Objectives:** + + * Check that the Verification Environment reported in the |str_abb| report + is equivalent to the Operational Environment described in the |tor_doc| + document. + + * Check the results of test execution. + + * In the case tests failed, it is necessary to investigate whether the + source of error is: + + * A misbehavior of the infrastructure used to run tests and compare actual + results to expected results: in this case, the |prj_toolset| + Qualification Team is in charge of reporting and fixing the problem. + + * A bug in the |prj_toolset| implementation: in this case, the + |prj_toolset| Development Team is in charge of reporting and fixing the + problem. + + * A reasonable limitation of the tool: in this case, the |prj_toolset| + Qualification Team is in charge of reporting and justifying the problem + as part of the known limitations of the tool. diff --git a/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst new file mode 100644 index 000000000..0d0ff47c3 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst @@ -0,0 +1,14 @@ +Compliance With Guidance +======================== + +|prj_toolset| is qualified as a TQL-5 tool. + +.. tabularcolumns:: |p{0.05\linewidth}|p{0.20\linewidth}|p{0.15\linewidth}|p{0.45\linewidth}| + +.. csv-table:: Compliance matrix for Table T-9 of |tool_supplement_standard| + :delim: & + :header: "Item", "Ref.", "Achieved", "Notes" + + 1,3,4 & 8.1.a,b,c & Not applicable & Not required for TQL-5 tools + 2 & 8.1.b & Yes & See :ref:`qa-activities` + 5 & 8.1.d & Yes & See :ref:`tool-conformity-review` diff --git a/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst new file mode 100644 index 000000000..1302e2509 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst @@ -0,0 +1,25 @@ +.. _tool-conformity-review: + +Tool Conformity Review +====================== + +These objectives are achieved in the scope of the tool conformity review: + + * **8.3.a**: Check that tool life cycle data is under configuration + management and managed as described + * **8.3.b**: Check that activities of the TQP, TCMP and TQAP are + completed and have produced the items described + at :ref:`tcmp` + * **8.3.c**: Check that problems have been reported and evaluated according to + the :ref:`tcmp`. + * **8.3.d**: Record and approve software requirements deviations arising from + two sources: (1) deviations exposed by test failures reported in the + |prj_toolset| |str_doc| provided as part of the tool qualification data; + and (2) deviations due to issues recorded in the known-problems + file maintained by |adacore| for a given release of |prj_toolset|. + * **8.3.e**: Check that the tool executable object code can be re-generated + from the tool source code. + * **8.3.f**: Check that problems from a previous Tool Conformity Review are + re-evaluated. + * **8.3.g**: Not applicable since no credit is sought for the use of + previously developed tools. diff --git a/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst new file mode 100644 index 000000000..4add34a34 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst @@ -0,0 +1,56 @@ +|QA| Cycles +=========== + +Each |QA| cycle consists of the following iterations: + +* The **Qualification Team** starts the cycle by adding the documents + submitted for review into the ``qa`` area. The **Quality Assurance Team** is + then notified. + +.. raw:: latex + + \begin{minipage}{\linewidth} + +* The **Quality Assurance Team** identifies defects in the documents. For each + defect the **Quality Assurance Team** enters in the report a unique *defect + id*, its *location and scope*, *description*, as well as defect *severity + code*, which can be: + + * **EDIT** - minor editorial remark. + * **MINOR** - minor defect, i.e. one that is not blocking the document + release. + * **MAJOR** - major defect, i.e. one that is blocking the document release. + + **Qualification Team** is notified when the review is complete. + +.. raw:: latex + + \end{minipage} + \begin{minipage}{\linewidth} + +* The **Qualification Team** reviews each defect, and either Accepts or + Rejects it. + + * If a defect is **Accepted**: *Corrective Action* is described and applied. + * If a defect is **Rejected**: *Reason* is provided. + +.. raw:: latex + + \end{minipage} + +* If any defects have been **Accepted** and *Corrective Actions* applied: new + version of the document(s) is generated and added to the ``qa`` area. + +* The **Quality Assurance Team** reviews remarks for **Rejected** defects, + description and proper application of *Corrective Actions* for **Accepted** + defects. If the **Quality Assurance Team** agrees with the **Qualification + Team**'s response to a defect, it is marked as *Resolved*. + +* The **Qualification Team** and The **Quality Assurance Team** converge until + at least all **MAJOR** defects are *Resolved*. + + i.e.: The **Quality Assurance Team** agrees either with the given *Reason* + if a defect is **Rejected**, or with the proposed *Corrective Action* (and + its proper application has then been verified) if defect is **Accepted**. + +* The documents are then deemed ready for release. diff --git a/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/content.rst new file mode 100644 index 000000000..641095096 --- /dev/null +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/content.rst @@ -0,0 +1,21 @@ +.. _tqap: + +=========================== +Tool Quality Assurance Plan +=========================== + +|prj_toolset| |QA| (QA) proceeds in cycles of activities. + +The QA outputs for a kit are stored in a "qa" directory dedicated to the +project for which the kit is produced. The most significant output is the +|tqa_doc| document, ``qa.doc``, where all the QA cycles are tracked. + +The responsibility for the |QA| process belongs to the |QA| team. + +.. toctree:: + :maxdepth: 1 + + Compliance/content + Cycles/content + Activities/content + Conformity_Review/content diff --git a/qualification/qualkit/plans/document_settings.yaml b/qualification/qualkit/plans/document_settings.yaml new file mode 100644 index 000000000..058036f4d --- /dev/null +++ b/qualification/qualkit/plans/document_settings.yaml @@ -0,0 +1,21 @@ +document: + subst: + doc_title: *prj_doc_plans + # USER_ENTRIES + doc_short_title: 'PLANS' + doc_hdr_title: *prj_doc_plans + doc_version: '1' + doc_status: 'DRAFT' + doc_id: *prj_docid_plans + + assignments: + authors: [*prj_assignment_wri] + project_manager: [*prj_assignment_pm] + verifier: [*prj_assignment_ver] + + history: + - version: 1 + date: today + comments: Initial version + + # END_OF_USER_ENTRIES diff --git a/qualification/qualkit/plans/plans.rst b/qualification/qualkit/plans/plans.rst new file mode 100644 index 000000000..7d9c1842c --- /dev/null +++ b/qualification/qualkit/plans/plans.rst @@ -0,0 +1,19 @@ +=================================================================== +GNATcoverage - |tool_standard| Qualification Material: |doc_title| +=================================================================== + +.. rubric:: Revision History + +.. csv-table:: + :delim: & + :header: "Version #", "Date", "Comment" + + |release| & |today| & Initial version + +.. toctree:: + :maxdepth: 1 + + Introduction/content + Tool_Qualification_Plan/content + Tool_Configuration_Management_Plan/content + Tool_Quality_Assurance_Plan/content diff --git a/qualification/qualkit/scripts/__init__.py b/qualification/qualkit/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/qualkit/scripts/logger.py b/qualification/qualkit/scripts/logger.py new file mode 100644 index 000000000..621cb37b0 --- /dev/null +++ b/qualification/qualkit/scripts/logger.py @@ -0,0 +1,100 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2024, AdaCore # +# # +# The QM is free software; you can redistribute it and/or modify it # +# under terms of the GNU General Public License as published by the Free # +# Software Foundation; either version 3, or (at your option) any later # +# version. The QM is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- # +# TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public # +# License for more details. You should have received a copy of the GNU # +# General Public License distributed with the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + +"""Module providing a message logger""" + +from enum import Enum +from functools import total_ordering + + +@total_ordering +class Log_Level_Kind(Enum): + DEBUG = 1 + VERBOSE = 2 + INFO = 3 + WARNING = 4 + ERROR = 5 + + def __lt__(self, other): + if self.__class__ is other.__class__: + return self.value < other.value + return NotImplementedError + + +current_level = Log_Level_Kind.VERBOSE + + +def print_msg(prefix, msg: str) -> None: + print(prefix + ": " + msg) + + +def log_error(msg: str) -> None: + """ + Logs an error message. + Error messages are always displayed. + """ + print_msg("ERROR", msg) + + +def log_warning(msg: str) -> None: + """ + Logs a warning message. + Warnings are always displayed + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.WARNING: + print_msg("WARNING", msg) + + +def log_info(msg: str) -> None: + """ + Logs an informative message. Such message is displayed by default, unless + the QM is run using -v or -d switches. + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.INFO: + print_msg("INFO", msg) + + +def log_verbose(msg: str) -> None: + """ + Logs a message that is only displayed when the QM is run is verbose + mode or debug mode (respectively -v switch and -d switches). + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.VERBOSE: + print_msg("VERBOSE", msg) + + +def log_debug(msg: str) -> None: + """ + Logs an debug message. + Such message is not displayed, unless in debug mode (-d switch) + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.DEBUG: + print_msg("DEBUG", msg) diff --git a/qualification/qualkit/scripts/qm_plugins/__init__.py b/qualification/qualkit/scripts/qm_plugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/qualkit/scripts/qm_plugins/importers.py b/qualification/qualkit/scripts/qm_plugins/importers.py new file mode 100644 index 000000000..c976024cd --- /dev/null +++ b/qualification/qualkit/scripts/qm_plugins/importers.py @@ -0,0 +1,1186 @@ +from __future__ import annotations + +from scripts.rest import ArtifactImporter, DefaultImporter, writer + +from itertools import zip_longest +from collections import OrderedDict +import os + +MISSING_TR_LOG = os.path.join(os.getcwd(), "missing_tr_log.txt") + + +def resolve_importer(qmlink_txt: str) -> ArtifactImporter | None: + """Return importer corresponding to the qmlink text""" + + # get importer name + importer_name = qmlink_txt.partition("\n")[0][ + len(ArtifactImporter.QMLINK_TAG) : + ].strip() + + # get importer + importer = ArtifactImporter.new(importer_name) + return importer + + +def class_to_string(a): + """ + Returns the two or three letters string + referring to the class of the artifact 'a' if defined, + the name of the class otherwise. + + :param a: the artifact + :type a: artifact + """ + + if "Appendix" in a.id: + return "app" + elif a.name == "OpEnviron": + return "env" + elif is_reqset(a): + return "rqg" + elif is_req(a): + return "rq" + elif is_tc(a): + return "tc" + elif is_tcset(a): + return "tcg" + else: + return a.__class__.__name__ + + +########################### +# Tests on artifact class # +########################### + + +def is_req(a): + return getattr(a, "req", False) + + +def is_reqset(a): + return getattr(a, "reqset", False) + + +def is_req_or_set(a): + return is_req(a) or is_reqset(a) + + +def is_tc(a): + return getattr(a, "tc", False) or getattr(a, "htc", False) + + +def is_tcset(a, extended: bool = False): + """Return True if tcset attribute is set + If extended if True then return true also when + the type is unknown, but some of the children are tc + """ + if extended: + return getattr(a, "ext_tcset", False) + else: + return getattr(a, "tcset", False) + + +def is_tc_or_set(a, extended: bool = False): + return is_tc(a) or is_tcset(a, extended) + + +def is_test_result(a): + # FIXME + return False + + +def is_lrm_section(a): + # FIXME + return False + + +def is_source(a): + # FIXME + return False + + +def is_consolidation(a): + # FIXME + return False + + +def is_helper(source_resource): + return not (is_driver(source_resource) or is_functional(source_resource)) + + +def is_driver(source_resource): + # a resource named with "test_" is necessarily a 'driver' + return "test_" in source_resource.basename + + +def is_functional(source_resource): + # a resource whom content contains "-- #" is + # a functional source. In case of Ada Sources !! + + content = source_resource.get_content() + is_func = False + + for line in content.splitlines(): + if "-- #" in line: + is_func = True + break + return is_func + + +######### +# Utils # +######### + + +def get_first_req_relative(artifact): + """ + Returns the first parent which is a req. + + :param artifact: the artifact + :type artifact: artifact + """ + parent = artifact.relative_to + return ( + parent + if (parent is None or is_req(parent)) + else get_first_req_relative(parent) + ) + + +def write_artifact_ref(artifact_full_name, label=None): + """ + Returns a sphinx :ref: on 'artifact_full_name' + using as label: 'label' if declared, 'artifact_full_name' otherwise + + :param artifact_full_name: the full name of the artifact + :type artifact_full_name: string + :param label: the label to be used un the hyperlink + :type label: string + """ + + if label is None: + label = artifact_full_name + + return writer.role( + "ref", "%s <%s>" % (label, artifact_full_name.replace("/", "_")[1:]) + ) + + +def kind_of(artifact): + """ + :param artifact: the artifact + :type artifact: artifact + """ + return ( + "Requirement Group" + if is_reqset(artifact) + else ( + "Requirement" + if is_req(artifact) + else ( + "Testcase Group" + if is_tcset(artifact) + else "Testcase" if is_tc(artifact) else "Chapter" + ) + ) + ) + + +def short_kind_of(artifact): + """ + :param artifact: the artifact + :type artifact: artifact + """ + kind = kind_of(artifact) + return "Group" if "Group" in kind else kind + + +def default_importer(artifact): + """ + Returns the importer whom the to_rest() method + must be used for a given 'artifact' according to its class. + + :param artifact: the artifact + :type artifact: artifact + """ + if is_req(artifact): + return RequirementImporter() + elif is_tcset(artifact): + return TCSetImporter() + elif is_tc(artifact): + return TestCaseImporter() + else: + return DefaultImporter() + + +#################################################################### +# Importers + + +class LRMTableImporter(ArtifactImporter): + """ + The specific importer to generate the Traceability matrix + between reference manual and testcases and requirements + + TODO: This is currently not used, but we keep the code around in case we + want to restore the LRMEF table generation. + """ + + def qmlink_to_rest(self, parent, artifacts): + """ + Returns a matrix of traceability between + lrm section artifact and thi associated test cases + and requirements. + chosen format was dicussed in MB23-001. + + :param parent: the artifact calling the qmlink + :type parent: artifact + :param artifacts: the list of artifacts listed in qmlink + :type artifacts: list of artifacts + """ + REQ_NAME_PREFIX = "/TOR/Ada" + pdf_items = [] + html_items = [] + output = "" + language_version = None + + for a in artifacts: + if is_lrm_section(a): + + if not language_version: + language_version = a.attributes["language"].strip() + + ref = {} + for children in a.derived_to: + for child in children.all: + if is_tc(child): + parent = get_first_req_relative(child).id + + if parent not in ref.keys(): + ref[parent] = [] + + ref[parent].append( + [child.id, child.id.replace(parent, "")] + ) + + pdf_tc_list = "" + html_tc_list = "" + pdf_comment = "" + html_comment = "" + + for req in ref.keys(): + + pdf_other_tcs = "" + html_tcs = "" + + if len(ref[req]) > 1: + pdf_other_tcs = "%s + %d other tests" % ( + writer.raw(r"\newline", "latex"), + (len(ref[req]) - 1), + ) + + html_tcs = writer.role("raw-html", r"
").join( + [ + write_artifact_ref(k[0], label=k[1]) + for k in ref[req] + ] + ) + + requirement_str = ( + "Req: %s" + % write_artifact_ref( + req, req.replace(REQ_NAME_PREFIX, "") + ).strip() + ) + first_tc_str = ( + "* TC: %s" + % write_artifact_ref( + ref[req][0][0], label=ref[req][0][1] + ).strip() + ) + + pdf_tc_list += "%s %s %s %s %s " % ( + requirement_str, + writer.raw(r"\newline", "latex"), + first_tc_str, + pdf_other_tcs, + writer.raw(r"\newline", "latex"), + ) + + html_tc_list += "%s %s * TC: %s %s " % ( + requirement_str, + writer.role("raw-html", r"
"), + html_tcs, + writer.role("raw-html", r"
"), + ) + + applicable = a.attributes["relevance"].strip() + if pdf_tc_list != "": + if applicable == "no" or applicable == "partial": + relevance = applicable + comment = a.attributes["comment"].strip() + + pdf_comment = ( + comment + + " " + + writer.raw(r"\newline", "latex") + + " " + ) + html_comment = ( + comment + + " " + + writer.role("raw-html", r"
") + + " " + ) + + elif applicable == "yes": + relevance = "yes" + elif applicable == "no*": + relevance = "no" + comment = ( + "Section does not require SCA-related " + + "tests, but some are supplied " + ) + + pdf_comment = ( + comment + writer.raw(r"\newline", "latex") + " " + ) + html_comment = ( + comment + writer.role("raw-html", r"
") + " " + ) + else: + relevance = "unexpected value %s" % applicable + + if relevance != "no": + # when applicable is set to no, the list of + # tc must be ommitted. + # otherwise it is added to the comment column + # see N102-011 Feb 8, 2014 + pdf_comment += pdf_tc_list + html_comment += html_tc_list + + else: + if applicable == "no": + relevance = "no" + comment = a.attributes["comment"].strip() + + pdf_comment = comment + html_comment = ( + comment + + " " + + writer.role("raw-html", r"
") + + " " + ) + + elif applicable == "partial": + relevance = "PARTIAL but not covered" + comment = a.attributes["comment"].strip() + + pdf_comment = comment + html_comment = ( + comment + + " " + + writer.role("raw-html", r"
") + + " " + ) + + elif applicable == "yes": + relevance = "YES but not covered" + elif applicable == "no*": + relevance = "NO but" + comment = ( + "Indicated as no* in matrix." + + " Some test should be provided." + ) + + pdf_comment = comment + html_comment = comment + " " + + else: + relevance = "unexpected value %s" % applicable + + pdf_items.append( + [ + "%s" % a.id.replace("/", ""), + a.attributes["title"].strip(), + relevance, + pdf_comment, + ] + ) + + html_items.append( + [ + "%s" % a.id.replace("/", ""), + a.attributes["title"].strip(), + relevance, + html_comment, + ] + ) + + pdf_table = writer.csv_table( + pdf_items, + title="TOR/LRM Traceability Matrix for Ada %s" % language_version, + headers=["Section", "Title", "Applicable", "Comment"], + latex_format=r"|p{0.08\linewidth}|p{0.20\linewidth}|" + r"p{0.10\linewidth}|p{0.50\linewidth}|", + ) + + html_table = writer.csv_table( + html_items, + headers=["Section", "Title", "Applicable", "Comment"], + widths=[8, 20, 10, 50], + ) + + output += ( + writer.paragraph( + "This particular table is established for **Ada %s**.\n\n" + % language_version + + r"the requirement identifiers in this table were shortened " + "by removing the *%s* common prefix.\n\n" % REQ_NAME_PREFIX + ) + + writer.only(pdf_table, "latex") + + writer.only(html_table, "html") + ) + + output += "\n\n" + + return output, [] + + +class TCIndexImporter(ArtifactImporter): + + def get_recursive_relatives(self, artifact, depth): + """ + Returns the list of the tc or tc_set children of an artifact + and recursively the children of its children until the + required depth + + :param artifact: + :type artifact: artifact + :param depth: + :type depth: positive integer + + """ + result = [] + + for child in artifact.relatives: + if is_tc_or_set(child, extended=True): + result.append(child) + if depth > 1: + result += self.get_recursive_relatives(child, depth - 1) + + return result + + def qmlink_to_rest(self, parent, artifacts): + + html_items = [] + pdf_items = [] + output = "" + docrefs = set() + + for a in artifacts: + # Don't put sources in the tables + if is_source(a): + continue + + if is_tc_or_set(a, extended=True): + reference = a.rest_doc_ref() + docrefs.add(a.docfile()) + + html_items.append( + [ + writer.strong(class_to_string(a)), + writer.strong(a.name), + reference, + ] + ) + pdf_items.append([class_to_string(a), a.name, reference]) + for suba in self.get_recursive_relatives(a, 1): + # We do include in the table children artifacts only + # in html format. + + if is_tc(suba) or is_tcset(suba, extended=True): + subref = suba.rest_doc_ref() + + html_items.append( + [ + class_to_string(suba), + "`..` %s" % suba.name, + subref, + ] + ) + docrefs.add(suba.docfile()) + + html_table = writer.csv_table( + html_items, + headers=["", "TestCases", "Description"], + widths=[3, 25, 65], + ) + + pdf_table = writer.csv_table( + pdf_items, + headers=["", "TestCases", "Description"], + widths=[3, 25, 65], + ).strip() + + output += writer.only(html_table, "html") + output += writer.only(pdf_table, "latex").strip() + output += "\n\n" + + links = [] + for a in artifacts: + if is_tc(a): + links.append((a, TestCaseImporter())) + elif is_source(a): + pass + else: + links.append((a, default_importer(a))) + + output += writer.toctree( + [ + lnk[0].docfile() + for lnk in links + if not is_tc_or_set(lnk[0]) or is_tc_or_set(parent) + ], + # docrefs, + hidden=True, + ) + + return output, links + + +class AppIndexImporter(ArtifactImporter): + + def qmlink_to_rest(self, parent, artifacts): + return "", [] + + +class RequirementImporter(ArtifactImporter): + """ + The specific importer for requirements + """ + + def to_rest(self, artifact): + """ + Returns the 'rest' content of a requirement with artifact + type and ID on the first line + """ + + result = ".. _%s:\n\n" % artifact.docfile(True) + result += DefaultImporter().to_rest(artifact) + "\n\n" + + return result + + +class TCSetImporter(ArtifactImporter): + """ + The specific importer for TCSet + """ + + def to_rest(self, artifact): + """ + Returns the 'rest' content of a tc set having the + title and the links to parents included in the same 'minipage' + in order to keep them close in the final pdf generation + """ + + reference = ".. _%s:\n\n" % artifact.docfile(True) + reference += writer.raw( + "\\label{tor/source/%s::doc}" % artifact.docfile(True), "latex" + ) + result = "" + qmlink = "" + in_qmlink = False + content = DefaultImporter().to_rest(artifact) + + for line in content.splitlines(): + if line.startswith(".. qmlink:: TCIndexImporter"): + in_qmlink = True + + if in_qmlink: + qmlink += line + "\n" + else: + result += line + "\n" + + result = reference + result + "\n\n" + result = ( + "|\n\n" + writer.minipage(result, r"\linewidth") + "\n\n" + qmlink + ) + + return result + + +class ToplevelIndexImporter(ArtifactImporter): + + def qmlink_to_rest(self, parent, artifacts): + + items = [] + html_top_index = "" + + for a in artifacts: + + items.append([writer.strong(a.tname), a.rest_doc_ref()]) + + if a.name == "Ada": + + def key(a): + d = {"stmt": 1, "decision": 2, "mcdc": 3} + for k in d: + if k in a.name: + return d[k] + + selected = [k for k in a.relatives if not is_source(k)] + selected.sort(key=key) + + else: + selected = a.relatives + + for suba in selected: + items.append(["`..` %s" % suba.tname, suba.rest_doc_ref()]) + + html_top_index += writer.csv_table( + items, headers=["Chapter", "Description"], widths=[30, 70] + ) + + output = writer.only(html_top_index, "html") + + links = [ + (a, DefaultImporter()) for a in artifacts if "Index/.+" not in a.id + ] + + output += writer.toctree( + [lnk[0].docfile() for lnk in links if not is_tc_or_set(lnk[0])], + hidden=True, + ) + + return output, links + + +class SubsetIndexTable(ArtifactImporter): + + def qmlink_to_rest(self, parent, artifacts): + + items = [] + header = "" + + req = len([a for a in artifacts if class_to_string(a) == "rq"]) + reqg = len([a for a in artifacts if class_to_string(a) == "rqg"]) + tcg = len([a for a in artifacts if class_to_string(a) == "tcg"]) + tc = len([a for a in artifacts if class_to_string(a) == "tc"]) + + for a in artifacts: + + name = a.tname + items.append([class_to_string(a), name, a.rest_doc_ref()]) + + # in the html, the title is adapted to the content of the table + header = ( + "Requirements and Groups" + if (req > 0 and reqg > 0) + else ( + "Requirements Group" + if (req == 0 and reqg == 1) + else ( + "Requirements Groups" + if (req == 0 and reqg > 1) + else ( + "Requirement" + if (req == 1 and reqg == 0) + else ( + "Requirements" + if (req > 1 and reqg == 0) + else ( + "Testcases and Groups" + if (tc > 0 and tcg > 0) + else ( + "Testcases" + if (tc > 0 and tcg == 0) + else ( + "Testcases Groups" + if (tc == 0 and tcg > 0) + else ("") + ) + ) + ) + ) + ) + ) + ) + ) + + output = writer.csv_table( + items, + headers=["", "%s" % header, "Description"], + widths=[3, 25, 65], + ) + + return output, [] + + +class SubsetIndexTocTree(ArtifactImporter): + + def qmlink_to_rest(self, parent, artifacts): + + links = [(a, default_importer(a)) for a in artifacts] + + output = writer.toctree( + [lnk[0].docfile() for lnk in links if not is_tc_or_set(lnk[0])], + hidden=True, + ) + + return output, links + + +class SubsetIndexImporter(SubsetIndexTable): + + def qmlink_to_rest(self, parent, artifacts): + + output, links = SubsetIndexTable.qmlink_to_rest( + self, parent, artifacts + ) + + links = [(a, default_importer(a)) for a in artifacts] + + output += writer.toctree( + [lnk[0].docfile() for lnk in links if not is_tc_or_set(lnk[0])], + hidden=True, + ) + return output, links + + +class TestCaseImporter(ArtifactImporter): + + def log_missing_TR(self, artifact): + """ + Logs in a specific files the test case + if it has no test results. + + :param artifact: the artifact to analyse + :type artifact: artifact + """ + + has_TR = False + + for child in artifact.files: + has_TR = "tcs.dump" in child + if has_TR: + break + + if not has_TR: + with open(MISSING_TR_LOG, "a") as fd: + fd.write("No TR for artifact %s\n" % (artifact.id)) + + def get_sources(self, artifact): + """ + Returns all the sources an artifact TC needs to + list. It means its own sources and all thoses + of its parents + + :param artifact: the artifact the sources are required from + :type artifact: artifact + """ + + result = [] + + for child in artifact.relatives: + if is_source(child): + result += [child] + + if artifact.relative_to is not None: + result += self.get_sources(artifact.relative_to) + + return result + + def to_rest(self, artifact): + + reference = "\n\n.. _%s:\n" % artifact.docfile(True) + + reference += writer.raw( + "\\label{tor/source/%s::doc}" % artifact.docfile(True), "latex" + ) + + result_pdf = "**TEST CASE**: %s\n\n" % artifact.id + result_html = "%s\n%s\n" % (artifact.id, "=" * len(artifact.id)) + + result_pdf += DefaultImporter().to_rest(artifact) + "\n\n" + result_html += DefaultImporter().to_rest(artifact) + "\n\n" + + result = reference + writer.only(result_pdf, "latex") + result += writer.only(result_html, "html") + + self.log_missing_TR(artifact) + + # Managing the list of the sources + + driver_list = [] + driver_list_qmref = [] + func_list = [] + func_list_qmref = [] + helper_list = [] + helper_list_qmref = [] + + consolidation_list = [] + consolidation_list_qmref = [] + + # Whether we will output sources for the PDF version + do_pdf = False + + for item in self.get_sources(artifact): + + if is_consolidation(item): + + consolidation_list += [item.tname] + consolidation_list_qmref += [item.rest_doc_ref()] + + continue + + for key in item.contents_keys: + if len(item.contents(key)) > 0: + + for resource in item.contents(key): + + if is_driver(resource): + driver_list += [resource.basename] + driver_list_qmref += [ + writer.qmref( + item.docfile(True), resource.basename + ) + ] + continue + + if is_functional(resource): + func_list += [resource.basename] + func_list_qmref += [ + writer.qmref( + item.docfile(True), resource.basename + ) + ] + continue + + helper_list += [resource.basename] + helper_list_qmref += [ + writer.qmref(item.docfile(True), resource.basename) + ] + + driver_list.sort() + driver_list_qmref.sort() + func_list.sort() + func_list_qmref.sort() + helper_list.sort() + helper_list_qmref.sort() + + headers = ["Functional Sources", "Drivers Sources", "Helpers Sources"] + + if consolidation_list: + headers += ["Consolidation Sources"] + consolidation_list.sort() + consolidation_list_qmref.sort() + + for_table_qmref = zip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + consolidation_list_qmref, + fillvalue="", + ) + + for_table = zip_longest( + func_list, + driver_list, + helper_list, + consolidation_list, + fillvalue="", + ) + else: + for_table_qmref = zip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + fillvalue="", + ) + + for_table = zip_longest( + func_list, driver_list, helper_list, fillvalue="" + ) + + html_content = writer.csv_table(list(for_table_qmref), headers) + + result += writer.only(html_content, "html") + + if do_pdf: + latex_content = writer.csv_table( + list(for_table), + headers, + ).strip() + result += writer.only(latex_content, "latex") + + output = "\n\n" + writer.minipage(result, r"\linewidth") + "|\n\n" + + return output + + +class IndexImporter(ArtifactImporter): + current_req = None + + def append_to_items(self, art, depth): + + if is_req(art): + self.current_req = art + kind_text = writer.strong("(%s)" % class_to_string(art)) + id_text = writer.strong("%s" % art.id.replace("/TOR", "")) + + else: + kind_text = "(%s)" % class_to_string(art) + + common_prefix_parent_req = os.path.commonprefix( + (art.id, self.current_req.id) + ) + + id_text = "[...]" + art.id.replace(common_prefix_parent_req, "") + + self.items.append([kind_text, id_text, art.rest_doc_ref()]) + + def handle(self, art, depth): + + if is_req(art) or is_tc(art): + self.append_to_items(art, depth) + + for child in art.relatives: + self.handle(art=child, depth=depth + 1) + + def qmlink_to_rest(self, parent, artifacts): + + self.items = [] + + # HACK: not sure how this importer is supposed to work, the only + # IndexImporter occurence in the `Qualif/Index` directory which doesn't + # have any subdirectories, and the directive does not feature any + # param/links to resolve. As we want this to walk all the tests and + # requirements, we hardcode the artifacts list to be all the children + # of the parents of self. + + def sortkey_for(art): + + # Arrange for stmt requirements to come first, before decision and + # mcdc. Work from locations, which contain the explicit ordering + # requests in the names (numeric prefixes like 1_). + + return str(art.id).replace("/stmt", "/a") + + artifacts = [ + art + for art in parent.pdo.relatives + if "Ada" in art.id or "Common" in art.id + ] + artifacts.sort(key=sortkey_for) + + for art in artifacts: + self.handle(art=art, depth=0) + + pdf_table = writer.csv_table( + self.items, + headers=["Kind", "Identification", "Description"], + latex_format=( + r"|p{0.05\linewidth}|p{0.47\linewidth}||p{0.37\linewidth}|" + ), + ) + + html_table = writer.csv_table( + self.items, headers=["Kind", "Ref"], widths=[5, 47, 37] + ) + + output = "" + output += writer.only(pdf_table, "latex") + output += writer.only(html_table, "html") + + output += "\n\n" + + return output, [] + + +class TestCasesImporter(ArtifactImporter): + + def short_descs_of_main_ancestors(self, artifact, head): + """ + Get the first line of both itself and the ancestor + if the ancestor name is ended with 'head' + + :param artifact: the artifact + :type artifact: artifact + :param head: the prefix of the main group of artifacts + the description is required for + :type head: string + """ + + parent = artifact.relative_to + desc = None + main_desc = None + + if parent is not None: + if parent.id.endswith(head): + main_desc = parent.title() + desc = artifact.title() + else: + main_desc, desc = self.short_descs_of_main_ancestors( + parent, head + ) + + return main_desc, desc + + def get_testcases(self, artifact): + """ + Returns either itself if artifact is a tc or a tc_set + or the list of the test cases children of the artifact + + :param artifact: the artifact + :type artifact: artifact + """ + result = [] + + if is_tc_or_set(artifact): + return [artifact] + + for child in artifact.relatives: + result += self.get_testcases(child) + + return result + + def get_sources(self, artifact): + """ + Returns either itself if artifact is a source or + the list of the sources children of artifact + + :param artifact: the artifact + :type artifact: artifact + """ + result = [] + + if is_source(artifact): + return [artifact] + + for child in artifact.relatives: + result += self.get_sources(child) + + return result + + def tc_pdf_for(self, toplevel, subdirs, links): + """ + String to emit in the PDF output for testcases (or sets) + found in the ``links`` list underneath the list of candidate + ``subdirs`` of the ``toplevel`` directory within the Qualif + tree (eg. toplevel='Ada', subdirs=['stmt', 'decision', 'mcdc']). + + :param toplevel: Name of toplevel subdirectory within the + Qualif hierarchy, such as 'Ada' or 'Common'. + :type toplevel: string + + :param subdirs: List of immediate subdirectories of ``toplevel`` + where we should be searching for testcases, possiby through + intermediate sets. There may be no testcase in any of these. + :type subdirs: list[str] + + :param links: List of (artifact, importer) tuples for actual + tc_or_set artifacts to include in the document we're generating. + :type links: list[(artifact,importer)] + """ + + pdf_output = "" + + for subdir in subdirs: + subdir_output = self.tc_pdf_for_subdir( + toplevel=toplevel, subdir=subdir, links=links + ) + + if subdir_output: + if len(pdf_output) == 0: + pdf_output += ( + writer.section("%s Testcases" % toplevel) + "\n" + ) + else: + pdf_output += writer.raw(r"\newpage", "latex") + "\n\n" + + pdf_output += subdir_output + + return pdf_output + + def tc_pdf_for_subdir(self, toplevel, subdir, links): + """ + Helper for tc_pdf_for, doing the work for a single subdir. + """ + + subdir_links = [ + sdl + for sdl in links + if sdl[0].id.startswith("/TOR/%s/%s" % (toplevel, subdir)) + ] + + if not subdir_links: + return "" + + links_dict = OrderedDict() + for sdl in subdir_links: + main_desc, desc = self.short_descs_of_main_ancestors( + sdl[0], subdir + ) + if desc: + if desc not in links_dict: + links_dict[desc] = [] + links_dict[desc].append(sdl) + + pdf_output = "" + pdf_output += writer.subsection("%s" % main_desc) + "\n" + + for desc in links_dict.keys(): + pdf_output += writer.subsubsection(desc) + "\n" + pdf_output += writer.toctree( + [lnk[0].docfile() for lnk in links_dict[desc]], hidden=True + ) + + return pdf_output + + def qmlink_to_rest(self, parent, artifacts): + + # cleanup missingTRfile + with open(MISSING_TR_LOG, "w") as fd: + fd.write("") + + # Precompute sets of (artifact, importer) pairs of relevance + # to our outputs. + + tc_or_set_links = [] + src_links = [] + for a in artifacts: + for suba in self.get_testcases(a) + self.get_sources(a): + if is_tc(suba): + tc_or_set_links.append((suba, TestCaseImporter())) + elif is_tcset(suba): + tc_or_set_links.append((suba, TCSetImporter())) + + mixed_links = src_links + tc_or_set_links + + # Build the html output + + html_output = writer.toctree( + [lnk[0].docfile() for lnk in mixed_links], hidden=True + ) + + # Then the PDF variant. A bit more work as we need to output + # intermediate section titles ourselves and we don't want to + # include the sources there. + + pdf_output = "" + pdf_output += self.tc_pdf_for( + toplevel="Ada", + subdirs=["stmt", "decision", "mcdc"], + links=tc_or_set_links, + ) + pdf_output += self.tc_pdf_for( + toplevel="Common", + subdirs=["Report", "UnitsOfInterest", "GprFacilities"], + links=tc_or_set_links, + ) + + output = writer.only(pdf_output, "latex") + output += writer.only(html_output, "html") + + return output, mixed_links diff --git a/qualification/qualkit/scripts/qm_plugins/link_lrm.py b/qualification/qualkit/scripts/qm_plugins/link_lrm.py new file mode 100644 index 000000000..0261201bb --- /dev/null +++ b/qualification/qualkit/scripts/qm_plugins/link_lrm.py @@ -0,0 +1,19 @@ +LRMREF = "LRMREF:" + + +def parse_req(artifact): + """ + Parses the requirements to extract LRM Sections + that are bound "from" of links 'Lrm_Req' defined in model + """ + + loc = artifact.resources[0][0] + ref_list = [] + + for line in loc.get_content().splitlines(): + if line.lstrip().startswith(LRMREF): + ref_list = [ + "/%s" % k.strip() for k in line.split(LRMREF, 1)[1].split(",") + ] + + return ref_list diff --git a/qualification/qm/qm_plugins/lrm_index_parser.py b/qualification/qualkit/scripts/qm_plugins/lrm_index_parser.py similarity index 76% rename from qualification/qm/qm_plugins/lrm_index_parser.py rename to qualification/qualkit/scripts/qm_plugins/lrm_index_parser.py index d424cc333..76a86ed2f 100644 --- a/qualification/qm/qm_plugins/lrm_index_parser.py +++ b/qualification/qualkit/scripts/qm_plugins/lrm_index_parser.py @@ -6,6 +6,7 @@ class LRMParser(qm.LocationParser): The parser used by the QM to parse lrm_ref file and creates LRM section locations. """ + def __init__(self): self.relpath = None @@ -15,15 +16,14 @@ def parse(self, path, parent): lines = [] self.parent = parent - with open(path, 'r') as fd: + with open(path, "r") as fd: lines = fd.read().splitlines() for line in lines: + if line.startswith("#"): + continue - if line.startswith('#'): - continue - - if line.startswith('Note'): + if line.startswith("Note"): break if len(line.strip()) > 0: @@ -31,4 +31,5 @@ def parse(self, path, parent): qm.LocationParser.register_repository_factory( - 'lrm', '*.txt', LRMParser(), False) + "lrm", "*.txt", LRMParser(), False +) diff --git a/qualification/qualkit/scripts/rest/__init__.py b/qualification/qualkit/scripts/rest/__init__.py new file mode 100644 index 000000000..98bdf4128 --- /dev/null +++ b/qualification/qualkit/scripts/rest/__init__.py @@ -0,0 +1,318 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2014, AdaCore # +# # +# The QM is free software; you can redistribute it and/or modify it # +# under terms of the GNU General Public License as published by the Free # +# Software Foundation; either version 3, or (at your option) any later # +# version. The QM is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- # +# TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public # +# License for more details. You should have received a copy of the GNU # +# General Public License distributed with the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + +"""This module handles the ReST related tasks. This involves both docutils used + for live previews and sphinx for the final documents creation""" +from __future__ import annotations + +import os.path +import hashlib + +from typing import Optional, Sequence + +ARTIFACT_IMPORTER_PLUGINS = {} + +"""Implement some utility function that ease generation of ReST code""" + +HEADING_CHARS = ["#", "*", "=", "-", "^", '"'] + + +def heading(title, heading_char): + if isinstance(heading_char, int): + heading_char = HEADING_CHARS[heading_char] + + result = "\n\n" + result += heading_char * len(title) + "\n" + result += title + "\n" + result += heading_char * len(title) + "\n\n" + return result + + +def part(title): + return heading(title, "#") + + +def chapter(title): + return heading(title, "*") + + +def section(title): + return heading(title, "=") + + +def subsection(title): + return heading(title, "-") + + +def subsubseciton(title): + return heading(title, "^") + + +def paragraph(title): + return heading(title, '"') + + +def toctree(itemlist, depth=2, attrlist=()): + return ( + "\n".join( + [".. toctree::", " :maxdepth: %s" % depth] + + [" %s" % attr for attr in attrlist] + + ["\n"] + + [" %s" % item for item in itemlist] + ) + + "\n" + ) + + +def emphasis(content): + return "*" + content + "*" + + +def strong(content): + return "**" + content + "**" + + +def generic_block(command, content, command_arg=None): + if content == "": + return "" + + if command_arg is None: + command_arg = "" + + result = "\n.. %s:: %s\n\n" % (command, command_arg) + result += "\n".join([" " + line for line in content.splitlines()]) + result += "\n\n" + return result + + +def warning(content): + return generic_block("warning", content) + + +def parsed_literal(content): + return generic_block("parsed-literal", content) + + +def code_block(content, language): + return generic_block("code-block", content, language) + + +def raw(content, doc_type): + return generic_block("raw", content, doc_type) + + +def line_block(content): + result = "\n\n" + result += "\n".join([" " + line for line in content.splitlines()]) + return result + + +def list(content): # noqa: A001 + result = "\n\n" + result += "\n".join([" * %s" % line for line in content]) + result += "\n\n" + return result + + +class Artifact(object): + pass + + def get_children(self: Artifact) -> Sequence[Artifact]: + """Return list of subartifacts""" + return [] + + def get_child(self: Artifact, name: str) -> Artifact | None: + """Return child artifact by name""" + stripped_name = name.strip() + for a in self.get_children(): + if a.get_name() == stripped_name: + return a + + return None + + def get_name(self: Artifact) -> str: + return "" + + @property + def full_name(self: Artifact) -> str: + return "" + + def dtext(self: Artifact) -> str: + """Return text of the artifact""" + return "" + + def title(self: Artifact) -> str: + """Return first line of artifact dtext(), remove formatting""" + content = self.dtext() + for line in content.splitlines(): + line = line.strip().strip("*") + if len(line) > 0 and not line.startswith(".. "): + # ** has to be removed + # from short_description when used in tables + line = line.replace("**", "") + import re + + # remove all directives + line = re.sub(r":[a-zA-Z0-9]*:", "", line) + # replace backquotes with single quotes + line = line.replace("`", "'") + + return line + + return "" + + def docfile(self: Artifact, no_extension: bool = False) -> str: + """Filename for the generated RST file""" + return "" + + def rest_doc_ref(self: Artifact) -> str: + """Returns a sphinx :doc: reference""" + return "" + + @property + def relatives(self: Artifact) -> Sequence[Artifact]: + """ + The list of sub-artifacts that are relative to self. + + :rtype: A list of :class:`Artifact` + """ + return [] + + @property + def relative_to(self: Artifact) -> Optional[Artifact]: + """ + The instance this artifact is relative to. + + :rtype: An instance of :class:`Artifact`, or None + """ + return None + + def hash(self: Artifact) -> str: # noqa: A003 + """Return a hash based on the artifact full name""" + use_full_slug = os.environ.get("GNATCOV_QUALKIT_FULL_SLUGS", None) + + if not use_full_slug or use_full_slug == "False": + hashobj = hashlib.new("sha1") + hashobj.update(self.full_name.encode("utf-8")) + return hashobj.hexdigest() + return ( + os.path.relpath(os.path.abspath(self.full_name), os.getcwd()) + .replace("/", "_") + .replace(".._", "") + ) + + +class MetaArtifactImporter(type): + """ + Metaclass for Artifact Importers: automatically registers new + importers. + """ + + def __new__(mcs, classname, bases, class_dict): + result = type.__new__(mcs, classname, bases, class_dict) + if classname != "ArtifactImporter": + ARTIFACT_IMPORTER_PLUGINS[classname] = result + return result + + +class ArtifactImporter(metaclass=MetaArtifactImporter): + """ + ArtifactImporter is responsible for the translation of an artifact to + rest format. + To declare a new Importer, just override the + :func:`ArtifactImporter.to_rest`. + """ + + QMLINK_TAG = ".. qmlink::" + + def __init__(self): + self._concatenate = False + + @classmethod + def new(cls, name): + """ + Given an importer class name, return a new instance of that importer + + :param str name: The name of the class + :return: an ArtifactImporter instance + """ + + if name not in ARTIFACT_IMPORTER_PLUGINS: + raise Exception("No such importer: %s" % name) + return ARTIFACT_IMPORTER_PLUGINS[name]() + + @staticmethod + def is_qmlink(line: str) -> bool: + return line.startswith(ArtifactImporter.QMLINK_TAG) + + @property + def concatenate(self): + """ + Wether the imported artifacts should be directly concatenated (if + several are present in the same qmlink directive) or should have + separate content. + + :return: A boolean (False by default) + """ + return self._concatenate + + @concatenate.setter + def concatenate(self, value): + "concatenate setter" + self._concatenate = value + + def copy_resources(self, artifact, dest_dir): + """ + Copies additional resources to the destination directory if needed, for + documentation generation purpose. + + By default, this is a no-op. + + :param artifact: The artifact being imported + :type artifact: a :class:`qm.Artifact` + :param dest_dir: The destination directory + :type dest_dir: A string + """ + pass + + def to_rest(self, artifact): + """ + Needs to be overriden. + + :param Artifact: the artifact to translate + :type Artifact: an instance of :class:`qm.Artifact` + + :rtype: a string + """ + + def qmlink_to_rest(self, parent, artifacts): + """ + Needs to be overriden. + """ + raise NotImplementedError("not implemented") + + +class DefaultImporter(ArtifactImporter): + """ + The default importer, used for importing artifacts with files already + in rest format + """ + + def to_rest(self, artifact): + return artifact.dtext() diff --git a/qualification/qualkit/scripts/rest/writer.py b/qualification/qualkit/scripts/rest/writer.py new file mode 100644 index 000000000..4d18dd168 --- /dev/null +++ b/qualification/qualkit/scripts/rest/writer.py @@ -0,0 +1,476 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2014, AdaCore # +# # +# The QM is free software; you can redistribute it and/or modify it # +# under terms of the GNU General Public License as published by the Free # +# Software Foundation; either version 3, or (at your option) any later # +# version. The QM is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- # +# TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public # +# License for more details. You should have received a copy of the GNU # +# General Public License distributed with the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + +"""Provides some high level function to ease generation of ReST strings""" + +INDENT = " " + + +# paragraph # +def paragraph(content=None): + """Return a string representing the inlining of a content + + :param content: the directive content + :type content: either a string or a list of strings + """ + if content is None: + return "\n" + + if isinstance(content, str): + result = content.splitlines() + else: + result = content[:] + + result.append("") + + return "\n".join(result) + "\n" + + +# Directives # +def directive(name, content=None, argument=None, options=None): + """Return a string representing a directive + + :param name: the directive name + :type name: a string + :param content: the directive content + :type content: either a string or a list of strings + :param argument: the directive argument (for example the language for + for a ``code-block`` directive + :type argument: a string + :param options: the directive options + :type options: None or a dictionnary + :rtype: a string + """ + result = ["\n\n.. %s::" % name] + if argument is not None: + result[0] += " %s" % argument + + if options is not None: + for option in options: + if options[option] is None: + result.append("%s:%s:" % (INDENT, option)) + else: + result.append("%s:%s: %s" % (INDENT, option, options[option])) + + # add empty line + result.append("") + + if content is not None: + # add directive content. content can either be a string or a list + if isinstance(content, str): + content = content.splitlines() + + for line in content: + result.append("%s%s" % (INDENT, line)) + + result.append("") + + return "\n".join(result) + "\n" + + +def code_block(content, language=None): + """Return a code-block directive string + + :param content: the code to be highlighted + :type content: string or list of strings + :param language: the programming language name + :type language: string + :rtype: a string + """ + return directive("code-block", content=content, argument=language) + + +def toctree(content, hidden=False): + """Return a toctree directive + + :param content: the list of sub documents + :type content: list of string + :param hidden: if True then toctree is hidden + :type hidden: boolean + :rtype: a string + """ + options = {} + if hidden: + options["hidden"] = None + options["maxdepth"] = 1 + + return directive("toctree", content=content, options=options) + + +def csv_table( + content, headers=None, title=None, widths=None, latex_format=None +): + """Return a ReST csv-table + + :param content: the elements of the table + :type content: a list of list of strings + :param headers: the column titles + :type headers: a list of strings + :param title: the table title + :type title: a string + :param widths: list of width percentage (for html) + :type widths: list of integers + :param latex_format: set the LateX tabular env environment + :type latex_format: string + :rtype: a string + """ + + table_content = [] + for line in content: + table_line = ", ".join(['"%s"' % k.replace('"', '""') for k in line]) + table_content.append(table_line) + + options = {} + if headers is not None: + options["header"] = ", ".join(['"%s"' % k for k in headers]) + if widths is not None: + options["widths"] = ",".join(["%s" % k for k in widths]) + + result = "" + if latex_format is not None: + result += directive("tabularcolumns", argument=latex_format) + elif widths is not None: + latex_w = ["p{%.2f\\textwidth}" % (float(w) / 100.0) for w in widths] + result += directive( + "tabularcolumns", argument="|" + "|".join(latex_w) + "|" + ) + + result += directive( + "csv-table", table_content, argument=title, options=options + ) + return result + + +def raw(content, format_tag): + """Raw output for a given format + + Allows to emit directly latex, html, ... into a sphinx document + + :param content: the raw content + :type content: a string + :param format_tag: the selected format (html, latex) + :type format_tag: a string + :rtype: a string + """ + + return directive("raw", content=content, argument=format_tag) + + +def only(content, format_tag): + """Return a ReST only directive + + :param content: the content + :type content: a string + :param format_tag: expression of format tags (html, latex, ...) + :type format_tag: a string + :rtype: a string + """ + + return directive("only", content=content, argument=format_tag) + + +def include(format_tag): + """Return a ReST include directive""" + + return directive("include", argument=format_tag) + + +# Roles # +def role(name, argument): + """Generic function to generate ReST roles + + :param name: the role name + :type name: a string + :param argument: the content on which the role is applied + :type argument: a string + :rtype: a string + """ + return ":%s:`%s`" % (name, argument) + + +def qmref(full_path, name=None): + """Generate a qmref role + + :param full_path: the target of the ref + :type full_path: a string + :param name: intelligible name or description + :type name: a string + :rtype: a string + """ + + if name is not None: + # Protect potential '<' in the explicit text. + name = name.replace("<", r"\<") + content = "%s <%s>" % (name, full_path) + else: + content = full_path + + return role("doc", content) + + +def doc(name, explicit_text=None): + """Generate a doc role + + :param name: name of the doc file + :type name: a string + :param explicit_text: intelligible name or description + :type explicit_text: a string + :rtype: a string + """ + + # if explicit_text is not None: + # # Protect potential '<' in the explicit text. + # explicit_text = explicit_text.replace('<', '\<') + # content = '%s <%s>' % (explicit_text, name) + # else: + # content = name + + return role("doc", name) + + +def ref(reflabel, explicit_text=None): + """Generate a ref role + + :param reflabel: the target label to reference + :type reflabel: a string + :param explicit_text: intelligible name or description + :type explicit_text: a string + :rtype: a string + """ + + if explicit_text is not None: + # Protect potential '<' in the explicit text. + explicit_text = explicit_text.replace("<", r"\<") + content = "%s <%s>" % (explicit_text, reflabel) + else: + content = reflabel + + return role("ref", content) + + +def emphasis(content): + """Generate an emphasis role equivalent to ``*content*`` + + :param content: the content + :type content: a string + :rtype: a string + """ + return role("emphasis", content) + + +def strong(content): + """Generate a string role equivalent to ``**content**`` + + :param content: the content + :type content: a string + :rtype: a string + """ + return role("strong", content) + + +def literal(content): + """Generate an inline code sample + + :param content: the content + :type content: a string + :rtype: a string + """ + return role("literal", content) + + +# Lists # +def generic_list(content_list, marker="*"): + """Generate a ReST list + + :param content: the elements of the list + :type content: a list of strings and list (to generate sublists) + :param marker: the marker used to mark new elements + :type marker: a string + :rtype: a string + """ + prefix = "%s " % marker + blank = " " * len(prefix) + result = [] + for element in content_list: + + if isinstance(element, str): + element = element.splitlines() + + result.append("%s%s" % (prefix, element[0])) + for line in element[1:]: + result.append("%s%s" % (blank, line)) + else: + # assume element is either a list or a tuple + result.append("") + result.append(generic_list(element, " " * len(prefix) + marker)) + result.append("") + return "\n".join(result) + "\n\n" + + +def enumerated_list(content_list): + """Generate an enumerated ReST list + + :param content: the elements of the list + :type content: a list of strings and list (to generate sublists) + :rtype: a string + """ + return generic_list(content_list, marker="#.") + + +def definition_list_item(definition_name, definition_text): + """Generate a single definition ReST list + + :param definition_name: The name of the definition + :type definition_name: a string + :param definition_text: The text of the definition + :type definition_text: a string + :rtype: a string + """ + res = [definition_name] + + if isinstance(definition_text, str): + definition_text = definition_text.splitlines() + + for line in definition_text: + res.append("%s%s" % (INDENT, line)) + + return "\n".join(res) + "\n\n" + + +def definition_list(content_list): + """Generate a definition ReST list + + :param content: the elements of the list, each element containing first + the name of the definition, then the definition itself + :type content: a list of tuple (string, string) + :rtype: a string + """ + result = "" + for defname, deftext in content_list: + result += definition_list_item(defname, deftext) + + return result + + +# Sections # +def heading(title, level=1): + """Generate a ReST heading + + :param title: the title of that heading + :type title: a string + :param level: depth of the heading + :type level: integer + :rtype: a string + """ + markers = ["#", "*", "=", "-", "^", '"'] + marker = markers[level - 1] + result = [title, marker * len(title)] + return "\n".join(result) + "\n\n" + + +def part(title): + """Equivalent to heading with level set to 1""" + return heading(title, 1) + + +def chapter(title): + """Equivalent to heading with level set to 2""" + return heading(title, 2) + + +def section(title): + """Equivalent to heading with level set to 3""" + return heading(title, 3) + + +def subsection(title): + """Equivalent to heading with level set to 4""" + return heading(title, 4) + + +def subsubsection(title): + """Equivalent to heading with level set to 5""" + return heading(title, 5) + + +def paragraph_title(title): + """Equivalent to heading with level set to 6""" + return heading(title, 6) + + +def rubric(title): + return directive("rubric", argument=title) + + +def macro(value, expanded): + """Creates a sphinx macro""" + return "\n\n.. |%s| replace:: %s\n\n" % (value, expanded) + + +def macrolatex(value, expanded): + """Creates a latex specific sphinx macro""" + return "\n\n.. |%s| raw:: latex\n\n %s\n\n" % (value, expanded) + + +def minipage(content, latex_format=r"{\linewidth}"): + """ + Return a string representing the insertion of a latex minipage + 'around' the given content. + if not latex generation then, only includes the content as it. + + :param content: the content to be included in minipage + :type content: either a string or a list of strings + :param latex_format: the format to be associated with the minipage + structure + :type latex_format: a string + """ + + result = [] + result.append( + directive( + "raw", + ("\\begin{minipage}%s" % latex_format).replace("\\\\", "\\"), + "latex", + ) + ) + + if content is not None: + # add mini page content. content can either be a string or a list + if isinstance(content, str): + content = content.splitlines() + + result += content + + result.append(directive("raw", r"\end{minipage}", "latex")) + + str_result = "\n".join(result) + + return str_result + + +def define_role(role_name, options): + """Allows to define a new role + then usable through the previous function 'role' + + :param role_name: the name of the role to be defined + :type role_name: a string, + :param options: the expected effect of the role + :type options: a dictionnary or None + """ + return directive("role", argument=role_name, options=options) diff --git a/qualification/qualkit/str/Makefile b/qualification/qualkit/str/Makefile new file mode 100644 index 000000000..2090b7862 --- /dev/null +++ b/qualification/qualkit/str/Makefile @@ -0,0 +1,4 @@ +DOC=str +MASTER_DOC=source/content +TOOL?=$(realpath ../) +include ../../Makefile.common diff --git a/qualification/qualkit/str/document_settings.yaml b/qualification/qualkit/str/document_settings.yaml new file mode 100644 index 000000000..9b9094cca --- /dev/null +++ b/qualification/qualkit/str/document_settings.yaml @@ -0,0 +1,21 @@ +document: + subst: + doc_title: *prj_doc_str + # USER_ENTRIES + doc_short_title: 'STR' + doc_hdr_title: *prj_doc_str + doc_version: '1' + doc_status: 'DRAFT' + doc_id: *prj_docid_str + + assignments: + authors: [*prj_assignment_wri] + project_manager: [*prj_assignment_pm] + verifier: [*prj_assignment_ver] + + history: + - version: 1 + date: today + comments: Initial version + + # END_OF_USER_ENTRIES diff --git a/qualification/qualkit/tor/Makefile b/qualification/qualkit/tor/Makefile new file mode 100644 index 000000000..3d212a0f1 --- /dev/null +++ b/qualification/qualkit/tor/Makefile @@ -0,0 +1,4 @@ +DOC=tor +MASTER_DOC=source/index +TOOL?=$(realpath ../) +include ../../Makefile.common diff --git a/qualification/qualkit/tor/__init__.py b/qualification/qualkit/tor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/qualkit/tor/document_settings.yaml b/qualification/qualkit/tor/document_settings.yaml new file mode 100644 index 000000000..c660ebced --- /dev/null +++ b/qualification/qualkit/tor/document_settings.yaml @@ -0,0 +1,21 @@ +document: + subst: + doc_title: *prj_doc_tor + # USER_ENTRIES + doc_short_title: 'TOR' + doc_hdr_title: 'Tool Operational Requirements' + doc_version: '1' + doc_status: 'DRAFT' + doc_id: *prj_docid_tor + + assignments: + authors: [*prj_assignment_wri] + project_manager: [*prj_assignment_pm] + verifier: [*prj_assignment_ver] + + history: + - version: 1 + date: today + comments: Initial version + + # END_OF_USER_ENTRIES diff --git a/qualification/qualkit/tor/genrest.py b/qualification/qualkit/tor/genrest.py new file mode 100755 index 000000000..1be4ad914 --- /dev/null +++ b/qualification/qualkit/tor/genrest.py @@ -0,0 +1,1910 @@ +#!/usr/bin/env python +from __future__ import annotations + +import os +import glob +import re +import sys +import json +import optparse + +from tor.genrest_conf import ALLOW_UNCLASSIFIED_FOLDERS, SUPRESS_MSG_TYPES + +import scripts.rest as rest +import scripts.logger as logger +from scripts.rest import Artifact, ArtifactImporter, writer +from scripts.qm_plugins.importers import ( + resolve_importer, + default_importer, + is_req_or_set, + is_tc_or_set, +) +from itertools import zip_longest + +from typing import Callable, Dict, List, Set, Optional, Sequence, Any, IO + +# ***************************************************************************** +# ** GENERAL DESCRIPTION ** +# ***************************************************************************** + +# This file implements the core of the GNATcoverage TOR document production, +# generating sphinx-REST from artifacts held within our testsuite/Qualif +# filesystem tree. + +# Except on rare occasions, each directory in this tree represents some TOR +# related entity: requirement, testcase, appendix material, or groups of such, +# possibly nested (groups may hold direct artifacts or further intermediate +# groups). +# +# The general structure is very hierarchical, going from requirement +# groups (REQG kind) to requirements (REQ kind), to testcases (TC kind) +# possibly via testcase groups (TCG kind). +# +# Very roughly, our processing here first constructs an internal tree +# datastructure representing the directory tree, where each node holds +# attributes qualifying its nature (e.g. "this node/directory holds a +# testcase"). This is determined from two elements: +# +# * The presence in the directory of some text file: +# - tc.rst for a testcase, +# - req.rst for a requirement, +# - content.rst for a group +# +# * For groups, the node is further qualified by looking at the set of +# children of the node. Despite the possibility to nest groups within +# groups, mixing a testcase artifacts at the same level as requirement +# artifacts is disallowed. +# +# Expected tree structure is as follows: +# +# content.rst +# content.rst +# req_set.rst +# req.rst +# tc_set.rst +# tc.rst +# tc.rst +# req.rst +# +# req.txt -> req.rst +# set.txt -> tc_set.rst +# set.txt -> content.rst +# [tc.txt; test.py] -> [tc.rst; test.py] +# +# Relative to where this script reside, path to ... + +# The root of the directory tree mapping qualification artifacts +# (requirements, testcases, ...): + +RST_ROOTDIR = "source" + +# The root of the directory where the REST documents describing +# these artifacts will reside: + +ART_ROOTDIR = "../../../testsuite/Qualif" + +# Prefix artifact ID with this string + +ART_ID_PREFIX = "TOR" + +# Switch verbose messages on/off + +verbose = False + +# Maximum accepted directory tree depth + +MAX_TREE_DEPTH = 255 + +# count of typed warnings + +warn_stats: Dict[str, int] = {} + +# ********************** +# ** Helper functions ** +# ********************** + + +def get_content(filename: str) -> str: + """Return contents of file FILENAME as a string""" + + with open(filename, "r") as fd: + return fd.read() + + +def to_title(title: str) -> str: + """Given an entity name return a suitable string to be inserted + in the documentation""" + m = re.search(r"^[0-9]+_(.*)$", title) + if m is not None: + title = m.group(1) + return title.replace("_", " ") + + +def header(text: str, pre_skip: int, post_skip: int) -> str: + """Return the string to be used as a section header for STR, + framed with PRE_SKIP new_lines before and POST_SKIP new_lines after""" + return "\n" * pre_skip + text + "\n" * post_skip + + +def sec_header(text: str) -> str: + """Return a Section header text to be used for section title STR""" + return header(rest.strong(text), pre_skip=2, post_skip=2) + + +def subsec_header(text: str) -> str: + """Return a Subsection header text to be used for subsection title STR""" + return header(rest.emphasis(text), pre_skip=2, post_skip=2) + + +def info(text: str): + logger.log_info(text) + + +def warn(text: str, msg_type: str = ""): + if not msg_type or not any( + re.match(pattern, msg_type) for pattern in SUPRESS_MSG_TYPES + ): + logger.log_warning(text) + + if msg_type: + if msg_type in warn_stats: + warn_stats[msg_type] += 1 + else: + warn_stats[msg_type] = 1 + + +def warn_if(cond: bool, text: str, msg_type: str = ""): + if cond: + warn(text, msg_type) + + +def exit_if(p: bool, msg: str): + if p: + logger.log_error(msg) + sys.exit(1) + + +def err(text: str): + logger.log_error(text) + sys.exit(1) + + +def print_warn_stats(): + for key in warn_stats: + logger.log_info("%s: %d" % (key, warn_stats[key])) + + +def err_if(p: bool, text: str): + if p: + logger.log_error(text) + sys.exit(1) + + +def is_functional(src: str) -> bool: + # a resource whom content contains "-- #" is + # a functional source. In case of Ada Sources !! + + with open(src) as f: + content = f.read() + + is_func = False + + for line in content.splitlines(): + if "-- #" in line: + is_func = True + break + return is_func + + +# ************************** +# ** TestCase abstraction ** +# ************************** + +# Helper for the Directory abstraction, to encapsulate research of driver +# and functional source file sets + + +class TestCase: + def __init__(self: TestCase, dir_name: str, dgen: DocGenerator): + self.dir = dir_name + self.dgen = dgen + + self.fnsources: set[str] = set() + self.hlpsources: set[str] = set() + self.drsources: set[str] = set() + self.conspecs: set[str] = set() + self.find_sources() + + def parent_globbing( + self: TestCase, + dir_name: str, + pattern: str, + include_start_dir: bool = True, + ) -> Set[str]: + """Look for src/[pattern] files in dir and its parents directory + up to document root directory""" + + head = os.path.relpath(dir_name, self.dgen.art_rootdir) + tail = "" + if not include_start_dir: + head, tail = os.path.split(head) + files = set() + while len(head) > 0: + files |= set( + glob.glob( + os.path.join( + self.dgen.art_rootdir, + head, + "src", + pattern, + ) + ) + ) + head, tail = os.path.split(head) + return files + + def find_with_clauses( + self: TestCase, + dir_name: str, + sourcefile: str, + ) -> Set[str]: + content = get_content(sourcefile) + # Remove all comments + content = "\n".join( + [k for k in content.splitlines() if not re.match(r"\s*--", k)] + ) + + # Find all the with clauses + matches = re.findall(r"(?:\n|;|^)\s*with\s*([^;]+)\s*;", content, re.S) + matches = [k.replace(" ", "") for k in matches] + matches = [k.replace(".", "-") for k in matches] + + result = set() + for m in matches: + result |= set(m.lower().split(",")) + + # Remove packages we don't care about and probably could locate + result -= {"support", "system"} + + file_list = set() + for item in result: + spec = self.parent_globbing(dir_name, item + ".ads", True) + warn_if( + len(spec) > 1, + 'multiple specs for unit "%s" (from %s)' % (item, sourcefile), + "SRC_MULTIPLE_SPECS", + ) + file_list |= spec + + body = self.parent_globbing(dir_name, item + ".adb", True) + warn_if( + len(body) > 1, + 'multiple bodies for unit "%s" (from %s)' % (item, sourcefile), + "SRC_MULTIPLE_BODIES", + ) + file_list |= body + + warn_if( + len(body | spec) == 0, + 'no body or spec source found for unit "%s" (from %s)' + % (item, sourcefile), + "SRC_NO_BODY_OR_SPEC", + ) + + return file_list + + def find_closure( + self: TestCase, + dir_name: str, + sourcefile: str, + ) -> Set[str]: + """Given an Ada source file find it's closure. Not that we ignore the + support package""" + + result_set = self.find_with_clauses(dir_name, sourcefile) + + current_size = len(result_set) + previous_size = 0 + while current_size > previous_size: + previous_size = current_size + tmp = set() + for item in result_set: + tmp |= self.find_with_clauses(dir_name, item) + + result_set |= tmp + current_size = len(result_set) + + return result_set + + def find_sources(self: TestCase) -> None: + """Locate the functional and driver sources of testcase SELF""" + + # Seek the test drivers first, and infer closure from there. Then + # append consolidation specs to the set of drivers. We will typically + # end up on common functional units from drivers, so use sets to + # prevent duplicates. + + # Test drivers: search the local "src" subdir first, walk uptree + # if no driver there. + + local_sources = set( + glob.glob(os.path.join(self.dir, "src", "*.ad[sb]")) + ) + + self.drsources = { + k for k in local_sources if os.path.basename(k).startswith("test_") + } + + if len(self.drsources) == 0: + data_names = { + os.path.basename(k).split(".")[0] for k in local_sources + } + for name in data_names: + self.drsources.update( + self.parent_globbing(self.dir, "test_" + name + "*.ad[sb]") + ) + + warn_if( + len(self.drsources) == 0, + "no driver source for testcase in %s" % self.dir, + "SRC_NO_DRIVER_SOURCE", + ) + + # Driver Closure: + + self.fnsources = set() + self.hlpsources = set() + for driver in self.drsources: + for src in self.find_closure(self.dir, driver): + if is_functional(src): + self.fnsources.add(src) + else: + self.hlpsources.add(src) + + warn_if( + len(self.fnsources) == 0, + "no functional source for testcase in %s" % self.dir, + "SRC_NO_FUNCTIONAL_SOURCE", + ) + + # Consolidation specs. These are always local. + + self.conspecs = set() + self.conspecs |= set( + glob.glob(os.path.join(self.dir, "src", "cons_*.txt")) + ) + + +# *************************** +# ** Path Info abstraction ** +# *************************** + + +class PathInfo: + """Holds info about the path to the current node when walking + a directory tree""" + + def __init__(self: PathInfo): + self.n_req = 0 # Number of requirement expressions so far + self.n_tc = 0 # Number of tc nodes so far + self.depth = 0 # Depth of this node wrt root of walk operation + + +# ************************** +# ** Node Set abstraction ** +# ************************** + + +class NodeSet: + """Node Set abstraction, used to compute composite attributes + for a set of nodes. We compute two categories of composite attributes: + + * The "some_" attributes tell whether some (at least one) node in set has + such or such characteristic. These are updated as nodes are added to the + set, via the "register_one" method. + + * The "all_" attributes tell whether all the nodes in the set has such or + such characteristic. These are computed from the current "some_" values + when the "sync" method is called, + """ + + def __init__(self: NodeSet, diros: List[Dir]): + """Initialize the some_ attributes for SELF, then register + each directory object in the DIROS sequence and sync() to update + the all_ attributes from there.""" + + self.some_reqgroup = False + self.some_notreqgroup = False + self.some_tcgroup = False + self.some_nottcgroup = False + self.some_appmat = False + self.some_notappmat = False + + self.some_reqorset = False + self.some_notreqorset = False + self.some_tcorset = False + self.some_nottcorset = False + + self.some_reqorgroup = False + self.some_notreqorgroup = False + self.some_tcorgroup = False + self.some_nottcorgroup = False + + self.some_req = False + self.some_notreq = False + self.some_tc = False + self.some_nottc = False + self.some_app = False + self.some_notapp = False + self.some_set = False + self.some_notset = False + + self.some_notreqset = False + self.some_nottcset = False + self.some_notappset = False + + self.diros: List[Dir] = [] + + [self.register_one(diro) for diro in diros] + self.sync() + + def register_one(self: NodeSet, diro: Dir): + """Add one directory object to this set, updating the + some_ attributes accordingly.""" + + self.some_req |= diro.req + self.some_tc |= diro.tc + self.some_set |= diro.set + self.some_app |= diro.app + + self.some_notreq |= not diro.req + self.some_nottc |= not diro.tc + self.some_notset |= not diro.set + self.some_notapp |= not diro.app + + self.some_notreqset |= not diro.reqset + self.some_nottcset |= not diro.tcset + self.some_notappset |= not diro.appset + + self.some_reqgroup |= diro.reqgroup + self.some_notreqgroup |= not diro.reqgroup + + self.some_tcgroup |= diro.tcgroup + self.some_nottcgroup |= not diro.tcgroup + + self.some_appmat |= diro.appmat + self.some_notappmat |= not diro.appmat + + self.some_reqorset |= diro.req | diro.reqset + self.some_tcorset |= diro.tc | diro.tcset + + self.some_notreqorset |= not (diro.req | diro.reqset) + self.some_nottcorset |= not (diro.tc | diro.tcset) + + self.some_reqorgroup |= diro.req | diro.reqgroup + self.some_tcorgroup |= diro.tc | diro.tcgroup + + self.some_notreqorgroup |= not (diro.req | diro.reqgroup) + self.some_nottcorgroup |= not (diro.tc | diro.tcgroup) + + self.diros.append(diro) + info( + f"registering {diro.root}: TC {diro.tc}, REQ {diro.req}, " + "TCG {diro.tcgroup}, RG {diro.reqgroup}" + ) + + def sync(self: NodeSet): + """Compute the all_ attributes of this set from what we know of the + current elements in the set. All the all_ attributes are set to False + on empty sets.""" + + # Beware of queries over empty sets. All the some_ attributes + # start False, so the all_ attributes would turn true if we're + # not cautious + + has_diro = len(self.diros) > 0 + + self.all_tc = has_diro and not self.some_nottc + self.all_req = has_diro and not self.some_notreq + self.all_set = has_diro and not self.some_notset + self.all_app = has_diro and not self.some_notapp + + self.all_reqset = has_diro and not self.some_notreqset + self.all_tcset = has_diro and not self.some_nottcset + self.all_appset = has_diro and not self.some_notappset + + self.all_reqorset = has_diro and not self.some_notreqorset + self.all_tcorset = has_diro and not self.some_nottcorset + + self.all_reqgroup = has_diro and not self.some_notreqgroup + self.all_tcgroup = has_diro and not self.some_nottcgroup + self.all_appmat = has_diro and not self.some_notappmat + + self.all_reqorgroup = has_diro and not self.some_notreqorgroup + self.all_tcorgroup = has_diro and not self.some_nottcorgroup + + +# *************************** +# ** Directory abstraction ** +# *************************** + +# The kind of material node that the directory holds. This is used +# to determine the hyperlink and the page title texts + + +class DirKind: + def __init__(self: DirKind, txthdl: str, image: str): + self.image = image + self.txthdl = txthdl + + +class dcl: + TC = DirKind(image="tc", txthdl="Testcase") + + TCG = DirKind(image="tcg", txthdl="Testcase Group") + + REQ = DirKind(image="rq", txthdl="Requirement") + + REQG = DirKind(image="rqg", txthdl="Requirement Group") + + APP = DirKind(image="app", txthdl="Appendix Material") + + INTRO = DirKind(image="intro", txthdl="Introductory Material") + + kinds = (TC, TCG, REQ, REQG, APP, INTRO) + + +# DocGenerator helper to process one specific subdirectory of the TOR/TC +# hierarchy + + +class Dir(Artifact): + def __init__( + self: Dir, + root: str, + subdirs: List[str], + files: List[str], + parent: Optional[Dir], + art_root: str, + ): + # Filesystem attributes for this directory + + def to_id(name: str) -> str: + """remove leading number from name""" + m = re.search(r"^[0-9]+_(.*)$", name) + if m is not None: + return m.group(1) + else: + return name + + self.root = root # path to this dir + self.subdirs = subdirs # list of local subdir names + self.files = files # list of local file names + self.pdo = parent + self.id: str = "" + + self.name = os.path.basename(root) # local name of this dir + if self.pdo: + self.id = self.pdo.id + "/" + to_id(self.name) + else: + self.id = ( + "/" + + ART_ID_PREFIX + + to_id(self.root[len(os.path.abspath(art_root)) :]) + ) + + # If we are at the root directory then return our documentation + # entry point. + if os.path.relpath(self.root, art_root) == ".": + # predefined name of the root document + self._docfile_base_ = "index" + else: + # avoid name conflict with the root document + self._docfile_base_ = self.hash() + + # Links children in the directory tree. These are + # set as dir objects get mapped within a DirTree instance. + + # list of pruned Dir objects + self.subdos: List[Dir] = [] + # list of child Dir obejects eactly as they appear in the + # folder tree + self.children: List[Dir] = [] + + # NodeSet for subdos, which we'll populate when computing + # attributes bottom-up + + self.sdset: NodeSet | None = None + + # Properties from presence of local files, better cached to prevent + # repeated real file presence checks + + self.req: bool = "req.rst" in self.files + self.hreq: bool = "hreq.rst" in self.files + self.test: bool = "test.py" in self.files + self.tc: bool = "tc.rst" in self.files + self.htc: bool = "htc.rst" in self.files + self.chset: bool = "content.rst" in self.files + self.reqset: bool = "req_set.rst" in self.files + self.tcset: bool = "tc_set.rst" in self.files + self.app: bool = "app.rst" in self.files + + # TODO: decide later if this is required + # currently it is to silence the warning about missing description file + self.tcres = "test.rep" in self.files + + self.set = self.chset or self.reqset or self.tcset + + # title name, to be displayed in index tables, and sorting key. + + # The sorting key is the directory name (not title name) for starters, + # which is meant to allow prefix characters (numbers prior to the + # first '_') to influence sorts while not being displayed. We will + # need to update that when bridging over nodes, to make sure that the + # children remain grouped wrt their new parent and set of siblings. + + self.tname = to_title(self.name) + self.sname = self.name + + # source file copies for rst toctree + self.sources: Set[str] = set() + + # ------------------------------------------ + # -- Bottom-Up node attribute computation -- + # ------------------------------------------ + + def botmup_compute_attributes(self: Dir, pathi, data): + # Compute predicates over our set of children. We expect the children + # attributes to be available here. + # + # pathi and data are note used here. The method is eventually called + # through a generic lambda function "process" that may instantiate + # to a method that does use them. + + self.sdset = NodeSet(diros=self.subdos) + + # Populate extra attributes on this node + + self.container = self.set or self.req or self.reqset or self.tcset + + # TC, APP or REQ SETS are nodes with consistent children (all reqs, + # all tcs, or all apps). + + self.appset = self.set and self.sdset.all_app + + # Some mixes are legitimate, as long as the leaf item kinds (tc + # or req) remain consistent. We call GROUPS those containers, and at + # this stage we let the notion propagate up pretty freely: + + self.tcgroup = self.set and self.sdset.all_tcorgroup + self.reqgroup = self.set and self.sdset.all_reqorgroup + self.appmat = self.app or (self.set and self.sdset.all_appmat) + + # when configuration permits implicit folder types then derive type for + # folders without an existing content file + if self.children and not self.dfile(): + if ALLOW_UNCLASSIFIED_FOLDERS: + if self.sdset.all_reqorgroup: + self.reqset = True + elif self.sdset.all_tcorgroup: + self.tcset = True + else: + warn( + f"Artifact without a default content file" + f" in {self.full_name}", + "ARTIFACT_WITH_CHILDREN_NO_FILE", + ) + + # Consistency checks need to be applied elswhere to determine whether + # such or such mix is acceptable. Consider for example the difference + # in consistency between + # + # 1) either: + # set/tc + # /tc + # /tc + # + # or: + # set/set/tc + # /tc + # /set/tc + # /tc + # + # (only allow sets of TCs, or sets of sets) + # + # 2) or possibly + # set/set/tc + # /tc + # /tc + # + # (allow sets of either tc or set) + + # Now compute the node KIND, which conveys how we want the node to be + # referenced (in index table hyperlinks) and titled. This is not meant + # to be representative of structural properties. REQ nodes often are + # tcset or tcgroup as well, for example. + + self.kind = ( + dcl.TC + if self.tc + else ( + dcl.REQ + if self.req + else ( + dcl.TCG + if self.tcgroup + else ( + dcl.REQG + if self.reqgroup + else dcl.APP if self.appmat else dcl.INTRO + ) + ) + ) + ) + + def dfile(self: Dir, path: bool = False) -> str | None: + """Name of the text file which holds the meat of this dir/artifact""" + + base = ( + "tc.rst" + if self.tc + else ( + "content.rst" + if self.chset + else ( + "req_set.rst" + if self.reqset + else ( + "tc_set.rst" + if self.tcset + else ( + "req.rst" + if self.req + else ( + "htc.rst" + if self.htc + else ( + "hreq.rst" + if self.hreq + else "app.rst" if self.app else None + ) + ) + ) + ) + ) + ) + ) + + return os.path.join(self.root, base) if base and path else base + + @property + def ext_tcset(self: Dir) -> bool: + self.tcset = self.tcset or ( + not self.dfile() + and (self.sdset.some_tcorset if self.sdset else False) + ) + + return self.tcset + + def dtext(self: Dir) -> str: + if self.dfile() is None: + # This means that dtext was called on an artifact with unknown type + if ALLOW_UNCLASSIFIED_FOLDERS: + warn( + "Artifact without a default content file" + " in %s" % self.full_name + ) + return "" + else: + err( + "Artifact without a default content file in" + " %s" % self.full_name + ) + return "" + else: + file = self.dfile(path=True) + content = "" + if file and os.path.isfile(file): + content = get_content(file) + else: + warn("Content file %s does not exist." % file) + if self.tcset: + # the folder contains test cases, construct a default tcset + content = ( + self.id + + """ + +.. qmlink:: TCIndexImporter + + * +""" + ) + # ensure that content starts with title + if file and file.endswith(".rst"): + title_prefix = "" + title = "" + body = "" + title_candidate = "" + + for line in content.splitlines(): + if title: + # The title is identified. + # Add all the remaining lines to the body + body += "\n" + line + else: + if title_candidate: + # check the line following the title candidate + clean_line = line.strip() + if not clean_line: + # empty line after the first row. Promote the + # first row to be the "title". + title = title_candidate + elif ( + not re.search(r"[^=]", clean_line) + or not re.search(r"[^\*]", clean_line) + or not re.search(r"[^#]", clean_line) + ): + # first level title -- the next line is + # entirely composed of one of the title markers + title = title_candidate + "\n" + clean_line + else: + # the following line contains arbitrary text + # give a warning and stop the search + warn(f"No title found in {file}") + break + else: + # no lines with content yet + # if we find one then that is treated as + # a title candidate. + if not line or line.startswith(".. "): + # preserve empty lines and rst directives + title_prefix += line + "\n" + else: + # any other text is considered as title + title_candidate = line.strip() + + if title: + content = title + "\n\n" + self.parent_ref + "\n\n" + body + else: + content = content + "\n\n" + self.parent_ref + else: + content = content + "\n\n" + self.parent_ref + + return content + + def docfile(self: Dir, no_extension: bool = True) -> str: + """Filename for the generated RST file""" + + if no_extension: + return self._docfile_base_ + else: + return self._docfile_base_ + ".rst" + + def get_children(self: Dir) -> Sequence[Dir]: + """Return list of subartifacts""" + return self.children + + def get_name(self: Dir) -> str: + return self.name + + def rest_doc_ref(self: Dir, id_as_title: bool = False) -> str: + """Returns a sphinx :doc: on a.docfile() + + By default uses the title string as link label. + id_as_title=True replaces it with id string. + """ + + return writer.qmref( + self.docfile(True), + self.title() if not id_as_title else self.id, + ) + + @property + def full_name(self: Dir) -> str: + return self.root + + @property + def relatives(self: Dir) -> Sequence[Dir]: + """ + The list of sub-artifacts that are relative to self. + """ + return self.children + + @property + def relative_to(self) -> Optional[Dir]: + """ + The instance this artifact is relative to. + """ + return self.pdo + + @property + def full_id(self: Dir) -> str: + """Return an id prefixed with item kind""" + return "**" + self.kind.txthdl.upper() + "** " + self.id + + @property + def parent_ref(self: Dir) -> str: + """Return link to the parent object, if self's parent is a + requirement(set) or testcase(set) + + Include artifact type when parent is requirement. + """ + if self.pdo and ( + is_req_or_set(self.pdo) + or is_tc_or_set(self.pdo) + or self.pdo.tcgroup + or self.pdo.reqgroup + ): + return ( + "**Parent" + + ((" " + self.pdo.kind.txthdl) if self.pdo.req else "") + + "** " + + self.pdo.rest_doc_ref() + ) + else: + return "" + + +# ******************************** +# ** Directory Tree abstraction ** +# ******************************** + +# Helper to manage dirname -> dirobject associations and establish +# parent/children relationships over dir objects, assuming the tree +# is walked top down. + +# Values to denote possible ways to walk a tree and possible actions to take +# at every directory node when walking the tree + + +topdown, botmup = range(2) + +dirProcess, dirSkip, dirCutPre, dirCutPost = range(4) +# dirProcess: process this node and walk children +# dirCutPre: don't process this node and don't walk children +# dirCutPost: process this node and don't walk children +# dirSkip: skip processing for this node, walk children nevertheless + +im = { + dirSkip: "dirSkip", + dirProcess: "dirProcess", + dirCutPre: "dirCutPre", + dirCutPost: "dirCutPost", +} + + +class DirTree: + def __init__(self: DirTree, roots: List[Dir]): + self.roots = roots + + # ------------------------------------------------------------ + # -- Tree walking facilities, once we're past the first doc -- + # -- generation pass, all the parent children links are set -- + # ------------------------------------------------------------ + + # Local facilities. Beware that walks are used to compute directory + # object attributes, so these can't be relied upon. + + class WalkInfo: + def __init__( + self: DirTree.WalkInfo, + data: DirTree.WalkInfo | None, + pathi: PathInfo, + process: Callable | None, + ctl: Callable, + mode: int, + ): + self.process = process if process else lambda diro, pathi, wi: None + self.ctl = ctl + self.mode = mode + self.pathi = pathi + self.data = data + + def __enter(self: DirTree, diro: Dir, wi): + if diro.req: + wi.pathi.n_req += 1 + if diro.tc: + wi.pathi.n_tc += 1 + return wi.ctl(diro, wi.pathi, wi.data) + + def __exit(self: DirTree, diro: Dir, wi: DirTree.WalkInfo): + if diro.req: + wi.pathi.n_req -= 1 + if diro.tc: + wi.pathi.n_tc -= 1 + + def __visit(self: DirTree, diro: Dir, wi: DirTree.WalkInfo): + ctl = self.__enter(diro, wi) + + process_this = ctl not in [dirSkip, dirCutPre] + visit_children = ctl not in [dirCutPre, dirCutPost] + + if process_this and wi.mode == topdown: + wi.process(diro, wi.pathi, wi.data) + + if visit_children: + wi.pathi.depth += 1 + [self.__visit(subdo, wi) for subdo in diro.subdos] + wi.pathi.depth -= 1 + + if process_this and wi.mode == botmup: + wi.process(diro, wi.pathi, wi.data) + + self.__exit(diro, wi) + + def __default_ctl(self: DirTree, diro: Dir, pathi, widata): + return dirProcess + + # Exposed facilities. + + def walk( + self: DirTree, + mode: int, + process: Callable, + data: WalkInfo | None = None, + ctl: Callable | None = None, + ): + if ctl is None: + ctl = self.__default_ctl + + [ + self.__visit( + diro=diro, + wi=DirTree.WalkInfo( + process=process, + pathi=PathInfo(), + data=data, + mode=mode, + ctl=ctl, + ), + ) + for diro in sorted(self.roots, key=Dir.get_name) + ] + + # --------------------------------------- + # -- Tree filtering/pruning facilities -- + # --------------------------------------- + + def rprune(self: DirTree, namelist: List[str]): + """prune all subdirs of self that are do *not* lead to any dir + in NAMELIST""" + + class WalkInfo(DirTree.WalkInfo): + def __init__(self: WalkInfo, tokeep: List[str]): + self.tokeep = tokeep + self.toprune: List[Dir] = [] + + def prunectl(diro: Dir, pathi, wi: WalkInfo) -> int: + # See if diro is within or beyond any of our dirs to keep. + # Keep going (skip) if within. Cut search if beyond. + + # Append "/" to items to prevent "bla/C" from being considered + # a directory prefix of "bla/Common" + + rootdir = diro.root + os.sep + + for tokeep in wi.tokeep: + dirtokeep = tokeep + os.sep + if os.path.commonprefix((rootdir, dirtokeep)) == rootdir: + return ( + dirSkip if len(rootdir) < len(dirtokeep) else dirCutPre + ) + + # diro is for sure not within or down any of our dirs to keep. + # register for actual pruning and don't search past it. + + wi.toprune.append(diro) + return dirCutPre + + # Walk this tree to compute the list of directories to prune, then do + # prune for real. We don't effectively prune nodes during the walk to + # prevent mishaps caused by changes to our internal datastructures + # while they are being processed. + + wi = WalkInfo(tokeep=namelist) + self.walk( + mode=topdown, + process=lambda diro, pathi, wi: None, + ctl=prunectl, + data=wi, + ) + + for diro in wi.toprune: + if diro.pdo: + diro.pdo.subdos.remove(diro) + + # --------------------- + # -- Sorting entries -- + # --------------------- + + def sort(self: DirTree): + """Sort the list of subdirectory objects registered for each tree + node, to influence processing order in tree walks (hence insertion + order in auto-indexes)""" + + def sort_subdos(diro, pathi, wi): + # Sort subdirectories of DIRO. Arrange to get + # + # * All the non containers first, to make sure that + # + # sub/x + # y + # + # gets out as + # + # y bla + # sub blo + # x blu + # + # and not as + # + # sub blo + # x blu + # y bla + # + # where y would be perceived as a child of "sub" + # + # * Those for which a local key in their respective key order, + # all before or after those without explicit keys depending + # on the "default" entry, + # + # * In every subcase, sort by subdirectory name + + # Fetch the local { subdirname: key } dictionary, if any + + kfile = os.path.join(diro.root, "keys.txt") + keys = ( + json.loads(get_content(kfile)) + if os.path.exists(kfile) + else {"default": 0} + ) + + # Then sort according to our three criteria of interest + + diro.subdos.sort( + key=lambda subdo: ( + subdo.container, + ( + keys[subdo.sname] + if subdo.sname in keys + else keys["default"] + ), + subdo.sname, + ) + ) + + self.walk(mode=botmup, process=sort_subdos) + + # ----------------------------------------- + # -- Checking directory tree consistency -- + # ----------------------------------------- + + def check_local_consistency(self: DirTree, diro: Dir, pathi: PathInfo): + """Perform checks on the files present in DIRO""" + + warn_if( + not ( + diro.set + or diro.req + or diro.tc + or diro.app + or diro.htc + or diro.hreq + or diro.tcres + ), + "missing description text at %s" % diro.root, + "MISSING_DESCRITPTION_TEXT", + ) + rst_count = len([f for f in diro.files if f.endswith(".rst")]) + warn_if( + diro.req and rst_count > 1, + "req.rst not alone in %s" % diro.root, + ) + warn_if( + diro.chset and rst_count > 1, + "content.rst not alone in %s" % diro.root, + ) + warn_if( + diro.tc and not diro.test, + "tc.rst without test.py in %s" % diro.root, + ) + warn_if( + diro.test and not diro.tc and not diro.htc, + "test.py without tc.rst in %s" % diro.root, + ) + + warn_if( + (diro.tc or diro.tcgroup) and pathi.n_req < 1, + "tc or set without req uptree at %s" % diro.root, + ) + + warn_if( + diro.req and pathi.n_req > 1, + "nested req (%d up) at %s" % (pathi.n_req - 1, diro.root), + ) + + warn_if( + diro.req and pathi.n_tc > 0, + "req with tc uptree at %s" % diro.root, + ) + + def check_downtree_consistency(self, diro, pathi): + """Perform checks on the relationships DIRO and its children""" + + warn_if( + (diro.req or diro.set) and not diro.subdos, + "missing subdirs for artifact at %s" % diro.root, + ) + + if not diro.subdos: + return + + # Warn on structural inconsistencies + + warn_if( + diro.req and not diro.sdset.all_tcorgroup, + "inconsistent subdirs down req.rst at %s" % diro.root, + ) + + warn_if( + diro.req + and not (diro.sdset.all_reqorgroup or diro.sdset.all_tcorgroup), + "missing testcases for leaf req in %s" % diro.root, + ) + + def topdown_check_consistency( + self: DirTree, diro: Dir, pathi: PathInfo, data + ): + self.check_local_consistency(diro, pathi) + self.check_downtree_consistency(diro, pathi) + + def check_consistency(self: DirTree): + self.walk(mode=topdown, process=self.topdown_check_consistency) + + +class DirTree_FromPath(DirTree): + + def __init__(self: DirTree_FromPath, rootp: str, dolevel: str): + DirTree.__init__(self, roots=[]) + + # First compute the tree of directory objects starting at path ROOTP, + # setting up for each the .pdo link to parent and the .subdos list of + # children. This is achieved by performing a top down walk of the os + # directory structure. + + self.dolevel = dolevel + self.root = rootp + + self.dir = {} # dir-name -> dir-object dictionary + [ + self.topdown_map(dirname, subdirs, files) + for (dirname, subdirs, files) in os.walk(os.path.abspath(rootp)) + ] + + # Arrange for the intermediate directories just there for file + # organisation purposes to disappear from our tree representation + + self.do_cross_overs() + + # Then compute exta node attributes, once the tree of internal + # directory objects is setup. + + self.compute_attributes() + + def topdown_map( + self: DirTree_FromPath, + dirname: str, + subdirs: List[str], + files: List[str], + ): + # Map directory DIRNAME into our dictionary and set up links to/from + # its parent directory, if any. We're called along a topdown walk, so + # we have mapped the parent directory already if there is one. + + # Ignore some subdirectories + excluded_levels = {"doA", "doB", "doC"} + excluded_levels.remove(self.dolevel) + + for d in subdirs.copy(): + if ( + d in (".svn", "mylib", "App", "__pycache__") + or "src" in d + or "obj" in d + or d.startswith("tmp_") + or d.startswith("s_") + or d.startswith("d_") + or d.startswith("m_") + or d.startswith("u_") + or d in excluded_levels + or os.path.exists(os.path.join(dirname, d, ".tor_ignore")) + ): + subdirs.remove(d) + + # Find out its parent object by name. If there's no parent object, + # this dir is a root. Setup the links otherwise. + + parentname = os.path.dirname(dirname) + + if parentname not in self.dir: + parento = None + else: + parento = self.dir[parentname] + + # Map a new object for this dir ... + + diro = Dir( + root=dirname, + subdirs=subdirs, + files=files, + parent=parento, + art_root=self.root, + ) + + self.dir[dirname] = diro + + # Set links to parent + + if not parento: + self.roots.append(diro) + else: + parento.subdos.append(diro) + parento.children.append(diro) + + # -------------------------------------------------------------- + # -- Abstract away nodes that were introduced only for source -- + # -- sharing purposes, and that should not introduce an extra -- + # -- layer in the qualification material. -- + # -- ----------------------------------------------------------- + + def __do_bridge_over(self: DirTree_FromPath, diro: Dir): + """Arrange for DIRO to disappear from the dir tree structure + it is in.""" + + print("======== Bridging over " + diro.root) + + # Remove this diro from the list of children of its parent, + # and update each of this diro's children to have its parent + # as a new parent instead of this diro itself. + + # Turn: + # P <----- PARENT + # | + # DIRO <----- TO VANISH + # | + # +---+---+---+ + # | | | | + # c1 c2 c3 c4 <---- CHILDREN + # + # into: + # + # P <----- PARENT + # | + # +---+---+---+ + # | | | | + # c1 c2 c3 c4 <---- CHILDREN + + if not diro.pdo: + err(f"malformed direcotry object: {diro.get_name()}") + return + + diro.pdo.subdos.remove(diro) + + for subdo in diro.subdos: + diro.pdo.subdos.append(subdo) + subdo.pdo = diro.pdo + + subdo.tname = ".".join([diro.tname, subdo.tname]) + subdo.sname = ".".join([diro.sname, subdo.sname]) + + class WalkInfo(DirTree.WalkInfo): + def __init__(self: DirTree_FromPath.WalkInfo): + self.tobridge = [] + + def __decide_cross_over( + self: DirTree_FromPath, + diro: Dir, + pathi: PathInfo, + wi: DirTree_FromPath.WalkInfo, + ): + """Add DIRO to WI.tobridge if DIRO ought to be removed from the + tree.""" + + file = diro.dfile(path=True) + if file is None: + file = "" + + if diro.set and os.path.getsize(file) == 0: + wi.tobridge.append(diro) + + def do_cross_overs(self: DirTree_FromPath): + """Remove (bridge links over) intermediate nodes that should not + produce intermediate layers in the final document.""" + + # Collect the set of nodes to remove first, then remove each one in + # turn. Removing while we're walking the tree is, mm, hazardous. + + wi = DirTree_FromPath.WalkInfo() + self.walk(mode=topdown, process=self.__decide_cross_over, data=wi) + + [self.__do_bridge_over(diro) for diro in wi.tobridge] + + # --------------------------------------------- + # -- Computing tree/node attributes, before -- + # -- more sophisticated walks can take place -- + # --------------------------------------------- + + def compute_attributes(self: DirTree_FromPath): + self.walk(mode=botmup, process=Dir.botmup_compute_attributes) + + +# ************************ +# ** Document Generator ** +# ************************ + +icLink, icNid, icBrief = range(3) + + +class DocGenerator(object): + def __init__( + self: DocGenerator, + art_rootdir: str, + rst_rootdir: str, + options: optparse.Values, + ): + + # Command line options + self.o = options + + # Root of the directory tree where the qualification artifacts + # are to be found: + self.art_rootdir = os.path.abspath(art_rootdir) + logger.log_debug(f"Root testsuite dir: {self.art_rootdir}") + + # Root of the directory tree where the generated document sources + # are to be produced: + self.rst_rootdir = os.path.abspath(rst_rootdir) + + if os.path.exists(self.rst_rootdir): + if self.o.force: + warn("Deleting an existing directory %s" % self.rst_rootdir) + for root, dirs, files in os.walk( + self.rst_rootdir, topdown=False + ): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + os.rmdir(os.path.join(root, name)) + os.rmdir(self.rst_rootdir) + else: + err( + "Directory %s already exists. " + "Use --force to delete it or clean up filesystem manually." + % self.rst_rootdir + ) + + os.mkdir(self.rst_rootdir) + + self.resource_list: Set[str] = set() + + # current output file descriptor, while walking the tor/tc tree + self.ofd: IO[Any] + + def register_resources(self: DocGenerator, rset: Set[str]): + self.resource_list |= rset + + def docpath_to(self: DocGenerator, filename: str) -> str: + return os.path.join(self.rst_rootdir, filename) + + def get_docfile( + self: DocGenerator, diro: Dir, must_exist: bool = False + ) -> str | None: + """Return full path to output file of diro. + If must_exist is True, then return the name only for existing files + """ + name = self.docpath_to(diro.docfile(no_extension=False)) + return name if not must_exist or os.path.isfile(name) else None + + def file2docfile( + self: DocGenerator, filename: str, must_exist: bool = False + ) -> str | None: + """Return the associated filename for a given path""" + docfile = os.path.relpath(filename, self.art_rootdir) + # If we are at the root directory then return our documentation + # entry point. + if docfile == ".": + return "index.rst" + + docfile = docfile.replace("/", "_").replace("\\", "_") + ".rst" + return docfile if not must_exist or os.path.isfile(docfile) else None + + def ref(self: DocGenerator, name: str) -> str: + """Transform string NAME into another string suitable to be used as + index name""" + result = os.path.relpath(name, self.art_rootdir) + return result.replace("/", "_").replace("\\", "_").replace(".", "_") + + # --------------------------------------------- + # -- Generating doc contents for a directory -- + # --------------------------------------------- + + def contents_from(self: DocGenerator, diro: Dir) -> str: + """Fetch descriptive text form the file corresponding to diro. + Append a TC index to TC set descriptions that don't have one.""" + + # Fetch the descriptive text either through a specialized importer, or + # through our own + + importer = default_importer(diro) + # if isinstance(importer, DefaultImporter): + # res = diro.to_rest() + # else: + res = importer.to_rest(diro) + res = self.process_qmlink(diro, res) + + return res + + def process_qmlink( + self: DocGenerator, diro: Dir, content_text: str + ) -> str: + """extract ´.. qmlink::´ directives and replace their content""" + + res = "" + in_qmlink = False + subartifacts: Sequence[Artifact] = [] + importer: ArtifactImporter | None = None + for line in content_text.splitlines(): + if in_qmlink: + stripped_line = line.rstrip() + if stripped_line: + indent_len = len(stripped_line) - len( + stripped_line.strip() + ) + if indent_len == 0 or stripped_line.startswith(".. "): + # the indent declined or a new block + # end the current block + if importer: + qmlink_rst, links = importer.qmlink_to_rest( + diro, subartifacts + ) + diro.subdos += [ + item + for item in subartifacts + if item not in diro.subdos + ] + res += "\n" + qmlink_rst + + in_qmlink = False + subartifacts = [] + importer = None + + elif stripped_line.strip() == "*": + subartifacts.extend( + sorted(diro.get_children(), key=Dir.get_name) + ) + else: + a = diro.get_child(stripped_line) + if a: + subartifacts.append(a) + else: + logger.log_error( + "Cannot locate artifact '" + + stripped_line + + "'" + ) + + if ArtifactImporter.is_qmlink(line): + in_qmlink = True + importer = resolve_importer(line) + if not importer: + logger.log_error( + "Cannot locate importer for '" + line + "'" + ) + elif not in_qmlink: + res += "\n" + line + + if importer: + # rst section in the end of the document + qmlink_rst, links = importer.qmlink_to_rest(diro, subartifacts) + diro.subdos += [ + item for item in subartifacts if item not in diro.subdos + ] + res += "\n" + qmlink_rst + + return res + + def gen_tc_section(self: DocGenerator, diro: Dir): + """Generate the TestCase Sources section, and register the + sources as resources + + TODO: This should really belong in an artifatc importer?? + """ + + def restore_extension(name: str) -> str: + """restores .ad[bs] extension in name""" + if name.endswith("_ads"): + return name[:-4] + ".ads" + elif name.endswith("_adb"): + return name[:-4] + ".adb" + elif name.endswith("_txt"): + return name[:-4] + ".txt" + else: + return name + + tco = TestCase(dir_name=diro.root, dgen=self) + + if ( + not tco.fnsources + and not tco.drsources + and not tco.hlpsources + and not tco.conspecs + ): + # no sources, nothing to process + return + + headers = ["Functional Sources", "Drivers Sources", "Helpers Sources"] + + func_list = sorted(tco.fnsources) + driver_list = sorted(tco.drsources) + helper_list = sorted(tco.hlpsources) + + func_list_ref = [self.ref(d) for d in func_list] + driver_list_ref = [self.ref(d) for d in driver_list] + helper_list_ref = [self.ref(d) for d in helper_list] + + func_list_qmref = [":ref:`%s`" % d for d in func_list_ref] + driver_list_qmref = [":ref:`%s`" % d for d in driver_list_ref] + helper_list_qmref = [":ref:`%s`" % d for d in helper_list_ref] + + if tco.conspecs: + consolidation_list_ref = [ + self.ref(d) for d in sorted(tco.conspecs) + ] + consolidation_list_qmref = [ + ":ref:`%s`" % d for d in consolidation_list_ref + ] + + headers += ["Consolidation Sources"] + + for_table_qmref = zip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + consolidation_list_qmref, + fillvalue="", + ) + + else: + consolidation_list_ref = [] + for_table_qmref = zip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + fillvalue="", + ) + + html_content = writer.only( + writer.csv_table(list(for_table_qmref), headers), "html" + ) + + self.ofd.write(html_content) + + diro.sources = { + restore_extension(f) + for f in ( + func_list_ref + + driver_list_ref + + helper_list_ref + + consolidation_list_ref + ) + if f + } + + self.register_resources( + tco.fnsources | tco.drsources | tco.hlpsources | tco.conspecs + ) + + # -------------------------------------- + # -- Tailored directory tree instance -- + # -------------------------------------- + + def art_dirtree_for( + self: DocGenerator, chapdirs: List[str] + ) -> DirTree_FromPath: + dirtree = DirTree_FromPath( + rootp=self.art_rootdir, dolevel=self.o.dolevel + ) + + dirtree.rprune( + [os.path.join(self.art_rootdir, dirname) for dirname in chapdirs] + ) + + dirtree.check_consistency() + dirtree.sort() + + return dirtree + + # --------------------------- + # -- generate doc chapters -- + # --------------------------- + + ALT_TITLES = {"Qualif": "GNATcoverage TORs"} + + def __gen_doc_contents(self: DocGenerator, diro: Dir, pathi, wi): + """Generate the RST file for the DIRO artifact/directory-object, as + part of a dirtree walk carrying a general DirTree.WalkInfo object WI + and path info PATHI""" + + filename = self.get_docfile(diro) + if not filename: + err(f"Could not get filename for {diro.get_name()}") + return + if not os.path.isdir(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + self.ofd = open(filename, "w") + + if diro.dfile(): + self.ofd.write(self.contents_from(diro)) + + if diro.tc: + self.gen_tc_section(diro) + + # close the document to measure the size + # that is more robust than trying to keep track of all the write + # operations and we can affort the small overhead of reopening it + # once more + self.ofd.close() + + # remove the document if no content was generated + if os.path.getsize(filename) == 0: + os.remove(filename) + else: + # reopen the file to add toc + self.ofd = open(filename, "a") + self.ofd.close() + + def generate_chapters(self: DocGenerator): + self.art_dirtree.walk(mode=topdown, process=self.__gen_doc_contents) + + # ---------------------------- + # -- generate resource file -- + # ---------------------------- + + def generate_resources(self: DocGenerator): + fd = open(self.docpath_to("resources.rst"), "w") + fd.write(rest.chapter("Resources")) + fd.write( + rest.toctree( + [ + file + for d in self.resource_list + if (file := self.file2docfile(d, must_exist=True)) + ] + ) + ) + fd.close() + + for r in self.resource_list: + filename = self.file2docfile(r) + if not filename: + err(f"Could not get doc filename for {r}") + return + fd = open(self.docpath_to(filename), "w") + fd.write("\n.. _%s:\n\n" % self.ref(r)) + fd.write(rest.section(os.path.basename(r))) + fd.write(rest.code_block(get_content(r), "ada")) + fd.close() + + # --------------------------------------------- + # -- generate all the document items, -- + # -- checking tree consistency along the way -- + # --------------------------------------------- + + def generate_all(self: DocGenerator): + # Compute the set of subdirs/chapters our document ought to include. + # This is the explicit list when one was provided, and a set of common + # subdirs + those of relevance for the requested criterion otherwise. + + crit_subdirs_for = { + "doC": ["stmt"], + "doB": ["stmt", "decision"], + "doA": ["stmt", "decision", "mcdc"], + } + + this_subdirs = ( + self.o.chapdirs.split(",") + if self.o.chapdirs + else ( + ["OpEnviron", "Appendix", "Common"] + + [ + os.path.join("Ada", csd) + for csd in crit_subdirs_for[self.o.dolevel] + ] + ) + ) + + self.art_dirtree = self.art_dirtree_for(this_subdirs) + + self.generate_chapters() + self.generate_resources() + + print_warn_stats() + + +# The main of the script + +valid_dolevels = ("doA", "doB", "doC") + +if __name__ == "__main__": + op = optparse.OptionParser(usage="%prog ") + + op.add_option( + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, + help=("Target DO178 qualification level."), + ) + + op.add_option( + "--chapdirs", + dest="chapdirs", + default=None, + help=("Comma separated list of chapter directories to consider"), + ) + + op.add_option( + "--force", + dest="force", + action="store_true", + default=False, + help=("Delete existing output directory if it exists and continue"), + ) + + op.add_option( + "--verbose", + "-v", + dest="verbose", + action="store_true", + default=False, + help=("Show detailed info messages"), + ) + + op.add_option( + "--testsuite-dir", + dest="testsuite_dir", + default=None, + help="Root directory of the qualification testsuite", + ) + + (options, args) = op.parse_args() + + exit_if( + not options.chapdirs and not options.dolevel, + "A DO level or a set of chapter dirs must be specified", + ) + + exit_if( + options.chapdirs and options.dolevel, + "A DO level may not be specified together with an explicit " + "set of chapter dirs.", + ) + + verbose = options.verbose + logger.current_level = ( + logger.Log_Level_Kind.DEBUG + if verbose + else logger.Log_Level_Kind.WARNING + ) + + actual_root_dir = ( + options.testsuite_dir if options.testsuite_dir else ART_ROOTDIR + ) + if not actual_root_dir.endswith("Qualif"): + actual_root_dir = os.path.join(actual_root_dir, "Qualif") + + mygen = DocGenerator( + art_rootdir=actual_root_dir, rst_rootdir=RST_ROOTDIR, options=options + ) + + mygen.generate_all() diff --git a/qualification/qualkit/tor/genrest_conf.py b/qualification/qualkit/tor/genrest_conf.py new file mode 100644 index 000000000..722d08ee4 --- /dev/null +++ b/qualification/qualkit/tor/genrest_conf.py @@ -0,0 +1,13 @@ +# configurable options of the genrest module + +# when this constant is true, genrest tries to deduce the artifact type of a +# folder that doesn't have content .rst file by looking a the subartifacts. +# In case of False, the processing stops with error if such a folder is +# encountered. + +ALLOW_UNCLASSIFIED_FOLDERS = False + +# a list of warning type patters that should be suppressed +# if there is a match, then genrest computes only the stats + +SUPRESS_MSG_TYPES = ["SRC_.*", "MISSING_DESCRITPTION_TEXT"] diff --git a/qualification/setup.sh b/qualification/setup.sh deleted file mode 100644 index 8b6ce6514..000000000 --- a/qualification/setup.sh +++ /dev/null @@ -1,107 +0,0 @@ -# Very rough script that collects the steps necessary to prepare an -# environment capable of producing the GNATcoverage qualification package -# (with genbundle.py). - -# This script usually doesn't work straight out (for example the format in -# which some of the preriquisites are archived has changed, or today's build -# of one component has failed). It provides, nevertheless, a precise idea of -# the required components and a possible way to set them up for the task. - -# The general idea is to setup a temporary work directory where we -# will have -# -# - a "PACKAGES" subdirectory, where the preriquisite components are fetched -# (binary distributions pre-packaged by gnatmail somewhere) -# -# - a "local" subdirectory, where they are all installed and that should be -# prepended to PATH to produce a qualification bundle. - -TMP=$HOME/tmp-gnatcov -mkdir $TMP || exit 1 - -# ------------------------------ -# -- fetch & install packages -- -# ------------------------------ - -# fetch - -GNATMAIL=tolbiac:/tolbiac.a/gnatmail -FTP=tolbiac:/ftpserver/art/file-view -DAILYBINDIR=$GNATMAIL/gcc-45/binaries/today/ -OS=$(uname -o) - -case $OS in - *win*) - OS=windows - HOST_GNATEMU=rostov - HOST_GNATCOV=rostov - HOST_QMACHINE=tormes - UNPACK="unzip -q" - PACKEXT="zip" - ;; - - *Linux*) - OS=linux - HOST_GNATEMU=chinon - HOST_GNATCOV=chinon - HOST_QMACHINE=chinon - UNPACK="tar xzf" - PACKEXT="tar.gz" - ;; - -esac - -PACKDIR=$TMP/PACKAGES -mkdir $PACKDIR || exit 1 - -cd $PACKDIR - -rsync $DAILYBINDIR/ppc-elf-$OS/${HOST_GNATEMU}/gnatemulator-\*.$PACKEXT . -rsync $DAILYBINDIR/x86-$OS/${HOST_GNATCOV}/gnatcoverage-\*.$PACKEXT . -rsync $DAILYBINDIR/x86-$OS/${HOST_QMACHINE}/qmachine-\*.$PACKEXT . - -rsync $GNATMAIL/svn-binaries/gnatpython/1.2/distrib/x86-$OS/gnatpython-\*.tgz . - -rsync $FTP/ada-6.4.2/ppc-elf-$OS/gnat/gnatpro-\* . - -# install - -LOCAL=$TMP/local -mkdir $LOCAL || exit 1 - -$(echo $UNPACK) gnatemulator-*.$PACKEXT -cp -rp gnatemulator-*-bin/* $LOCAL - -$(echo $UNPACK) gnatcoverage-*.$PACKEXT -cp -rp gnatcoverage-*-bin/* $LOCAL - -$(echo $UNPACK) qmachine-*.$PACKEXT -cp -rp qmachine-*-bin/* $LOCAL - -tar xzf gnatpython-*.tgz -cp -rp gnatpython-*-bin $LOCAL/gnatpython - -case $OS in - windows) - ./gnatpro-*.exe /S "/D=`cygpath -w $LOCAL`";; - - *) - tar xzf gnatpro-* - cd gnat-*bin - ./doinstall -esac - -# ------------------------------------------------ -# -- retrieve and run the material build script -- -# ------------------------------------------------ - -PATH=$LOCAL/bin:$LOCAL/gnatpython:$LOCAL/gnatpython/Scripts:$PATH - -cd $TMP - -svn export svn://scm.forge.open-do.org/scmrepos/svn/couverture/trunk/couverture/qualification/genbundle.py - -TEMP=$TMP -DATE=`date +%Y-%m-%d` -python ./genbundle.py --root-dir=$TMP/QMAT - diff --git a/testsuite/.gitignore b/testsuite/.gitignore index f6174cf15..76bf9fdee 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -1,7 +1,21 @@ -mc_* -uc_* -dc_* -st_* +d_* +datc_* +datcc_* +ddecision_* +g_* +m_* +s_* +u_* +*fc_*/ tmp_* +tmp +bin +obj1 +obj2 +devnul +gprbuild.out +__pycache__ wd_* test.py.* +.~undo-tree~ +internal-tests diff --git a/testsuite/OCOV/__init__.py b/testsuite/OCOV/__init__.py index 3543ec32b..3346078a4 100644 --- a/testsuite/OCOV/__init__.py +++ b/testsuite/OCOV/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +""" TODO -''' +""" diff --git a/testsuite/OCOV/tc.py b/testsuite/OCOV/tc.py index 5a5408d45..6ec93466e 100644 --- a/testsuite/OCOV/tc.py +++ b/testsuite/OCOV/tc.py @@ -8,8 +8,14 @@ from SUITE.context import thistest import SUITE.control from SUITE.cutils import Wdir -from SUITE.tutils import (gprbuild, gprfor, tracename_for, unixpath_to, xcov, - xrun) +from SUITE.tutils import ( + gprbuild, + gprfor, + tracename_for, + unixpath_to, + xcov, + xrun, +) # Cache some values we need repeatedly @@ -17,39 +23,40 @@ class TestCase(object): - - ROUTINES_FILE = 'routines.list' - RESULT_FILE = 'coverage.result' + ROUTINES_FILE = "routines.list" + RESULT_FILE = "coverage.result" SYMBOL_COVERAGE_PATTERN = re.compile( - '^([a-zA-Z_][a-zA-Z0-9_]*)' # Symbol name - ' ([-!+]): ' # Symbol coverage result - '[0-9a-f]+-[0-9a-f]+\n$' # Address range for the symbol + "^([a-zA-Z_][a-zA-Z0-9_]*)" # Symbol name + " ([-!+]): " # Symbol coverage result + "[0-9a-f]+-[0-9a-f]+\n$" # Address range for the symbol ) - NO_COV, PART_COV, FULL_COV = '-!+' + NO_COV, PART_COV, FULL_COV = "-!+" def __init__( self, - test_drivers, coverage_expectations, - extra_sourcedirs=[], - level='branch', annotate='asm', - extra_xcov_args=[] + test_drivers, + coverage_expectations, + extra_sourcedirs=None, + level="branch", + annotate="asm", + extra_xcov_args=None, ): self.test_drivers = test_drivers self.coverage_expectations = { TARGET_INFO.to_platform_specific_symbol(symbol): data for symbol, data in coverage_expectations.items() } - self.extra_sourcedirs = extra_sourcedirs + self.extra_sourcedirs = extra_sourcedirs or [] self.level = level self.annotate = annotate - self.extra_xcov_args = extra_xcov_args + self.extra_xcov_args = extra_xcov_args or [] def run(self, register_failure=True): - ''' + """ Return if "gnatcov coverage" executed properly. - ''' - Wdir('tmp_') + """ + Wdir("tmp_") # Compile and run separately each test driver. for test_driver, switches in self.test_drivers.items(): @@ -63,45 +70,44 @@ def run(self, register_failure=True): # Consolidate resulting traces and parse the object coverage results. # If consolidation fails, return False. if ( - not self._consolidate_traces(self.RESULT_FILE, - register_failure) and - not register_failure + not self._consolidate_traces(self.RESULT_FILE, register_failure) + and not register_failure ): return False # We can parse the result only if the output is an annotated ASM. - if self.annotate == 'asm': + if self.annotate == "asm": coverage_result = self._parse_coverage_results(self.RESULT_FILE) # Compare results with expectations... thistest.fail_if( coverage_result != self.coverage_expectations, - 'Coverage result:\n' - '{}' - 'do not match coverage expectations:\n' - '{}'.format( + "Coverage result:\n" + "{}" + "do not match coverage expectations:\n" + "{}".format( self.format_coverage(coverage_result), - self.format_coverage(self.coverage_expectations) - ) + self.format_coverage(self.coverage_expectations), + ), ) return True def _compile(self, test_driver, compile_unit_switches): - mkdir('{}-obj'.format(test_driver)) + mkdir("{}-obj".format(test_driver)) project_file = gprfor( - mains=[test_driver + '.c'], + mains=[test_driver + ".c"], prjid=test_driver, - srcdirs=['..'] + self.extra_sourcedirs, - objdir='{}-obj'.format(test_driver), - langs=['C', 'ASM'], - compiler_extra='\n'.join( - ('for Switches("{}") use ' - ' Compiler\'Default_Switches ("C") & ({});').format( - cu, self.fmt_list(switches) - ) + srcdirs=[".."] + self.extra_sourcedirs, + objdir="{}-obj".format(test_driver), + langs=["C", "ASM"], + compiler_extra="\n".join( + ( + 'for Switches("{}") use ' + ' Compiler\'Default_Switches ("C") & ({});' + ).format(cu, self.fmt_list(switches)) for cu, switches in compile_unit_switches.items() - ) + ), ) # We never want the testuite optimization options or source coverage @@ -113,18 +119,18 @@ def _run(self, test_driver): xrun(unixpath_to(test_driver)) def _generate_routines_list(self): - with open(self.ROUTINES_FILE, 'w') as f: + with open(self.ROUTINES_FILE, "w") as f: for routine in self.coverage_expectations: - f.write('{}\n'.format(routine)) + f.write("{}\n".format(routine)) def _consolidate_traces(self, output, register_failure): xcov_args = [ - 'coverage', - '--level=' + self.level, - '--annotate=' + self.annotate, + "coverage", + "--level=" + self.level, + "--annotate=" + self.annotate, ] - if self.level in ('insn', 'branch'): - xcov_args.append('--routines=@' + self.ROUTINES_FILE) + if self.level in ("insn", "branch"): + xcov_args.append("--routines=@" + self.ROUTINES_FILE) xcov_args.extend(self.extra_xcov_args) xcov_args.extend(map(tracename_for, self.test_drivers)) p = xcov(xcov_args, out=output, register_failure=register_failure) @@ -136,7 +142,7 @@ def _parse_coverage_results(self, input_file): lambda: {self.NO_COV: 0, self.PART_COV: 0, self.FULL_COV: 0} ) - with open(input_file, 'r') as f: + with open(input_file, "r") as f: for line in f: m = self.SYMBOL_COVERAGE_PATTERN.match(line) if m: @@ -146,13 +152,13 @@ def _parse_coverage_results(self, input_file): return result def fmt_list(self, items): - ''' + """ Format a list of string for the GPR file. >>> fmt_list(('a', 'b', 'c')) "a", "b", "c" - ''' - return ', '.join(['"{}"'.format(item) for item in items]) + """ + return ", ".join(['"{}"'.format(item) for item in items]) def format_coverage(self, coverage): result = [] @@ -162,6 +168,6 @@ def format_coverage(self, coverage): symbol, cov_result[self.NO_COV], cov_result[self.PART_COV], - cov_result[self.FULL_COV] + cov_result[self.FULL_COV], ) - return ''.join(result) + return "".join(result) diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb index 025294c6b..84097be42 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb @@ -1,9 +1,9 @@ pragma Unsuppress (All_Checks); pragma Check_Float_Overflow; - + package body Ops is - + function Both_Ok (A, B : Capsum) return Boolean is begin if A.X + A. Y <= A.Cap and then B.X + B.Y <= B.Cap then -- # test diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads index 7dea345ce..291b4d349 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads @@ -1,19 +1,19 @@ package Ops is - + type Constrained_Float is new Float range Float'Range; - + type Capsum is record X, Y, Cap : Constrained_Float; end record; - + Cs_Ok : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); Cs_Ko : constant Capsum := (X => 1.0, Y => 2.0, Cap => 1.0); Cs_Ov : constant Capsum := (X => Constrained_Float'Last, Y => Constrained_Float'Last, Cap => 3.0); - + N_Ok, N_Ko, N_Ov : Integer := 0; - + function Both_Ok (A, B : Capsum) return Boolean; - + end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb index 86ef863d1..ac552bb1a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb @@ -4,7 +4,7 @@ procedure Test_Ops_All is begin Assert (not Both_Ok (Cs_Ok, Cs_Ko)); Assert (Both_Ok (Cs_Ok, Cs_Ok)); - + Assert (not Both_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 1); Assert (N_Ko = 1); @@ -16,4 +16,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb index 3b6515435..61aa50aa7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb index ffe91be1c..ebc9cc558 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb @@ -3,7 +3,7 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_KoOva is begin Assert (not Both_Ok (Cs_Ok, Cs_Ko)); - + Assert (not Both_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 0); Assert (N_Ko = 1); @@ -15,4 +15,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb index f2cd21836..c2348e82a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb @@ -3,7 +3,7 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_OkOvb is begin Assert (Both_Ok (Cs_Ok, Cs_Ok)); - + Assert (not Both_Ok (Cs_Ok, Cs_Ov)); Assert (N_Ok = 1); Assert (N_Ko = 0); @@ -15,4 +15,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb index d8d2e2375..d4461f2c8 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb index beae253e8..db4973999 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb index 1bb59c25f..7b65afab6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb @@ -13,4 +13,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt index 270577407..f69ac429d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt @@ -3,4 +3,4 @@ p55-elf XFAIL Machine_Overflows True, no raise on overflow -- No urgent need for support bin-traces,RTS_ZFP XFAIL PB15-008: inaccurate decision coverage for floating-point overflow check on ZFP 5.04a1 DEAD pragma "Check-Float-Overflow" not available in 5.04, causing assertion failure -7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure \ No newline at end of file +7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb index a6de5d642..bd953d398 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb @@ -2,7 +2,7 @@ pragma Unsuppress (All_Checks); pragma Check_Float_Overflow; package body Ops is - + function One_Ok (A, B : Capsum) return Boolean is begin if A.X + A. Y <= A.Cap or else B.X + B.Y <= B.Cap then -- # test diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads index b55456af4..51dd46833 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads @@ -1,19 +1,19 @@ package Ops is - + type Constrained_Float is new Float range Float'Range; - + type Capsum is record X, Y, Cap : Constrained_Float; end record; - + Cs_Ok : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); Cs_Ko : constant Capsum := (X => 1.0, Y => 2.0, Cap => 1.0); Cs_Ov : constant Capsum := (X => Constrained_Float'Last, Y => Constrained_Float'Last, Cap => 3.0); - + N_Ok, N_Ko, N_Ov : Integer := 0; - + function One_Ok (A, B : Capsum) return Boolean; - + end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb index 760c7385d..7e33a271b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb @@ -4,7 +4,7 @@ procedure Test_Ops_All is begin Assert (not One_Ok (Cs_Ko, Cs_Ko)); Assert (One_Ok (Cs_Ok, Cs_Ok)); - + Assert (not One_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 1); Assert (N_Ko = 1); @@ -16,4 +16,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb index 3f0fa68de..112fb9c60 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb index 53ce48f32..29ed0931a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb @@ -3,7 +3,7 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_KoOva is begin Assert (not One_Ok (Cs_Ko, Cs_Ko)); - + Assert (not One_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 0); Assert (N_Ko = 1); @@ -15,4 +15,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb index d1320042e..e09946a26 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb @@ -3,11 +3,11 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_OkOvb is begin Assert (One_Ok (Cs_Ok, Cs_Ko)); - + Assert (One_Ok (Cs_Ok, Cs_Ov)); - + -- The overflow is shortcircuited - + Assert (N_Ok = 2); Assert (N_Ko = 0); Assert (N_Ov = 0); @@ -18,4 +18,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb index 664d55099..163cc5810 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb index 67e4276c3..90b939c0e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb @@ -4,7 +4,7 @@ procedure Test_Ops_Ovb is begin -- We must put a Ko first to evaluate the overflow Assert (not One_Ok (Cs_Ko, Cs_Ov)); - + Assert (N_Ok = 0); Assert (N_Ko = 0); Assert (N_Ov = 1); @@ -15,4 +15,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb index 902119e53..8ed1d167f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb @@ -13,4 +13,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt index 270577407..f69ac429d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt @@ -3,4 +3,4 @@ p55-elf XFAIL Machine_Overflows True, no raise on overflow -- No urgent need for support bin-traces,RTS_ZFP XFAIL PB15-008: inaccurate decision coverage for floating-point overflow check on ZFP 5.04a1 DEAD pragma "Check-Float-Overflow" not available in 5.04, causing assertion failure -7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure \ No newline at end of file +7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb index 9d885b03a..cf83313e3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb @@ -2,9 +2,9 @@ with Support; use Support; with System; package body Fuand is - + use type System.Address; - + function Eval (R1, R2 : Integer) return Boolean is begin if R1+R2 > 12 -- # eval0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads index 9bea05e8b..826971c6e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + Data : array (1 .. 32) of Integer := (others => 0); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 > 12 and then data(R1)'address < data(R2)'address R1 : Integer := 8; - R2_FX : Integer := 1; - R2_TF : Integer := 5; + R2_FX : Integer := 1; + R2_TF : Integer := 5; R2_TT : Integer := 9; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads index e98f3169d..bbe502dfa 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads @@ -10,6 +10,3 @@ package Fuor is R2_FT : String := "12345"; R2_TX : String := "123"; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb index 931458e90..bcf29f55b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb @@ -4,8 +4,8 @@ package body FUAND is begin if Ops.A and then Ops.B then -- # eval0 return True; -- # true - else + else return False; -- # false - end if; + end if; end; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads index 63f4b769b..091b757e8 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads @@ -1,11 +1,11 @@ with System; use System; package FUAND is - + type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use High_Order_First; for Operands use record A at 0 range 0 .. 0; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb index bb7725fe7..039ed052d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb index b69213d60..89a1a7cb7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb @@ -4,8 +4,8 @@ package body FUOR is begin if Ops.A or else Ops.B then -- # eval0 return True; -- # true - else + else return False; -- # false - end if; + end if; end; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads index 257c98b30..c6c879f3f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads @@ -4,7 +4,7 @@ package FUOR is type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use Low_Order_First; for Operands use record A at 0 range 0 .. 0; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb index 3a68afb21..0138e1c5d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads index adbb90bc1..64064bd2a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads @@ -1,24 +1,24 @@ with Ada.Unchecked_Conversion; package FUAND is - + type Rint is new Integer range 1 .. 5; for Rint'Size use 32; - + function To_Rint is new Ada.Unchecked_Conversion (Integer, Rint); - - Values : array (1 .. 3) of Rint := + + Values : array (1 .. 3) of Rint := (1 => To_Rint(1), -- valid 2 => To_Rint(999), -- invalid 3 => To_Rint(1) -- valid - ); - + ); + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 > 1 and then Values(R1+R2)'Valid R1 : Integer := 1; - R2_FX : Integer := 0; + R2_FX : Integer := 0; R2_TF : Integer := 1; R2_TT : Integer := 2; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads index c6b620cce..e2181bcd6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads @@ -1,26 +1,26 @@ package FUAND is - + type Bitmap is array (1 .. 32) of Boolean; - + BM1 : Bitmap := (1 .. 16 => False, 17 .. 32 => True); -- 00000000000000001111111111111111 - + BM2 : Bitmap := (1 .. 8 => False, 9 .. 16 => True, 17 .. 24 => False, 25 .. 32 => True); -- 00000000111111110000000011111111 - + function Eval (R1, R2 : Integer) return Boolean; - + -- BM1(R1+R2) and then BM2(R1+R2) R1 : Integer := 1; - R2_FX : Integer := 0; - R2_TF : Integer := 15; + R2_FX : Integer := 0; + R2_TF : Integer := 15; R2_TT : Integer := 30; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads index 496626cfb..dd3edb927 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit_Pair is record Bit0, Bit1 : Boolean; end record; - - Values : array (0 .. 3) of Bit_Pair := + + Values : array (0 .. 3) of Bit_Pair := (0 => (Bit1 => False, Bit0 => False), 1 => (Bit1 => False, Bit0 => True), 2 => (Bit1 => True, Bit0 => False), 3 => (Bit1 => True, Bit0 => True)); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether Values(R1+R2).Bit0 and then Values(R1+R2).Bit1 @@ -17,7 +17,7 @@ package FUAND is R1 : Integer := 0; - R2_FX : Integer := 0; + R2_FX : Integer := 0; R2_TF : Integer := 1; R2_TT : Integer := 3; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/customdef.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/customdef.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/customdef.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/customdef.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads index 00ee631b5..7f1a4378b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads @@ -1,10 +1,10 @@ package FUAND is - + type Value_T is (FF, TT); - + type Operands is record A, B : Value_T; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb index 9ff1337bd..5dcc3f01d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF, FF))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb index 4f814764b..5f9dde606 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb @@ -4,7 +4,7 @@ package body FUOR is begin if Ops.A = TT or else Ops.B = TT then -- # eval0 return True; -- # true - else + else return False; -- # false end if; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads index 284ec0f6e..5064af98f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads @@ -1,11 +1,11 @@ package FUOR is - + type T_Values is (TT, FF); for T_Values use (4, 5); - + type Operands is record A, B : T_Values; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb index df4a340ba..e4a7a5c19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads index f2a8d5a81..c75860991 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb index 9ff1337bd..5dcc3f01d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF, FF))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads index 72fa89695..e282aed19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb index df4a340ba..e4a7a5c19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads index b4cc48de7..8c7083925 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - - type My_Float is digits 10 range -5.0 .. 5.0; - + + type My_Float is digits 10 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb index 9ff1337bd..5dcc3f01d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF, FF))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads index ff6ec9867..1d8a3fc95 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - - type My_Float is digits 8 range -5.0 .. 5.0; - + + type My_Float is digits 8 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb index df4a340ba..e4a7a5c19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads index 0ca4b9693..2f9504372 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads @@ -1,23 +1,23 @@ package FUAND is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Ref is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Ref; end record; - + -- We will evaluate for each operand whether .data(.index) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUAND is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Ref := (Index => 602, Data => Common_Data); TT2 : constant Ref := (Index => 605, Data => Common_Data); FF1 : constant Ref := (Index => 600, Data => Common_Data); FF2 : constant Ref := (Index => 607, Data => Common_Data); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb index fce9311a4..0211ee80e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF1, TT1))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb index 3bf43fde8..3261f7865 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb @@ -1,5 +1,5 @@ package body FUOR is - + function Orelse (Ops : Operands) return Boolean is A : Ref renames Ops.A; -- # decl B : Ref renames Ops.B; -- # decl diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads index 7052dc3b7..a12b91c91 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads @@ -1,23 +1,23 @@ package FUOR is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Ref is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Ref; end record; - + -- We will evaluate for each operand whether .data(.index) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUOR is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Ref := (Index => 602, Data => Common_Data); TT2 : constant Ref := (Index => 605, Data => Common_Data); FF1 : constant Ref := (Index => 600, Data => Common_Data); FF2 : constant Ref := (Index => 607, Data => Common_Data); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb index 5238fd950..55cdd1d4c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads index 63178caeb..7e6fe26db 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads @@ -1,20 +1,20 @@ package FUAND is - + type Bit4 is mod 2 ** 4; for Bit4'Size use 4; - + type Bitmap is array (1 .. 8) of Bit4; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 4 => 0, 5 .. 8 => 7); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; - -- data(R1.X + R2.X) > 5 and then data(R1.Y + R2+Y) > 5 - + -- data(R1.X + R2.X) > 5 and then data(R1.Y + R2+Y) > 5 + R1 : XY := (X => 1, Y => 1); R2_FX : XY := (X => 0, Y => 1); -- data(1+0) = 0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads index b2396eb58..e75d9f84c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads @@ -1,13 +1,13 @@ package FUBOOL is - + type Bit4 is mod 2 ** 4; for Bit4'Size use 4; - + type Bitmap is array (1 .. 8) of Bit4; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 4 => 0, 5 .. 8 => 7); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) > 5 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads index 517e62691..3e9bd0e79 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads @@ -1,12 +1,12 @@ package FUAND is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb index 7e7cfe343..c249cbf06 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -18,4 +18,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads index 5e9091817..fb411c6d2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads @@ -1,12 +1,12 @@ package FUOR is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb index 2d320f623..490338002 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb index 0359ed17e..302a242b0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb @@ -3,16 +3,16 @@ pragma Ada_2012; with Support; use Support; package body Ops is - + type T_Status is tagged record A : T_Action; W : T_What_Ahead; end record; - + type T_Qualified_Status is new T_Status with record Ss : T_Safety_Status; end record; - + function Q1 (S : T_Status) return T_Safety_Status is begin if S.A = Step and then S.W = Pit then -- # test @@ -21,7 +21,7 @@ package body Ops is return Safe; -- # safe end if; end; - + procedure Q2 (S : T_Status; Ss : out T_Safety_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -30,7 +30,7 @@ package body Ops is Ss := Safe; -- # safe end if; end; - + procedure Q3 (S : in out T_Qualified_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -39,7 +39,7 @@ package body Ops is S.Ss := Safe; -- # safe end if; end; - + function Q4 (S : in out T_Qualified_Status) return Integer is begin if S.A = Step and then S.W = Pit then -- # test @@ -49,26 +49,26 @@ package body Ops is end if; return 0; end; - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status is S1 : T_Safety_Status; begin S1 := Q1 ((A, W)); - + declare S2 : T_Safety_Status; begin Q2 ((A, W), S2); Assert (S2 = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); begin Q3 (QS); Assert (QS.Ss = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); X : Integer; @@ -79,5 +79,5 @@ package body Ops is return S1; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads index d1b21c4f8..c206f1d87 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads @@ -1,9 +1,9 @@ package Ops is - + type T_Action is (Hold, Step); type T_What_Ahead is (Ground, Pit); - + type T_Safety_Status is (Safe, Unsafe); - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads index 99586867f..1a0a71874 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 32) := (1 .. 16 => 0, 17 .. 32 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads index 76b6554ed..3e7c063a0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 32) := (1 .. 16 => 0, 17 .. 32 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads index f035e8c96..539d5b6c1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads @@ -1,15 +1,15 @@ package FUOR is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 32) := (1 .. 16 => 0, 17 .. 32 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 or else data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads index eb62a23fd..ddaefd325 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 1024) := (1 .. 512 => 0, 513 .. 1024 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads index e15ba4b40..cc7b3b9b6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 1024) := (1 .. 512 => 0, 513 .. 1024 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads index d0105be4d..1340d70d7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => 0, 17 .. 32 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads index e4bfbc99a..78dd6bbfc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => 0, 17 .. 32 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads index 304697743..845837b52 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads @@ -1,17 +1,17 @@ with Params; package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. Params.Mapsize) := (1 .. 16 => 0, others => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads index e4bfbc99a..78dd6bbfc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => 0, 17 .. 32 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads index ee8886285..0046da938 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads index cd6dfd2a4..e6b830cc7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads index 473b7f2b9..f5ad9b5d6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads @@ -1,18 +1,18 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (1 .. 32) of Bit; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- indexes 1 to 16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -- indexes 17 to 32 ); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads index c5949c605..c895c35f3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads @@ -1,14 +1,14 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (1 .. 32) of Bit; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- indexes 1 to 16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -- indexes 17 to 32 ); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads index b8aee83a4..eeb86e085 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (1 .. 1024) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads index 383c45244..1811531ad 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (1 .. 1024) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads index f61ba46f4..188f292ed 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads @@ -1,14 +1,14 @@ package FUAND is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) and then data(R1.Y + R2+Y) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads index 77d816c25..3aff021f0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads @@ -1,10 +1,10 @@ package FUBOOL is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = True diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads index 482f3b392..fb6c936e9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads @@ -1,7 +1,7 @@ package FUAND is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUAND is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb index fe846109e..ddbfbfcdd 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads index 519fdf48a..f78d01831 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads @@ -1,7 +1,7 @@ package FUOR is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUOR is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb index 2d320f623..490338002 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads index cf8ee58e4..c08e21d7f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads @@ -1,10 +1,10 @@ package FUAND is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + function Eval (R1, R2 : Integer) return Boolean; -- R1 + R2 is even and then data(R1 + R2) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads index e017cde5b..753d7e9ce 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads @@ -1,10 +1,10 @@ package FUOR is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + function Eval (R1, R2 : Integer) return Boolean; -- data(R1 + R2) or else R1 + R2 is even diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads index 833f3de04..0059203b0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads @@ -1,24 +1,24 @@ package FUAND is - + type Bit is mod 2; for Bit'Size use 1; - + type Bits is record Bit0, Bit1 : Bit; end record; for Bits'Size use 2; pragma Pack (Bits); - + type Bitmap is array (1 .. 16) of Bits; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (1 .. 4 => (Bit0 => 0, Bit1 => 0), 5 .. 8 => (Bit0 => 0, Bit1 => 1), 9 .. 12 => (Bit0 => 1, Bit1 => 0), 13 .. 16 => (Bit0 => 1, Bit1 => 1) ); - + function Eval (R1, R2 : Integer) return Boolean; -- data(R1+R2).bit0 is set and then data(R1+R2).bit1 is set diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads index c9f01cc6d..8996c8737 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads @@ -1,22 +1,22 @@ package FUBOOL is - + type Bit is mod 2; for Bit'Size use 1; - + type Bits is record Bit0, Bit1 : Bit; end record; for Bits'Size use 2; pragma Pack (Bits); - + type Bitmap is array (1 .. 16) of Bits; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (1 .. 8 => (Bit0 => 0, Bit1 => 0), 9 .. 16 => (Bit0 => 1, Bit1 => 0) ); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2).bit0 = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb index e77ca057b..b2a996e6c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb @@ -1,9 +1,9 @@ with Support; use Support; package body Fuand is - + type Conflict is (False, True); -- like Boolean - + function Eval (R1, R2 : Integer) return Boolean is begin if Boolean'(R1+R2 > 10) -- # eval0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads index 6b4b43936..26286601b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads @@ -3,7 +3,7 @@ package FUAND is function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 > 10 and then R1 < R2 - + R1 : Integer := 8; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads index 29ef99459..1134f22d6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads @@ -1,5 +1,5 @@ package FUOR is - + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 is in 1 .. 10 or else R1+R2 is in 20 .. 30 @@ -7,8 +7,8 @@ package FUOR is R1 : Integer := 7; - R2_FF : Integer := 8; - R2_FT : Integer := 15; + R2_FF : Integer := 8; + R2_FT : Integer := 15; - R2_TX : Integer := 2; + R2_TX : Integer := 2; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads index 89d8b75cf..8fe81ba55 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads @@ -1,8 +1,8 @@ package FUAND is - + subtype RangeP is Integer range 10 .. 15; subtype RangeM is Integer range 1 .. 5; - + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 is in RangeP and then R1-R2 is in RangeM diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads index 905dea8e0..09aeb01f7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads @@ -4,20 +4,20 @@ pragma Ada_2012; -- yielding Integer values. package FUAND is - - type Op_Name is (Op_A, Op_B); - + + type Op_Name is (Op_A, Op_B); + type Operands is tagged record A, B : aliased Integer; end record with Variable_Indexing => V_Indexing; - + type Integer_Ref (Ref : access Integer) is null record with Implicit_Dereference => Ref; - + function V_Indexing (X : aliased in out Operands; Op : Op_Name) - return integer_Ref is + return integer_Ref is (Ref => (case Op is when OP_A => X.A'Access, diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb index 2bc6ba4c4..6b7a59c92 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((A => 0, B => 0))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads index 09b72c2b4..d52458917 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads @@ -1,20 +1,20 @@ pragma Ada_2012; package FUOR is - - type Op_Name is (Op_A, Op_B); - + + type Op_Name is (Op_A, Op_B); + type Operands is tagged record A, B : Float; end record with Constant_Indexing => C_Indexing; - + function C_Indexing (X : aliased Operands'Class; Op : Op_Name) - return Float is + return Float is (case Op is when Op_A => X.A, when Op_B => X.B); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb index 092f74b86..a9a489e4a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb index 4298904a1..31bec0eac 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb @@ -6,15 +6,15 @@ package body FUAND_Helper is begin Assert (Fuand.Eval (R1, R2_FX) = False); end; - + procedure Eval_TF_F is begin - Assert (Fuand.Eval (R1, R2_TF) = False); + Assert (Fuand.Eval (R1, R2_TF) = False); end; - + procedure Eval_TT_T is begin - Assert (Fuand.Eval (R1, R2_TT) = True); + Assert (Fuand.Eval (R1, R2_TT) = True); end; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb index 8c27384ae..ae1b6dce9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb @@ -6,7 +6,7 @@ package body FUBOOL_Helper is begin Assert (Fubool.Eval (R1, R2_F) = False); end; - + procedure Eval_T is begin Assert (Fubool.Eval (R1, R2_T) = True); diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_0.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_0.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_0.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_f.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_f.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_f.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fu.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fu.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fu.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fu.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fx.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fx.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fx.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fx.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_t.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_t.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_t.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_tf.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_tf.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_tf.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb index 2eafcbe5e..e530fc14c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb @@ -17,4 +17,3 @@ end; -- %tags:7.1.2 -- =/decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb index 00ba67c2f..ece4a16c5 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb @@ -11,4 +11,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb index be1837f59..f50c64f5b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb @@ -12,5 +12,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb index eab135f5d..09dde96d0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb @@ -11,4 +11,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb index 1ca4a644e..07244e366 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb @@ -11,5 +11,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb index ce04ba31b..f1b08f0ba 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb @@ -10,5 +10,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb index 67904595e..9ea9482bc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb @@ -9,5 +9,3 @@ end; -- /eval0/ l- ## s- -- /true/ l- ## s- -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb index 4fa4c652c..0264ec8a0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb @@ -9,5 +9,3 @@ end; -- /eval0/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb index 23131973f..aa06c4eb3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb @@ -9,5 +9,3 @@ end; -- /eval0/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb index 978cda77b..ebb7994fc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb @@ -10,5 +10,3 @@ end; -- /eval0/ l+ ## 0 -- /true/ l+ ## 0 -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb index 5f64d9e7c..ce61ab7a7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb @@ -12,4 +12,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb index f4639db04..a46e8368c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb @@ -11,5 +11,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb index c757331fb..2bce417cc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb @@ -10,4 +10,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l- ## s- -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb index d0b3d742f..8926024b9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb @@ -11,4 +11,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb index 144c200cf..26fea25c9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb @@ -17,6 +17,3 @@ package body Andthen is return F (A, B, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb index bdaf36884..c13d3c738 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb @@ -8,6 +8,3 @@ package body Andthen is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb index c816b80fc..4610672db 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb @@ -5,6 +5,3 @@ package body Andthen is return (if A and then B then True else False); -- # andthen :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb index 1cd7de2e8..5e503d125 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb @@ -7,6 +7,3 @@ package body Andthen is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb index 60bad65cf..eb85fc9a1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb @@ -8,6 +8,3 @@ package body Andthen is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb index f2756ce8d..01cf80ba6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb @@ -11,4 +11,3 @@ end; -- /retTrue/ l- ## s- -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb index 513ba788b..a7aec5128 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb @@ -17,4 +17,3 @@ package body Flip is return Doflip (X, Bomb => Identity(False)); -- # returnVal end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb index a9b7ac969..f843fe926 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb @@ -8,4 +8,3 @@ package body Flip is end if; end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb index d6175794d..2d6533c3c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb @@ -5,4 +5,3 @@ package body Flip is return (if not X then True else False); -- # ifx-eval :o/d: end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb index 104bc2b8a..771cbe582 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb @@ -7,4 +7,3 @@ package body Flip is return False; -- # returnFalse end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb new file mode 100644 index 000000000..d6befcfba --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb @@ -0,0 +1,18 @@ +pragma Debug_Policy (Check); + +with Support; use Support; + +package body Pval is + function F (X : Boolean) return Boolean is + Res : Boolean := False; -- # true + + procedure Set_Res_True is + begin + Res := True; -- # false + end Set_Res_True; + + begin + pragma Debug (Identity (not X), Set_Res_True); -- # eval + return Res; -- # ret + end F; +end Pval; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads new file mode 100644 index 000000000..39b9ab7f1 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads @@ -0,0 +1,3 @@ +package Pval is + function F (X : Boolean) return Boolean; +end Pval; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb index 54995c862..c06c62e22 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb @@ -3,14 +3,10 @@ with Support, Pval; use Support, Pval; procedure Test_Pval_0 is begin Assert (True); -end; - ---# pval.ads --- /eval/ l- ## s- +end Test_Pval_0; --# pval.adb --- /__l!d!/ l- ## s- --- /eval/ l- ## s- --- /returnTrue/ l- ## s- --- /returnFalse/ l- ## s- --- /returnVal/ l- ## s- +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /ret/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb index 0c73f2c12..d03986b11 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb @@ -3,13 +3,16 @@ with Support, Pval; use Support, Pval; procedure Test_Pval_F is begin Assert (F (False) = True); -end; - ---# pval.ads --- /eval/ l! ## o! +end Test_Pval_F; --# pval.adb --- /eval/ l! ## o! --- /returnTrue/ l+ ## 0 --- /returnFalse/ l- ## s- --- /returnVal/ l+ ## 0 +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /val/ l+ ## 0 + +-- Decision coverage with bin traces is imprecise on simple expressions + +-- %opts: --trace-mode=bin +-- +-- =/eval/ l! ## d! diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb index d69d07563..b3a95fafa 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb @@ -1,17 +1,18 @@ -with Support, Silent_Last_Chance, Pval; use Support, Pval; +with Support, Pval; use Support, Pval; procedure Test_Pval_T is begin Assert (F (True) = False); -exception - when others => null; -end; - ---# pval.ads --- /eval/ l! ## o! +end Test_Pval_T; --# pval.adb --- /eval/ l! ## o! --- /returnTrue/ l- ## s- --- /returnFalse/ l- ## s- --- /returnVal/ l- ## s- +-- /eval/ l! ## dT- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /val/ l+ ## 0 + +-- Decision coverage with bin traces is imprecise on simple expressions + +-- %opts: --trace-mode=bin +-- +-- =/eval/ l! ## d! diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb index 4aae54331..ff28f6a50 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb @@ -1,18 +1,13 @@ -with Support, Silent_Last_Chance, Pval; use Support, Pval; +with Support, Pval; use Support, Pval; procedure Test_Pval_TF is begin Assert (F (False) = True); Assert (F (True) = False); -exception - when others => null; -end; - ---# pval.ads --- /eval/ l+ ## 0 +end Test_Pval_TF; --# pval.adb --- /eval/ l+ ## 0 --- /returnTrue/ l+ ## 0 --- /returnFalse/ l+ ## 0 --- /returnVal/ l+ ## 0 +-- /eval/ l+ ## 0 +-- /set_true/ l+ ## 0 +-- /set_false/ l+ ## 0 +-- /ret_val/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst new file mode 100644 index 000000000..09dbbe139 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst @@ -0,0 +1 @@ +**DC on a negated single-value expression in a pragma** diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst deleted file mode 100644 index c11cf3760..000000000 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst +++ /dev/null @@ -1,8 +0,0 @@ -Check DC on a negated single-value expression in various Pragma contexts -======================================================================== -| -.. qmlink:: TCIndexImporter - - * - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.opt new file mode 100644 index 000000000..cfce9a434 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.opt @@ -0,0 +1 @@ +gnatcov-25 DEAD Support for debug pragma was introduced in 26 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.py b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.py old mode 100755 new mode 100644 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb index 5f830b49b..f8e957e31 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb @@ -8,4 +8,3 @@ package body Flip is return False; -- # returnFalse end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads index 864886c64..76ac8416e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads @@ -1,4 +1,3 @@ package Flip is function F (X : Boolean) return Boolean; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb index 2c89f7c99..93a590f34 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb @@ -20,6 +20,3 @@ package body Orelse is return F (A, B, X => Support.Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb index ac0fe1efb..f86d8ed93 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb @@ -8,6 +8,3 @@ package body Orelse is return True; -- # retTrue end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb index 6cf273c87..95391f41f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb @@ -8,6 +8,3 @@ package body Orelse is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb index c8a4244ea..097259f98 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb @@ -5,6 +5,3 @@ package body Orelse is return (if A or else B then True else False); -- # orelse :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb index 24fe7f3c6..7ae3a8210 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb @@ -7,6 +7,3 @@ package body Orelse is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb index 81ec0134f..136c160bf 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb @@ -7,6 +7,3 @@ package body Orelse is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb index 06d7efbad..7bbe03119 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb @@ -8,4 +8,3 @@ package body Value is return False; -- # returnFalse end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads index 026f0f2ed..f9c0a8c47 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads @@ -1,4 +1,3 @@ package Value is function F (X : Boolean) return Boolean; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb index 3e070b3dd..56218b8b2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb index 30a67639f..e886733ed 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb index df9e34d8e..d6120dc1e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb index 2b1b239e4..f9e2a7c5f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb index 6a59ea564..e1badcb77 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb index 0453702a3..75ec0501d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb index 0ee1c22b8..d4dc466af 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb index f82e77907..cd664548b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb index 5d3b8a416..e4488cb26 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb index b79af4d55..deb835e2d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb index 492c0c0cc..73fdf2106 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb index 373f815dc..d509b184e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb index 92f48c406..aa79631bc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb index dd6e5f71f..65d09c012 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb index e46f5fb9f..7167312aa 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb index d508abec1..f3c527499 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb index 8d1a8ffab..ce5cfe612 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb @@ -11,4 +11,3 @@ end; -- /retTrue/ l- ## s- -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb index 539096465..055bd0287 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb @@ -20,6 +20,3 @@ package body Expr is return F (A, B, X => Support.Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb index b4d4819a0..4f13d660c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return True; -- # retTrue end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb index 3ee067f1d..81ce98b85 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb index b364b7027..7cadc7768 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb index c7beada48..719230c63 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb index fa8b205ff..bd0cd0ff7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb index f951443bb..d526a2aa1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb index 4e672a696..f588ae3d3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb index 6eb51cca6..da872875a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb index 116d370a0..7cda7a558 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb index 4621dc66c..7cddf34c9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb index 55a2c7262..b7c2b132c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb index 88c24f381..1e088ea9e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb index b80073715..5e7b93860 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb index 15ca8f019..a3dfb3c63 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb index a1173b427..6321d2381 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb index 19649cc24..cc6fff34a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst new file mode 100644 index 000000000..c33d664f5 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst @@ -0,0 +1,6 @@ +Check DC on various expressions form involving non-short-circuiting operators in various contexts +================================================================================================= + +.. qmlink:: TCIndexImporter + + * diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb index 68eae5b1f..111248266 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb index efa0da511..c8b29c237 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for all I in Irange => (AA(I) and then BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb index 94a058677..f1ec1e831 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for some I in Irange => (AA(I) and then BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb index a9c931691..376da95ee 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb index 6bf32bf2e..063138b6a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb @@ -5,6 +5,3 @@ package body Expr is return (if (A and then B) or else (C and then D) then True else False); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb index f01127db1..e687fb3b2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb index 8734c18e8..7781522e7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb index 4a3de9d07..1c4bf6627 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb index 876f4242a..923eeeb3f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for all I in Irange => (AA(I) and then BB(I)) or else (CC(I) or else DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb index a46335981..46fe7e02c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for some I in Irange => (AA(I) and then BB(I)) or else (CC(I) or else DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb index 4a3992d12..eedb5d671 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb index 4dd1ec741..aad0a2dce 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb @@ -5,6 +5,3 @@ package body Expr is return (if (A and then B) or else (C or else D) then True else False); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb index 5186e4ee5..2acbc06e3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb index 6c74f7806..3c3326a07 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb index 6538efd1b..b9a392db1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb index 6c552fe43..cdc267da2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for all I in Irange => (AA(I) or else BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb index c3e7c1a96..543bc5b82 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for some I in Irange => (AA(I) or else BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb index f4d126afc..ced89eeb2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb index 6ddf23948..227c1c804 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb index ae1176e2d..8f967369a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/req.rst b/testsuite/Qualif/Ada/decision/1_Core/req.rst index 0fcbc5d75..e2254d79d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/req.rst +++ b/testsuite/Qualif/Ada/decision/1_Core/req.rst @@ -4,8 +4,6 @@ Core DC requirements Core expectations for Decision Coverage (DC) assessments. All the other DC-related sections rely on this one. -%REQ_ID% - For Decision Coverage assessments, the tool processes as decisions the following set of expressions: diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb index 387619312..69320002d 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb @@ -4,11 +4,11 @@ pragma Assertion_Policy (Ignore); package body Ops is - + procedure Latch_X (X : Integer) is begin Last_X := X; -- # stmt Latches := Latches + 1; -- # stmt pragma Assert (Latches > 0); -- # assert - end; + end; end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads index 8b7423984..72f1bd702 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads @@ -1,8 +1,8 @@ package Ops is Latches : Integer := 0; - + Last_X : Integer := -1; - + procedure Latch_X (X : Integer); - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb index 6af4362d7..6ec4bd5c3 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb @@ -9,4 +9,3 @@ end; --# ops.adb -- /stmt/ l+ ## 0 -- /eval/ l. ## 0 - diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb index e467dae65..59680d89a 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb @@ -1,6 +1,6 @@ package body Ops is - + procedure Check (P : T_Pair) is begin if P.X > 0 then -- # test_pos diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads index a7ff22986..92a1cf8bd 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads @@ -2,13 +2,13 @@ pragma Ada_12; pragma Assertion_Policy (Dynamic_Predicate => Disable); package Ops is - + type T_Pair is record X, Y : Integer; end record with Dynamic_Predicate => T_Pair.X > 0 and then T_Pair.Y > T_Pair.X; -- # check - + N_Positives : Integer := 0; - + procedure Check (P : T_Pair); end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb index 032d8ad31..9184b3d5c 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb @@ -1,6 +1,6 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -9,5 +9,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads index 0cb4b6346..a843e1ebf 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads @@ -3,11 +3,11 @@ pragma Ada_12; with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Post => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Post => (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb index 032d8ad31..9184b3d5c 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb @@ -1,6 +1,6 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -9,5 +9,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads index 6cb886e69..1687bf3f9 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads @@ -3,11 +3,11 @@ pragma Ada_12; with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Post => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Post'Class => (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb index cfd13b8c2..08ffdb314 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb @@ -1,5 +1,5 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -8,5 +8,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads index 1137e4905..5e23e6ebc 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads @@ -3,11 +3,11 @@ pragma Ada_12; with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Pre => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Pre => (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb index 947d2f051..1081e635b 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb @@ -1,14 +1,14 @@ pragma Ada_12; package body Ops is - + pragma Assertion_Policy (Pre => Disable); - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is - + procedure Perform (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Pre => (A.Valid and then B.Valid); -- # cond - + procedure Perform (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin @@ -21,5 +21,5 @@ package body Ops is begin Perform (Op, A, B); end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads index 8c7d20034..2d7f1373b 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads @@ -1,8 +1,8 @@ with Optypes; use Optypes; package Ops is - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand); end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb index cfd13b8c2..08ffdb314 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb @@ -1,5 +1,5 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -8,5 +8,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads index 26ff26852..c8d0d89d3 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads @@ -1,11 +1,11 @@ with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Pre => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand); - pragma Pre (A.Valid and then B.Valid); -- # cond + pragma Precondition (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst index d7adc3cac..cb7f81c79 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst @@ -1,3 +1,3 @@ -**DC on a library level subpgrogram with a disabled Pre pragma** +**DC on a library level subpgrogram with a disabled Precondition pragma** LRMREF: 11.4.2, 6.1.1 diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads index 54c424c4e..8ef3a5d86 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads @@ -3,6 +3,6 @@ package Optypes is Valid : Boolean := False; Value : Integer; end record; - + type T_Operation is (Op_Add, Op_Sub); end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb index 9d8484e0e..66624ec95 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb @@ -3,7 +3,7 @@ pragma Ada_12; with Support; use Support; package body Ops is - + pragma Assertion_Policy (Static_Predicate => Disable); function Wpos (D : T_Day) return T_Wpos is @@ -19,23 +19,23 @@ package body Ops is return Mid; -- # mid end if; end; - + procedure Check_Early (D : T_Day) is ED : Early_Day := D; -- # check_early begin Assert (Wpos (ED) = Early); -- # check_early end; - + procedure Check_Late (D : T_Day) is ED : Late_Day := D; -- # check_late begin Assert (Wpos (ED) = Late); -- # check_late end; - + procedure Check_Mid (D : T_Day) is ED : Mid_Day := D; -- # check_mid begin Assert (Wpos (ED) = Mid); -- # check_mid end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads index c6e297b91..ebd54323d 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads @@ -2,22 +2,22 @@ pragma Ada_12; pragma Assertion_Policy (Static_Predicate => Disable); package Ops is - + type T_Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); - + subtype Early_Day is T_Day with Static_Predicate => Early_Day in Monday | Tuesday | Wednesday; -- # check-early - + subtype Mid_Day is T_Day with Static_Predicate => Mid_Day = Thursday; -- # check-mid - + subtype Late_Day is T_Day with Static_Predicate => Late_Day in Friday | Saturday | Sunday; -- # check-late - + type T_Wpos is (Early, Mid, Late); function Wpos (D : T_Day) return T_Wpos; - + procedure Check_Early (D : T_Day); procedure Check_Mid (D : T_Day); procedure Check_Late (D : T_Day); diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb index 7baa084be..f57186976 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb @@ -1,17 +1,17 @@ package body Ops is - + function I_Check (V : T_Value) return Boolean is begin return V.N_Sets >= 0; -- # check end; - + procedure Set (I : in out T_Int; V : Integer; Count : Boolean) is begin I.Value := V; -- # stmt - + if Count then -- # test_count I.N_Sets := I.N_Sets + 1; -- # count end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads index c48d8011d..22fc3d02e 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads @@ -1,26 +1,26 @@ pragma Ada_2012; -pragma Assertion_Policy (Invariant => Disable); +pragma Assertion_Policy (Type_Invariant'Class => Disable); package Ops is - + type T_Value is tagged private with Type_Invariant'Class => I_Check(T_Value); - + function I_Check (V : T_Value) return Boolean; - + type T_Int (UB : Integer) is new T_Value with Private; - + procedure Set (I : in out T_Int; V : Integer; Count : Boolean); private - + type T_Value is tagged record N_Sets : Integer := 0; end record; - + type T_Int (UB : Integer) is new T_Value with record Value : Integer := UB; end record with Type_Invariant => (T_Int.Value <= T_Int.UB); - + end; diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads b/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads index 10f4386a7..a16b1dbf7 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads @@ -7,4 +7,3 @@ function Andthen (A, B : Boolean) return Boolean; -- F X F v0 -- T F F v1 -- T T T v2 - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb index d2d4f9615..6f116cde9 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb @@ -11,5 +11,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb index 7d47309bb..d00da6530 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb @@ -9,5 +9,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb index c5b3dcfc8..c9f5f8470 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb @@ -9,5 +9,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads index 5427b6c78..37fd01550 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads @@ -7,4 +7,3 @@ function Orelse (A, B : Boolean) return Boolean; -- F F F v0 -- F T T v1 -- T X T v2 - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb index 5d154e86c..5dc0a506c 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb @@ -9,5 +9,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb index 353f864ca..45869bb9e 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb @@ -9,4 +9,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb index 2170bfab5..f154372c4 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb @@ -11,5 +11,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/req.rst b/testsuite/Qualif/Ada/decision/Consolidation/req.rst index 8d40923b5..698c6f1eb 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/req.rst +++ b/testsuite/Qualif/Ada/decision/Consolidation/req.rst @@ -1,8 +1,6 @@ DC requirements for the combination of multiple execution traces ================================================================ -%REQ_ID% - When the coverage achieved by multiple execution traces is evaluated, a decision coverage violation shall only be reported when it would have been reported for each trace individually. diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt index a779144f4..8bb367943 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt @@ -4,10 +4,12 @@ drivers=_overlap|_no_overlap -- Exempted precondition evaluated True only. raise not covered. --# ranges.adb --- /checkValid/ l! ## dT- --- /assignValid/ l+ ## 0 --- /assignInvalid/ l- ## s- --- /preValid/ l* ## x+ --- /checkOverlap/ l+ ## 0 --- /overlapTrue/ l+ ## 0 --- /overlapFalse/ l+ ## 0 +-- /checkValid/ l! ## dT- +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l- ## s- +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_raise/ l= ## Xs- +-- /checkOverlap/ l+ ## 0 +-- /overlapTrue/ l+ ## 0 +-- /overlapFalse/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb index 9026e82ca..2621a2f75 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb @@ -15,8 +15,8 @@ package body Ranges is begin pragma Annotate -- # preValid (Xcov, Exempt_On, "expect no invalid ranges"); -- # preValid - if not (R1.Valid and then R2.Valid) then -- # preValid - raise Program_Error; -- # preValid + if not (R1.Valid and then R2.Valid) then -- # preValid_if + raise Program_Error; -- # preValid_raise end if; -- # preValid pragma Annotate (Xcov, Exempt_Off); -- # preValid diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb index e1035008d..643fb7d6d 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb @@ -19,11 +19,12 @@ exception end; --# ranges.adb --- /checkValid/ l+ ## 0 --- /assignValid/ l+ ## 0 --- /assignInvalid/ l+ ## 0 --- /preValid/ l* ## x+ --- /checkOverlap/ l- ## s- --- /overlapTrue/ l- ## s- --- /overlapFalse/ l- ## s- - +-- /checkValid/ l+ ## 0 +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l+ ## 0 +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoF- +-- /preValid_raise/ l= ## X0 +-- /checkOverlap/ l- ## s- +-- /overlapTrue/ l- ## s- +-- /overlapFalse/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb index 3464c8934..7b4055177 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb @@ -20,10 +20,12 @@ begin end; --# ranges.adb --- /checkValid/ l! ## dT- --- /assignValid/ l+ ## 0 --- /assignInvalid/ l- ## s- --- /preValid/ l* ## x+ --- /checkOverlap/ l! ## dT- --- /overlapTrue/ l- ## s- --- /overlapFalse/ l+ ## 0 +-- /checkValid/ l! ## dT- +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l- ## s- +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_raise/ l= ## Xs- +-- /checkOverlap/ l! ## dT- +-- /overlapTrue/ l- ## s- +-- /overlapFalse/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb index fa751f210..9c780c1d1 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb @@ -36,11 +36,12 @@ begin end; --# ranges.adb --- /checkValid/ l! ## dT- --- /assignValid/ l+ ## 0 --- /assignInvalid/ l- ## s- --- /preValid/ l* ## x+ --- /checkOverlap/ l! ## dF- --- /overlapTrue/ l+ ## 0 --- /overlapFalse/ l- ## s- - +-- /checkValid/ l! ## dT- +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l- ## s- +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_raise/ l= ## Xs- +-- /checkOverlap/ l! ## dF- +-- /overlapTrue/ l+ ## 0 +-- /overlapFalse/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Exemptions/extra.opt b/testsuite/Qualif/Ada/decision/Exemptions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/extra.opt +++ b/testsuite/Qualif/Ada/decision/Exemptions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/Exemptions/req.rst b/testsuite/Qualif/Ada/decision/Exemptions/req.rst index 972d1751d..3f8522ad2 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/decision/Exemptions/req.rst @@ -1,8 +1,6 @@ DC requirements for exemption regions ===================================== -%REQ_ID% - Exemption regions shall apply to decision coverage violations as they do to statement coverage violations. diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt b/testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt new file mode 100644 index 000000000..cccf1c20d --- /dev/null +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt @@ -0,0 +1 @@ +c XFAIL Runtime check bug in CCG, see eng/toolchain/gnat-llvm#73 diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb index 3b5b4b2a2..fdd37df89 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb @@ -34,4 +34,3 @@ package body Sensors.Status is end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb index 0ced98b40..be69593d5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb @@ -3,24 +3,24 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Broken is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Two history entries, both out of range - - S.V := 15; + + S.V := 15; Sample (S); Sample (S); - + Assert (Status_Of (S) = Broken); - + -- A third entry, in range. Still two out of range. - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Broken); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb index 7149f8f0a..5cfc621e2 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb @@ -3,23 +3,23 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Single history entry, out of range - - S.V := 15; + + S.V := 15; Sample (S); - + Assert (Status_Of (S) = Check); - + -- Two history entries, only one out of range - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb index 88cf2aba9..fb2851233 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb @@ -3,13 +3,13 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_F_FF is S : Sensor; - + begin -- Outer If False only. Inner If False only from F or else F. S.ALB := 1; S.AHB := 15; S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb index 131d500eb..807de762e 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb @@ -3,17 +3,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_FU_FF is S : Sensor; - + begin -- Outer If both True and False. Inner If False only from F or else F. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb index c95713f98..a891c55b2 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb @@ -3,18 +3,18 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_FU_FU is S : Sensor; - + begin -- Outer and Inner If both True and False. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - S.V := 0; -- < low bound + S.V := 0; -- < low bound Sample (S); - + S.V := 5; -- in range Sample (S); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb index a1f70f383..79ab5e80b 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb @@ -6,15 +6,15 @@ procedure Test_FU_TX is begin -- Outer If both True and False. Inner If True only from T or else X. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 0; -- < low bound Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb index 50394b7cb..03c8e7c56 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_OK is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb index b7a7d439d..674978979 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Sample (S); Assert (Status_Of (S) = Broken); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb index 7a32e1b3d..adf7d20b5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb index d6533600d..07c469831 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb @@ -4,19 +4,19 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb index a8dd68a25..9bf811870 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb @@ -3,7 +3,7 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_T_0 is S : aliased Sensor; - + begin -- Outer If True only. Inner If not reached. S.V := 5; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb index c69010279..87286041a 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb @@ -4,21 +4,21 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb index d73d62aa8..d71ed71a7 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); - + Sample (S); Assert (Status_Of (S) = Ok); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb index b3f615ea2..aa3c5b380 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb index 3b4c5e5a5..3e50f7c12 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb index 0dbd628d0..ed6ab2578 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Undecide is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads index be1a4bef4..7dfcde28c 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads @@ -6,4 +6,3 @@ package Slists.Count is SP : SP_Access := Pass'Access; NT, NF : out Natural); end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb index 452057a8f..66fde41e1 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb @@ -26,4 +26,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb index ba97d001e..65c6fc1f9 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb @@ -27,4 +27,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l- ## s- -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb index 76312d21b..91786e246 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb @@ -10,22 +10,22 @@ procedure Test_Iftf is Sin : aliased Sensor (Hist_Size => 5); -- in range sensor Sout : aliased Sensor (Hist_Size => 5); -- out of range sensor SL : Sensor_List; - + Nt, Nf : Natural; begin - + Sin.V := 5; Sin.ALB := 1; Sin.AHB := 10; - + Prepend (Sin'Unchecked_Access, SL); - + Sout.V := 5; Sout.ALB := 1; Sout.AHB := 3; - + Prepend (Sout'Unchecked_Access, SL); - + Count_In (Sl, Inrange'Access, Nt, Nf); Assert (Nt = 1); Assert (Nf = 1); @@ -40,4 +40,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb index 645b25b0e..c039912db 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb @@ -21,4 +21,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l- ## s- -- /CO_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb index 0ce55e079..78a70bfd4 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb index d504b04a4..74da8b900 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb index c46f26d9f..f8d1f419e 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb index acc6cac42..35b61b732 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb index a18667518..6308ac408 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb index 4a55c3ecf..4c6cd0284 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb index f6ada261e..bb507610d 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb @@ -16,4 +16,3 @@ begin Assert (Skip.Len = 1 and then Fault.Len = 0 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb index 8f1de5501..446195ea8 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb @@ -21,4 +21,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb index c00f76a1b..944e6f307 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb @@ -7,7 +7,7 @@ procedure Test_DF_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; end; @@ -25,4 +25,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb index 607625d83..97822124a 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb @@ -3,12 +3,12 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF; procedure Test_DF_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; end; @@ -26,4 +26,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb index bc296ec08..b48e33125 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb @@ -4,10 +4,10 @@ procedure Test_FU_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; - + Doif_TT_XX; end; @@ -24,4 +24,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb index 2dee78d20..4d8cf777c 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb @@ -3,15 +3,15 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF, Doif_TT_XX; procedure Test_FU_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; - + Doif_TT_XX; end; @@ -28,4 +28,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb index 6c8d726ff..58c74ba50 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb index a93ffb3c1..3caac5fbd 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb index 1b846ea2d..841b44ff5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb index 1af77d031..c02e262b5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb index 53b003ec6..bf5bf2852 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb index 9e2c537d0..1b93fd997 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb index 9d414583a..0e66a352f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt new file mode 100644 index 000000000..510071fba --- /dev/null +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt @@ -0,0 +1 @@ +morello DEAD The test uses memory tricks that are prohibited on CHERI platforms diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb index dd2dd3ea3..f734bf26f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb @@ -26,4 +26,3 @@ package body Slists.Forall is end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads index d1d942c70..5d475d37b 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads @@ -3,4 +3,3 @@ package Slists.Forall is procedure ForAll_In (SL : Sensor_List; Op : Sensor_Op; Active_Only : Boolean := False); end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb index eb6b2ff8e..b30b503b7 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb index c1fdc00c6..08ab934fb 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb @@ -7,16 +7,16 @@ procedure Test_Activate is begin S1.ALB := 1; S1.AHB := 10; - + S2.ALB := 5; S2.AHB := 15; Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + Forall_In (SL, Activate, Active_Only => True); Assert ((not S1.Active) and then (not S2.Active)); - + Forall_In (SL, Activate); Assert (S1.Active and then S2.Active); end; @@ -32,4 +32,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb index b6cac0779..e50cf022d 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb @@ -22,4 +22,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb index 3e2108385..904ad2066 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb @@ -26,4 +26,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb index 4125c0496..a86293311 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb @@ -28,4 +28,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb index 9e6f2f56a..321b29c16 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb @@ -11,10 +11,10 @@ begin -- Inner If decision not reached. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Activate, Active_Only => False); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb index 1b5001f0b..29e25ec82 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb @@ -11,10 +11,10 @@ begin -- Inner If False only from F or else F. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S.Active := True; S.ALB := 1; S.AHB := 12; @@ -33,4 +33,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb index 81e7afb63..c5bdae456 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb @@ -11,10 +11,10 @@ begin -- Inner If True only from F or else T. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S.Active := True; S.ALB := 1; S.AHB := 12; @@ -33,4 +33,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb index 4305d51b3..76c45c970 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb @@ -12,16 +12,16 @@ begin Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + S1.Active := False; S2.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S1.Active := True; S1.ALB := 1; S1.AHB := 12; S1.V := 0; -- < low bound - + S2.Active := True; S2.ALB := 1; S2.AHB := 12; @@ -40,4 +40,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb index 0b715496f..b13113a6f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb @@ -11,10 +11,10 @@ begin -- Inner If True only from T or else X. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S.Active := True; S.ALB := 1; S.AHB := 12; @@ -33,4 +33,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb index 3f3641bd3..337dbbef9 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb index 960567620..a5d3ee5a2 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision False only from F or else F. - + S1.ALB := 1; S1.AHB := 15; S1.V := 5; -- in range Prepend (S1'Unchecked_Access, SL); - + S1.Active := True; for X in False .. True loop - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb index 4dfd25e54..f8ff6f4dc 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 30; -- > high bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb index 2fc2809e6..a66b9170f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 0; -- < low bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb index b50f37c55..37549fde0 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb index 070f2bfbd..a169fc396 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb @@ -24,4 +24,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb index 5ecd96515..7509dbb46 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb @@ -18,4 +18,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb index bb2dae1c1..248a17063 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb @@ -7,14 +7,14 @@ procedure Test_Noinhibit is begin -- get into the inhibit case selection, arranging for the -- if statement there to always evaluate false - + S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + Prepend (S1'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst b/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst index bf260e864..2675394c7 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst @@ -5,8 +5,6 @@ DC requirements for combinations of statement and decision constructs representative of application code. -%REQ_ID% - Correct coverage is reported for programs that use a combination of Ada constructs, with arbitrary levels of syntactic nesting diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb index 404de97f8..a4f0b96fc 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb @@ -5,5 +5,3 @@ package body Sensors is Vbufs.Push (S.V, S.History); end; end; - - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads index 4af84cd8c..1700b03cd 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads @@ -16,4 +16,3 @@ package Sensors is -- latch current sensor value for S in its history buffer end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb index 168c92b9f..2701bf287 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb @@ -5,7 +5,7 @@ package body Slists is package Sensor_Nodes_Pool is new Simple_Pools.Basic_Pool (Data_Type => Sensor_Node, Capacity => 20); - + procedure Prepend (S : Sensor_Access; SL : in out Sensor_List) is NA : constant Sensor_Nodes_Pool.Data_Access := Sensor_Nodes_Pool.Allocate; begin diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads index 1e5ad1b18..49646f52c 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads @@ -13,4 +13,3 @@ package Vbufs is procedure Push (V : Value; VB : in out Vbuffer); end; - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads index 7f1d5d0ce..9422b2b17 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads @@ -2,7 +2,7 @@ pragma Ada_2012; package Ops is pragma Assertion_Policy (Ignore); - + procedure Add_Or_Mult (X, Y : Integer; Z : out Integer) with Pre => (if X > 0 then Y > 0 else Y <= 0), Post => (case X is diff --git a/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads index 4b730577f..4faee4576 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads @@ -2,9 +2,9 @@ pragma Ada_2012; package Ops is pragma Assertion_Policy (Ignore); - + function Plus1 (I : Integer) return Integer is (I + 1); - + procedure Add_Or_Mult (X, Y : Integer; Z : out Integer) with Post => (Z in 1 .. Y | 3 | Plus1 (X)); end; diff --git a/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads index ef1b43c4a..4ec5a462f 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads @@ -2,9 +2,9 @@ pragma Ada_2012; package Ops is pragma Assertion_Policy (Ignore); - + Data : array (1 .. 50) of Integer with Volatile; - + procedure Add_Or_Mult (X, Y : Integer; Z : out Integer) with Pre => (for some X of Data => X < 0 or else X mod 2 /= 0), Post => (for all X of Data => X > 0 and then X mod 2 = 0); diff --git a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb index caf3118c4..c442f6695 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb @@ -7,8 +7,16 @@ end; --# ops.adb -- /incOp/ l- ## s- +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l- ## s- +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb index 8383e906d..5d61738de 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb @@ -9,8 +9,16 @@ end; --# ops.adb -- /incOp/ l+ ## 0 +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l+ ## 0 +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt deleted file mode 100644 index f10d6338c..000000000 --- a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-012: src-traces and inhibited code diff --git a/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb b/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb index e85b8a543..2571934cd 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb @@ -1,18 +1,18 @@ pragma Ada_2012; package body Ops is - + -- Decision on the if-expression below. Single operand and -- no statement involved, so no dominance info available. - + function "abs" (X : Int64) return Uns64 is (if X = Int64'First -- # eval then 2**63 else Uns64 (Int64'(abs X))); -- - + procedure Process (X, Y : Int64) is - + -- Below, two calls to the "abs" expression function -- above in a row. When both calls are inlined, special -- treatment is required to untangle the two decisions. @@ -25,5 +25,3 @@ package body Ops is end; end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb index 44357981b..004bf36fe 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb @@ -8,5 +8,3 @@ begin return False; -- # false end if; end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb index 740afa7f9..a594a9a18 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb @@ -9,5 +9,3 @@ begin return False; -- # false end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb index 3d1046a41..910a12094 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb @@ -8,5 +8,3 @@ begin return False; -- # false end if; end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb index d4f75199b..60dd5637a 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb @@ -8,5 +8,3 @@ begin return False; -- # false end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb index 51cf7128c..b27535962 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb @@ -28,4 +28,3 @@ end Test_Register1; -- =/double/ l! ## s!,dT-:"if Double" -- =/triple/ l! ## s!,dT-:"if Triple" -- =/hits/ l! ## s!,dT- - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb index 0641fe6d8..166f98eec 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb @@ -24,5 +24,3 @@ end Test_Register2; -- %tags:(7.1.2|7.2.2), bin-traces -- =/init/ l! ## s!, dF- -- =/triple/ l! ## s!, dT- - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb index 0c69d7e8c..998eec0ce 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb @@ -28,4 +28,3 @@ end; -- =/double/ l! ## s!,dT-:"if Double" -- =/triple/ l! ## s!,dT-:"if Triple" -- =/hits/ l! ## s!,dT- - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb index 9de8bf9f9..4d8876a98 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb @@ -19,7 +19,7 @@ begin -- if/else; simple decision if Hit > 0 then This_Score := Hit; else This_Score := 0; End if; -- # init - -- if/no-else; simple decision. No check nor expr eval + -- if/no-else; simple decision. No check nor expr eval if Double then This_Score := Times (This_Score, 2); end if; -- # double -- if/no-else; stmt; simple decision diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb index ee9d154c2..87c79488e 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb @@ -24,4 +24,3 @@ end; -- %tags:(7.1.2|7.2.2), bin-traces -- =/init/ l! ## s!,dF-:"if Hit > 0" -- =/triple/ l! ## s!,dT-:"if Triple" - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads index dd918c42f..75a1acc6b 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads @@ -1,4 +1,4 @@ -package Darts is +package Darts is type Game is record Score, Hits, Fancy_Hits : Natural := 0; end record; diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads index ef27fd4f0..fa8cd0958 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads @@ -2,5 +2,3 @@ with Darts; use Darts; procedure Register (Hit : Natural; Double, Triple : Boolean; G : in out Game); - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb index cd91343e5..7892123e9 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb @@ -38,4 +38,3 @@ package body Basic is end; end; - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads index 6a14a46e4..1b39618e7 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads @@ -1,11 +1,10 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package Basic is - + Last_Long, Last_Short : Unbounded_String := Null_Unbounded_String; - + procedure Try1 (A : String); procedure Try2 (A : String); procedure Try3 (A : String); end; - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads index 4a866e76d..fea7b58db 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads @@ -3,11 +3,11 @@ use Ada.Strings; use Ada.Strings.Unbounded; package Ops is procedure Tryme (A : String; N : Natural; B : String; X : Integer); - + Last_Long, Last_Short, Last_mapped : Unbounded_String := Null_Unbounded_String; N_Xpos, N_Xneg, N_Xzero : Integer := 0; - + type Last_Category is (Long, Short, Mapped); - + procedure Check (Which : Last_Category; S : String); end; diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb index f5758a490..6ae18e887 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb @@ -6,7 +6,7 @@ begin Check (Which => Long, S => ""); Check (Which => Short, S => "A*1"); Check (Which => Mapped, S => "22"); - + Tryme (A => "A", N => 2, B => "B", X => 1); Check (Which => Long, S => ""); Check (Which => Short, S => "A*2"); diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb index 448da4a5c..b8c5c0a8c 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb @@ -21,4 +21,3 @@ end; -- /test/ l! ## dT- -- /long/ l- ## s- -- /short/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb index fcc7503c6..5ecdd6e5f 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb @@ -21,4 +21,3 @@ end; -- /test/ l! ## dF- -- /long/ l+ ## 0 -- /short/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb index 6feb9e0c3..0d835fb95 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb @@ -33,4 +33,3 @@ end; -- /test/ l+ ## 0 -- /long/ l+ ## 0 -- /short/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt index 468c8f45e..46096cdfa 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt @@ -1,3 +1,4 @@ RTS_ZFP DEAD no support for unbounded strings in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for unbounded string in light-tasking runtimes CARGS_O1,7.1.2,bin-traces XFAIL Debug info issue fixed post 7.0, PB30-044 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/Robustness/req.rst b/testsuite/Qualif/Ada/decision/Robustness/req.rst index 20fedebc9..02b321d1b 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/req.rst +++ b/testsuite/Qualif/Ada/decision/Robustness/req.rst @@ -1,8 +1,6 @@ DC requirements for potentially confusing constructs ==================================================== -%REQ_ID% - Combined Statement and Decision Coverage assessments shall remain correct in the presence of code constructs that require sophisticated analysis by the coverage tool not to end up confused by the visible or internal complexity, diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads new file mode 100644 index 000000000..3a40c6608 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads @@ -0,0 +1,18 @@ +pragma Ada_2012; + +package Pkg is + + function P + (A : Boolean; + B : Boolean; + C : Boolean; + D : Boolean; + E : Boolean; + F : Boolean) return Boolean + is + ((if A -- # eval-if-expr + then B and then C -- # decision-1-if-expr + else D and then E) -- # decision-2-if-expr + or else F); -- # last-cond + +end Pkg; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb new file mode 100644 index 000000000..6e40849cf --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_1 is +begin + Assert (P (True, True, True, True, True, True)); +end Test_1; + +--# pkg.ads +-- +-- /decision-1-if-expr/ l! ## eF- +-- /decision-2-if-expr/ l! ## e- +-- /last-cond/ l! ## 0 +-- +--%opts: --trace-mode=bin +-- /eval-if-expr/ l! ## eF-, d! +-- +--%opts: --trace-mode=src +-- /eval-if-expr/ l! ## eF-, dF- diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb new file mode 100644 index 000000000..bc437be3e --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_2 is +begin + Assert (P (True, False, True, True, True, True)); +end Test_2; + +--# pkg.ads +-- +-- /decision-1-if-expr/ l! ## eT- +-- /decision-2-if-expr/ l! ## e- +-- /last-cond/ l! ## 0 +-- +--%opts: --trace-mode=bin +-- /eval-if-expr/ l! ## eF-, d! +-- +--%opts: --trace-mode=src +-- /eval-if-expr/ l! ## eF-, dF- diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb new file mode 100644 index 000000000..0e7365d5d --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb @@ -0,0 +1,20 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_3 is +begin + Assert (P (True, True, True, True, True, True)); + Assert (P (True, True, False, True, True, True)); +end Test_3; + +--# pkg.ads +-- +-- /decision-1-if-expr/ l! ## c! +-- /decision-2-if-expr/ l! ## e- +-- /last-cond/ l! ## 0 +-- +--%opts: --trace-mode=bin +-- /eval-if-expr/ l! ## eF-, d! +-- +--%opts: --trace-mode=src +-- /eval-if-expr/ l! ## eF-, dF- diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb new file mode 100644 index 000000000..65d69959a --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_4 is +begin + Assert (P (False, True, True, True, False, True)); + Assert (P (True, True, True, True, True, False)); + Assert (not P (False, True, True, False, True, False)); +end Test_4; + +--# pkg.ads +-- +-- /eval-if-expr/ l+ ## 0 +-- /decision-1-if-expr/ l! ## eF- +-- /decision-2-if-expr/ l! ## eT- +-- /last-cond/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb new file mode 100644 index 000000000..5a746f94b --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb @@ -0,0 +1,21 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_Full is +begin + Assert (P (True, True, True, True, True, True)); + Assert (P (True, False, True, True, True, True)); + Assert (P (True, True, False, True, True, True)); + Assert (P (False, True, True, True, True, True)); + Assert (P (False, True, True, False, True, True)); + Assert (P (False, True, True, True, False, True)); + + Assert (not P (False, True, True, True, False, False)); +end Test_Full; + +--# pkg.ads +-- +-- /eval-if-expr/ l+ ## 0 +-- /decision-1-if-expr/ l+ ## 0 +-- /decision-2-if-expr/ l+ ## 0 +-- /last-cond/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst new file mode 100644 index 000000000..dea592510 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst @@ -0,0 +1,3 @@ +**MCDC on an if expression in a decision, with decisions as sub expressions** + +LRMREF: 4.5.7 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt new file mode 100644 index 000000000..bb690ece6 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt @@ -0,0 +1 @@ +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py new file mode 100644 index 000000000..6987337a8 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb index 91827e62c..9dfeeed57 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb @@ -17,4 +17,3 @@ end; --%opts: --trace-mode=src -- =/ifa/ l! ## dT- -- =/ifnota/ l! ## dT- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb index 43b69c2c1..436f3ca75 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb @@ -17,4 +17,3 @@ end; --%opts: --trace-mode=src -- =/ifa/ l! ## dF- -- =/ifnota/ l! ## dF- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb index 5ba7aec4e..322f66f77 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb @@ -17,5 +17,3 @@ end; --# sys.adb -- /ifa/ l+ ## 0 -- /ifnota/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb index 9f0e6828e..fc4294f0d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb @@ -11,4 +11,3 @@ begin return False; -- # false end if; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads index e36d249b5..e419fcd41 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads @@ -20,4 +20,3 @@ package Pools is Valid_Loc : Pool := (others => 'C'); end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads index ff82b82c0..d7de06657 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads @@ -11,6 +11,3 @@ package FUAND is function Poslen_And_Eql (Ops : Keys) return Boolean; -- Whether Ops.A'Length is positive and the same as Ops.B'Length end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb index 26bb3ccc0..d672e6e38 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb @@ -34,4 +34,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads index b6d8ff187..a47f322a1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads @@ -11,6 +11,3 @@ package FUOR is function Empty_Or_Eql (Ops : Keys) return Boolean; -- Whether Ops.A'Length is null or the same as Ops.B'Length end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb index aaa5e9402..b3e310e4a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb @@ -33,4 +33,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads index ff6bd5224..7e52ff999 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads @@ -1,16 +1,16 @@ with System; use System; package FUAND is - + type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use High_Order_First; for Operands use record A at 0 range 0 .. 0; B at 0 range 1 .. 1; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb index 484ee3042..d2fddfb57 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads index 0be8c5d0d..ba108bf8f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads @@ -4,7 +4,7 @@ package FUOR is type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use Low_Order_First; for Operands use record A at 0 range 0 .. 0; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb index a9e905750..ee96d2797 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb index 484ee3042..d2fddfb57 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb index a9e905750..ee96d2797 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads index a214d0cb5..ff5179279 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads @@ -6,4 +6,3 @@ package FUAND is (S, Post1, Post2 : String; Max : Integer) return Boolean; -- Whether Op & Post1 and Op & Post2 remain <= Max in length end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb index 680285f3f..1178df7fe 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb @@ -35,4 +35,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads index 62976b480..e9b5e63e3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads @@ -6,6 +6,3 @@ package FUOR is (S, Post1, Post2 : String; Max : Integer) return Boolean; -- Whether Op & Post1 or Op & Post2 remain <= Max in length end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb index c8353377e..b2051f512 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb @@ -35,4 +35,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads index 1d3ec79bf..34cfb801f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads @@ -1,10 +1,10 @@ package FUAND is - + type Value_T is (TT, FF); - + type Operands is record A, B : Value_T; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb index a6e04b35a..0f7ff0d2b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads index 6c07d4075..91f52df5d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads @@ -1,11 +1,11 @@ package FUOR is - + type T_Values is (FF, TT); for T_Values use (4, 5); - + type Operands is record A, B : T_Values; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb index 0d27e2ce8..6d9e19a3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads index f2a8d5a81..c75860991 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb index a6e04b35a..0f7ff0d2b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads index 72fa89695..e282aed19 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb index 0d27e2ce8..6d9e19a3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads index b4cc48de7..8c7083925 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - - type My_Float is digits 10 range -5.0 .. 5.0; - + + type My_Float is digits 10 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb index a6e04b35a..0f7ff0d2b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads index ff6ec9867..1d8a3fc95 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - - type My_Float is digits 8 range -5.0 .. 5.0; - + + type My_Float is digits 8 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb index 0d27e2ce8..6d9e19a3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads index 183691852..99a63c530 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads @@ -1,23 +1,23 @@ package FUAND is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Operand is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Operand; end record; - + -- We will evaluate for each operand whether .data(.index+1) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUAND is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Operand := (Index => 601, Data => Common_Data); TT2 : constant Operand := (Index => 604, Data => Common_Data); FF1 : constant Operand := (Index => 600, Data => Common_Data); FF2 : constant Operand := (Index => 605, Data => Common_Data); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb index ae58eca96..5baa576c9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF1, FF2))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads index 7e097fd9b..f2a3b001b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads @@ -1,23 +1,23 @@ package FUOR is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Operand is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Operand; end record; - + -- We will evaluate for each operand whether .data(.index+1) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUOR is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Operand := (Index => 601, Data => Common_Data); TT2 : constant Operand := (Index => 604, Data => Common_Data); FF1 : constant Operand := (Index => 600, Data => Common_Data); FF2 : constant Operand := (Index => 605, Data => Common_Data); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb index 81864abb1..9eb7d1a3b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb index 355eb2d3b..198f7e29c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb @@ -3,4 +3,3 @@ begin return Key'Length <= S'Length -- # startsLength and then S (S'First .. S'First + Key'Length - 1) = Key; -- # startsKey end Starts; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb index aefa4b8c6..e12e3b24d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb @@ -3,4 +3,3 @@ begin return Len <= S'Length -- # startsLength and then S (S'First .. S'First + Len - 1) = (1 .. Len => C); -- # startsKey end Starts; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads index 857499cdd..24b6ed4d3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads @@ -9,6 +9,3 @@ package FUAND is function Mod0_And (OpA, OpB : Modop) return Boolean; -- Whether OpA.X mod OpA.Y and OpB.X mod OpB.Y are null end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb index 76a766289..50a76ffe4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb @@ -26,4 +26,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads index ecc21cad0..a8af32167 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads @@ -9,6 +9,3 @@ package FUOR is function Mod0_Or (OpA, OpB : Modop) return Boolean; -- Whether OpA.X mod OpA.Y or OpB.X mod OpB.Y is null end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb index 01085abec..b65cd2873 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb @@ -26,4 +26,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads index 517e62691..3e9bd0e79 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads @@ -1,12 +1,12 @@ package FUAND is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb index 470b08e19..959039231 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads index 5e9091817..fb411c6d2 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads @@ -1,12 +1,12 @@ package FUOR is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb index 5253fa9d0..60b7e88c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb index 0359ed17e..302a242b0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb @@ -3,16 +3,16 @@ pragma Ada_2012; with Support; use Support; package body Ops is - + type T_Status is tagged record A : T_Action; W : T_What_Ahead; end record; - + type T_Qualified_Status is new T_Status with record Ss : T_Safety_Status; end record; - + function Q1 (S : T_Status) return T_Safety_Status is begin if S.A = Step and then S.W = Pit then -- # test @@ -21,7 +21,7 @@ package body Ops is return Safe; -- # safe end if; end; - + procedure Q2 (S : T_Status; Ss : out T_Safety_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -30,7 +30,7 @@ package body Ops is Ss := Safe; -- # safe end if; end; - + procedure Q3 (S : in out T_Qualified_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -39,7 +39,7 @@ package body Ops is S.Ss := Safe; -- # safe end if; end; - + function Q4 (S : in out T_Qualified_Status) return Integer is begin if S.A = Step and then S.W = Pit then -- # test @@ -49,26 +49,26 @@ package body Ops is end if; return 0; end; - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status is S1 : T_Safety_Status; begin S1 := Q1 ((A, W)); - + declare S2 : T_Safety_Status; begin Q2 ((A, W), S2); Assert (S2 = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); begin Q3 (QS); Assert (QS.Ss = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); X : Integer; @@ -79,5 +79,5 @@ package body Ops is return S1; end; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads index d1b21c4f8..c206f1d87 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads @@ -1,9 +1,9 @@ package Ops is - + type T_Action is (Hold, Step); type T_What_Ahead is (Ground, Pit); - + type T_Safety_Status is (Safe, Unsafe); - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads index 482f3b392..fb6c936e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads @@ -1,7 +1,7 @@ package FUAND is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUAND is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb index 470b08e19..959039231 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads index 519fdf48a..f78d01831 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads @@ -1,7 +1,7 @@ package FUOR is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUOR is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb index 5253fa9d0..60b7e88c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb index 717c8bf14..47fef9ead 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb @@ -1,6 +1,6 @@ with Test_V0_V0, Test_V0_V1, Test_V0_V2, Test_V1_X, Test_V2_X; -procedure Test_C5 is +procedure Test_C6 is begin Test_V0_V0; Test_V0_V1; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb index 0689a5415..5d439a93a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb index 9296b6b15..e2371be33 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads index 2746e95ca..ddf93dae0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads @@ -1,26 +1,26 @@ package FUAND is - + type Key is new String (1 .. 5); - + type Caller_Operand is record X, Y : Integer; K : Key; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type Operand is record Pos, Even : Boolean; K : Key; end record; - + TTA : constant Caller_Operand := (1, 6, "AAKEY"); TTB : constant Caller_Operand := (5, 5, "BBKEY"); - + FFA : constant Caller_Operand := (1, 6, "AAKEX"); FFB : constant Caller_Operand := (1, 6, "BBKEY"); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb index 5526edb51..753e03952 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FFA, FFB))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads index 5332b1554..97ec469c5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads @@ -1,26 +1,26 @@ package FUOR is - + type Key is new String (1 .. 5); - + type Caller_Operand is record X, Y : Integer; K : Key; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type Operand is record Pos, Even : Boolean; K : Key; end record; - + TTA : constant Caller_Operand := (1, 6, "AAKEY"); TTB : constant Caller_Operand := (5, 5, "BBKEY"); - + FFA : constant Caller_Operand := (1, 6, "AAKEX"); FFB : constant Caller_Operand := (1, 6, "BBKEY"); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb index 06d44f69d..1aaf75ec5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads index 4636352f0..5b8e5505f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads @@ -1,7 +1,7 @@ package Andthen_Variants is subtype Bool_Subtype is Boolean; function And_Then_Subtype (A, B : Bool_Subtype) return Bool_Subtype; - + type Bool_Type is new Boolean; function And_Then_Type (A, B : Bool_Type) return Bool_Type; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb index 2c2719e64..85d66a02f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb @@ -11,4 +11,3 @@ end; --# andthen_variants.adb -- /evaluate/ l! ## eT- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb index 98d566b59..edf4a3c9d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((Values => (A => 0, B => 0)))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb index e2f187b43..6337f3936 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb @@ -1,3 +1,5 @@ +pragma Ada_2012; + package body FUOR is function Orelse (Ops : Operands) return Boolean is diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb index aeef48e71..57fbf0215 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads index a3db71d5a..4c6d1367c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads @@ -1,28 +1,28 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package FUAND is - + type Key is new String (1 .. 5); - + type Caller_Operand is record X : Integer; US : Unbounded_String; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type Operand is record Pos : Boolean; K : Unbounded_String; end record; - + TTA : constant Caller_Operand := (1, To_Unbounded_String ("USA")); TTB : constant Caller_Operand := (5, To_Unbounded_String ("USB")); - + FFA : constant Caller_Operand := (-1, To_Unbounded_String ("USA")); FFB : constant Caller_Operand := (1, To_Unbounded_String ("not USB")); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb index 5526edb51..753e03952 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FFA, FFB))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb index 7edce8ece..5efdabfd0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb @@ -5,7 +5,7 @@ package body FUOR is function Orelse (Ops : Operands) return Boolean is Aop : Caller_Operand renames Ops.A; -- # decl Bop : Caller_Operand renames Ops.B; -- # decl - + begin return OperandA'(Match => To_String(Aop.US1 & Aop.US2) = "STARTEND") = (Match => True) -- # evalA or else OperandB'(To_Match => Translate (Bop.US1, To_Mapping("ABC", "012"))) = (To_Match => Bop.US2); -- # evalB diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads index 9c002b5f3..e2ceec6e2 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads @@ -1,34 +1,34 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package FUOR is - + type Key is new String (1 .. 5); - + type Caller_Operand is record US1, US2 : Unbounded_String; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type OperandA is record Match : Boolean; end record; - + type OperandB is record To_Match : Unbounded_String; end record; - - TTA : constant Caller_Operand := + + TTA : constant Caller_Operand := (To_Unbounded_String ("START"), To_Unbounded_String("END")); - TTB : constant Caller_Operand := + TTB : constant Caller_Operand := (To_Unbounded_String("CAB"), To_Unbounded_String("201")); - - FFA : constant Caller_Operand := + + FFA : constant Caller_Operand := (To_Unbounded_String("A"), To_Unbounded_String("B")); FFB : constant Caller_Operand := (To_Unbounded_String("CAB"), To_Unbounded_String("11")); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb index 06d44f69d..1aaf75ec5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt index 6e33ff527..4986592e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt @@ -1 +1,2 @@ RTS_ZFP DEAD no support for unbounded strings in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for unbounded strings in light-tasking runtimes diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb index 8832ae009..80d279e13 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb @@ -1,6 +1,6 @@ pragma Ada_2012; package body FUAND is - + function Andthen (Ops : Operands) return Boolean is Aop : Control renames Ops.A; -- # decl Bop : Control renames Ops.B; -- # decl @@ -9,4 +9,3 @@ package body FUAND is and then Ops.B.X in Plus1(Bop.Y) | Twice(Bop.Y); -- # evalB end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads index fce494f97..226c92e0c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads @@ -1,23 +1,23 @@ pragma Ada_2012; package FUAND is - + -- We will be checking if X in (2*Y | Y+1) - + type Control is record X, Y : Integer; end record; - + function Plus1 (Y : Integer) return Integer is (Y + 1); - + function Twice (Y : Integer) return Integer is (Y * 2); - + FF : constant Control := (X => 1, Y => 1); TT1 : constant Control := (X => 3, Y => 2); -- X = Y + 1 TT2 : constant Control := (X => 4, Y => 2); -- X = Y * 2 - + type Operands is record A, B : Control; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb index e8aef6048..a01349183 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb @@ -1,25 +1,25 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); end; - + procedure Eval_FT_F is begin Assert (not Andthen ((FF, TT1))); end; - + procedure Eval_TF_F is begin Assert (not Andthen ((TT2, FF))); end; - + procedure Eval_TT_T is begin Assert (Andthen ((TT1, TT2))); end; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb index bafb68bde..d158a3bb6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb @@ -10,4 +10,3 @@ end; -- /evalB/ l- ## 0c -- /oncall/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb index 42167c5db..c47a678e0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb @@ -9,4 +9,3 @@ end; --# fuand.adb -- /evalA/ l! ## 0 -- /evalB/ l! ## c!:"Op" - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb index 5109ef573..de11d5a5a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb @@ -10,4 +10,3 @@ end; --# fuand.adb -- /evalA/ l+ ## 0 -- /evalB/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb index 52d563b4b..1e4b972d9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb @@ -9,4 +9,3 @@ end; --# fuand.adb -- /evalA/ l! ## c!:"Op" -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb index abfacb1cd..f149c4eae 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb @@ -10,4 +10,3 @@ end; --# fuand.adb -- /evalA/ l! ## eT- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb index cc3ea60cb..c03165ae3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb @@ -8,4 +8,3 @@ end; --# fuand.adb -- /evalA/ l! ## eF- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb index d868ad212..36fa2f5d9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb @@ -9,4 +9,3 @@ end; --# fuor.adb -- /evalA/ l! ## 0 -- /evalB/ l! ## c!:"Op" - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb index 41d7ca78b..020840e04 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb @@ -10,4 +10,3 @@ end; --# fuor.adb -- /evalA/ l+ ## 0 -- /evalB/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb index a1dc5bbeb..00e74dab5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb @@ -9,4 +9,3 @@ end; --# fuor.adb -- /evalA/ l! ## c!:"Op" -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb index 14fa70efd..501888ccf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb @@ -8,4 +8,3 @@ end; --# fuor.adb -- /evalA/ l! ## eT- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb index dfcbfe585..74251979a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb @@ -10,4 +10,3 @@ end; --# fuor.adb -- /evalA/ l! ## eF- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb index 5b0ea626b..65e26b45f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb @@ -10,6 +10,3 @@ package body Andthen is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb index 624a8da98..51d909066 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb @@ -12,4 +12,3 @@ package body Andthen is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb index 3c0375165..1324c2769 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb @@ -6,6 +6,3 @@ package body Andthen is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb index 00f954849..5eb47e9a8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb @@ -5,4 +5,3 @@ package body Andthen is return (if A and then B then True else False); -- # evalStmt :o/d: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb index 303bb3a9a..16af4ec52 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb @@ -6,4 +6,3 @@ package body Andthen is return Values (A and then B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb index d0de1ab25..c3bebc485 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb @@ -6,4 +6,3 @@ begin pragma Debug (Assert (A and then B)); -- # eval null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt new file mode 100644 index 000000000..21cc3c381 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt @@ -0,0 +1 @@ +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb index fe127c413..52c0708e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb @@ -23,5 +23,3 @@ package body Points is return P1.X = P2.X and then P1.Y = P2.Y; -- # retSXY end; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb index 583d7e2c7..df6c30cfb 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb @@ -6,4 +6,3 @@ procedure Passand (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb index cb211628c..8c24e7ae2 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb @@ -4,4 +4,3 @@ procedure Passand (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb index 02670874b..642b453a5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb @@ -4,4 +4,3 @@ package body Andthen is return A and then B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb index 7df6c42b5..8ab468949 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb @@ -1,3 +1,2 @@ package body Andthen is end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads index 2a4962707..4b5437b25 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads @@ -1,9 +1,9 @@ pragma Ada_2012; package Andthen is - + pragma Elaborate_Body; -- # decl -- Just because the testcase architecture expects to always have a body - + function And_Then (A, B : Boolean) return Boolean is (A and then B); -- # evalStmt :o/e: end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb index ce9ef81c0..40c221f04 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb @@ -6,4 +6,3 @@ package body Andthen is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb index c27d52d46..4f66a8299 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb index 52266a15d..a0a743601 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb @@ -6,7 +6,7 @@ package body AndCOr is begin return Value (B or else C); -- # orelse :o/e: end; - + function F (A, B, C : Boolean) return Boolean is begin return Value (A and then Orelse (B, C)); -- # andthen :o/e: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb index 9814e7bbb..0e1f3ed83 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb @@ -23,6 +23,3 @@ package body Andcor is end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb index 7bec45763..41e9a0370 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb @@ -1,10 +1,10 @@ package body AndCOr is - + function Orelse (B, C : Boolean) return Boolean is begin return B or else C; -- # orelse :o/e: end; - + procedure Eval_F (A, B, C : Boolean; E : out Boolean) is begin E := A and then Orelse (B, C); -- # andthen :o/e: @@ -17,4 +17,3 @@ package body AndCOr is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb index c5f6f1b57..e54185152 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCOr is - + function Orelse (B, C : Boolean) return Boolean is begin case B or else C is -- # orelse :o/e: @@ -7,7 +7,7 @@ package body AndCOr is when False => return False; -- # orFalse end case; end; - + function F (A, B, C : Boolean) return Boolean is begin case A and then Orelse (B, C) is -- # andthen :o/e: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb index 631326e8c..5f77f7cd9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb @@ -19,6 +19,3 @@ package body AndCor is end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb index a9638dbbc..ff5a19cda 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb @@ -1,12 +1,12 @@ package body AndCor is - + type My_Type (Value : Boolean) is null record; - + function Orelse (B, C : Boolean) return Boolean is begin return B or else C; -- # orelse :o/e: end; - + function F (A, B, C : Boolean) return Boolean is R : My_Type (Value => A and then Orelse (B, C)); -- # andthen :o/e: begin diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb index 4e2006c1e..bace37f98 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCor is - + function Orelse (B, C : Boolean) return Boolean is begin loop @@ -8,7 +8,7 @@ package body AndCor is end loop; return True; -- # orTrue end; - + function F (A, B, C : Boolean) return Boolean is begin loop diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb index 10ab7ea86..dceeeec08 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCOr is - + function Orelse (B, C : Boolean) return Boolean is begin if B or else C then -- # orelse :o/d: @@ -8,7 +8,7 @@ package body AndCOr is return False; -- # orFalse end if; end; - + function F (A, B, C : Boolean) return Boolean is begin if A and then Orelse (B, C) then -- # andthen :o/d: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt index 460eb2f94..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt @@ -1,2 +1 @@ -bin-traces,CARGS_O1 XFAIL T706-019: decision map issue -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb index 608324a59..1edc62b3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb @@ -3,7 +3,7 @@ package body AndCOr is begin return B or else C; -- # orelse :o/e: end; - + function F (A, B, C : Boolean) return Boolean is Value : array (Boolean) of Boolean := (False => False, True => True); begin diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb index e9fcf6954..7b2a576c4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCor is - + function Orelse (B, C : Boolean) return Boolean is begin while B or else C loop -- # orelse :o/d: @@ -7,7 +7,7 @@ package body AndCor is end loop; return False; -- # orFalse end; - + function F (A, B, C : Boolean) return Boolean is begin while A and then Orelse (B, C) loop -- # andthen :o/d: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb index fe43188aa..836d939e0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb @@ -15,4 +15,3 @@ package body AndCor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb index 3691f9673..64b5b21d1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb @@ -10,4 +10,3 @@ package body AndIdOr is return E.Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb index 6b213617c..ed1f81665 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb @@ -12,4 +12,3 @@ package body AndIdOr is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb index 9630d1251..d5cbfa7cf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb @@ -6,4 +6,3 @@ package body AndIdOr is return R; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb index 8465ee537..1724c939f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb @@ -1,5 +1,5 @@ package body AndIdOr is - + type My_Type (Value : Boolean) is null record; function F (A, B, C : Boolean) return Boolean is diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb index f6eccb60f..6688bd7c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb @@ -8,4 +8,3 @@ package body Andidor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb index 5eda527cf..6906e6c1d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb @@ -10,6 +10,3 @@ package body Andnot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb index ff5de39f2..fe1165525 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb @@ -12,4 +12,3 @@ package body Andnot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb index 0bd7fcdfb..d6b74a579 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb @@ -6,6 +6,3 @@ package body Andnot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb index 02624aa39..2f0950d48 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb @@ -6,4 +6,3 @@ package body Andnot is return Values (A and then not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb index f0a51719a..61679555c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb @@ -4,4 +4,3 @@ package body Andnot is return A and then not B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb index 9f3db1f2a..e7fc3b704 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb @@ -6,4 +6,3 @@ package body Andnot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb index 6a9143a21..5c9fb7571 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb index 267a83513..6075bfb13 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb @@ -12,4 +12,3 @@ package body AndPorP is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb index 8d5fb10e2..31cf62266 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb @@ -7,4 +7,3 @@ package body AndPorP is return Values (A and then (B or else C)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads index 6f9ea93ac..af57bf3c7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads @@ -2,7 +2,7 @@ pragma Ada_2012; package Andporp is pragma Elaborate_Body; -- # decl -- Just because the testcase architecture expects to always have a body - + function F (A, B, C : Boolean) return Boolean is (A and then (B or else C)); -- # evalStmt :o/e: end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb index d06498435..312c4fc97 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb @@ -9,4 +9,3 @@ package body AndPorP is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads index 3880ef535..757833f42 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads @@ -1,3 +1,3 @@ -package AndPorP is - function F (A, B, C : Boolean) return Boolean; -end; \ No newline at end of file +package AndPorP is + function F (A, B, C : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb index 4c9c4527b..cfaed4fb1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb @@ -1,24 +1,23 @@ -package body AndPorPand_Coupled is - - function F1 (A, B, C : Boolean) return Boolean is - D : Boolean := A; -- # decl - begin - return A and then (B or else C) and then D; -- # F1_evaluate - end F1; - - function F2 (A, B, C : Boolean) return Boolean is - D : Boolean := B; -- # decl - pragma Volatile (D); -- preserve eval of B or else D - begin - return A and then (B or else D) and then C; -- # F2_evaluate - end F2; - - function F3 (A, B, C : Boolean) return Boolean is - D : Boolean := A; -- # decl - pragma Volatile (D); -- preserve eval - begin - return A and then (D or else B) and then C; -- # F3_evaluate - end F3; - -end AndPorPand_Coupled; - +package body AndPorPand_Coupled is + + function F1 (A, B, C : Boolean) return Boolean is + D : Boolean := A; -- # decl + begin + return A and then (B or else C) and then D; -- # F1_evaluate + end F1; + + function F2 (A, B, C : Boolean) return Boolean is + D : Boolean := B; -- # decl + pragma Volatile (D); -- preserve eval of B or else D + begin + return A and then (B or else D) and then C; -- # F2_evaluate + end F2; + + function F3 (A, B, C : Boolean) return Boolean is + D : Boolean := A; -- # decl + pragma Volatile (D); -- preserve eval + begin + return A and then (D or else B) and then C; -- # F3_evaluate + end F3; + +end AndPorPand_Coupled; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads index d2a10e2b3..06605c3c4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads @@ -9,4 +9,3 @@ package AndPorPand_Coupled is function F3 (A, B, C : Boolean) return Boolean; end AndPorPand_Coupled; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb index e338b26f3..588d7e4c6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb @@ -1,23 +1,22 @@ -package body AndPorPand_Coupled_Alt is - - function F1 (A, B, C : Boolean) return Boolean is - begin - return A and then (B or else C) -- # F1_evaluate - and then A; -- # coupF1_evaluate - end F1; - - function F2 (A, B, C : Boolean) return Boolean is - begin - return A and then (B -- # F2_evaluate - or else B) and then C; -- # coupF2_evaluate - end F2; - - function F3 (A, B, C : Boolean) return Boolean is - D : Boolean := A; -- # decl - begin - return A and then -- # F3_evaluate - (A or else B) and then C; -- # coupF3_evaluate - end F3; - -end AndPorPand_Coupled_Alt; - +package body AndPorPand_Coupled_Alt is + + function F1 (A, B, C : Boolean) return Boolean is + begin + return A and then (B or else C) -- # F1_evaluate + and then A; -- # coupF1_evaluate + end F1; + + function F2 (A, B, C : Boolean) return Boolean is + begin + return A and then (B -- # F2_evaluate + or else B) and then C; -- # coupF2_evaluate + end F2; + + function F3 (A, B, C : Boolean) return Boolean is + D : Boolean := A; -- # decl + begin + return A and then -- # F3_evaluate + (A or else B) and then C; -- # coupF3_evaluate + end F3; + +end AndPorPand_Coupled_Alt; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads index 168c991a6..3f10024e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads @@ -9,4 +9,3 @@ package AndPorPand_Coupled_Alt is function F3 (A, B, C : Boolean) return Boolean; end AndPorPand_Coupled_Alt; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb index 4fe10af12..5b47017a8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb @@ -50,5 +50,3 @@ end Test_AndPorPand_Coupled_2; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb index ccf3db565..4c2713ee1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb @@ -49,4 +49,3 @@ end Test_AndPorPand_Coupled_3; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb index 972a859c4..b6069affb 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb @@ -59,4 +59,3 @@ end Test_AndPorPand_Coupled_All; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb index 65d349a1e..4e2896b94 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb @@ -53,4 +53,3 @@ end Test_AndPorPand_Coupled_Alt_2; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb index 232c56931..aa7f22775 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb @@ -52,4 +52,3 @@ end Test_AndPorPand_Coupled_Alt_3; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb index 675299abe..ca1f6c5f6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb @@ -61,4 +61,3 @@ end Test_AndPorPand_Coupled_Alt_All; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb index 04cd17fab..c6216d00a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb @@ -20,5 +20,3 @@ end; --# cc4.adb -- /eval/ u=>l!, l+ ## u=>c!:"not A" - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb index e917d92c1..0388acea6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb @@ -15,5 +15,3 @@ end; --# cc4.adb -- /eval/ u=>l!, l+ ## u=>c!:"not A" - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads index 9b82d18e1..0ecb1efc6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads @@ -19,4 +19,3 @@ function C3 (A, B, C : Boolean) return Boolean; -- ip(A) = 1,5 -- ip(B) = 1,3 -- ip(C) = 2,3 4,5 + 2,5 3,4 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb index a222fcf30..5f5fdf37f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb @@ -9,5 +9,3 @@ end; --# c3.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb index 1e186c34c..7a94bb575 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb @@ -7,5 +7,3 @@ end; --# c3.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb index 5038b909c..b1f79ea81 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb @@ -7,5 +7,3 @@ end; --# c3.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb index 7414bf4e5..2f08c6e3d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb @@ -9,5 +9,3 @@ end; --# c3.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb index 7550676e6..1d739d2c0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb @@ -9,5 +9,3 @@ end; --# c3.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb index 5e36745c6..8f08f2310 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb @@ -10,6 +10,3 @@ package body Notand is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb index 6a3fe0fff..5d744e1d5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb @@ -12,4 +12,3 @@ package body Notand is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb index 665ec4574..797f6c48c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb @@ -6,6 +6,3 @@ package body Notand is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb index e894f6bb5..0eddf7deb 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb @@ -7,4 +7,3 @@ package body Notand is return Values ((not A) and then B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb index 17ba51b33..187502d89 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb @@ -4,4 +4,3 @@ package body Notand is return (not A) and then B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb index b92afb2f8..b4dc7b19b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb @@ -6,4 +6,3 @@ package body Notand is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb index 7fd39d499..a8be83cad 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb index 7796148e0..f533d857d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb @@ -10,6 +10,3 @@ package body Notandnot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb index 5a9a646f9..5382d2ca9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb @@ -12,4 +12,3 @@ package body Notandnot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb index e74d8d01d..be8d0551b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb @@ -6,6 +6,3 @@ package body Notandnot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb index 4b008339c..4ba04c6c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb @@ -7,4 +7,3 @@ package body Notandnot is return Values ((not A) and then (not B)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb index b7e5b8bf8..b7956146d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb @@ -4,4 +4,3 @@ package body Notandnot is return (not A) and then (not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb index 2d48f9fc0..5fecaa0be 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb @@ -6,4 +6,3 @@ package body Notandnot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb index 2ca75a3cc..2923de606 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb index 16b6eed75..1833f703f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb @@ -10,6 +10,3 @@ package body Notor is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb index fb5422b71..8ae6192c7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb @@ -12,4 +12,3 @@ package body Notor is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb index ffb0701b4..d1ebc8c2e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb @@ -6,6 +6,3 @@ package body Notor is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb index c67ea5fb5..b8261eb02 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb @@ -8,4 +8,3 @@ package body Notor is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb index efe29cf5c..998538ed9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb @@ -7,4 +7,3 @@ package body Notor is return Values ((not A) or else B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb index 27f277f62..b3e4c7c4e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb @@ -4,4 +4,3 @@ package body Notor is return (not A) or else B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb index 46b98d204..3654b4f52 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb @@ -6,4 +6,3 @@ package body Notor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb index 1c741a939..98167c30c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb @@ -10,6 +10,3 @@ package body Notornot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb index 32f7579c5..cc9415a88 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb @@ -12,4 +12,3 @@ package body Notornot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb index fdc95bedd..b84165401 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb @@ -6,6 +6,3 @@ package body Notornot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb index 9d541a99d..61fb29dc6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb @@ -8,4 +8,3 @@ package body Notornot is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb index fd75514dd..6b2ec1bdd 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb @@ -6,4 +6,3 @@ package body Notornot is return Values ((not A) or else (not B)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb index a86f68be2..2c5e989b9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb @@ -4,4 +4,3 @@ package body Notornot is return (not A) or else (not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb index 3286b3c5b..efb0705e6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb @@ -6,4 +6,3 @@ package body Notornot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb index a691af102..387d3950b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb index 2eff69d85..8a311548c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb @@ -10,6 +10,3 @@ package body Orelse is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb index fbcc6addc..77cf56078 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb @@ -12,4 +12,3 @@ package body Orelse is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb index 8071136c4..a1519eede 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb @@ -6,6 +6,3 @@ package body Orelse is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb index 5e211c47b..cab437f3c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb @@ -8,4 +8,3 @@ package body Orelse is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb index a3bce670b..475dca9c4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb @@ -6,4 +6,3 @@ package body Orelse is return Values (A or else B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb index 71bd1ccee..8e0f82f3d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb @@ -6,4 +6,3 @@ begin pragma Debug (Assert (A or else B)); -- # eval null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt new file mode 100644 index 000000000..fee549a96 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt @@ -0,0 +1,2 @@ + +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb index b525e505f..bfa782c5e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb @@ -6,4 +6,3 @@ procedure Passor (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb index 1b4c92529..dd12488e7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb @@ -4,4 +4,3 @@ procedure Passor (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb index 22398b4b0..6671f6b01 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb @@ -4,4 +4,3 @@ package body Orelse is return A or else B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb index 2ed183ab5..e85acf379 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb @@ -6,4 +6,3 @@ package body Orelse is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb index 127c70c10..5a6767735 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb @@ -10,6 +10,3 @@ package body Ornot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb index 4f94a0560..e407d69e6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb @@ -12,4 +12,3 @@ package body Ornot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb index f66a770f0..5bcef28f3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb @@ -6,6 +6,3 @@ package body Ornot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb index 92c8e22e1..1475151d1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb @@ -8,4 +8,3 @@ package body Ornot is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb index 53ddbf122..d419767e7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb @@ -7,4 +7,3 @@ package body Ornot is return Values (A or else (not B)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb index 502537c88..af26ed00c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb @@ -4,4 +4,3 @@ package body Ornot is return A or else (not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb index c3b66b866..d54b7b2b4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb @@ -6,4 +6,3 @@ package body Ornot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb index e2a65173d..4517fe533 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb index 4bb871b9c..9de688ab4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb @@ -12,4 +12,3 @@ package body PandPor is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb index 7d90c1e53..e04ff6c51 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb @@ -6,4 +6,3 @@ package body PandPor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb index 06d45a695..36462ea26 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb index 7f2dbee8d..eff6f2fe9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb index d2a8e968d..08a21634f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb index 70a21ccae..267cde734 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb @@ -14,4 +14,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb index 5f1e3651f..920ad743f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb @@ -14,4 +14,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb index da861f05e..29e15267c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb index bb985b7c3..ccfebd345 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb index be8773c36..90b96ec22 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb index 0258c40cb..5d8e80db8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb @@ -14,4 +14,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb index 341d32f9a..f835fc077 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb index babb3f976..d9e0b46c0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb index 387423f30..1c1553856 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb index 54560f044..ff12e17cf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb @@ -15,4 +15,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb index 6f67d43a5..45aad66fc 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb @@ -12,4 +12,3 @@ package body PorPandPorP is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb index 422c5776e..9f7767181 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb @@ -12,4 +12,3 @@ package body POrPAndPorP is return Touched (True); -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb index fbc2ca992..87b343958 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb @@ -6,4 +6,3 @@ package body PorPandPorP is return Values ((A or else B) and then (C or else D)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb index 82d68101f..39303cea4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb @@ -9,4 +9,3 @@ package body PorPandPorP is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/req.rst b/testsuite/Qualif/Ada/mcdc/1_Core/req.rst index f6b301e8e..a1fc30ba9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/req.rst +++ b/testsuite/Qualif/Ada/mcdc/1_Core/req.rst @@ -1,8 +1,6 @@ Core MCDC requirements ====================== -%REQ_ID% - For MCDC assessments, the tool processes as decisions all the expressions processed as such for Decision Coverage (Boolean expressions used to influence control flow constructs), as well as all the Boolean expressions with more than diff --git a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb index 67150aad0..9930eea1b 100644 --- a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb +++ b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb @@ -1,17 +1,17 @@ package body Ops is - + procedure Set (P : in out T_Pair'Class; X, Y : Integer) is begin P.X := X; -- # stmt P.Y := Y; -- # stmt P.Is_Set := True; -- # stmt end; - + function Valid (D : T_Double) return Boolean is begin return D.Y = D.X * 2; -- # check end; - + function Bad_Set (D : T_Double) return Boolean is begin return D.Is_Set and then D.Y /= D.X * 2; -- # eval diff --git a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads index 9f9cb2936..177d9e26c 100644 --- a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads +++ b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads @@ -1,22 +1,22 @@ pragma Ada_2012; -pragma Assertion_Policy (Invariant => Disable); +pragma Assertion_Policy (Disable); package Ops is - + type T_Pair (Checked : Boolean := True) is tagged limited private with Type_Invariant'Class => Valid(T_Pair) or else Unchecked(T_Pair); - + procedure Set (P : in out T_Pair'Class; X, Y : Integer); function Valid (P : T_Pair) return Boolean is (True); -- # fn function Unchecked (P : T_Pair) return Boolean is (not P.Checked); -- # fn - + type T_Double is new T_Pair with private; - + function Valid (D : T_Double) return Boolean; function Bad_Set (D : T_Double) return Boolean; private - + type T_Pair (Checked : Boolean := True) is tagged limited record X, Y : Integer := 0; Is_Set : Boolean := False; @@ -24,5 +24,5 @@ private type T_Double is new T_Pair with null record with Type_Invariant => T_Double.X > 0 and then T_Double.Y > 0; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads index a6591813a..3600d1583 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads @@ -13,5 +13,3 @@ function Andthen (A, B : Boolean) return Boolean; -- ip(A) = 3,0 3,1 -- ip(B) = 3,2 - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb index a0d410a9f..c222ac99e 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb index 78eb32d97..84f14350e 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb index 6260d1a20..a2ac95a57 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb index 7c663e17b..66228778a 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb index 8c7238583..39caf5ef1 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb @@ -13,5 +13,3 @@ package body A1O2 is return Andthen (A and then B, C or else D); -- # evals end; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads index ef0afee69..7fe77dc80 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads @@ -13,5 +13,3 @@ function Orelse (A, B : Boolean) return Boolean; -- ip(A) = 0,2 0,3 -- ip(B) = 0,1 - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb index fb875377b..0e41a0ffd 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb index b443d6f8e..55d03b105 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb index 517ec51cf..16734e0a0 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb index 7ab32716c..8970b1253 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb index 64278cb2b..bb2accfc5 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb @@ -2,4 +2,3 @@ function Porpand (A, B, C : Boolean) return Boolean is begin return (A or else B) and then C; -- # eval end; - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb index 990b357b6..3fe765cdc 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb @@ -9,5 +9,3 @@ end; --# porpand.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb index dfceb83b9..43e0a7424 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb @@ -7,5 +7,3 @@ end; --# porpand.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb index e794928f9..b03c19622 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb @@ -7,5 +7,3 @@ end; --# porpand.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb index 6ee0a105f..c3574e4a8 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb @@ -9,4 +9,3 @@ end; --# porpand.adb -- /eval/ l! ## eT- - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb index 631434ffa..e77f1d5a5 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb @@ -9,5 +9,3 @@ end; --# porpand.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst b/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst index 015f8e5e2..b036bc633 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst @@ -1,8 +1,6 @@ MCDC requirements for the combination of multiple execution traces ================================================================== -%REQ_ID% - When the coverage achieved by multiple execution traces is evaluated, an mcdc violation shall only be reported when it would have been for all the traces individually. diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb new file mode 100644 index 000000000..950bcb3a4 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Exemptions (Debug_Mode : Boolean; I : Integer) is +begin + pragma Annotate (Xcov, Exempt_On, "Exempted"); -- # ex + if Debug_Mode and then I < 0 then -- # ex_if_neg + Put_Line ("I is negative."); -- # ex_error + elsif Debug_Mode then -- # ex_if_debug + Put_Line ("No error."); -- # ex_no_error + end if; -- # ex + pragma Annotate (Xcov, Exempt_Off); -- # ex +end Exemptions; diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb new file mode 100644 index 000000000..d01d2a398 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb @@ -0,0 +1,16 @@ +with Exemptions; + +-- Test driver for exemptions. Call the subprogram and execute only part of +-- the exempted code, evaluating all conditions of all decisions. + +procedure Test_Call_Debug is +begin + Exemptions (True, 42); +end Test_Call_Debug; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## s=>X0, dmu=>XoT- +-- /ex_error/ l= ## Xs- +-- /ex_if_debug/ l= ## XoF- +-- /ex_no_error/ l= ## X0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb new file mode 100644 index 000000000..f3bcbcbdb --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb @@ -0,0 +1,16 @@ +with Exemptions; + +-- Test driver for exemptions. Exercise only part of the exempted code, +-- evaluating only part of the decisions. + +procedure Test_Call_Debug_Neg is +begin + Exemptions (True, -42); +end Test_Call_Debug_Neg; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## XoF- +-- /ex_error/ l= ## X0 +-- /ex_if_debug/ l= ## Xs- +-- /ex_no_error/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb new file mode 100644 index 000000000..8b8c69085 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb @@ -0,0 +1,16 @@ +with Exemptions; + +-- Test driver for exemptions. Exercise only part of the exempted code, +-- evaluating all decisions but only part of the conditions. + +procedure Test_Call_No_Debug is +begin + Exemptions (False, 42); +end Test_Call_No_Debug; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## XoT- +-- /ex_error/ l= ## Xs- +-- /ex_if_debug/ l= ## s=>X0, dmu=>XoT- +-- /ex_no_error/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb new file mode 100644 index 000000000..7b796ffcd --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb @@ -0,0 +1,18 @@ +with Exemptions; + +-- Test driver for exemptions. It only "withes" the functional code, so the +-- only constructs that are expected to be reported as covered are those that +-- are executed/elaborated when the spec and body of the package Exemptions +-- are elaborated, of which there are none. + +procedure Test_No_Call is +begin + null; +end; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## Xs- +-- /ex_error/ l= ## Xs- +-- /ex_if_debug/ l= ## Xs- +-- /ex_no_error/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst new file mode 100644 index 000000000..5ea46ada6 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst @@ -0,0 +1,4 @@ +**Exercise exemptions over a group of statements and complex decisions** + +Exercice an exemption region within a subprogram body. + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/test.py b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/test.py old mode 100755 new mode 100644 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/test.py rename to testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/test.py diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt index 417ceef31..1005dc17e 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt @@ -8,4 +8,5 @@ drivers=_overlap|_no_overlap -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt index bcf056ca2..4642b97cb 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt @@ -9,4 +9,5 @@ drivers=_overlap|_no_overlap|invalid_a -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## Xc! -- /checkOverlap/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt index dc331d162..c3638328a 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt @@ -9,4 +9,5 @@ drivers=_overlap|_no_overlap|invalid_b -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## Xc! -- /checkOverlap/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb index 60fe80de3..03bb60845 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb @@ -14,7 +14,7 @@ package body Ranges is function Overlap (R1, R2 : XYrange) return Boolean is pragma Annotate -- # preValid (Xcov, Exempt_On, "expect no invalid ranges"); -- # preValid - pragma Precondition (R1.Valid and then R2.Valid); -- # preValid + pragma Precondition (R1.Valid and then R2.Valid); -- # preValid_cond pragma Annotate (Xcov, Exempt_Off); -- # preValid begin diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb index d6cca3064..1229dcd43 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb @@ -23,5 +23,5 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoT- -- /checkOverlap/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb index 2fe724395..e05d51638 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb @@ -23,5 +23,5 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoT- -- /checkOverlap/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb index 1adfaed7d..06eb48f37 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb @@ -24,5 +24,5 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l! ## eT- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb index 6b4c6ca4a..0e69afa0e 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb @@ -40,5 +40,5 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l! ## eF- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt b/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst b/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst index 4d946b9f5..7169abce4 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst @@ -1,8 +1,6 @@ MCDC requirements for exemption regions ======================================= -%REQ_ID% - Exemption regions shall operate over MCDC violations as they do for statement coverage violations. diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb index 3b5b4b2a2..fdd37df89 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb @@ -34,4 +34,3 @@ package body Sensors.Status is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb index 44603b2a7..8177416b8 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb @@ -3,13 +3,13 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_F_FF is S : Sensor; - + begin -- Outer If False only. Inner If False only from F or else F. S.ALB := 1; S.AHB := 15; S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb index 5cf3c1967..ccf2169ce 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb @@ -3,17 +3,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_FU_FF is S : Sensor; - + begin -- Outer If both True and False. Inner If False only from F or else F. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb index 178f5c853..9cca081b1 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb @@ -6,15 +6,15 @@ procedure Test_FU_TX is begin -- Outer If both True and False. Inner If True only from T or else X. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 0; -- < low bound Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb index ccf7554dc..c0427ae5b 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_OK is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb index 19b502264..a2b3ff264 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb @@ -4,19 +4,19 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb index a8dd68a25..9bf811870 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb @@ -3,7 +3,7 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_T_0 is S : aliased Sensor; - + begin -- Outer If True only. Inner If not reached. S.V := 5; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb index 84ac650cf..bd5d27804 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); - + Sample (S); Assert (Status_Of (S) = Ok); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb index ccacd60e1..3f3299f28 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb index 0dbd628d0..ed6ab2578 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Undecide is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb index 0ce55e079..78a70bfd4 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb index d504b04a4..74da8b900 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb index c46f26d9f..f8d1f419e 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb index acc6cac42..35b61b732 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb index a18667518..6308ac408 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb index 4a55c3ecf..4c6cd0284 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb index f6ada261e..bb507610d 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb @@ -16,4 +16,3 @@ begin Assert (Skip.Len = 1 and then Fault.Len = 0 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb index 8f1de5501..446195ea8 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb @@ -21,4 +21,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb index c00f76a1b..944e6f307 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb @@ -7,7 +7,7 @@ procedure Test_DF_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; end; @@ -25,4 +25,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb index 607625d83..97822124a 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb @@ -3,12 +3,12 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF; procedure Test_DF_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; end; @@ -26,4 +26,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb index bc296ec08..b48e33125 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb @@ -4,10 +4,10 @@ procedure Test_FU_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; - + Doif_TT_XX; end; @@ -24,4 +24,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb index 2dee78d20..4d8cf777c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb @@ -3,15 +3,15 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF, Doif_TT_XX; procedure Test_FU_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; - + Doif_TT_XX; end; @@ -28,4 +28,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb index 6c8d726ff..58c74ba50 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb index a93ffb3c1..3caac5fbd 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb index 1b846ea2d..841b44ff5 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb index 1af77d031..c02e262b5 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb index 53b003ec6..bf5bf2852 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb index 9e2c537d0..1b93fd997 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb index 9d414583a..0e66a352f 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt new file mode 100644 index 000000000..510071fba --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt @@ -0,0 +1 @@ +morello DEAD The test uses memory tricks that are prohibited on CHERI platforms diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb index dd2dd3ea3..f734bf26f 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb @@ -26,4 +26,3 @@ package body Slists.Forall is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads index d1d942c70..5d475d37b 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads @@ -3,4 +3,3 @@ package Slists.Forall is procedure ForAll_In (SL : Sensor_List; Op : Sensor_Op; Active_Only : Boolean := False); end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb index eb6b2ff8e..b30b503b7 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb index 304088fcf..fee4db76c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb @@ -42,4 +42,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb index b6cac0779..e50cf022d 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb @@ -22,4 +22,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb index 41846741b..0ef1fe350 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb @@ -44,4 +44,3 @@ end; -- /FA_tinhibitHB/ l! ## c!:"Na.S.V" -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb index ddc2e7f46..c4f15815c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb @@ -37,4 +37,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb index 734aae0d1..2e0370e01 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb @@ -37,4 +37,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb index 6d8e01c7a..3c0cfca65 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb @@ -37,4 +37,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb index 7d50620f1..1c8a40ff0 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb @@ -34,4 +34,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb index 3e2108385..904ad2066 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb @@ -26,4 +26,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb index 4125c0496..a86293311 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb @@ -28,4 +28,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb index 3f3641bd3..337dbbef9 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb index 960567620..a5d3ee5a2 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision False only from F or else F. - + S1.ALB := 1; S1.AHB := 15; S1.V := 5; -- in range Prepend (S1'Unchecked_Access, SL); - + S1.Active := True; for X in False .. True loop - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb index 4dfd25e54..f8ff6f4dc 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 30; -- > high bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb index 2fc2809e6..a66b9170f 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 0; -- < low bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb index b50f37c55..37549fde0 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb index 070f2bfbd..a169fc396 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb @@ -24,4 +24,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb index 5ecd96515..7509dbb46 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb @@ -18,4 +18,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb index bb2dae1c1..248a17063 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb @@ -7,14 +7,14 @@ procedure Test_Noinhibit is begin -- get into the inhibit case selection, arranging for the -- if statement there to always evaluate false - + S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + Prepend (S1'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst b/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst index 27da5178f..c6c9179e3 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst @@ -1,8 +1,6 @@ MCDC requirements for mixed statement and decision constructs ============================================================= -%REQ_ID% - The Core requirements are honored on programs mixing arbitrary Ada constructs together, with arbitrary levels of syntactic nesting (such as loops within IFs within subprograms etc). diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb index 404de97f8..a4f0b96fc 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb @@ -5,5 +5,3 @@ package body Sensors is Vbufs.Push (S.V, S.History); end; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads index 4af84cd8c..1700b03cd 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads @@ -16,4 +16,3 @@ package Sensors is -- latch current sensor value for S in its history buffer end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb index 168c92b9f..2701bf287 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb @@ -5,7 +5,7 @@ package body Slists is package Sensor_Nodes_Pool is new Simple_Pools.Basic_Pool (Data_Type => Sensor_Node, Capacity => 20); - + procedure Prepend (S : Sensor_Access; SL : in out Sensor_List) is NA : constant Sensor_Nodes_Pool.Data_Access := Sensor_Nodes_Pool.Allocate; begin diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads index 1e5ad1b18..49646f52c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads @@ -13,4 +13,3 @@ package Vbufs is procedure Push (V : Value; VB : in out Vbuffer); end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb index caf3118c4..c442f6695 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb @@ -7,8 +7,16 @@ end; --# ops.adb -- /incOp/ l- ## s- +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l- ## s- +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb index 8383e906d..5d61738de 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb @@ -9,8 +9,16 @@ end; --# ops.adb -- /incOp/ l+ ## 0 +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l+ ## 0 +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt deleted file mode 100644 index f10d6338c..000000000 --- a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-012: src-traces and inhibited code diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb index f90033c9b..cc4f4994e 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb @@ -6,4 +6,3 @@ begin return False; -- # false end if; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads index 714977050..9a2115848 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads @@ -9,5 +9,3 @@ function And_Eq_Or (A, B, C, D : Boolean) return Boolean; -- 1) F F F -- 2) T X T -- 3) F T T - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb index d3c27527c..665bbb5ea 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", c!:"D", dF-:"(A" -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb index 382773744..3265190d2 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", eT-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb index 615dc1be7..bcd61cbf7 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", eF-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb index 02db31115..00b3f1b18 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"A", c!:"C", dT-:"(A" -- /true/ l- ## s- -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb index 30c181e80..17289fabb 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"A", eT-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb index 1f1db709a..ebaa4f0bd 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## eT-:"A", c!:"D" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb index 3c518745e..d811f8ddb 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## eT-:"A", eT-:"C", dF-:"(A" -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb index e68b8676c..601206dd9 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb @@ -12,4 +12,3 @@ end; -- /eval/ l! ## eT-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb index 05de6d400..2c594b51b 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb @@ -12,4 +12,3 @@ end; -- /eval/ l! ## eF-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb index 06ca1bc82..0552aa03b 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## eF-:"A", c!:"D" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb index 769507a90..b2d4df7ba 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## eF-:"A", c!:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb index b3317c584..3830d7a00 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb @@ -12,4 +12,3 @@ end; -- /eval/ l! ## eF-:"A" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb index de9c71c77..d3995be0f 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## eF-:"A", eF-:"C", dF-:"(A" -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb index e89c32a3e..f2c536d04 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb @@ -2,5 +2,3 @@ function Mix (A, B, C, D, E, Z, T : Boolean) return Boolean is begin return (A and then ((B or else C) = ((D and then E) /= (Z or else T)))); -- # eval end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb index 6be17a8fe..18dcb4b92 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb @@ -4,8 +4,8 @@ procedure Test_1 is begin Assert (Mix (A => True, B => True, C => False, -- B or C True | = is T - D => False, E => False, -- D and E False | /= is T | - Z => True, T => True) -- F or G True | + D => False, E => False, -- D and E False | /= is T | + Z => True, T => True) -- F or G True | = True); end; diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb index 78ba1f3cf..290657767 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb @@ -8,5 +8,3 @@ end; --# or_eq_and_not.adb -- /eval/ l! ## c!:"B", c!:"not D" - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb index 60ba71aa7..f738d734a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb @@ -7,5 +7,3 @@ end; --# or_eq_and_not.adb -- /eval/ l! ## eF-:"A", eF-:"C" - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb index 478afbc0f..9f45fcb61 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb @@ -10,4 +10,3 @@ end; --# a1a1.adb -- /evals/ l! ## eT-:"A and then B," # eT-:"A and then B)" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb index 295479011..4cbc39255 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb @@ -1,10 +1,9 @@ with Evals; use Evals; package body A1A2 is - + procedure Process (A, B, C, D : Boolean) is begin Eval (A and then B, C and then D); -- # evals end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads index 713809595..3af024823 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads @@ -2,4 +2,3 @@ package A1A2 is procedure Process (A, B, C, D : Boolean); -- Evaluate A and then B as well as C and then B on the same line. end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb index f35128403..2a3b33107 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb index 2f10b8713..50c627ae1 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb index 706d07fad..3f1ae10b4 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb index 2b2848977..369766e59 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb index bfeffa40d..a8ebae2e4 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb index e43158709..bdb7c3e49 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb index 31835eb98..d184d0043 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb index 3d7621ea1..95c922864 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb index 67237f22f..c0f2cafbd 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb index 7c63e3fe5..0cfd2a967 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb index 47cc5403c..8e8339a65 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb index 8f884d956..acef0de02 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb index c329a5a11..d2e9d92b2 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb index 043193f21..1398bbb2c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb index a7369ec3f..0181d5975 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb index 9fc4620ea..77c52cc84 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb index b2b15fe3a..5c474c4df 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb index 80a205891..2e1bc8f04 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb index a8f4089f1..92ee9541c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb @@ -5,10 +5,9 @@ begin Process (A => True, B => False, C => True, D => False); Process (A => False, B => False, C => True, D => False); Process (A => False, B => True, C => True, D => False); - + Process (A => False, B => True, C => False, D => True); end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb index 5545381ed..4da8405b1 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb @@ -7,4 +7,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb index 2ee645591..06cd6b531 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb index 8798a0ef2..a15f5bfbf 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb index d81168336..a4aed3570 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb index 052374ee3..80feebbb5 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb @@ -7,4 +7,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb index 5cea57143..ba21bf5b0 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb @@ -7,4 +7,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb index 9d5f1276b..da606ac58 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb @@ -7,4 +7,3 @@ package body A1O2 is Eval (A and then B, C or else D); -- # evals end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads index 3e0d8e72b..629ac84db 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads @@ -2,4 +2,3 @@ package A1O2 is procedure Process (A, B, C, D : Boolean); -- Evaluate A and then B as well as C or else B on the same line. end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb index 393f1e327..3bfa0156d 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb index 2eb339f7b..37256abe2 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb index 2293263d6..ade0ceb5e 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb index 1f6bbb98c..57eccc005 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb index a91bc6dc7..3f234a6c0 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb index 43d0d31c5..ef6053313 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb index e5985ff7c..b81617d4a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb index aa1659fdf..ecae4f97d 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb index c8b6ec71c..71a2ebe22 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb index 6fa1183ad..cfcd342cc 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb index 347e18b93..7f6f621af 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb index c54ad1146..6697e6da4 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb index dc9ebaefc..762440a2d 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb index 89c65a813..cc6c8e4a6 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb index f1a67b1d7..a2842cf43 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb index 8e17f7ddb..7ac80b10e 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb index 94e4e3707..cf12bc75a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb index c26576f28..83843b0ff 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb index 2e97f56de..382ee8de6 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb @@ -5,10 +5,9 @@ begin Process (A => True, B => False, C => False, D => False); Process (A => False, B => False, C => False, D => False); Process (A => False, B => True, C => False, D => False); - + Process (A => False, B => True, C => False, D => False); end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb index c45fce867..b9a55c688 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb index d392fefa8..f81648d24 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb index 520a26d29..e7073407b 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb index c6d4e2bba..92edd8a4c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb index 349bb0a55..eeaac6697 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb @@ -7,4 +7,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb index 2b6f8d964..663f61dcd 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb @@ -7,4 +7,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb index 72a74034e..22d599584 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb @@ -9,4 +9,3 @@ package body Evals is VB := B; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads index 58ac94219..74243918a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads @@ -7,4 +7,3 @@ package Evals is procedure Eval (A, B : Boolean); end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb index 93ef737ac..8387e9793 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb @@ -8,5 +8,3 @@ begin return False; -- # false end if; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb index 5f2733a1e..78be2de43 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb @@ -3,5 +3,3 @@ begin return A -- # eval0 :o/e: and then B; -- # eval1 end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb index 7934451d2..5c2639b8c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb @@ -10,4 +10,3 @@ end; -- /eval1/ l! ## 0 -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb index d1c2c8a35..da8fb0848 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb @@ -12,4 +12,3 @@ end; -- /eval1/ l! ## 0 -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb index 9ae1c6569..ef4ed97d3 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb @@ -1,10 +1,10 @@ with Simple_Pools; package body Constructors is - + package Band_Pool is new Simple_Pools.Basic_Pool (Data_Type => Band, Capacity => 20); - + function Expr_And (A, B : Expr_Ref) return Expr_Ref is Eptr : constant Band_Pool.Data_Access := Band_Pool.Allocate; begin @@ -23,4 +23,3 @@ package body Constructors is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb index cf4477d3c..38d6535b7 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb @@ -4,5 +4,5 @@ package body Exprs.E_And is begin return E.A.all.Eval and then E.B.all.Eval; -- # eval end; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb index 73bb95dd4..424e817f8 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb @@ -4,7 +4,7 @@ package body Constructors is package Bandor_Pool is new Simple_Pools.Basic_Pool (Data_Type => Bandor, Capacity => 20); - + function Expr_Andor (A, B, C : Expr_Ref) return Expr_Ref is Eptr : constant Bandor_Pool.Data_Access := Bandor_Pool.Allocate; begin @@ -23,4 +23,3 @@ package body Constructors is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb index 37423d2bb..c5957c5bc 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb @@ -4,7 +4,7 @@ package body Constructors is package Bandor_Pool is new Simple_Pools.Basic_Pool (Data_Type => Bandor, Capacity => 20); - + function Expr_Andor (A, B, C : Expr_Ref) return Expr_Ref is Eptr : constant Bandor_Pool.Data_Access := Bandor_Pool.Allocate; begin @@ -23,4 +23,3 @@ package body Constructors is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb index acc9f379b..281481854 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb @@ -1,10 +1,10 @@ with Simple_Pools; package body Exprs.E_Val is - + package Bval_Pool is new Simple_Pools.Basic_Pool (Data_Type => Bval, Capacity => 64); - + function Eval (E : Bval) return Boolean is begin return E.V; @@ -18,4 +18,3 @@ package body Exprs.E_Val is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads index 416ded972..18407d837 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads @@ -8,4 +8,3 @@ package Exprs.E_Val is function Expr_Val (V : Boolean) return Expr_Ref; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads index 13c126148..b46c937b9 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads @@ -1,9 +1,8 @@ package Exprs is - + type Expr is abstract tagged null record; type Expr_Ref is access all Expr'Class; - + function Eval (E : Expr) return Boolean is abstract; function Eval (E : Expr_Ref) return Boolean; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/req.rst b/testsuite/Qualif/Ada/mcdc/Robustness/req.rst index dc6c9958f..bef165965 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/req.rst +++ b/testsuite/Qualif/Ada/mcdc/Robustness/req.rst @@ -1,8 +1,6 @@ MCDC requirements for potentially confusing constructs ====================================================== -%REQ_ID% - The Core MCDC requirements shall remain satisfied in presence of constructs that could fool simple minded analyzers, e.g. multiple decisions sharing a line. diff --git a/testsuite/Qualif/Ada/src/silent_last_chance.adb b/testsuite/Qualif/Ada/src/silent_last_chance.adb deleted file mode 100644 index e5b394bd3..000000000 --- a/testsuite/Qualif/Ada/src/silent_last_chance.adb +++ /dev/null @@ -1,18 +0,0 @@ -package body Silent_Last_Chance is - - ------------------------- - -- Last_Chance_Handler -- - ------------------------- - - procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is - pragma Unreferenced (Msg, Line); - - procedure C_abort; - pragma Import (C, C_abort, "abort"); - pragma No_Return (C_abort); - begin - -- No return procedure. - C_abort; - end Last_Chance_Handler; - -end; diff --git a/testsuite/Qualif/Ada/src/support.adb b/testsuite/Qualif/Ada/src/support.adb deleted file mode 100644 index e7e059c05..000000000 --- a/testsuite/Qualif/Ada/src/support.adb +++ /dev/null @@ -1,20 +0,0 @@ - -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - - function Identity (X : Integer) return Integer is - begin - return X; - end; - - function Identity (B : Boolean) return Boolean is - begin - return B; - end; -end; diff --git a/testsuite/Qualif/Ada/src/support.ads b/testsuite/Qualif/Ada/src/support.ads deleted file mode 100644 index f009ccc8c..000000000 --- a/testsuite/Qualif/Ada/src/support.ads +++ /dev/null @@ -1,9 +0,0 @@ - -package Support is - procedure Assert (Cond : Boolean); - function Identity (X : Integer) return Integer; - function Identity (B : Boolean) return Boolean; - - function Value (X : Integer) return Integer renames Identity; - function Value (B : Boolean) return Boolean renames Identity; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_assert_debug.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_assert_debug.adb deleted file mode 100755 index ca11eb8d5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_assert_debug.adb +++ /dev/null @@ -1,38 +0,0 @@ --- Test driver for pragmas. It calls a subprogram that has Precondition and --- Postcondition pragmas associated with it, so these pragmas are expected to --- be reported as covered, and Debug and Assert pragmas - as uncovered. - -with Support; use Support; -with Pragmas; use Pragmas; - -procedure Test_Pragmas_Assert_Debug is -begin - Assert (not In_Range (1, 2, 1)); - Assert (not In_Range (1, 2, 2)); - Assert (In_Range (3, 2, 4)); - Assert (not In_Range (5, 2, 4)); - Assert (not In_Range (1, 2, 4)); -end Test_Pragmas_Assert_Debug; - ---# pragmas.adb --- /pre_check_val/ l. ## 0 --- /post_check_val/ l. ## 0 --- /check_val/ l- ## s- --- /neverexecuted/ l- ## s- - --- /mainstream/ l+ ## 0 --- /nonemptyrange/ l+ ## 0 --- /morethenoneinrange/ l+ ## 0 --- /emptyrange/ l+ ## 0 --- /oneelement/ l+ ## 0 --- /XgtR/ l+ ## 0 --- /XltL/ l+ ## 0 --- /1debug/ l+ ## 0 --- /2debug/ l+ ## 0 --- /1assert/ l+ ## 0 --- /2assert/ l+ ## 0 --- /3assert/ l+ ## 0 --- /4assert/ l+ ## 0 - --- /safedecl/ ~l- ## ~s- --- /is_safe/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst deleted file mode 100755 index 794042b5c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst +++ /dev/null @@ -1,7 +0,0 @@ -**Exercise SC on active pragmas** - -Check that active pragmas which are not elaborated are reported as -uncovered. Exercise Assert, Debug, Precondition and Postcondition pragmas -placed in various source contexts. - -LRMREF: 2.8 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt deleted file mode 100644 index 9271f3fe6..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL TODO: revisit requirements and expectations once we re-enable assertion instrumentation (U528-022) \ No newline at end of file diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.adb deleted file mode 100644 index 49f4f0106..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.adb +++ /dev/null @@ -1,17 +0,0 @@ --- Disable the pragmas we will use downstream - -pragma Check_Policy (Assertion, Off); - -package body Asserts is - procedure Sum (X, Y, UB : Integer; R : out Integer) is - begin - pragma Assert (X + Y <= UB); -- # assert - R := X + Y; -- # eval - end; - - procedure Dif (X, Y, LB : Integer; R : out Integer) is - begin - R := X - Y; -- # eval - pragma Assert (X - Y >= LB); -- # assert - end; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads deleted file mode 100644 index 6046428a1..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Asserts is - procedure Sum (X, Y, UB : Integer; R : out Integer); - procedure Dif (X, Y, LB : Integer; R : out Integer); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb deleted file mode 100644 index 880d0ed8d..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb +++ /dev/null @@ -1,14 +0,0 @@ -with Support, Asserts; use Asserts, Support; - --- Don't call into the functional code. Expect s- only on active lines --- with real statements, not on the pragma ones since deactivated by the --- check policy. - -procedure Test_Asserts_0 is -begin - null; -end; - ---# asserts.adb --- /eval/ l- ## s- --- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb deleted file mode 100644 index 7b3d00994..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb +++ /dev/null @@ -1,14 +0,0 @@ -with Support, Asserts; use Asserts, Support; - -procedure Test_Asserts_T is - R : Integer; -begin - Sum (X => 2, Y => 3, UB => 10, R => R); - Assert (R = 5); - Dif (X => 5, Y => 1, LB => 1, R => R); - Assert (R = 4); -end; - ---# asserts.adb --- /eval/ l+ ## 0 --- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst deleted file mode 100644 index 2ba136583..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst +++ /dev/null @@ -1,8 +0,0 @@ -**Exercise SC on inactive pragmas** - -Check that inactive pragmas are ignored; Place Assert pragmas at various -locations in a number of subprogram bodies, and verify that they are never -reported uncovered, even when the subprograms are not called. - -LRMREF: 2.8 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.adb new file mode 100644 index 000000000..bfb8973c9 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.adb @@ -0,0 +1,25 @@ +-- Disable the pragmas we will use downstream + +pragma Check_Policy (Assertion, Off); + +package body Pragmas is + + procedure Log_Debug is + begin + Debug_Events := Debug_Events + 1; -- # log + end; + + procedure Sum (X, Y, UB : Integer; R : out Integer) is + begin + pragma Debug (Log_Debug); -- # debug + pragma Assert (X + Y <= UB); -- # assert + R := X + Y; -- # eval + end; + + procedure Dif (X, Y, LB : Integer; R : out Integer) is + begin + pragma Debug (Log_Debug); -- # debug + R := X - Y; -- # eval + pragma Assert (X - Y >= LB); -- # assert + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads new file mode 100644 index 000000000..e0c224e9e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads @@ -0,0 +1,16 @@ +package Pragmas is + procedure Sum (X, Y, UB : Integer; R : out Integer); + procedure Dif (X, Y, LB : Integer; R : out Integer); + + -- Number of calls to subprogram invoked through pragma + -- Debug. Shoulds remain 0 as we're in a testcase intended to + -- exercise situations where such pragmas are deactivated + -- by a Check_Policy. + Debug_Events : Integer := 0; + + procedure Log_Debug; + -- Register a Debug_Event. Exposed to prevent removal of the + -- entire subprogram by optimization when it happens to be + -- never called, which would make it "no code" for binary traces. + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb new file mode 100644 index 000000000..56c62856b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb @@ -0,0 +1,21 @@ +with Support, Pragmas; use Pragmas, Support; + +-- Don't call into the functional code. Expect s- only on active lines +-- with real statements, not on the inactive pragma ones. + +procedure Test_Pragmas_0 is +begin + Assert (Pragmas.Debug_Events = 0); +end; + +--# pragmas.adb +-- /eval/ l- ## s- +-- /log/ l- ## s- + +--%opts:--trace-mode=bin +-- /debug/ l. ## 0 +-- /assert/ l. ## 0 + +--%opts:--trace-mode=src +-- /debug/ l- ## s- +-- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb new file mode 100644 index 000000000..2d704568c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb @@ -0,0 +1,30 @@ +with Support, Pragmas; use Pragmas, Support; + +-- Invoke the two subprograms, each featuring Assert and Debug +-- pragmas. Compilation-wise, the pragmas are inactive and the +-- Log_Debug subprogram is never called. + +-- pragma Debug is perceived as an active "statement" by the +-- source instrumenter, though, and pragma Assert not. + +procedure Test_Pragmas_T is + R : Integer; +begin + Sum (X => 2, Y => 3, UB => 10, R => R); + Assert (R = 5); + Dif (X => 5, Y => 1, LB => 1, R => R); + Assert (R = 4); + Assert (Debug_Events = 0); +end; + +--# pragmas.adb +-- /eval/ l+ ## 0 +-- /log/ l- ## s- + +--%opts:--trace-mode=bin +-- /debug/ l. ## 0 +-- /assert/ l. ## 0 + +--%opts:--trace-mode=src +-- /debug/ l+ ## 0 +-- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst new file mode 100644 index 000000000..ba25bc6af --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst @@ -0,0 +1,10 @@ +**Exercise SC on pragmas deactivated by a Debug or Assertion/Check policy** + +With binary traces, all the pragmas possibly generating code should +not be considered as statements. + +With source traces, the non-Assert pragmas should be considered as +statements despite the Policy deactivating them for compilation purposes. + +LRMREF: 2.8 + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/test.py b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.ads rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.adb similarity index 99% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.adb index c752ec3ae..98d03b1a9 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.adb @@ -11,4 +11,3 @@ package body Support_Pragmas is end Debug_Proc2; end Support_Pragmas; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.ads rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_assert_debug.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_assert_debug.adb new file mode 100755 index 000000000..b48085c74 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_assert_debug.adb @@ -0,0 +1,46 @@ +-- Test driver for pragmas. It calls a subprogram that has +-- Precondition and Postcondition pragmas associated with it and +-- paths to all the Debug and Assert pragmas therein are exercised. + +with Support; use Support; +with Pragmas; use Pragmas; + +procedure Test_Pragmas_Assert_Debug is +begin + Assert (not In_Range (1, 2, 1)); + Assert (not In_Range (1, 2, 2)); + Assert (In_Range (3, 2, 4)); + Assert (not In_Range (5, 2, 4)); + Assert (not In_Range (1, 2, 4)); +end Test_Pragmas_Assert_Debug; + +--# pragmas.adb +-- /pre_check_val/ l. ## 0 +-- /post_check_val/ l. ## 0 +-- /check_val/ l- ## s- +-- /neverexecuted/ l- ## s- + +-- /mainstream/ l+ ## 0 +-- /nonemptyrange/ l+ ## 0 +-- /morethenoneinrange/ l+ ## 0 +-- /emptyrange/ l+ ## 0 +-- /oneelement/ l+ ## 0 +-- /XgtR/ l+ ## 0 +-- /XltL/ l+ ## 0 +-- /safedecl/ ~l- ## ~s- +-- /is_safe/ l- ## s- + +-- /1debug/ l+ ## 0 +-- /2debug/ l+ ## 0 + +--%opts: --trace-mode=bin +-- /1assert/ l+ ## 0 +-- /2assert/ l+ ## 0 +-- /3assert/ l+ ## 0 +-- /4assert/ l+ ## 0 + +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_full.adb similarity index 85% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_full.adb index efc131937..6ad53e7c6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_full.adb @@ -28,11 +28,19 @@ end Test_Pragmas_Full; -- /oneelement/ l+ ## 0 -- /XgtR/ l+ ## 0 -- /XltL/ l+ ## 0 +-- /is_safe/ l+ ## 0 + -- /1debug/ l+ ## 0 -- /2debug/ l+ ## 0 + +--%opts: --trace-mode=bin -- /1assert/ l+ ## 0 -- /2assert/ l+ ## 0 -- /3assert/ l+ ## 0 -- /4assert/ l+ ## 0 --- /is_safe/ l+ ## 0 +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_no.adb similarity index 83% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_no.adb index be9fcff48..41fc8ca8d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_no.adb @@ -25,12 +25,20 @@ end Test_Pragmas_No; -- /oneelement/ l- ## s- -- /XgtR/ l- ## s- -- /XltL/ l- ## s- +-- /safedecl/ ~l- ## ~s- +-- /is_safe/ l- ## s- + -- /1debug/ l- ## s- -- /2debug/ l- ## s- + +--%opts: --trace-mode=bin -- /1assert/ l- ## s- -- /2assert/ l- ## s- -- /3assert/ l- ## s- -- /4assert/ l- ## s- --- /safedecl/ ~l- ## ~s- --- /is_safe/ l- ## s- +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_pre_post.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_pre_post.adb similarity index 77% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_pre_post.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_pre_post.adb index 200a68534..546baabd4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_pre_post.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_pre_post.adb @@ -25,11 +25,22 @@ end Test_Pragmas_Pre_Post; -- /oneelement/ l- ## s- -- /XgtR/ l- ## s- -- /XltL/ l- ## s- +-- /is_safe/ l+ ## 0 + -- /1debug/ l- ## s- -- /2debug/ l- ## s- + +-- Assert pragmas are activated explicitly in this testcase, +-- but considered always inactive for source traces + +--%opts: --trace-mode=bin -- /1assert/ l- ## s- -- /2assert/ l- ## s- -- /3assert/ l- ## s- -- /4assert/ l- ## s- --- /is_safe/ l+ ## 0 +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst new file mode 100755 index 000000000..dc8440406 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst @@ -0,0 +1,9 @@ +**Exercise SC on pragmas activated by a Debug or Assertion/Check policy** + +With binary traces, all the pragmas possibly generating code should +be considered as statements. + +With source traces, the Assert pragmas should not be considered as +statements despite the Policy activating them for compilation purposes. + +LRMREF: 2.8 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst index 91350979d..ac653e750 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst @@ -2,32 +2,37 @@ SC requirements for Pragmas (ARM 2.8) ===================================== -%REQ_ID% +Different kinds of pragmas exist, some possibly generating code such +as `Debug` or `Assert` pragmas. From the compiler standpoint, these +are either active or ignored depending on `Assertion_Policy`, +`Check_Policy` controls or alike. For statement coverage analysis, +they shall be considered as statements on their own according to the +following rules: -Different kinds of pragmas exist, some always active, some possibly ignored -depending on configuration parameters. They may be located in various -contexts, some possibly never elaborated such as as subprogram declarative -parts. - -* Inactive pragmas shall be ignored; - -* Active pragmas that were never elaborated as part of the program execution - shall be reported uncovered. +- With binary traces, a pragma is considered as a statement in + accordance with the actual Assertion/Debug/Check policy applicable + to the unit where the pragma appears, which makes it active or + inactive from the compiler's standpoint. +- With source instrumentation, Assert-like pragmas (Assert, + Assert_And_Cut, Check, Precondition/Postcondition, Assume, + Loop_Invariant, Type_Invariant) are never considered as statements + on their own and all the other pragmas are always considered as + statements, regardless of the Assertion/Debug/Check policy applying to + their unit. .. rubric:: Testing Strategy +Exercise Assert, Debug, Precondition and Postcondition pragmas placed +in various source contexts, explicitly either activated or deactivated +by local Check_Policy or Debug_Policy. - -We check this requirement for different kinds of pragmas in various -possible source regions, with the following set of testcases: - +Check that pragmas considered as statements but never elaborated are +reported uncovered and that other pragmas are ignored. .. qmlink:: TCIndexImporter * - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb index c67bd53c9..c26151380 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb @@ -47,4 +47,4 @@ package body Defs is return Result; -- # 2_stmt end Some_Fun_2; -end; \ No newline at end of file +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads index b4bc3465a..91c54c392 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads @@ -29,4 +29,4 @@ package Defs is -- real-life-looking contest for a discrete subtype definition in the -- body. -end; \ No newline at end of file +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb index f83329177..1a8967e5a 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb @@ -28,7 +28,3 @@ end; -- /2_1_loop/ l- ## s- -- /2_2_loop/ l- ## s- -- /2_if/ l- ## s- - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb index 9fbf4a74e..a35240c76 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb @@ -1,5 +1,5 @@ package body Heap is - + function Ptr_To_Abs (X : Integer) return Integer_Access is begin if X > 0 then -- # on-call diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads index 2f52e7cfe..481000c12 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads @@ -1,10 +1,10 @@ package Heap is - + -- This unit is devised to expose services making use of heap allocation -- in object declarations. type Integer_Access is access Integer; function Ptr_To_Abs (X : Integer) return Integer_Access; - + Global : Integer_Access := new Integer'(15); -- # global-decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb index 7f30afa8b..377d24cd3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb @@ -14,4 +14,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb index b4f8723c8..2879643e7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb @@ -17,4 +17,3 @@ end; -- /pos-stmt/ l+ ## 0 -- /neg-decl/ l+ ## 0 -- /neg-stmt/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb index 5d7717a7e..69e7e89ce 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb @@ -15,4 +15,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l+ ## 0 -- /neg-stmt/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb index 6870db52c..ea4a63496 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb @@ -15,4 +15,3 @@ end; -- /pos-stmt/ l+ ## 0 -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb index 6a2bd1e58..9d9428a69 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb @@ -1,6 +1,6 @@ with Vectors; use Vectors; - -procedure Test_Vector_0 is + +procedure Test_Vectors_0 is begin null; end; @@ -11,4 +11,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb index beaa3f237..313f5b0cf 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb @@ -1,5 +1,5 @@ with Support, Vectors; use Support, Vectors; - + procedure Test_Vectors_Neg is begin Assert (Sum_All_Abs (N => 7, Value => -4) = 28); @@ -11,4 +11,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l+ ## 0 -- /neg-stmt/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb index e0883533b..373abe394 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb @@ -1,5 +1,5 @@ with Support, Vectors; use Support, Vectors; - + procedure Test_Vectors_Pos is begin Assert (Sum_All_Abs (N => 5, Value => 3) = 15); @@ -11,4 +11,3 @@ end; -- /pos-stmt/ l+ ## 0 -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb index 2c1642151..8c60b3370 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb @@ -1,11 +1,11 @@ package body Vectors is - + function All_Same (N : Integer; Value : Integer) return Vector is begin return Vector'(1 .. N => Value); -- # on-call end; - + function Sum_All_In (V : Vector) return Integer is Sum : Integer := 0; -- # on-call begin @@ -14,12 +14,12 @@ package body Vectors is end loop; return Sum; -- # on-call end; - + function Sum_All_Abs (N : Integer; Value : Integer) return Integer is begin -- point here is to have conditional object declarations resorting to a -- function returning unconstrained for initializers - + if Value > 0 then -- # on-call declare V : Vector := All_Same (N, Value); -- # pos-decl @@ -34,5 +34,5 @@ package body Vectors is end; end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads index 8f0e7e447..6eef34a53 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads @@ -1,10 +1,10 @@ package Vectors is - + -- This unit is devised to expose services making use of unconstrained -- array types requiring secondary stack allocations for oject declarations. - + type Vector is array (Natural range <>) of Integer; - + function Sum_All_Abs (N : Integer; Value : Integer) return Integer; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt index 5484161b8..22f48c3f5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt @@ -1 +1 @@ -7.1.2,RTS_ZFP DEAD the 7.1.2 zfp RTS doesn't support dynamic allocations \ No newline at end of file +7.1.2,RTS_ZFP DEAD the 7.1.2 zfp RTS doesn't support dynamic allocations diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb index a15c2b5b3..7d48c1121 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb @@ -9,4 +9,3 @@ begin I := J; -- # stmt J := Tmp; -- # stmt end Integer_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb index 5b9111134..669d716d6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb @@ -9,4 +9,3 @@ begin M1 := M2; -- # stmt M2 := Tmp; -- # stmt end Matrix_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb index c85f575db..02051f135 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb @@ -8,4 +8,3 @@ begin V1 := V2; -- # stmt V2 := Tmp; -- # stmt end Private_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb index 6ffef2c1e..a52ef805f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb @@ -12,4 +12,3 @@ begin V2 := Tmp; -- # if end if; end Record_Derived_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb index d385fc272..f89673b47 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb @@ -12,4 +12,3 @@ begin V2 := Tmp; -- # if end if; end Record_Impl_Init_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb index edd45d6bf..80dc3e03f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb @@ -8,4 +8,3 @@ begin C1 := C2; -- # stmt C2 := Tmp; -- # stmt end Record_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb index ca486db22..764837e16 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb @@ -19,7 +19,7 @@ with Support; use Support; procedure Test_Object_Declarations_Full is package Decls_Pack_Matrix is new Decls_Pack_Matrix_G (1, 2); use Decls_Pack_Matrix; - + package Decls_Pack_Records is new Decls_Pack_Records_G; use Decls_Pack_Records; @@ -37,7 +37,7 @@ procedure Test_Object_Declarations_Full is Coord1 : Coordinate := Coordinate_Zero; Coord2 : Coordinate := (1.0, 1.0); - + Coord_Value1 : aliased Coordinate := (1.0, 2.0); Coord_Value2 : aliased Coordinate := (3.0, 4.0); Coord_Var1 : Access_All_Coordinate := Coord_Value1'Unchecked_Access; @@ -48,10 +48,10 @@ procedure Test_Object_Declarations_Full is Matr1 : Matrix := (1 => (1 => 1)); Matr2 : Matrix := (1 => (1 => 2)); - + P_Var1 : T_Private := Get_Private (10); P_Var2 : T_Private := Get_Private (20); - + Int_Value1 : aliased Integer := 1; Int_Value2 : aliased Integer := 2; Var1 : Access_All_Integer := Int_Value1'Unchecked_Access; @@ -97,7 +97,7 @@ begin Assert (Coord2 = Coordinate_Zero and then Coord1 = (1.0, 1.0)); -- Call all the subprograms from library packages - + Decls_Pack_1.Local_Swap (Int1, Int2); Assert (Int1 = 1 and then Int2 = 2); Assert (Decls_Pack_1.Local_Fun (Mon) = Tue); @@ -112,7 +112,7 @@ begin Decls_Pack_Records.Local_Swap (Coord1, Coord2); Assert (Coord1 = Coordinate_Zero and then Coord2 = (1.0, 1.0)); - + Decls_Pack_Derived_Records.Local_Swap (V1, V2); Assert (V1.X = 2.0 and then V1.Y = 20.0 and then diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb index fe03e74b2..868b3b06d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb @@ -40,4 +40,3 @@ end Test_Object_Declarations_No; --# record_impl_init_swap.adb -- /stmt/ l- ## s- -- /if/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb index 17e5f5ea6..1cd5a77f2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb @@ -27,7 +27,7 @@ procedure Test_Object_Declarations_Part_1 is package Decls_Pack_Matrix is new Decls_Pack_Matrix_G (1, 2); use Decls_Pack_Matrix; - + package Decls_Pack_Derived_Records is new Decls_Pack_Derived_Records_G; use Decls_Pack_Derived_Records; @@ -44,7 +44,7 @@ procedure Test_Object_Declarations_Part_1 is Matr1 : Matrix := (1 => (1 => 1)); Matr2 : Matrix := (1 => (1 => 2)); - + V1 : Derived_Coordinate := (1.0, 10.0); V2 : Derived_Coordinate := (2.0, 20.0); begin @@ -64,7 +64,7 @@ begin Matrix_Swap (Matr1, Matr2); Assert (Matr1 (1, 1) = 2 and then Matr2 (1, 1) = 1); - + -- Call subprograms from library packages Decls_Pack_1.Local_Swap (Int1, Int2); Assert (Int1 = 1 and then Int2 = 2); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_full.adb new file mode 100755 index 000000000..96780bec2 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_full.adb @@ -0,0 +1,33 @@ +-- Test driver for subtype indications. It calls all the subprograms from the +-- functional code, so the library-level declaration and all the local +-- declarations are expected to be reported as covered. + +with Decls_Support; use Decls_Support; +with Subtype_Indications; use Subtype_Indications; +with Support; use Support; + +procedure Test_Full is + V : Var_String := Get_Var_String (1, "a"); + V1 : Vector (1 .. 3) := (1, 2, 3); + V2 : Vector (1 .. 3); + +begin + Assert (V.Data = "a"); + + V2 := Simple_Sort (V1); + Assert (V2 (1) = 3 and then V2 (2) = 2 and then V2 (3) = 1); + + Assert (Some_Fun (2, "ab") = 2); +end Test_Full; + +--# subtype_indications.ads +-- /dcl/ l+ ## 0 + +--# subtype_indications.adb +-- /1_local_dcl/ l+ ## 0 +-- /1_stmt/ l+ ## 0 +-- /2_local_dcl/ l+ ## 0 +-- /2_bare_dcl/ ~l+ ## 0 +-- /2_stmt/ l+ ## 0 +-- /3_local_dcl/ l+ ## 0 +-- /3_stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_no.adb new file mode 100755 index 000000000..91f32b66b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_no.adb @@ -0,0 +1,23 @@ +-- Test driver for subtype indications. It only 'with's the functional code +-- but does not call anything from it, so only the library-level declaration +-- is expected to be reported as covered. + +with Subtype_Indications; +with Support; use Support; + +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# subtype_indications.ads +-- /dcl/ l+ ## 0 + +--# subtype_indications.adb +-- /1_local_dcl/ l- ## s- +-- /1_stmt/ l- ## s- +-- /2_local_dcl/ l- ## s- +-- /2_bare_dcl/ ~l- ## ~s- +-- /2_stmt/ l- ## s- +-- /3_local_dcl/ l- ## ~s- +-- /3_stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_1.adb new file mode 100755 index 000000000..b71172adb --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_1.adb @@ -0,0 +1,27 @@ +-- Test driver for subtype indications. It calls a subprogram from the +-- functional code (another driver - Test_Part_2 calls other routines), +-- so the library-level declaration and some of the local declarations are +-- expected to be reported as covered, and other local declarations are +-- expected to be reported as uncovered. + +with Decls_Support; use Decls_Support; +with Subtype_Indications; use Subtype_Indications; +with Support; use Support; + +procedure Test_Part_1 is + V : Var_String := Get_Var_String (1, "a"); +begin + Assert (V.Data = "a"); +end Test_Part_1; + +--# subtype_indications.ads +-- /dcl/ l+ ## 0 + +--# subtype_indications.adb +-- /1_local_dcl/ l+ ## 0 +-- /1_stmt/ l+ ## 0 +-- /2_local_dcl/ l- ## s- +-- /2_bare_dcl/ ~l- ## ~s- +-- /2_stmt/ l- ## s- +-- /3_local_dcl/ l- ## ~s- +-- /3_stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_2.adb new file mode 100755 index 000000000..6f89e2fe7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_2.adb @@ -0,0 +1,32 @@ +-- Test driver for subtype indications. It calls two subprograms from the +-- functional code (another driver - Test_Part_1 calls another routine), so +-- the library-level declaration and some of the local declarations are +-- expected to be reported as covered, and other local declarations are +-- expected to be reported as uncovered. + +with Decls_Support; use Decls_Support; +with Subtype_Indications; use Subtype_Indications; +with Support; use Support; + +procedure Test_Part_2 is + V1 : Vector (1 .. 3) := (1, 2, 3); + V2 : Vector (1 .. 3); + +begin + V2 := Simple_Sort (V1); + Assert (V2 (1) = 3 and then V2 (2) = 2 and then V2 (3) = 1); + + Assert (Some_Fun (2, "ab") = 2); +end Test_Part_2; + +--# subtype_indications.ads +-- /dcl/ l+ ## 0 + +--# subtype_indications.adb +-- /1_local_dcl/ l- ## s- +-- /1_stmt/ l- ## s- +-- /2_local_dcl/ l+ ## 0 +-- /2_bare_dcl/ ~l+ ## 0 +-- /2_stmt/ l+ ## 0 +-- /3_local_dcl/ l+ ## 0 +-- /3_stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb deleted file mode 100755 index 16ff72855..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb +++ /dev/null @@ -1,38 +0,0 @@ --- Test driver for subtype indications. It calls all the subprograms from the --- functional code, so the library-level declaration and all the local --- declarations are expected to be reported as covered. - -with Decls_Support; use Decls_Support; -with Subtype_Indications; use Subtype_Indications; -with Support; use Support; - -procedure Test_Subtype_Indications_Full is - V : Var_String := Get_Var_String (1, "a"); - V1 : Vector (1 .. 3) := (1, 2, 3); - V2 : Vector (1 .. 3); - -begin - Assert (V.Data = "a"); - - V2 := Simple_Sort (V1); - Assert (V2 (1) = 3 and then V2 (2) = 2 and then V2 (3) = 1); - - Assert (Some_Fun (2, "ab") = 2); -end Test_Subtype_Indications_Full; - ---# subtype_indications.ads --- /dcl/ l+ ## 0 - ---# subtype_indications.adb --- /1_local_dcl/ l+ ## 0 --- /1_stmt/ l+ ## 0 --- /2_local_dcl/ l+ ## 0 --- /2_bare_dcl/ ~l+ ## 0 --- /2_stmt/ l+ ## 0 --- /3_local_dcl/ l+ ## 0 --- /3_stmt/ l+ ## 0 - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb deleted file mode 100755 index 15bdcfdc8..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb +++ /dev/null @@ -1,28 +0,0 @@ --- Test driver for subtype indications. It only 'with's the functional code --- but does not call anything from it, so only the library-level declaration --- is expected to be reported as covered. - -with Subtype_Indications; -with Support; use Support; - -procedure Test_Subtype_Indications_No is -begin - Assert (True); -end Test_Subtype_Indications_No; - ---# subtype_indications.ads --- /dcl/ l+ ## 0 - ---# subtype_indications.adb --- /1_local_dcl/ l- ## s- --- /1_stmt/ l- ## s- --- /2_local_dcl/ l- ## s- --- /2_bare_dcl/ ~l- ## ~s- --- /2_stmt/ l- ## s- --- /3_local_dcl/ l- ## ~s- --- /3_stmt/ l- ## s- - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb deleted file mode 100755 index 3c6bb7722..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb +++ /dev/null @@ -1,32 +0,0 @@ --- Test driver for subtype indications. It calls a subprogram from the --- functional code (another driver - Test_Subtype_Indications_Part_2 calls --- other routines), so the library-level declaration and some of the local --- declarations are expected to be reported as covered, and other local --- declarations are expected to be reported as uncovered. - -with Decls_Support; use Decls_Support; -with Subtype_Indications; use Subtype_Indications; -with Support; use Support; - -procedure Test_Subtype_Indications_Part_1 is - V : Var_String := Get_Var_String (1, "a"); -begin - Assert (V.Data = "a"); -end Test_Subtype_Indications_Part_1; - ---# subtype_indications.ads --- /dcl/ l+ ## 0 - ---# subtype_indications.adb --- /1_local_dcl/ l+ ## 0 --- /1_stmt/ l+ ## 0 --- /2_local_dcl/ l- ## s- --- /2_bare_dcl/ ~l- ## ~s- --- /2_stmt/ l- ## s- --- /3_local_dcl/ l- ## ~s- --- /3_stmt/ l- ## s- - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb deleted file mode 100755 index dfeb13a2d..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb +++ /dev/null @@ -1,37 +0,0 @@ --- Test driver for subtype indications. It calls two subprograms from the --- functional code (another driver - Test_Subtype_Indications_Part_1 calls --- another routin), so the library-level declaration and some of the local --- declarations are expected to be reported as covered, and other local --- declarations are expected to be reported as uncovered. - -with Decls_Support; use Decls_Support; -with Subtype_Indications; use Subtype_Indications; -with Support; use Support; - -procedure Test_Subtype_Indications_Part_2 is - V1 : Vector (1 .. 3) := (1, 2, 3); - V2 : Vector (1 .. 3); - -begin - V2 := Simple_Sort (V1); - Assert (V2 (1) = 3 and then V2 (2) = 2 and then V2 (3) = 1); - - Assert (Some_Fun (2, "ab") = 2); -end Test_Subtype_Indications_Part_2; - ---# subtype_indications.ads --- /dcl/ l+ ## 0 - ---# subtype_indications.adb --- /1_local_dcl/ l- ## s- --- /1_stmt/ l- ## s- --- /2_local_dcl/ l+ ## 0 --- /2_bare_dcl/ ~l+ ## 0 --- /2_stmt/ l+ ## 0 --- /3_local_dcl/ l+ ## 0 --- /3_stmt/ l+ ## 0 - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt index 41fffe494..3bdc92db6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt @@ -1 +1 @@ -7.1.2,RTS_ZFP DEAD test resorts to sec stack, not in the 7.1.2 zfp RTS \ No newline at end of file +7.1.2,RTS_ZFP DEAD test resorts to sec stack, not in the 7.1.2 zfp RTS diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst index 8aef7d67b..31647949c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst @@ -1,8 +1,6 @@ SC requirements for ARM chap. 3 : Declarations and Types ======================================================== -%REQ_ID% - Declarations that were never elaborated as part of the program execution shall be reported as uncovered. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb index 7eacf06bd..65b79a8b4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb @@ -20,4 +20,3 @@ package body Assignment_Statements is end Max_Value; end Assignment_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads index 0c9ad10a3..839c835ee 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads @@ -4,4 +4,3 @@ package Assignment_Statements is -- These subprograms contain assignment statements in straightline -- statement sequences end Assignment_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb index 8a5826ec6..294f5ad30 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb @@ -2,4 +2,3 @@ package body Assignment_Statements_Elab is begin I := 1 ; end Assignment_Statements_Elab; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads index 1e62794c9..78012f874 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads @@ -3,4 +3,3 @@ package Assignment_Statements_Elab is pragma Elaborate_Body; I: Integer; end Assignment_Statements_Elab; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads index 594f4372d..8ce2e885f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads @@ -17,4 +17,3 @@ package Null_Statements is -- statement sequence end Null_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb index 00bdcce73..1210df1b5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb @@ -88,4 +88,3 @@ package body EXIT_Statements is end Compute_On_Matrix; end EXIT_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads index fbbed4f92..16e3ea3cf 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads @@ -35,4 +35,3 @@ package EXIT_Statements is -- inner loop, both of them exit the outer loop. end EXIT_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads index 6a2fd3041..2a54b73cb 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads @@ -7,4 +7,3 @@ package EXIT_Statements_Support is type Matrix_Sample is array (Natural range <>, Natural range <>) of Integer; end EXIT_Statements_Support; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb index 40bb67fab..b212c79f2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb @@ -122,4 +122,3 @@ package body GOTO_Statements_Loop is end Update_Sample; end GOTO_Statements_Loop; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb index c4c2094ac..70ce37b5d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb @@ -23,4 +23,3 @@ package body GOTO_Statements_Straight is end; end GOTO_Statements_Straight; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst index 6531fea1d..11fe795d7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst @@ -2,8 +2,6 @@ SC requirements for ARM chap. 5 : Simple Statements =================================================== -%REQ_ID% - A simple statement (i.e., one that does not contain other statements) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb index ecbc45472..a5a502808 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb @@ -16,8 +16,6 @@ begin Assert (My_Max_From_Two (1, 3) = 3); - Assert (Global_Var = 11); - Set_Prime_Number (Num => 50, Res => Res); Assert (Res = 0); @@ -57,7 +55,3 @@ end Test_ELSE_Path; -- /max/ l+ ## 0 -- /ifmax/ l- ## s- -- /elsemax/ l+ ## 0 --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb index b583fce2b..9f62cb5ce 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb @@ -14,8 +14,6 @@ begin Set_Prime_Number (Res, 2); Assert (Res = 3); - - Assert (Global_Var = 11); end Test_ELSIF_Path_First; --# if_statements.adb @@ -52,10 +50,6 @@ end Test_ELSIF_Path_First; -- /max/ ~l- ## ~s- -- /ifmax/ ~l- ## ~s- -- /elsemax/ ~l- ## ~s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- -- We have stricter expectations on uncalled subprograms -- with instrumentation, in particular wrt declarations. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb index aeb49b500..2eefb4b90 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb @@ -11,8 +11,6 @@ begin Set_Prime_Number (Res, 10); Assert (Res = 29); - - Assert (Global_Var = 11); end Test_ELSIF_Path_Last; --# more_if_statements.adb @@ -40,10 +38,6 @@ end Test_ELSIF_Path_Last; -- /max/ ~l- ## ~s- -- /ifmax/ ~l- ## ~s- -- /elsemax/ ~l- ## ~s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- -- %opts: --trace-mode=src -- =/max/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb index 429dcebc0..45a1c555c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb @@ -11,8 +11,6 @@ begin Set_Prime_Number (Res, 6); Assert (Res = 13); - - Assert (Global_Var = 11); end Test_ELSIF_Path_Middle; --# more_if_statements.adb @@ -40,10 +38,6 @@ end Test_ELSIF_Path_Middle; -- /max/ ~l- ## ~s- -- /ifmax/ ~l- ## ~s- -- /elsemax/ ~l- ## ~s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- -- %opts: --trace-mode=src -- =/max/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads new file mode 100644 index 000000000..72dcb0e77 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + Init_Ref : Integer := -2; + -- A value to get into the ELSE branch +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb new file mode 100644 index 000000000..17e8686a0 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb @@ -0,0 +1,17 @@ +with Lib_If_Statements; +with Support; use Support; + +procedure Test_Init_Else is + X : Integer; +begin + X := Lib_If_Statements.Probe (Slot => 1); + Assert (X < 0); +end; + +--# lib_if_statements.adb +-- /test_if/ l+ ## 0 +-- /do_if/ l- ## s- +-- /test_elsif/ l+ ## 0 +-- /do_elsif/ l- ## s- +-- /test_else/ l+ ## 0 +-- /do_else/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst new file mode 100755 index 000000000..db494f354 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst @@ -0,0 +1,3 @@ +**Exercise the ELSE branch of an elaboration IF statement** + +LRMREF: 5.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads new file mode 100644 index 000000000..123aa43c1 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + Init_Ref : Integer := 0; + -- A value to get into the ELSIF branch +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb new file mode 100644 index 000000000..2e71a4813 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb @@ -0,0 +1,17 @@ +with Lib_If_Statements; +with Support; use Support; + +procedure Test_Init_ElsIf is + X : Integer; +begin + X := Lib_If_Statements.Probe (Slot => 1); + Assert (X = 0); +end; + +--# lib_if_statements.adb +-- /test_if/ l+ ## 0 +-- /do_if/ l- ## s- +-- /test_elsif/ l+ ## 0 +-- /do_elsif/ l+ ## 0 +-- /test_else/ l- ## s- +-- /do_else/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst new file mode 100755 index 000000000..482a0b3f4 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst @@ -0,0 +1,3 @@ +**Exercise the ELSIF branch of an elaboration IF statement** + +LRMREF: 5.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads new file mode 100644 index 000000000..f937b69ec --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + Init_Ref : Integer := 15; + -- A value to get the IF test True +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb new file mode 100644 index 000000000..802c843d9 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb @@ -0,0 +1,17 @@ +with Lib_If_Statements; +with Support; use Support; + +procedure Test_Init_If is + X : Integer; +begin + X := Lib_If_Statements.Probe (Slot => 1); + Assert (X > 0); +end; + +--# lib_if_statements.adb +-- /test_if/ l+ ## 0 +-- /do_if/ l+ ## 0 +-- /test_elsif/ l- ## s- +-- /do_elsif/ l- ## s- +-- /test_else/ l- ## s- +-- /do_else/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst new file mode 100755 index 000000000..201bdbd81 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst @@ -0,0 +1,3 @@ +**Exercise the IF branch of an elaboration IF statement** + +LRMREF: 5.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb index 5138cba92..e6c936586 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb @@ -18,8 +18,6 @@ begin Assert (Res = 2); Assert (My_Max_From_Two (2, 1) = 2); - - Assert (Global_Var = 11); end Test_IF_Path; --# if_statements.adb @@ -56,7 +54,3 @@ end Test_IF_Path; -- /max/ l+ ## 0 -- /ifmax/ l+ ## 0 -- /elsemax/ l- ## s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb index bf457373a..f2e9d2005 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb @@ -50,8 +50,6 @@ begin -- Covering all paths in More_IF_Statements.Max_From_Two Assert (My_Max_From_Two (2, 1) = 2); Assert (My_Max_From_Two (1, 2) = 2); - - Assert (Global_Var = 11); end Test_Multiple_Paths; --# if_statements.adb @@ -88,7 +86,3 @@ end Test_Multiple_Paths; -- /max/ l+ ## 0 -- /ifmax/ l+ ## 0 -- /elsemax/ l+ ## 0 --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb index 1c3a4187c..aac83cb8c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb @@ -45,7 +45,3 @@ end Test_No_Execution; -- /max/ l- ## s- -- /ifmax/ l- ## s- -- /elsemax/ l- ## s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst index c1290a710..c6930ad6e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst @@ -2,8 +2,6 @@ SC requirements for If statements (ARM 5.3) =========================================== -%REQ_ID% - An IF statement comprises an IF branch, zero or more ELSIF branches and zero diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb index 0b84a14c1..ba8c36b63 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb @@ -24,4 +24,3 @@ package body IF_Statements is end Set_Max; end IF_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads index 1a1e1066e..b8441332d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads @@ -14,4 +14,3 @@ package IF_Statements is -- Set Res to maximun from Arg1 and Arg2. The body contains IF statement -- without ELSE path and without ELSIF path end IF_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads index 721c6bc97..5ddcb67d1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads @@ -10,4 +10,3 @@ package Instances is function My_Max_From_Two is new More_If_Statements.Max_From_Two (Integer); end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb new file mode 100644 index 000000000..90068bc2b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb @@ -0,0 +1,21 @@ +with Lib_Init; +-- A helper to be provided by each test, to influence which +-- part of the IF statement below gets exercised. + +package body Lib_If_Statements is + + Values : array (1 .. 8) of Integer; + + function Probe (Slot : Integer) return Integer is + begin + return Values (Slot); + end; +begin + if Lib_Init.Init_Ref > 0 then -- # test_if + Values := (others => 1); -- # do_if + elsif Lib_Init.Init_Ref = 0 then -- # test_elsif + Values := (others => 0); -- # do_elsif + else + Values := (others => -1); -- # do_else + end if; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads new file mode 100644 index 000000000..daa5adf43 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads @@ -0,0 +1,5 @@ +-- A package which features an IF statement within its elaboration body + +package Lib_If_Statements is + function Probe (Slot : Integer) return Integer; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb index 051d9b347..e6d907548 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb @@ -44,15 +44,4 @@ package body More_IF_Statements is return Result; -- # max end Max_From_Two; -begin - - Global_Var := Identity (1); -- # elab - - if Global_Var > 0 then -- # elab - Global_Var := Global_Var + 10; -- # gt0elab - elsif Global_Var = 0 then -- # notgt0elab - Global_Var := Identity (100); -- # eq0elabeq0 - end if; - end More_IF_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads index 4f1712248..7dea18249 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads @@ -1,12 +1,9 @@ -- Contains routines with different forms of IF statements in different kinds --- of program units. The body contains IF statement is an elaboration --- statement sequence +-- of program units. package More_IF_Statements is pragma Elaborate_Body; - Global_Var : Integer; - procedure Set_Prime_Number (Res : out Natural; Num : Natural); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst index 723e27132..4958440df 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst @@ -2,8 +2,6 @@ SC requirements for Case statements (ARM 5.4) ============================================= -%REQ_ID% - A CASE statement starts with a *header* that introduces the controlling diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb index 44d12f502..89b10e751 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb @@ -40,4 +40,3 @@ package body CASE_Statements is end Adjust_Int_P; end CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads index 93e19f8dd..652f3bed6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads @@ -20,4 +20,3 @@ package CASE_Statements is -- CASE statement with OTHERS choice, with alternatives with one and with -- multiple choices, choices are values or ranges. end CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads index 1bd6d2b08..0f62059bd 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads @@ -8,4 +8,3 @@ package CASE_Statements_Support is subtype Int_Range_2 is Integer range 11 .. 20; end CASE_Statements_Support; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb index 7bca6a138..0b5179b1b 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb @@ -78,4 +78,3 @@ begin end case; end More_CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads index 3cbde0305..6c51d722e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads @@ -25,4 +25,3 @@ package More_CASE_Statements is -- choices that are subtype marks. end More_CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads new file mode 100644 index 000000000..ddf69d259 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + N1 : Integer := 0; + -- Number of value items to initialize to 1 +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb new file mode 100644 index 000000000..5e3aae698 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb @@ -0,0 +1,19 @@ +with Lib_Loop_Statements; +with Support; use Support; + +procedure Test_Init_Loop is + X : Integer; +begin + X := Lib_Loop_Statements.N_Ones; + Assert (X = 0); +end; + +--# lib_loop_statements.adb +-- /count/ l+ ## 0 +-- /iter/ l+ ## 0 +-- /test-inc/ l+ ## 0 +-- /inc/ l- ## s- + +-- /elab/ l+ ## 0 +-- /test-init/ l+ ## 0 +-- /init/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst new file mode 100755 index 000000000..3a49f8472 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst @@ -0,0 +1,3 @@ +**Exercise an elaboration WHILE-loop statement, not entering the loop** + +LRMREF: 5.5 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads new file mode 100644 index 000000000..91780dd70 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + N1 : Integer := 2; + -- Number of value items to initialize to 1 +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb new file mode 100644 index 000000000..fbcb7c1c0 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb @@ -0,0 +1,19 @@ +with Lib_Loop_Statements; +with Support; use Support; + +procedure Test_Init_Loop is + X : Integer; +begin + X := Lib_Loop_Statements.N_Ones; + Assert (X = 2); +end; + +--# lib_loop_statements.adb +-- /count/ l+ ## 0 +-- /iter/ l+ ## 0 +-- /test-inc/ l+ ## 0 +-- /inc/ l+ ## 0 + +-- /elab/ l+ ## 0 +-- /test-init/ l+ ## 0 +-- /init/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst new file mode 100755 index 000000000..e04431151 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst @@ -0,0 +1,3 @@ +**Exercise an elaboration WHILE-loop statement, entering the loop** + +LRMREF: 5.5 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst index fcc07e017..a73e70118 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst @@ -2,8 +2,6 @@ SC requirements for Loop statements (ARM 5.5) ============================================= -%REQ_ID% - A LOOP statement contains a loop *header* (optional iteration scheme followed diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb index 44d12f502..89b10e751 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb @@ -40,4 +40,3 @@ package body CASE_Statements is end Adjust_Int_P; end CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb new file mode 100644 index 000000000..359650e05 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb @@ -0,0 +1,24 @@ +with Lib_Init; + +package body Lib_Loop_Statements is + + N : Integer; + + function N_Ones return Integer is + begin + N := 0; -- # count + for I in Values'Range loop -- # iter + if Values (I) = 1 then -- # test-inc + N := N + 1; -- # inc + end if; + end loop; + return N; -- # count + end; + +begin + N := 0; -- # elab + while N < Lib_Init.N1 loop -- # test-init + N := N + 1; -- # init + Values (Values'First + N) := 1; -- # init + end loop; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads new file mode 100644 index 000000000..f7ad17731 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads @@ -0,0 +1,15 @@ +-- Package featuring a loop controlled by a decision within +-- its body elaboration code. + +package Lib_Loop_Statements is + + -- An array of integers, all zero for starters. A number of these + -- are set to 1 in the package elab body. The number of values so + -- initialized is controlled by a variable in a distinct package spec, + -- provided by each testcase. + Values : array (1 .. 8) of Integer := (others => 0); + + function N_Ones return Integer; + -- Recompute the number of slots set by looking at the values + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb index b672435b4..7c93dbe6d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb @@ -78,4 +78,3 @@ package body LOOP_Statements is end Sum_First_Under_Limit; end LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads index 729151c98..afe2677d4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads @@ -35,4 +35,3 @@ package LOOP_Statements is -- loop. end LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads index ab900648e..7be1d477e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads @@ -8,4 +8,3 @@ package LOOP_Statements_Support is type Big_Sample is array (Natural range <>) of Integer; end LOOP_Statements_Support; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb index 099b291e4..276429fb5 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb @@ -36,16 +36,8 @@ package body More_LOOP_Statements is end Change_Char; begin - Idx := Identity (1); --# elab - - while Idx <= Identity (10) loop --# elab - Global_Sample (Idx) := Level (Identity (Idx)); --# elab - Idx := Idx + 1; --# elab - end loop; - for J in Global_String'Range loop --# elab Global_String (J) := Character'Val (J); --# elab end loop; end More_LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads index 64a1bc69a..113c329f8 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads @@ -21,4 +21,3 @@ package More_LOOP_Statements is -- Replaces in S Old_Ch with New_Ch. The implementation uses FOR loop end More_LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb index a96249a6c..31518a8e9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb @@ -3,7 +3,7 @@ with Values.Arg, Support; use Values, Support; procedure Test_Empty is begin Arg.Do_Loop_Over (EA, Early_Return => False, Max_Iterations => EA'Length); -end; +end; --# values-arg.adb -- /decl/ l+ ## 0 -- /test-return/ l+ ## 0 @@ -13,5 +13,3 @@ end; -- /exit/ l- ## s- -- /loop_op/ l- ## s- -- /post-loop/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb index 860c60665..1e9109ec4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Integer; V : Integer) is begin Assert (E = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads index cce9758d4..af210f5f4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads @@ -1,9 +1,9 @@ package Values is procedure Touch (E : in out Integer); procedure Check_Value (E : Integer; V : Integer); - + type Array_Type is array (Natural range <>) of Integer; VA : Array_Type := (1 .. 8 => 5); - + EA : Array_Type := (1 .. 0 => <>); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb index 9e2989520..10bdee3ab 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb @@ -1,12 +1,12 @@ with Support; use Support; package body Values is - + procedure Touch (E : in out Object) is begin E.X := E.X * 2; end; - + procedure Check_Value (E : Object; V : Integer) is begin Assert (E.X = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads index f4568cb83..fdbd6a433 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads @@ -1,13 +1,13 @@ package Values is - + type Object is tagged record X : Integer; end record; - + procedure Touch (E : in out Object); procedure Check_Value (E : Object; V : Integer); - + type Array_Type is array (1 .. 8) of Object; VA : Array_Type := (others => (X => 5)); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb index 41f567d09..35f8441c0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Num; V : Integer) is begin Assert (Integer(E) = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads index 1e05c3ec0..cfcfff706 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads @@ -2,12 +2,12 @@ package Values is type Num is mod 2**8; for Num'Size use 8; - + type Array_Type is array (1 .. 4) of Num; pragma Pack (Array_Type); - + procedure Touch (E : in out Num); procedure Check_Value (E : Num; V : Integer); - + VA : Array_Type := (others => 5); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb index 860c60665..1e9109ec4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Integer; V : Integer) is begin Assert (E = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads index 4baf2f760..444b68003 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads @@ -1,7 +1,7 @@ package Values is procedure Touch (E : in out Integer); procedure Check_Value (E : Integer; V : Integer); - + type Array_Type is array (1 .. 8) of Integer; VA : Array_Type := (others => 5); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb index 860c60665..1e9109ec4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Integer; V : Integer) is begin Assert (E = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads index 897aeb87a..5f021f458 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads @@ -1,7 +1,7 @@ package Values is procedure Touch (E : in out Integer); procedure Check_Value (E : Integer; V : Integer); - + type Array_Type is array (Natural range <>) of Integer; VA : Array_Type := (1 .. 8 => 5); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb index ba7afce83..4563aecbc 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb @@ -2,7 +2,7 @@ pragma Ada_2012; with Values.ARG, Support; use Values, Support; -procedure Test_Values_ARG is +procedure Test_Values_ARG is begin ARG.Do_Loop_Over (VA, Early_Return => False, Max_Iterations => VA'Length); @@ -20,4 +20,3 @@ end; -- /exit/ l- ## s- -- /loop_op/ l+ ## 0 -- /post-loop/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb index f3ec6f901..baa6d607c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb @@ -4,7 +4,7 @@ with Values.ARG, Support; use Values, Support; -- test with Early Return -procedure Test_Values_ARG_ER is +procedure Test_Values_ARG_ER is begin ARG.Do_Loop_Over (VA, Early_Return => True, Max_Iterations => VA'Length); @@ -22,4 +22,3 @@ end; -- /exit/ l- ## s- -- /loop_op/ l- ## s- -- /post-loop/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb index 5520a630a..acf4073a6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb @@ -4,7 +4,7 @@ with Values.ARG, Support; use Values, Support; -- test with limit to 0 iteration -procedure Test_Values_ARG_IT0 is +procedure Test_Values_ARG_IT0 is begin ARG.Do_Loop_Over (VA, Early_Return => False, Max_Iterations => 0); @@ -22,4 +22,3 @@ end; -- /exit/ l+ ## 0 -- /loop_op/ l- ## s- -- /post-loop/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb index c10e2822f..2fc86d38a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb @@ -4,7 +4,7 @@ with Values.ARG, Support; use Values, Support; -- test with limit to 1 iteration -procedure Test_Values_ARG_IT1 is +procedure Test_Values_ARG_IT1 is begin ARG.Do_Loop_Over (VA, Early_Return => False, Max_Iterations => 1); @@ -23,4 +23,3 @@ end; -- /exit/ l+ ## 0 -- /loop_op/ l+ ## 0 -- /post-loop/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb index 55f0794cf..879ce9a38 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb @@ -10,4 +10,3 @@ end; --# values-global.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb index 71cb167c6..49c68a41f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb @@ -3,7 +3,7 @@ pragma Ada_2012; with Support; use Support; package body Values.ARG is - + procedure Do_Loop_Over (A : in out Array_Type; Early_Return : Boolean; @@ -23,5 +23,5 @@ package body Values.ARG is end loop; Assert (N_Iterations <= Max_Iterations); -- # post-loop end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads index 3f0d49c9b..74e9811d9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads @@ -1,5 +1,5 @@ -package Values.Arg is +package Values.Arg is procedure Do_Loop_Over (A : in out Array_Type; Early_Return : Boolean; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb index a4f1e3447..98158f351 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Values.Global is - + procedure Do_Loop is begin for E of VA loop -- # stmt Touch (E); -- # loop_op end loop; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst index 7fb0efb3e..973cdbbf4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst @@ -2,8 +2,6 @@ SC requirements for generalized Loop iterations (ARM 5.5.2) =========================================================== -%REQ_ID% - Generalized loop iterators are similar to simple For loop statements in structure so share the same set of structural coverage requirements. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb index da06e56e0..52eda162d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb @@ -98,4 +98,3 @@ package body Block_Statements is end Sum_Min_Max; end Block_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads index 151fa4935..5bee0672e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads @@ -27,4 +27,3 @@ package Block_Statements is -- each. end Block_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst index 97a80b19a..8cd2bb652 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst @@ -2,8 +2,6 @@ SC requirements for Block statements (ARM 5.6) ============================================== -%REQ_ID% - A block statement contains a sequence of statements and, optionally, diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb index 812e0f5f0..51668970f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb @@ -10,4 +10,3 @@ end; -- /red/ l- ## s- -- /green/ l- ## s- -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb index 437011e16..c0338669b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb @@ -10,4 +10,3 @@ end; -- /red/ l- ## s- -- /green/ l- ## s- -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb index 503b7b55b..6c15d6976 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb @@ -10,4 +10,3 @@ end; -- /red/ l- ## s- -- /green/ l+ ## 0 -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb index 41f20cd17..f70a0b889 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb @@ -11,4 +11,3 @@ end; -- /red/ l- ## s- -- /green/ l+ ## 0 -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb index 364c39b41..6debd0823 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb @@ -10,4 +10,3 @@ end; -- /red/ l+ ## 0 -- /green/ l- ## s- -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb index 6e66b017d..4956bc5c1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb @@ -11,4 +11,3 @@ end; -- /red/ l+ ## 0 -- /green/ l- ## s- -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb index 3d5257668..04ba2673b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb @@ -11,4 +11,3 @@ end; -- /red/ l+ ## 0 -- /green/ l+ ## 0 -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb index bbf29402f..4b9c89279 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb @@ -12,4 +12,3 @@ end; -- /red/ l+ ## 0 -- /green/ l+ ## 0 -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb index c2a280486..9c674eb8b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb @@ -1,78 +1,78 @@ with Support; use Support; package body Nest is - + Value : Integer := 0; pragma Volatile (Value); - + procedure Touch (Cd : access Cdata) is begin Cd.Nops := Cd.Nops + 1; -- # touch end; - - procedure Check + + procedure Check (Lfun, Lproc, Pfun, Pproc, Indirect : Boolean; Cd : access Cdata) is -- nested procedure and function - + procedure Inc (X : in out Integer; Cd : access Cdata) is begin Touch (Cd); -- # lproc X := X + 1; -- # lproc end; - + function Positive (X : Integer; Cd : access Cdata) return Boolean is begin Touch (Cd); -- # lfun return X > 0; -- # lfun end; - + -- nested package - + package Ops is - + -- visible operations - + procedure Dec (X : in out Integer; Cd : access Cdata); function Negative (X : Integer; Cd : access Cdata) return Boolean; - + private -- private operations function Neg_P (X : Integer) return Boolean; end; - + package body Ops is - + -- internal subpgram (package body only) - + procedure My_Dec (X : in out Integer) is begin X := X - 1; -- # pproc end; - + procedure Dec (X : in out Integer; Cd : access Cdata) is begin Touch (Cd); -- # pproc My_Dec (Value); -- # pproc end; - + function Neg_P (X : Integer) return Boolean is begin return X < 0; -- # pfun end; - + function Negative (X : Integer; Cd : access Cdata) return Boolean is begin Touch (Cd); -- # pfun return Neg_P (X); -- # pfun end; end; - + type Opcodes is mod 4; Op_Lfun : constant := 1; Op_Pfun : constant := 2; - + type Trigger (Opc : Opcodes; Value : Integer; Cd : access Cdata) is limited record case Opc is @@ -83,14 +83,14 @@ package body Nest is Neg : Boolean := Ops.Negative (Value, Cd); when 3 => P : Boolean := Positive (Value, Cd); - N : Boolean := Ops.Negative (Value, Cd); + N : Boolean := Ops.Negative (Value, Cd); end case; end record; - + Opc : Opcodes := 0; begin Value := 5; -- # check - + if Lfun then -- # check if Indirect then -- # lfun Opc := Opc or Op_Lfun; -- # lfi @@ -98,11 +98,11 @@ package body Nest is Assert (Positive (Value, Cd)); -- # lfd end if; end if; - + if Lproc then -- # check Inc (Value, Cd); -- # lpd end if; - + if Pfun then -- # check if Indirect then -- # pfun Opc := Opc or Op_Pfun; -- # pfi @@ -110,11 +110,11 @@ package body Nest is Assert (not Ops.Negative (Value, Cd)); -- # pfd end if; end if; - + if Pproc then -- # check Ops.Dec (Value, Cd); -- # ppd end if; - + if Indirect then -- # check declare T : Trigger (Opc => Opc, Value => Value, Cd => Cd); -- # indirect @@ -122,7 +122,7 @@ package body Nest is null; -- # indirect end; end if; - + end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb index a0e12f7bf..8258629a0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb index d6a3f34f5..5cd8d8385 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb index a587d1d36..53c50e982 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb index f886e3c92..13e70662c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l+ ## 0 -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb index d483dff42..2cd53e5d6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb index ea8906ef5..0a8ac0547 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb index b90ead504..32f948d6e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb @@ -30,4 +30,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb index e8d800c39..3b75b0bea 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb @@ -30,4 +30,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb index 33c050af0..1550001b6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l+ ## 0 -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb index 167d7ad5a..961646d91 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb @@ -27,4 +27,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb index 367bf55b5..4a8c34d03 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb @@ -31,4 +31,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb index 32b8310bf..49e9cd60b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb index d55164d40..da467c729 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb index 91f215a55..d31f25956 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb index 829e039cb..3aa2354a4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l+ ## 0 -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst index 498742051..0a9ad65a0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst @@ -2,8 +2,6 @@ SC requirements for subprogram declarations and calls ===================================================== -%REQ_ID% - SC shall be assessed correctly within each kind of subprogram, diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb index ba969d5e8..11e74aab6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb @@ -8,7 +8,7 @@ begin Characterize2 (IV); T_Int_Characterize1 (IV); T_Int_Characterize2 (IV); - + Assert (N_Positives = 0); Assert (N_Negatives = 4); Assert (N_Zeroes = 0); @@ -20,4 +20,3 @@ end; -- /test_neg/ l+ ## 0 -- /neg/ l+ ## 0 -- /zero/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb index d1600694a..f00eebda2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb @@ -8,7 +8,7 @@ begin Characterize2 (IV); T_Int_Characterize1 (IV); T_Int_Characterize2 (IV); - + Assert (N_Positives = 4); Assert (N_Negatives = 0); Assert (N_Zeroes = 0); @@ -20,4 +20,3 @@ end; -- /test_neg/ l- ## s- -- /neg/ l- ## s- -- /zero/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb index a27b2ef22..45e8c192f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb @@ -8,7 +8,7 @@ begin Characterize2 (IV); T_Int_Characterize1 (IV); T_Int_Characterize2 (IV); - + Assert (N_Positives = 0); Assert (N_Negatives = 0); Assert (N_Zeroes = 4); @@ -20,4 +20,3 @@ end; -- /test_neg/ l+ ## 0 -- /neg/ l- ## s- -- /zero/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb index 4d7129459..3ca1bb02a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb @@ -11,10 +11,10 @@ procedure Test_Mix1 is begin Characterize1 (IV0); Characterize2 (IVpos); - + T_Int_Characterize1 (IVpos); T_Int_Characterize2 (IVneg); - + Assert (N_Positives = 2); Assert (N_Negatives = 1); Assert (N_Zeroes = 1); @@ -44,4 +44,3 @@ end; -- /test_neg_i2/ l+ ## 0 -- /neg_i2/ l+ ## 0 -- /zero_i2/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb index c417c75e4..a0e578bb3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb @@ -11,17 +11,17 @@ procedure Test_Mix2 is begin Characterize1 (IV0); Characterize1 (IVpos); - + Characterize2 (IV0); Characterize2 (IVneg); - + T_Int_Characterize1 (IVpos); T_Int_Characterize1 (IVneg); - + T_Int_Characterize2 (IV0); T_Int_Characterize2 (IVpos); T_Int_Characterize2 (IVneg); - + Assert (N_Positives = 3); Assert (N_Negatives = 3); Assert (N_Zeroes = 3); @@ -51,4 +51,3 @@ end; -- /test_neg_i2/ l+ ## 0 -- /neg_i2/ l+ ## 0 -- /zero_i2/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb index 58f3bfee2..d517b401d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb @@ -1,5 +1,5 @@ package body Values is - + procedure Characterize1 (IV : T_Int) is begin if IV.Value > 0 then -- # test_pos_c1 @@ -10,7 +10,7 @@ package body Values is N_Zeroes := N_Zeroes + 1; -- # zero_c1 end if; end; - + overriding procedure Characterize2 (IV : T_Int) is begin @@ -22,7 +22,7 @@ package body Values is N_Zeroes := N_Zeroes + 1; -- # zero_c2 end if; end; - + procedure T_Int_Characterize1 (IV : T_Int) is begin if IV.Value > 0 then -- # test_pos_i1 @@ -31,9 +31,9 @@ package body Values is N_Negatives := N_Negatives + 1; -- # neg_i1 else N_Zeroes := N_Zeroes + 1; -- # zero_i1 - end if; + end if; end; - + not overriding procedure T_Int_Characterize2 (IV : T_Int) is begin @@ -43,6 +43,6 @@ package body Values is N_Negatives := N_Negatives + 1; -- # neg_i2 else N_Zeroes := N_Zeroes + 1; -- # zero_i2 - end if; + end if; end; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads index 373bdbf89..f529290fd 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads @@ -1,26 +1,26 @@ package Values is - + type T_Value is abstract tagged null record; - + N_Positives : Integer := 0; N_Negatives : Integer := 0; N_Zeroes : Integer := 0; - + procedure Characterize1 (V : T_Value) is abstract; procedure Characterize2 (V : T_Value) is abstract; - + type T_Int is new T_Value with record Value : Integer; end record; - + procedure Characterize1 (IV : T_Int); - + overriding procedure Characterize2 (IV : T_Int); - + procedure T_Int_Characterize1 (IV : T_Int); - + not overriding procedure T_Int_Characterize2 (IV : T_Int); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb index eafc66baa..11f42f84c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb @@ -1,5 +1,5 @@ package body I_Objects is - + procedure Characterize (IV : T_Int) is begin if IV.Value > 0 then -- # char_test_pos_int @@ -10,7 +10,7 @@ package body I_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_int end if; end; - + procedure Characterize (FV : T_Float) is begin if FV.Value > 0.0 then -- # char_test_pos_float @@ -21,5 +21,5 @@ package body I_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_float end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads index 70cf06472..0801769bb 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads @@ -2,33 +2,33 @@ -- Case where the object types are derived from a single Interface type. package I_Objects is - + -- The base Interface type: - + type I_Value is Interface; - + N_Positives : Integer := 0; N_Negatives : Integer := 0; N_Zeroes : Integer := 0; - + procedure Characterize (V : I_Value) is abstract; - + -- - + type T_Int is new I_Value with record Value : Integer; end record; - + overriding procedure Characterize (IV : T_Int); - + -- - + type T_Float is new I_Value with record Value : Float; end record; - + overriding procedure Characterize (FV : T_Float); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb index 954b210e5..4623d335b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb @@ -10,16 +10,16 @@ procedure Test_I_All_Pos is begin IO.Value := 1; Characterize (IO); - + FO.Value := -11.0; Characterize (FO); - + FO.Value := 117.0; Characterize (FO); - + FO.Value := 0.0; Characterize (FO); - + Assert (N_Positives = 2); Assert (N_Negatives = 1); Assert (N_Zeroes = 1); @@ -37,4 +37,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb index 3c0808d0d..57a03affd 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb @@ -10,10 +10,10 @@ procedure Test_I_Neg_Pos is begin IO.Value := -1; Characterize (IO); - + FO.Value := 11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 1); Assert (N_Zeroes = 0); @@ -31,4 +31,3 @@ end; -- /char_test_neg_float/ l- ## s- -- /char_neg_float/ l- ## s- -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb index 50889debb..81ccd3bc9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb @@ -10,28 +10,28 @@ procedure Test_TI_All_All is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + IO.Value := 1; Characterize (IO); - + IO.Value := 0; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := -11.0; Characterize (FO); - + FO.Value := 7.0; Characterize (FO); - + FO.Value := 0.0; Characterize (FO); - + Assert (N_Positives = 2); Assert (N_Negatives = 2); Assert (N_Zeroes = 2); @@ -53,4 +53,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb index d6b8a0847..56c6ff30d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb @@ -10,22 +10,22 @@ procedure Test_TI_All_Neg is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + IO.Value := 1; Characterize (IO); - + IO.Value := 0; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := -11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 2); Assert (N_Zeroes = 1); @@ -47,4 +47,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb index 1a4f21152..35155aa82 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb @@ -10,16 +10,16 @@ procedure Test_TI_Neg_Pos is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := 11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 1); Assert (N_Zeroes = 0); @@ -41,4 +41,3 @@ end; -- /char_test_neg_float/ l- ## s- -- /char_neg_float/ l- ## s- -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb index f95ebaf64..032a3ae65 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb @@ -7,16 +7,16 @@ procedure Test_TI_Neg_Zero is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := 0.0; Characterize (FO); - + Assert (N_Positives = 0); Assert (N_Negatives = 1); Assert (N_Zeroes = 1); @@ -38,4 +38,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l- ## s- -- /char_zero_float/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb index 58db71f98..f35bdaed3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb @@ -10,16 +10,16 @@ procedure Test_TI_Pos_Neg is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := 1; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := -11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 1); Assert (N_Zeroes = 0); @@ -41,4 +41,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb index 35135e5f1..bc958325f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb @@ -1,8 +1,8 @@ package body TI_Objects is - + N_Id_Recall : Integer := 0; Next_Id : Integer := 0; - + procedure Assign_Id_To (O : in out Identifiable) is begin if O.Id > 0 then -- # id_test @@ -12,7 +12,7 @@ package body TI_Objects is Next_Id := Next_Id + 1; -- # id_assign end if; end; - + procedure Characterize (IV : T_Int) is begin if IV.Value > 0 then -- # char_test_pos_int @@ -23,7 +23,7 @@ package body TI_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_int end if; end; - + procedure Characterize (FV : T_Float) is begin if FV.Value > 0.0 then -- # char_test_pos_float @@ -34,5 +34,5 @@ package body TI_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_float end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads index e6df0c94b..6b0d8951f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads @@ -3,41 +3,41 @@ -- type and an Interface type. package TI_Objects is - + -- The Tagged type: - + type Identifiable is abstract tagged record Id : Integer := -1; end record; - + procedure Assign_Id_To (O : in out Identifiable); - + -- The base Interface type: - + type I_Value is Interface; - + N_Positives : Integer := 0; N_Negatives : Integer := 0; N_Zeroes : Integer := 0; - + procedure Characterize (V : I_Value) is abstract; - + -- - + type T_Int is new Identifiable and I_Value with record Value : Integer; end record; - + overriding procedure Characterize (IV : T_Int); - + -- - + type T_Float is new Identifiable and I_Value with record Value : Float; end record; - + overriding procedure Characterize (FV : T_Float); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb index dd7733b26..3f7b52d61 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb @@ -19,4 +19,3 @@ end; -- --%opts: --trace-mode=src -- /no-code/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_full.adb deleted file mode 100755 index e076c4f20..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_full.adb +++ /dev/null @@ -1,62 +0,0 @@ --- Test driver for derived subprograms. It executes all of the functional code --- using different ways to call subprograms (direct, indirect, dispatching --- calls). All the functional code is expected to be reported as being --- covered. - -with Derived_1; use Derived_1; -with Derived_2; use Derived_2; -with Subprogram_Pack; use Subprogram_Pack; -with Support; use Support; -procedure Test_Derived_Subprograms_Full is - Var_T : T := (I => 1); - Var_Derived_T_1 : Derived_T_1 := (I => 2); - Var_Derived_T_2 : Derived_T_2 := (I => 3); - Int : Integer; - - Var_Rec1 : Rec1; - -- Call to Fun1 from evaluation of default expression for record - -- component - - Var_Rec2 : Rec2; - -- Call to overriding Derived_2.Fun2 from evaluation of default expression - -- for record component. - - Indirect_Call : Access_DT2_Proc; -begin - Assert (Var_Rec1.Comp = 0); - Assert (Var_Rec2.Comp = -1); - - Int := Fun3 (Var_Derived_T_1); - -- Call to Subprogram_Pack.Fun2 from evaluation of default expression for - -- a parameter. - Assert (Int = 4); - - Class_Wide_Proc (T'Class (Var_T)); - -- Results in dispatching to Subprogram_Pack.Proc2. - Assert (Var_T.I = -1); - - Indirect_Call := Proc2'Access; - Indirect_Call (Var_Derived_T_2); - Assert (Var_Derived_T_2.I = 13); - - Proc1 (Var_Derived_T_2); - Assert (Var_Derived_T_2.I = 14); - - Proc2 (Var_Derived_T_1); - Assert (Var_Derived_T_1.I = 4); -end Test_Derived_Subprograms_Full; - ---# subprogram_pack.adb --- /fun1/ l+ ## 0 --- /fun2/ l+ ## 0 --- /fun3/ l+ ## 0 --- /proc1/ l+ ## 0 --- /proc2/ l+ ## 0 --- /class_wide/ l+ ## 0 - ---# derived_1.adb --- /proc2/ l+ ## 0 - ---# derived_2.adb --- /fun2/ l+ ## 0 --- /proc2/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_1.adb deleted file mode 100755 index a8755b933..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_1.adb +++ /dev/null @@ -1,52 +0,0 @@ --- Test driver for derived subprograms. It "with's" the functional code and --- executes only a part of it. It contains a subprogram call resulted from --- evaluating default initialization expression, an indirect call through --- access-to-subprogram value and a dispatching call. - -with Derived_1; use Derived_1; -with Derived_2; use Derived_2; -with Subprogram_Pack; use Subprogram_Pack; -with Support; use Support; -procedure Test_Derived_Subprograms_Indirect_1 is - Var_T : T := (I => 1); - Var_Derived_T_1 : Derived_T_1 := (I => 2); - Var_Derived_T_2 : Derived_T_2 := (I => 3); - Int : Integer; - - Rec : Rec1; - -- Call to Fun1 from evaluation of default expression for record - -- component - - Indirect_Call : Access_DT1_Proc; -begin - Assert (Rec.Comp = 0); - - Int := Fun3 (Var_Derived_T_2); - -- Call to Subprogram_Pack.Fun2 from evaluation of default expression for - -- a parameter. Note that Derived_2.Fun2 shall be reported as uncovered! - Assert (Int = 5); - - Class_Wide_Proc (T'Class (Var_Derived_T_2)); - -- Results in dispatching to Derived_2.Proc2, all the other Proc2 shall be - -- reported as uncovered - Assert (Var_Derived_T_2.I = 13); - - Indirect_Call := Proc1'Access; - Indirect_Call (Var_Derived_T_1); - Assert (Var_Derived_T_1.I = 3); -end Test_Derived_Subprograms_Indirect_1; - ---# subprogram_pack.adb --- /fun1/ l+ ## 0 --- /fun2/ l+ ## 0 --- /fun3/ l+ ## 0 --- /proc1/ l+ ## 0 --- /proc2/ l- ## s- --- /class_wide/ l+ ## 0 - ---# derived_1.adb --- /proc2/ l- ## s- - ---# derived_2.adb --- /fun2/ l- ## s- --- /proc2/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_2.adb deleted file mode 100755 index 443b2fff5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_2.adb +++ /dev/null @@ -1,41 +0,0 @@ --- Test driver for derived subprograms. It "with's" the functional code and --- executes only a part of it. It contains a subprogram call resulted from --- evaluating default initialization expression and a dispatching call. - -with Derived_1; use Derived_1; -with Derived_2; use Derived_2; -with Subprogram_Pack; use Subprogram_Pack; -with Support; use Support; -procedure Test_Derived_Subprograms_Indirect_2 is - Var_T : T := (I => 1); - Var_Derived_T_1 : Derived_T_1 := (I => 2); - Var_Derived_T_2 : Derived_T_2 := (I => 3); - - Rec : Rec2; - -- Call to overriding Derived_2.Fun2 from evaluation of default expression - -- for record component, overridden function in Subprogram_Pack shall be - -- reported as uncovered. -begin - Assert (Rec.Comp = -1); - - Class_Wide_Proc (T'Class (Var_Derived_T_1)); - -- Results in dispatching to Derived_1.Proc2, all the other Proc2 shall be - -- reported as uncovered - Assert (Var_Derived_T_1.I = 4); - -end Test_Derived_Subprograms_Indirect_2; - ---# subprogram_pack.adb --- /fun1/ l- ## s- --- /fun2/ l- ## s- --- /fun3/ l- ## s- --- /proc1/ l- ## s- --- /proc2/ l- ## s- --- /class_wide/ l+ ## 0 - ---# derived_1.adb --- /proc2/ l+ ## 0 - ---# derived_2.adb --- /fun2/ l+ ## 0 --- /proc2/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_no.adb deleted file mode 100755 index b24447740..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_no.adb +++ /dev/null @@ -1,27 +0,0 @@ --- Test driver for derived subprograms. It only "with's" the functional code, --- but does not execute anything from it, so everything is expected to be --- reported as uncovered. - -with Derived_1; use Derived_1; -with Derived_2; use Derived_2; -with Subprogram_Pack; use Subprogram_Pack; -with Support; use Support; -procedure Test_Derived_Subprograms_No is -begin - Assert (True); -end Test_Derived_Subprograms_No; - ---# subprogram_pack.adb --- /fun1/ l- ## s- --- /fun2/ l- ## s- --- /fun3/ l- ## s- --- /proc1/ l- ## s- --- /proc2/ l- ## s- --- /class_wide/ l- ## s- - ---# derived_1.adb --- /proc2/ l- ## s- - ---# derived_2.adb --- /fun2/ l- ## s- --- /proc2/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_part.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_part.adb deleted file mode 100755 index e7a2473e5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_part.adb +++ /dev/null @@ -1,34 +0,0 @@ --- Test driver for derived subprograms. It "with's" the functional code and --- executes only a part of it. There is no subprogram calls resulted from --- evaluating default initialization expressions in this test, no indirect --- calls through access-to-subprogram values and no dispatching calls. - -with Derived_1; use Derived_1; -with Derived_2; use Derived_2; -with Subprogram_Pack; use Subprogram_Pack; -with Support; use Support; -procedure Test_Derived_Subprograms_Part is - Var_T : T := (I => 1); - Var_Derived_T_1 : Derived_T_1 := (I => 2); - Var_Derived_T_2 : Derived_T_2 := (I => 3); - Int : Integer; -begin - Int := Fun3 (Var_Derived_T_2, 1); - Assert (Int = 4); - -end Test_Derived_Subprograms_Part; - ---# subprogram_pack.adb --- /fun1/ l- ## s- --- /fun2/ l- ## s- --- /fun3/ l+ ## 0 --- /proc1/ l- ## s- --- /proc2/ l- ## s- --- /class_wide/ l- ## s- - ---# derived_1.adb --- /proc2/ l- ## s- - ---# derived_2.adb --- /fun2/ l- ## s- --- /proc2/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_full.adb new file mode 100755 index 000000000..775a88800 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_full.adb @@ -0,0 +1,62 @@ +-- Test driver for derived subprograms. It executes all of the functional code +-- using different ways to call subprograms (direct, indirect, dispatching +-- calls). All the functional code is expected to be reported as being +-- covered. + +with Derived_1; use Derived_1; +with Derived_2; use Derived_2; +with Subprogram_Pack; use Subprogram_Pack; +with Support; use Support; +procedure Test_Full is + Var_T : T := (I => 1); + Var_Derived_T_1 : Derived_T_1 := (I => 2); + Var_Derived_T_2 : Derived_T_2 := (I => 3); + Int : Integer; + + Var_Rec1 : Rec1; + -- Call to Fun1 from evaluation of default expression for record + -- component + + Var_Rec2 : Rec2; + -- Call to overriding Derived_2.Fun2 from evaluation of default expression + -- for record component. + + Indirect_Call : Access_DT2_Proc; +begin + Assert (Var_Rec1.Comp = 0); + Assert (Var_Rec2.Comp = -1); + + Int := Fun3 (Var_Derived_T_1); + -- Call to Subprogram_Pack.Fun2 from evaluation of default expression for + -- a parameter. + Assert (Int = 4); + + Class_Wide_Proc (T'Class (Var_T)); + -- Results in dispatching to Subprogram_Pack.Proc2. + Assert (Var_T.I = -1); + + Indirect_Call := Proc2'Access; + Indirect_Call (Var_Derived_T_2); + Assert (Var_Derived_T_2.I = 13); + + Proc1 (Var_Derived_T_2); + Assert (Var_Derived_T_2.I = 14); + + Proc2 (Var_Derived_T_1); + Assert (Var_Derived_T_1.I = 4); +end Test_Full; + +--# subprogram_pack.adb +-- /fun1/ l+ ## 0 +-- /fun2/ l+ ## 0 +-- /fun3/ l+ ## 0 +-- /proc1/ l+ ## 0 +-- /proc2/ l+ ## 0 +-- /class_wide/ l+ ## 0 + +--# derived_1.adb +-- /proc2/ l+ ## 0 + +--# derived_2.adb +-- /fun2/ l+ ## 0 +-- /proc2/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_1.adb new file mode 100755 index 000000000..2ee33e97c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_1.adb @@ -0,0 +1,52 @@ +-- Test driver for derived subprograms. It "with's" the functional code and +-- executes only a part of it. It contains a subprogram call resulted from +-- evaluating default initialization expression, an indirect call through +-- access-to-subprogram value and a dispatching call. + +with Derived_1; use Derived_1; +with Derived_2; use Derived_2; +with Subprogram_Pack; use Subprogram_Pack; +with Support; use Support; +procedure Test_Indirect_1 is + Var_T : T := (I => 1); + Var_Derived_T_1 : Derived_T_1 := (I => 2); + Var_Derived_T_2 : Derived_T_2 := (I => 3); + Int : Integer; + + Rec : Rec1; + -- Call to Fun1 from evaluation of default expression for record + -- component + + Indirect_Call : Access_DT1_Proc; +begin + Assert (Rec.Comp = 0); + + Int := Fun3 (Var_Derived_T_2); + -- Call to Subprogram_Pack.Fun2 from evaluation of default expression for + -- a parameter. Note that Derived_2.Fun2 shall be reported as uncovered! + Assert (Int = 5); + + Class_Wide_Proc (T'Class (Var_Derived_T_2)); + -- Results in dispatching to Derived_2.Proc2, all the other Proc2 shall be + -- reported as uncovered + Assert (Var_Derived_T_2.I = 13); + + Indirect_Call := Proc1'Access; + Indirect_Call (Var_Derived_T_1); + Assert (Var_Derived_T_1.I = 3); +end Test_Indirect_1; + +--# subprogram_pack.adb +-- /fun1/ l+ ## 0 +-- /fun2/ l+ ## 0 +-- /fun3/ l+ ## 0 +-- /proc1/ l+ ## 0 +-- /proc2/ l- ## s- +-- /class_wide/ l+ ## 0 + +--# derived_1.adb +-- /proc2/ l- ## s- + +--# derived_2.adb +-- /fun2/ l- ## s- +-- /proc2/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_2.adb new file mode 100755 index 000000000..c4c81bdee --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_2.adb @@ -0,0 +1,41 @@ +-- Test driver for derived subprograms. It "with's" the functional code and +-- executes only a part of it. It contains a subprogram call resulted from +-- evaluating default initialization expression and a dispatching call. + +with Derived_1; use Derived_1; +with Derived_2; use Derived_2; +with Subprogram_Pack; use Subprogram_Pack; +with Support; use Support; +procedure Test_Indirect_2 is + Var_T : T := (I => 1); + Var_Derived_T_1 : Derived_T_1 := (I => 2); + Var_Derived_T_2 : Derived_T_2 := (I => 3); + + Rec : Rec2; + -- Call to overriding Derived_2.Fun2 from evaluation of default expression + -- for record component, overridden function in Subprogram_Pack shall be + -- reported as uncovered. +begin + Assert (Rec.Comp = -1); + + Class_Wide_Proc (T'Class (Var_Derived_T_1)); + -- Results in dispatching to Derived_1.Proc2, all the other Proc2 shall be + -- reported as uncovered + Assert (Var_Derived_T_1.I = 4); + +end Test_Indirect_2; + +--# subprogram_pack.adb +-- /fun1/ l- ## s- +-- /fun2/ l- ## s- +-- /fun3/ l- ## s- +-- /proc1/ l- ## s- +-- /proc2/ l- ## s- +-- /class_wide/ l+ ## 0 + +--# derived_1.adb +-- /proc2/ l+ ## 0 + +--# derived_2.adb +-- /fun2/ l+ ## 0 +-- /proc2/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_no.adb new file mode 100755 index 000000000..f29bb1142 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_no.adb @@ -0,0 +1,27 @@ +-- Test driver for derived subprograms. It only "with's" the functional code, +-- but does not execute anything from it, so everything is expected to be +-- reported as uncovered. + +with Derived_1; use Derived_1; +with Derived_2; use Derived_2; +with Subprogram_Pack; use Subprogram_Pack; +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# subprogram_pack.adb +-- /fun1/ l- ## s- +-- /fun2/ l- ## s- +-- /fun3/ l- ## s- +-- /proc1/ l- ## s- +-- /proc2/ l- ## s- +-- /class_wide/ l- ## s- + +--# derived_1.adb +-- /proc2/ l- ## s- + +--# derived_2.adb +-- /fun2/ l- ## s- +-- /proc2/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_part.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_part.adb new file mode 100755 index 000000000..9315a4d20 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_part.adb @@ -0,0 +1,34 @@ +-- Test driver for derived subprograms. It "with's" the functional code and +-- executes only a part of it. There is no subprogram calls resulted from +-- evaluating default initialization expressions in this test, no indirect +-- calls through access-to-subprogram values and no dispatching calls. + +with Derived_1; use Derived_1; +with Derived_2; use Derived_2; +with Subprogram_Pack; use Subprogram_Pack; +with Support; use Support; +procedure Test_Part is + Var_T : T := (I => 1); + Var_Derived_T_1 : Derived_T_1 := (I => 2); + Var_Derived_T_2 : Derived_T_2 := (I => 3); + Int : Integer; +begin + Int := Fun3 (Var_Derived_T_2, 1); + Assert (Int = 4); + +end Test_Part; + +--# subprogram_pack.adb +-- /fun1/ l- ## s- +-- /fun2/ l- ## s- +-- /fun3/ l+ ## 0 +-- /proc1/ l- ## s- +-- /proc2/ l- ## s- +-- /class_wide/ l- ## s- + +--# derived_1.adb +-- /proc2/ l- ## s- + +--# derived_2.adb +-- /fun2/ l- ## s- +-- /proc2/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst index 44ded4b57..ac2320988 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst @@ -2,8 +2,6 @@ SC requirements for subprogram overridings ========================================== -%REQ_ID% - An overriding subprogram shall be recognized as distinct from the one it diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst index 10542e1b1..6421884ea 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst @@ -2,8 +2,6 @@ SC requirements for Inlining effects ==================================== -%REQ_ID% - SC assessments for simple statements shall not be influenced by subprogram diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb index 2da4ddb91..0d11fad49 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb @@ -1,13 +1,13 @@ package body Objects is - + procedure Register_Pos is begin N_Positives := N_Positives + 1; -- # pos end; - + procedure Characterize (X : Integer); pragma No_Return (Characterize); - + procedure Characterize (X : Integer) is begin if X > 0 then -- # test @@ -15,7 +15,7 @@ package body Objects is end if; raise Constraint_Error; -- # test end; - + procedure Proxy_Characterize (X : Integer) is begin Characterize (X); -- # test diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads index a35754bc8..6397a816b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads @@ -1,8 +1,8 @@ package Objects is - + N_Positives : Integer := 0; - + procedure Proxy_Characterize (X : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb index d0e75b00f..8fb29aa8d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb @@ -1,10 +1,10 @@ package body Objects is - + procedure Register_Pos is begin N_Positives := N_Positives + 1; -- # pos end; - + procedure Characterize (X : Integer) is begin if X > 0 then -- # test @@ -12,7 +12,7 @@ package body Objects is end if; raise Constraint_Error; -- # test end; - + procedure Proxy_Characterize (X : Integer) is begin Characterize (X); -- # test diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads index 57b2d12d1..62613049e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads @@ -1,11 +1,11 @@ package Objects is - + N_Positives : Integer := 0; - + procedure Characterize (X : Integer); pragma No_Return (Characterize); - + procedure Proxy_Characterize (X : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb index f6eaec583..829c13d8b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb @@ -1,15 +1,15 @@ package body Objects is - + procedure Register_Pos is begin N_Positives := N_Positives + 1; -- # pos end; - + procedure Proxy_Characterize (X : Integer) is - + procedure Characterize (X : Integer); pragma No_Return (Characterize); -- # pragma - + procedure Characterize (X : Integer) is begin if X > 0 then -- # test @@ -17,7 +17,7 @@ package body Objects is end if; raise Constraint_Error; -- # test end; - + begin Characterize (X); -- # test end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads index a35754bc8..6397a816b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads @@ -1,8 +1,8 @@ package Objects is - + N_Positives : Integer := 0; - + procedure Proxy_Characterize (X : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst index aa0f52bb9..c029d577c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst @@ -2,8 +2,6 @@ SC requirements for No_Return pragmas on subprograms ==================================================== -%REQ_ID% - SC assessments shall not be influenced by the presence of a No_Return pragma attached to a subprogram. In particular, calls to such subprograms, statements within such subprograms or within subprograms called by them shall be diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb index 685d7c007..1402967cb 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb @@ -11,7 +11,7 @@ end; -- /pos/ l- ## s- -- Old compilers are less precise in tracking --- dominance +-- dominance -- %tags:(7.1.2|7.2.2) -- =/pragma/ ~l- ## ~s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb index cd3e988cd..b0369b628 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb @@ -1,15 +1,15 @@ package body Ops is - + procedure Nop3 (X: in out Integer) is null; -- # do_nop3 - + procedure Nop2 (X: in out Integer) is null; -- # do_nop2 - - procedure Inc (X : in out Integer) is + + procedure Inc (X : in out Integer) is begin X := X + 1; -- # do_inc - end; - + end; + procedure Do_Pv1 (X : in out Integer; Opcode : T_Opcode) is begin @@ -23,7 +23,7 @@ package body Ops is Nop3 (X); -- # pv1_nop3 end if; end; - + procedure Do_Pv2 (X : in out Integer; Opcode : T_Opcode) is begin case Opcode is -- # pv2_test @@ -37,7 +37,7 @@ package body Ops is Nop3 (X); -- # pv2_nop3 end case; end; - + procedure Process (X : in out Integer; Opcode : T_Opcode; Pv : T_Processing_Variant) @@ -48,5 +48,5 @@ package body Ops is when Pv2 => Do_Pv2 (X, Opcode); -- # pv2_call end case; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads index 3b09d6c35..aff428013 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads @@ -1,14 +1,13 @@ package Ops is procedure Nop1 (X: in out Integer) is null; -- # do_nop1 - + procedure Nop2 (X : in out Integer); - + procedure Inc (X : in out Integer); - + type T_Opcode is (Op_Nop1, Op_Nop2, Op_Nop3, Op_Inc); type T_Processing_Variant is (PV1, PV2); - + procedure Process (X : in out Integer; Opcode : T_Opcode; Pv : T_Processing_Variant); end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb index 8dbf22723..81aa6a5f3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb @@ -33,5 +33,3 @@ end; --# ops.ads -- /do_nop1/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb index bfab31f1f..60a36671b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb @@ -33,5 +33,3 @@ end; --# ops.ads -- /do_nop1/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb index 0823ebe02..d32ae4c21 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb @@ -33,4 +33,3 @@ end; --# ops.ads -- /do_nop1/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb index f8dd3052e..1949dc866 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb @@ -39,4 +39,3 @@ end; -- %cargs: -O1 -- =/do_nop1/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb index e866fbd8d..0a463ca4c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb @@ -1,12 +1,12 @@ package body Objects is procedure Probe (O : T_Object) is null; -- # test - + procedure Process (O : T_Object) is procedure Local_Probe (O : T_Object); -- # decl - + procedure Local_Probe (O : T_Object) is null; -- # test - + begin Local_Probe (O); -- # test end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads index e4636765a..09fb783f6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads @@ -2,10 +2,10 @@ with System; package Objects is type T_Object is tagged null record; - + procedure Probe (O : T_Object); - + procedure Process (O : T_Object); - + A_Probe : System.Address; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb index 868069765..3779ef473 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb @@ -1,11 +1,11 @@ package body Objects is procedure Local_Probe (O : T_Object) is null; -- # local - + procedure Process (O : T_Object; Local : Boolean) is begin if Local then -- # test Local_Probe (O); -- # local - else + else Probe (O); -- # global end if; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads index 9d85804de..f6d71c868 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads @@ -2,14 +2,14 @@ with Support; package Objects is type T_Object is null record; - + procedure Probe (O : T_Object) is null; -- # global - + -- Some declaration with initialization code here, to verify -- that coverage by elaboration doesn't backpropagate: - + X : Integer := Support.Identity(54); -- # decl_with_elab - + procedure Process (O : T_Object; Local : Boolean); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst index caf6a4396..66b65dc2d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst @@ -1,8 +1,6 @@ SC requirements for Null subprograms ===================================== -%REQ_ID% - The null statement attached to a null procedure, as a completion or part of a definition, shall be treated as a regular statement, diagnosed uncovered if the procedure is not called. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb index 21a28af12..251d9e0c5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Ops is - + type T_Point is record X, Y : Integer; Q : T_Quarter; end record; - + function Set_Q (P : in out T_Point) return T_Quarter is Q : T_Quarter; begin @@ -24,11 +24,11 @@ package body Ops is P.Q := Q; -- # stmt return Q; -- # stmt end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is P : T_Point := (X => X, Y => Y, Q => <>); begin return Set_Q (P); -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb index 453a52075..c52ed6324 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb @@ -1,10 +1,10 @@ package body Ops is - + type T_Point is record X, Y : Integer; Q : T_Quarter; end record; - + procedure Set_Q (P : in out T_Point) is Q : T_Quarter; begin @@ -21,12 +21,12 @@ package body Ops is end if; P.Q := Q; -- # stmt end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is P : T_Point := (X => X, Y => Y, Q => <>); begin Set_Q (P); -- # stmt return P.Q; -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb index b0ffc3797..7ea7ee955 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb @@ -3,11 +3,11 @@ pragma Ada_2012; with Support; use Support; package body Ops is - + type T_Point is record X, Y : Integer; end record; - + function Set_Q (P : T_Point; Q: out T_Quarter) return Integer is begin if P.X > 0 and then P.Y > 0 then -- # test-q1 @@ -27,8 +27,8 @@ package body Ops is return 0; -- # q0 end if; end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is P : T_Point := (X => X, Y => Y); Q : T_Quarter; Hint : Integer; @@ -37,5 +37,5 @@ package body Ops is Assert (Hint = T_Quarter'Pos (Q)); -- # stmt return Q; -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb index 67e07bb44..cc9637c07 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb @@ -1,9 +1,9 @@ package body Ops is - + type T_Point is record X, Y : Integer; end record; - + procedure Set_Q (P : T_Point; Q : out T_Quarter) is begin if P.X > 0 and then P.Y > 0 then -- # test-q1 @@ -18,12 +18,12 @@ package body Ops is Q := Q0; -- # q0 end if; end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is Q : T_Quarter; begin Set_Q ((X => X, Y => Y), Q); -- # stmt return Q; -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst index 0270323fd..38a1c2493 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst @@ -2,8 +2,6 @@ SC requirements for parameter modes =================================== -%REQ_ID% - The formal mode of subprogram parameters shall not influence the coverage assessment of statements referring to those parameters. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads index 6a155a553..aee770c94 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads @@ -1,11 +1,11 @@ package Ops is -- Y -- ^ - -- Q4 | Q1 + -- Q4 | Q1 -- -----------+----------> X -- Q3 | Q2 -- type T_Quarter is (Q0, Q1, Q2, Q3, Q4); - + function Quarter (X, Y : Integer) return T_Quarter; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb index 0fced26ec..916ac3441 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb @@ -37,4 +37,3 @@ end Test_Pret_Full; -- /proc2_3/ l+ ## 0 -- /proc2_others/ l+ ## 0 -- /proc2_fin/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb index 00ba9b429..722b72a2c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb @@ -26,4 +26,3 @@ end Test_Pret_Part; -- /proc2_3/ l- ## s- -- /proc2_others/ l- ## s- -- /proc2_fin/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst index 1a479638f..efdb9efa0 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst @@ -2,8 +2,6 @@ SC requirements for Return statements ===================================== -%REQ_ID% - A RETURN statement is both a statement per se and a control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb index 6e89cfe92..764a3d8c2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb @@ -1,10 +1,10 @@ pragma Ada_2012; package body Expr is - + function Plus (X, Y : Integer; Delegate : Boolean) return Integer is - + function Sum (X, Y : Integer) return Integer is (X + Y); -- # delegate - + Sx : Integer := Zx + X; -- # decl Sy : Integer := Zy + Y; -- # decl begin @@ -14,5 +14,5 @@ package body Expr is return Sx + Sy; -- # compute end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads index ba764c9b8..0f844ec1a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads @@ -2,5 +2,5 @@ pragma Ada_2012; package Expr is function Plus (X, Y : Integer; Delegate : Boolean) return Integer; Zx, Zy : Integer := 0; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb index 45187749c..dd7d0e4f4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb @@ -12,4 +12,3 @@ end; -- /test/ l+ ## 0 -- /delegate/ l+ ## 0 -- /compute/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb index 3c08e2fb5..218fa749f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb @@ -12,4 +12,3 @@ end; -- /test/ l+ ## 0 -- /delegate/ l- ## s- -- /compute/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb index f1cdea23e..da6be6e06 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb @@ -13,4 +13,3 @@ end; -- /test/ l+ ## 0 -- /delegate/ l+ ## 0 -- /compute/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads index 28ae7ea6d..8bdbd2ef5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads @@ -3,11 +3,11 @@ pragma Ada_2012; with Values; package Expr is - function Plus (X, Y : Integer) return Integer is + function Plus (X, Y : Integer) return Integer is (X + Y); -- # stmt - + -- Stick some decl with elab code to make sure that the -- coverage here in absence of call doesn't back-propagate. - + X : Integer := Values.One; -- # decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads index 3e538ba32..1de1a94af 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads @@ -4,9 +4,9 @@ with Values; package Expr is function Plus (X, Y : Integer) return Integer is (X + Y); -- # stmt - + -- Stick some decl with elab code to make sure that the -- coverage here in absence of call doesn't back-propagate. - + X : Integer := Values.One; -- # decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst index 9e2bd8b66..9f59b5534 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst @@ -1,8 +1,6 @@ SC requirements for Expression functions ======================================== -%REQ_ID% - An expression function definition (profile and expression), shall be recognized as a statement, diagnosed as not-executed when the function is never called. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb index 021979ddb..4a7ffbb79 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb @@ -3,5 +3,5 @@ package body Values is begin return 1; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads index af640d591..a4295e69c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads @@ -1,19 +1,19 @@ package Ops is - + -- This package features a private and an internal subprogram (operations), -- with a single API to call them: - + type Opdata is record Np, Ni : Integer := 0; -- Number of calls to each end record; - + procedure Call_Ops (Pop, Iop : Boolean; Opd : in out Opdata); - + private - + -- The private op declaration, within the private part of the package spec - + procedure Op_Private (Opd : in out Opdata); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb index cf3ca6e16..034323606 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb @@ -1,7 +1,7 @@ package body Environ is - + X : Value := 0; - + function Probe return State is begin X := X + 1; -- # probe @@ -12,10 +12,9 @@ package body Environ is end if; return (X => X); -- # probe end; - + function Match (A, B : State) return Boolean is begin return A.X = B.X; -- # compare end; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads index 968275fcb..a1f5be15e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads @@ -1,17 +1,16 @@ package Environ is - + type State is private; - + function Probe return State; - + Did_Initial_Probe, Did_Other_probe : Boolean := False; - + function Match (A, B : State) return Boolean; - + private type Value is mod 2; type State is record X : Value; end record; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb index fec072712..66b3035ef 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb @@ -1,7 +1,7 @@ with Environ; use Environ; package body Monitor is - + procedure Compare_With_Initial_State_Now is Current_Environ_State : State := Environ.Probe; -- # compare begin @@ -9,5 +9,5 @@ package body Monitor is N_Matches := N_Matches + 1; -- # match end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads index 3328a6f4c..13c920dac 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads @@ -1,12 +1,12 @@ with Environ; package Monitor is - + Initial_Environ_State : constant Environ.State; - + procedure Compare_With_Initial_State_Now; N_Matches : Natural := 0; - + private Initial_Environ_State : constant Environ.State := Environ.Probe; -- # decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb index 52a27f7bb..5754de817 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb @@ -5,7 +5,7 @@ procedure Test_Monitor_1Cmp is begin Assert (Did_Initial_Probe = True); Assert (Did_Other_Probe = False); - + Compare_With_Initial_State_Now; Assert (Did_Other_Probe = True); Assert (N_Matches = 0); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb index e3ada0916..6b2e95124 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb @@ -5,11 +5,11 @@ procedure Test_Monitor_2Cmp is begin Assert (Did_Initial_Probe = True); Assert (Did_Other_Probe = False); - + Compare_With_Initial_State_Now; Assert (Did_Other_Probe = True); Assert (N_Matches = 0); - + Compare_With_Initial_State_Now; Assert (Did_Other_Probe = True); Assert (N_Matches = 1); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst index 3c88eadbe..e3af286ca 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst @@ -1,8 +1,6 @@ SC requirements for ARM chap. 7 : Packages ========================================== -%REQ_ID% - The core SC requirements for statements and declarations shall be obeyed in all context variations allowed by package-related constructs. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst index 84246e0d6..7926a8bd2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst @@ -2,8 +2,6 @@ SC requirements for Renaming declarations (ARM 8.5) =================================================== -%REQ_ID% - * Renaming declarations shall be recognized and processed as regular object diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb deleted file mode 100644 index 49097ea23..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb +++ /dev/null @@ -1,7 +0,0 @@ -separate (Ops) -package body Lsub is - procedure Op (Opd: in out Opdata) is - begin - Touch (Opd); -- # lsub - end; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst index 93b94708c..feb393f38 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst @@ -2,8 +2,6 @@ SC requirements for Subunits (ARM 10.1.3) ========================================= -%REQ_ID% - SC assessments shall treat subunits as regular units. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb index a94cb3ecd..efdd2645c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb @@ -21,4 +21,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb index ff956b62a..4379f4b9a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb index 55e5129c1..9105450a7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb index fd779f026..cc0210004 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb index 60c538a74..cd4d7b811 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb index b40fe6321..e1e304ed3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb index 6c6c059de..d9ee633ad 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb index f1b5f8216..6d69d2c92 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/src/fuand.adb deleted file mode 100644 index 5369db5c6..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/src/fuand.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Fuand is - - pragma Unsuppress (All_Checks); - - function Andthen (A, B : Integer) return Boolean is - begin - -- Possible out of range array access here - return Bool_For (A) and then Bool_For(B); -- # eval - end; - - procedure Andthen (A, B : Integer; R : out Boolean) is - begin - R := Andthen (A, B); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/src/fuand.adb deleted file mode 100644 index 24547196a..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/src/fuand.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Fuand is - - pragma Unsuppress (All_Checks); - - function Andthen (A, B : Integer) return Boolean is - begin - -- Possible range check failure on conversion here - return Bool (Boolval(A)) and then Bool (Boolval(B)); -- # eval - end; - - procedure Andthen (A, B : Integer; R : out Boolean) is - begin - R := Andthen (A, B); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/src/fuand.adb deleted file mode 100644 index 1cf67eca8..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/src/fuand.adb +++ /dev/null @@ -1,16 +0,0 @@ -with Args; use Args; - -package body Fuand is - - function Andthen (A, B : Integer) return Boolean is - begin - -- Safe conversion here, possible raise from Args.Bool - return Bool (Intval(A)) and then Bool (Intval(B)); -- # eval - end; - - procedure Andthen (A, B : Integer; R : out Boolean) is - begin - R := Andthen (A, B); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/src/flip.adb deleted file mode 100644 index 138fd1da0..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/src/flip.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Flip is - - pragma Unsuppress (All_Checks); - - function Neg (A : Integer) return Boolean is - begin - -- Possible index check failure here - return not Bool_For (A); -- # eval - end; - - procedure Neg (A : Integer; R : out Boolean) is - begin - R := Neg (A); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/src/flip.adb deleted file mode 100644 index 611e88136..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/src/flip.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Flip is - - pragma Unsuppress (All_Checks); - - function Neg (A : Integer) return Boolean is - begin - -- Possible range check failure on conversion here - return not Bool (Boolval(A)); -- # eval - end; - - procedure Neg (A : Integer; R : out Boolean) is - begin - R := Neg (A); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/src/flip.adb deleted file mode 100644 index 4b60374a9..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/src/flip.adb +++ /dev/null @@ -1,16 +0,0 @@ -with Args; use Args; - -package body Flip is - - function Neg (A : Integer) return Boolean is - begin - -- Safe conversion here, possible raise from Args.Bool - return not Bool (Intval(A)); -- # eval - end; - - procedure Neg (A : Integer; R : out Boolean) is - begin - R := Neg (A); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/src/fuor.adb deleted file mode 100644 index 6c06de172..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/src/fuor.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Fuor is - - pragma Unsuppress (All_Checks); - - function Orelse (A, B : Integer) return Boolean is - begin - -- Possible out of range array access here - return Bool_For (A) or else Bool_For(B); -- # eval - end; - - procedure Orelse (A, B : Integer; R : out Boolean) is - begin - R := Orelse (A, B); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/src/fuor.adb deleted file mode 100644 index d1ebfd389..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/src/fuor.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Fuor is - - pragma Unsuppress (All_Checks); - - function Orelse (A, B : Integer) return Boolean is - begin - -- Possible range check failure on conversion here - return Bool (Boolval(A)) or else Bool (Boolval(B)); -- # eval - end; - - procedure Orelse (A, B : Integer; R : out Boolean) is - begin - R := Orelse (A, B); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/src/fuor.adb deleted file mode 100644 index cefe41081..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/src/fuor.adb +++ /dev/null @@ -1,16 +0,0 @@ -with Args; use Args; - -package body Fuor is - - function Orelse (A, B : Integer) return Boolean is - begin - -- Safe conversion here, possible raise from Args.Bool - return Bool (Intval(A)) or else Bool (Intval(B)); -- # eval - end; - - procedure Orelse (A, B : Integer; R : out Boolean) is - begin - R := Orelse (A, B); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/src/val.adb deleted file mode 100644 index e12aa6d71..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/src/val.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Args; use Args; - -package body Val is - - pragma Unsuppress (All_Checks); - - function To_Bool (A : Integer) return Boolean is - begin - -- Possible range check failure on conversion here - return Bool (Boolval(A)); -- # eval - end; - - procedure Bool (A : Integer; R : out Boolean) is - begin - R := To_Bool (A); -- # eval - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/tc_set.rst deleted file mode 100755 index f2ddc3bb5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/tc_set.rst +++ /dev/null @@ -1,29 +0,0 @@ -Check SC on expressions that can fail to evaluate because of exceptions -========================================================================= - -Check the effects of an expression evaluation interrupted by an exception -raise, for a set of expressions and a set of possible exception origins, as -part of a simple statement or in the control expression in compound -statements. - -For each variant, check a variety of situations where - -* No exception gets raised at all - -* An exception gets raised as part of all the evaluation attempts, - on the first or the last operand evaluation, - -* An exception would be raised by one operand but is not because of - the shortcircuit semantics, - -* An exception is raised by some evaluation but not others - - -.. qmlink:: TCIndexImporter - - * - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst deleted file mode 100644 index 564eeec67..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst +++ /dev/null @@ -1,3 +0,0 @@ -**Exercise SC on exception handlers for user-defined or standard exceptions** - -LRMREF: 11.2, 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.opt deleted file mode 100644 index 9e44a9266..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -RTS_RAVENSCAR,powerpc,7.1.2,bin-traces SKIP !zfp sjlj eh issue fixed post 7.0, K316-021 -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_1.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_1.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_1.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_2.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_2.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_2.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_ce.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_ce.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_ce.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_ce.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_multiple.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_multiple.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_multiple.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_multiple.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no_exception.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no_exception.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no_exception.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no_exception.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt new file mode 100644 index 000000000..21cc3c381 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt @@ -0,0 +1 @@ +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb new file mode 100644 index 000000000..887cca612 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Fuand is + + pragma Unsuppress (All_Checks); + + function Andthen (A, B : Integer) return Boolean is + begin + -- Possible out of range array access here + return Bool_For (A) and then Bool_For(B); -- # eval + end; + + procedure Andthen (A, B : Integer; R : out Boolean) is + begin + R := Andthen (A, B); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb new file mode 100644 index 000000000..3b893fb06 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Fuand is + + pragma Unsuppress (All_Checks); + + function Andthen (A, B : Integer) return Boolean is + begin + -- Possible range check failure on conversion here + return Bool (Boolval(A)) and then Bool (Boolval(B)); -- # eval + end; + + procedure Andthen (A, B : Integer; R : out Boolean) is + begin + R := Andthen (A, B); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb new file mode 100644 index 000000000..4eaf7552e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb @@ -0,0 +1,16 @@ +with Args; use Args; + +package body Fuand is + + function Andthen (A, B : Integer) return Boolean is + begin + -- Safe conversion here, possible raise from Args.Bool + return Bool (Intval(A)) and then Bool (Intval(B)); -- # eval + end; + + procedure Andthen (A, B : Integer; R : out Boolean) is + begin + R := Andthen (A, B); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tf.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tf.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tf.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tt.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tt.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tt.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb new file mode 100644 index 000000000..4255af607 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Flip is + + pragma Unsuppress (All_Checks); + + function Neg (A : Integer) return Boolean is + begin + -- Possible index check failure here + return not Bool_For (A); -- # eval + end; + + procedure Neg (A : Integer; R : out Boolean) is + begin + R := Neg (A); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb new file mode 100644 index 000000000..bac6d7072 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Flip is + + pragma Unsuppress (All_Checks); + + function Neg (A : Integer) return Boolean is + begin + -- Possible range check failure on conversion here + return not Bool (Boolval(A)); -- # eval + end; + + procedure Neg (A : Integer; R : out Boolean) is + begin + R := Neg (A); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb new file mode 100644 index 000000000..3ccb9ab77 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb @@ -0,0 +1,16 @@ +with Args; use Args; + +package body Flip is + + function Neg (A : Integer) return Boolean is + begin + -- Safe conversion here, possible raise from Args.Bool + return not Bool (Intval(A)); -- # eval + end; + + procedure Neg (A : Integer; R : out Boolean) is + begin + R := Neg (A); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_fu_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_fu_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_fu_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_fu_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_tf.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_tf.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_tf.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb new file mode 100644 index 000000000..722cb3dc8 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Fuor is + + pragma Unsuppress (All_Checks); + + function Orelse (A, B : Integer) return Boolean is + begin + -- Possible out of range array access here + return Bool_For (A) or else Bool_For(B); -- # eval + end; + + procedure Orelse (A, B : Integer; R : out Boolean) is + begin + R := Orelse (A, B); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb new file mode 100644 index 000000000..94ea1103d --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Fuor is + + pragma Unsuppress (All_Checks); + + function Orelse (A, B : Integer) return Boolean is + begin + -- Possible range check failure on conversion here + return Bool (Boolval(A)) or else Bool (Boolval(B)); -- # eval + end; + + procedure Orelse (A, B : Integer; R : out Boolean) is + begin + R := Orelse (A, B); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb new file mode 100644 index 000000000..fb407e60e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb @@ -0,0 +1,16 @@ +with Args; use Args; + +package body Fuor is + + function Orelse (A, B : Integer) return Boolean is + begin + -- Safe conversion here, possible raise from Args.Bool + return Bool (Intval(A)) or else Bool (Intval(B)); -- # eval + end; + + procedure Orelse (A, B : Integer; R : out Boolean) is + begin + R := Orelse (A, B); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ff.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ff.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ff.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ff.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ft.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ft.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ft.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ft.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_tx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_tx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_tx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_tx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/test.py old mode 100755 new mode 100644 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/test.py old mode 100755 new mode 100644 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/test.py old mode 100755 new mode 100644 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb new file mode 100644 index 000000000..49f58959d --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb @@ -0,0 +1,18 @@ +with Args; use Args; + +package body Val is + + pragma Unsuppress (All_Checks); + + function To_Bool (A : Integer) return Boolean is + begin + -- Possible range check failure on conversion here + return Bool (Boolval(A)); -- # eval + end; + + procedure Bool (A : Integer; R : out Boolean) is + begin + R := To_Bool (A); -- # eval + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_fu_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_fu_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_fu_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_fu_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_tf.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_tf.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_tf.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/tc_set.rst new file mode 100755 index 000000000..916ae179c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/tc_set.rst @@ -0,0 +1,29 @@ +Check SC on expressions that can fail to evaluate because of exceptions +========================================================================= + +Check the effects of an expression evaluation interrupted by an exception +raise, for a set of expressions and a set of possible exception origins, as +part of a simple statement or in the control expression in compound +statements. + +For each variant, check a variety of situations where + +* No exception gets raised at all, + +* An exception gets raised as part of all the evaluation attempts, + on the first or the last operand evaluation, + +* An exception would be raised by one operand but is not because of + the shortcircuit semantics, + +* An exception is raised by some evaluation but not others. + + +.. qmlink:: TCIndexImporter + + * + + + + + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_all_exception_raise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_all_exception_raise.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_all_exception_raise.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_all_exception_raise.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_full.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_full.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_no_raise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_no_raise.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_no_raise.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_no_raise.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_predefined.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_predefined.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_predefined.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_predefined.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_user.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_user.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_user.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_user.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst new file mode 100644 index 000000000..bf5086418 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst @@ -0,0 +1,17 @@ +**Exercise SC on a variety of situations involving raise operations** + +Exercise procedures and functions including conditional raise +statements for predefined or user defined exceptions, all handled +locally and followed by simple statements. Check situations where the +raise operation gets triggered or not, enforcing variations on the +conditionals guards. Verify that the explicit raise statements are +properly processed as regular statements and that the control flow +transfers are reflected on the coverage status of the statements +following the raise and in the exception handlers. + +Also exercise a few cases involving implicit raise events, for example +out of a range check. Verify that the control flow effects induced by +such events is also properly represented, on the triggering statements +and those that immediately follow. + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt new file mode 100644 index 000000000..b51b8ff11 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt @@ -0,0 +1,4 @@ +block DEAD Test with exceptions breaking the control flow +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no_raise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no_raise.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no_raise.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no_raise.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_all.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_all.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_all.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_predef.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_predef.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_predef.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_predef.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_user.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_user.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_user.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_user.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst new file mode 100644 index 000000000..7c9b34677 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst @@ -0,0 +1,8 @@ +**Exercise SC on subprograms with a choice of handlers for a block** + +Check a variety of subprograms which may raise either a standard +exception or a user defined one, handling the occurrence with a +dedicated handler selected either explicitly or as a default by +way of a "when others" alternative. + +LRMREF: 11.2, 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt new file mode 100644 index 000000000..df47406b3 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR,powerpc,7.1.2,bin-traces SKIP !zfp sjlj eh issue fixed post 7.0, K316-021 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb new file mode 100644 index 000000000..015326e46 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb @@ -0,0 +1,38 @@ +pragma Unsuppress (All_Checks); + +package body Ctxt is + + generic + Iraise : Boolean; + Xraise : Boolean; + package G_Checker is + end; + + package body G_Checker is + begin + declare + procedure Check (Iraise, Xraise : Boolean) is + begin + X := X + 1; -- # pre + if Iraise then -- # ieval + R0 := I1; -- # iraise + elsif Xraise then -- # xeval + raise Constraint_Error; -- # xraise + end if; + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # handler + end; + begin + Check (Iraise => Iraise, Xraise => Xraise); -- # pre + end; + end; + + procedure Run (Iraise, Xraise : Boolean) is + package Checker is + new G_Checker (Iraise => Iraise, Xraise => Xraise); + begin + null; -- # pre + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst new file mode 100644 index 000000000..fc6e7c780 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC on local exceptions within a generic package elaboration** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb new file mode 100644 index 000000000..e5a4fcd4f --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb @@ -0,0 +1,22 @@ +pragma Unsuppress (All_Checks); + +package body Ctxt is + procedure Run (Iraise, Xraise : Boolean) is + begin + R0 := I1; -- # pre + exception + when others => + begin + X := X + 1; -- # pre + if Iraise then -- # ieval + R0 := I1; -- # iraise + elsif Xraise then -- # xeval + raise Constraint_Error; -- # xraise + end if; + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # handler + end; + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst new file mode 100644 index 000000000..6ffdb3071 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC on local exceptions within an exception handler** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb new file mode 100644 index 000000000..83e981f92 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb @@ -0,0 +1,17 @@ +package body Ctxt is + pragma Unsuppress (All_Checks); + + procedure Run (Iraise, Xraise : Boolean) is + begin + X := X + 1; -- # pre + if Iraise then -- # ieval + R0 := I1; -- # iraise + elsif Xraise then -- # xeval + raise Constraint_Error; -- # xraise + end if; + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # handler + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst new file mode 100644 index 000000000..34b9aa113 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC on local exceptions within a regular subprogram** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads new file mode 100644 index 000000000..87f807554 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads @@ -0,0 +1,13 @@ + +package Ctxt is + -- Prevent compilation warnings on some versions of ctxt.adb + -- where X is accessed within generic bodies: + pragma Elaborate_Body; + + X : Integer; + R0 : Integer range 0 .. 0 := 0; + I1 : Integer := 1; + + Handled : Integer := 0; + procedure Run (Iraise, Xraise : Boolean); +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb new file mode 100644 index 000000000..3f41c049a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb @@ -0,0 +1,16 @@ +with Ctxt, Support; use Ctxt, Support; + +procedure Test_Ctxt_Iraise is +begin + Ctxt.Run (Iraise => True, Xraise => False); +end; + +--# ctxt.adb +-- /pre/ l+ ## 0 +-- /ieval/ l+ ## 0 +-- /iraise/ l+ ## 0 +-- /xeval/ l- ## s- +-- /xraise/ l- ## s- +-- /post/ l- ## s- +-- /handler/ l+ ## 0 +-- /other/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb new file mode 100644 index 000000000..4ac2380e6 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb @@ -0,0 +1,16 @@ +with Ctxt, Support; use Ctxt, Support; + +procedure Test_Ctxt_Noraise is +begin + Ctxt.Run (Iraise => False, Xraise => False); +end; + +--# ctxt.adb +-- /pre/ l+ ## 0 +-- /ieval/ l+ ## 0 +-- /iraise/ l- ## s- +-- /xeval/ l+ ## 0 +-- /xraise/ l- ## s- +-- /post/ l+ ## 0 +-- /handler/ l- ## s- +-- /other/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb new file mode 100644 index 000000000..140909040 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb @@ -0,0 +1,16 @@ +with Ctxt, Support; use Ctxt, Support; + +procedure Test_Ctxt_Xraise is +begin + Ctxt.Run (Iraise => False, Xraise => True); +end; + +--# ctxt.adb +-- /pre/ l+ ## 0 +-- /ieval/ l+ ## 0 +-- /iraise/ l- ## s- +-- /xeval/ l+ ## 0 +-- /xraise/ l+ ## 0 +-- /post/ l- ## s- +-- /handler/ l+ ## 0 +-- /other/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst new file mode 100644 index 000000000..b41abc5cc --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst @@ -0,0 +1,6 @@ +Check SC with exceptions never propagating across subprograms +============================================================= + +.. qmlink:: TCIndexImporter + + * diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb deleted file mode 100644 index d5492782b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb +++ /dev/null @@ -1,51 +0,0 @@ -package body Ops is - - procedure Div_CE (X, Y : Integer; T : out Integer) is - begin - if Y = 0 then -- # stmt - raise Constraint_Error; -- # fault - end if; - T := X / Y; -- # no_fault - end; - - Div_Error : exception; - - procedure Div_DE (X, Y : Integer; T : out Integer) is - begin - if Y = 0 then -- # stmt - raise Div_Error; -- # fault - end if; - T := X / Y; -- # no_fault - end; - - -- - - procedure Div - (X, Y : Integer; T : out Integer; Fault : out Boolean) - is - CE_Fault, DE_Fault : Boolean; - begin - begin - Div_CE (X, Y, T); -- # stmt - CE_Fault := False; -- # no_fault - exception - when Constraint_Error => - CE_Fault := True; -- # fault - when others => - null; -- # bad_handler - end; - - begin - Div_DE (X, Y, T); -- # stmt - DE_Fault := False; -- # no_fault - exception - when Div_Error => - DE_Fault := True; -- # fault - when others => - null; -- # bad_handler - end; - - Fault := CE_Fault or else DE_Fault; -- # stmt - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.ads deleted file mode 100644 index dd79e1b99..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.ads +++ /dev/null @@ -1,5 +0,0 @@ -package Ops is - procedure Div (X, Y : Integer; T : out Integer; Fault : out Boolean); - - N_Faults : Integer := 0; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_fault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_fault.adb deleted file mode 100644 index 6fc05ac5c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_fault.adb +++ /dev/null @@ -1,15 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_Ops_Fault is - T : Integer; - Fault : Boolean; -begin - Div (1, 0, T, Fault); - Assert (Fault); -end; - ---# ops.adb --- /fault/ l+ ## 0 --- /no_fault/ l- ## s- --- /stmt/ l+ ## 0 --- /bad_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_full.adb deleted file mode 100644 index 11c1e59d3..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_full.adb +++ /dev/null @@ -1,19 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_Ops_Full is - T : Integer; - Fault : Boolean; -begin - Div (4, 0, T, Fault); - Assert (Fault); - - Div (4, 2, T, Fault); - Assert (T = 2); - Assert (not Fault); -end; - ---# ops.adb --- /fault/ l+ ## 0 --- /no_fault/ l+ ## 0 --- /stmt/ l+ ## 0 --- /bad_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_nofault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_nofault.adb deleted file mode 100644 index e4514ea6c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_nofault.adb +++ /dev/null @@ -1,16 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_Ops_NoFault is - T : Integer; - Fault : Boolean; -begin - Div (4, 2, T, Fault); - Assert (T = 2); - Assert (not Fault); -end; - ---# ops.adb --- /fault/ l- ## s- --- /no_fault/ l+ ## 0 --- /stmt/ l+ ## 0 --- /bad_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb new file mode 100644 index 000000000..c8c3c7c1f --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb @@ -0,0 +1,94 @@ +package body Ops is + + -- req-rule #4 + + pragma Unsuppress (All_Checks); + I2 : Integer := 2; + pragma Volatile (I2); + + procedure Fail_Range_Check is + subtype R1_1 is Integer range 1 .. 1; + X : R1_1; -- # stmt + begin + X := I2; -- # stmt + end; + + procedure Div_CE (X, Y : Integer; T : out Integer) is + begin + if Y = 0 then -- # stmt + raise Constraint_Error; -- # div_fault req-rule #1 and #5 + end if; + T := X / Y; -- # no_div_fault + end; + + Div_Error : exception; + + procedure Div_DE (X, Y : Integer; T : out Integer) is + begin + if Y = 0 then -- # stmt + raise Div_Error; -- # div_fault req-rule #1 and #5 + end if; + T := X / Y; -- # no_div_fault req-rule #2 + end; + + -- + + procedure Div + (X, Y : Integer; T : out Integer; Fault : out Boolean) + is + CE_Fault, DE_Fault : Boolean; + + begin + + -- req-rule #4 + + begin + Fail_Range_Check; -- # stmt + exception + when Constraint_Error => null; -- # stmt + end; + + begin + Div_CE (X, Y, T); -- # stmt + CE_Fault := False; -- # no_div_fault req-rule #2 + exception + when Constraint_Error => + CE_Fault := True; -- # div_fault req-rule #3 and #5 + when others => + null; -- # bad_handler req-rule #3 + end; + + begin + Div_DE (X, Y, T); -- # stmt + DE_Fault := False; -- # no_div_fault req-rule #2 + exception + when Div_Error => + DE_Fault := True; -- # div_fault req-rule #3 and #5 + when others => + null; -- # bad_handler req-rule #3 + end; + + Fault := CE_Fault or else DE_Fault; -- # stmt + end; + + -- + + pragma Unsuppress (All_Checks); + + procedure Do_Bump (X : in out Integer) is + One : Integer := 1; + pragma Volatile (One); + begin + -- This will raise constraint_error on integer'last + X := One * (X + One); -- # do_bump #4 + end; + + procedure Bump (X : in out Integer; Fault : out Boolean) is + begin + Do_Bump (X); -- # do_bump + Fault := False; -- # no_bump_fault #2 + exception + when Constraint_Error => + Fault := True; -- # bump_fault #3 + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads new file mode 100644 index 000000000..17ea3794c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads @@ -0,0 +1,4 @@ +package Ops is + procedure Div (X, Y : Integer; T : out Integer; Fault : out Boolean); + procedure Bump (X : in out Integer; Fault : out Boolean); +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_fault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_fault.adb new file mode 100644 index 000000000..14226cd21 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_fault.adb @@ -0,0 +1,23 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_Fault is + T : Integer; + Fault : Boolean; +begin + Div (1, 0, T, Fault); + Assert (Fault); + + T := Integer'Last; + Bump (T, Fault); + Assert (Fault); +end; + +--# ops.adb +-- /div_fault/ l+ ## 0 +-- /no_div_fault/ l- ## s- +-- /stmt/ l+ ## 0 +-- /bad_handler/ l- ## s- + +-- /do_bump/ l+ ## 0 +-- /bump_fault/ l+ ## 0 +-- /no_bump_fault/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_full.adb new file mode 100644 index 000000000..7af72cce7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_full.adb @@ -0,0 +1,31 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_Full is + T : Integer; + Fault : Boolean; +begin + Div (4, 0, T, Fault); + Assert (Fault); + + Div (4, 2, T, Fault); + Assert (T = 2); + Assert (not Fault); + + Bump (T, Fault); + Assert (T = 3); + Assert (not Fault); + + T := Integer'Last; + Bump (T, Fault); + Assert (Fault); +end; + +--# ops.adb +-- /fault/ l+ ## 0 +-- /no_fault/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /bad_handler/ l- ## s- + +-- /do_bump/ l+ ## 0 +-- /bump_fault/ l+ ## 0 +-- /no_bump_fault/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_nofault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_nofault.adb new file mode 100644 index 000000000..4526066d8 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_nofault.adb @@ -0,0 +1,24 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_NoFault is + T : Integer; + Fault : Boolean; +begin + Div (4, 2, T, Fault); + Assert (T = 2); + Assert (not Fault); + + Bump (T, Fault); + Assert (T = 3); + Assert (not Fault); +end; + +--# ops.adb +-- /div_fault/ l- ## s- +-- /no_div_fault/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /bad_handler/ l- ## s- + +-- /do_bump/ l+ ## 0 +-- /bump_fault/ l- ## s- +-- /no_bump_fault/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb deleted file mode 100644 index ab2c70425..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb +++ /dev/null @@ -1,15 +0,0 @@ - -package body Ops is - - procedure To_Integer - (S : String; Value : out Integer; Fault : out Boolean) - is - begin - Value := Integer'Value (S); -- # convert - Fault := False; -- # no_fault - exception - when others => - Value := 0; -- # fault - Fault := True; -- # fault - end; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads deleted file mode 100644 index c142bdb9c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Ops is - procedure To_Integer - (S : String; Value : out Integer; Fault : out Boolean); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb deleted file mode 100644 index 163ce16fd..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb +++ /dev/null @@ -1,12 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_0 is -begin - null; -end; - ---# ops.adb --- /convert/ l- ## s- --- /no_fault/ l- ## s- --- /fault/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb deleted file mode 100644 index 6ba2fb64a..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb +++ /dev/null @@ -1,17 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_All is - X : Integer; - Fault : Boolean; -begin - To_Integer ("36", X, Fault); - Assert (X = 36 and then not Fault); - To_Integer ("blue", X, Fault); - Assert (X = 0 and then Fault); -end; - ---# ops.adb --- /convert/ l+ ## 0 --- /no_fault/ l+ ## 0 --- /fault/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb deleted file mode 100644 index 57eae52a5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb +++ /dev/null @@ -1,15 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_fault is - X : Integer; - Fault : Boolean; -begin - To_Integer ("blue", X, Fault); - Assert (X = 0 and then Fault); -end; - ---# ops.adb --- /convert/ l+ ## 0 --- /no_fault/ l- ## s- --- /fault/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb deleted file mode 100644 index 885ef1d3f..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb +++ /dev/null @@ -1,15 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_Ok is - X : Integer; - Fault : Boolean; -begin - To_Integer ("54", X, Fault); - Assert (X = 54 and then not Fault); -end; - ---# ops.adb --- /convert/ l+ ## 0 --- /no_fault/ l+ ## 0 --- /fault/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst deleted file mode 100644 index 7cf20f80b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst +++ /dev/null @@ -1,12 +0,0 @@ -**SC on a simple wrapper around an external service call which might raise** - -Check the case of a simple subprogram which invokes an external service which -might raise, catching all the possible exceptions and setting indicators to -convey whether an exception occurred or not. - -Exercise cases when the external service raises an exception, does not -raise an exception, or a combination thereof. - -LRMREF: 11.2, 11.4 - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb new file mode 100644 index 000000000..342539077 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb @@ -0,0 +1,11 @@ +with Silent_Last_Chance; +with Doraise; use Doraise; + +package body Ctxt is + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst new file mode 100644 index 000000000..f642f7733 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC with unhandled exception propagation** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb new file mode 100644 index 000000000..2410dfb7e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb @@ -0,0 +1,68 @@ +with Doraise; use Doraise; + +package body Ctxt is + + procedure Case1 (Rk : Raise_Kind; Rm : Raise_Mode); + -- Trigger an inner raise and handle within the same handler + + procedure Case2 (Rk : Raise_Kind; Rm : Raise_Mode); + procedure Case2_Helper (Rk : Raise_Kind; Rm : Raise_Mode); + -- Trigger an inner raise from within a handler and handle + -- one level up. + + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + Case1 (Rk, Rm); -- # pre + Case2 (Rk, Rm); -- # pre + end; + + procedure Case1 (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + + -- Arrange to reach a handler ... + raise Constraint_Error; -- # pre + exception + when others => + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # ce_handler + when Program_Error => + Handled := Handled + 1; -- # pe_handler + when User_Error => + Handled := Handled + 1; -- # ue_handler + end; + end; + + -- + + procedure Case2 (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + Case2_Helper (Rk, Rm); -- # pre + exception + when Constraint_Error => + Handled := Handled + 1; -- # ce_handler + when Program_Error => + Handled := Handled + 1; -- # pe_handler + when User_Error => + Handled := Handled + 1; -- # ue_handler + end; + + procedure Case2_Helper (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + -- Arrange to reach a handler ... + raise Constraint_Error; -- # pre + exception + when others => + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + end; + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst new file mode 100644 index 000000000..933de7b83 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC with exception propagation handled within an exception handler** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb new file mode 100644 index 000000000..0b84cdd23 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb @@ -0,0 +1,17 @@ +with Doraise; use Doraise; + +package body Ctxt is + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # ce_handler + when Program_Error => + Handled := Handled + 1; -- # pe_handler + when User_Error => + Handled := Handled + 1; -- # ue_handler + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst new file mode 100644 index 000000000..f68f69afd --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC with exception propagation handled within a regular subprogram** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt index d5aeaf6cb..d5f4f5ab9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt @@ -1 +1,3 @@ RTS_ZFP DEAD no support for exception propagation in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for exception propagation in light-tasking runtimes +block DEAD Tests with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads new file mode 100644 index 000000000..68f6394fa --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads @@ -0,0 +1,15 @@ +with Doraise; use Doraise; + +package Ctxt is + + -- A few globals that let us insert statements at various + -- spots and sanity check the logic we ran through. + + X : Integer := 0; + Handled : Integer := 0; + + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode); + -- Invoke and optionally handle Doraise operations in a specific + -- context. Body to be provided by the various testcases, each + -- exercising a particular situation. +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb new file mode 100644 index 000000000..1ad38c8fd --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb @@ -0,0 +1,83 @@ +with Ctxt; use Ctxt; + +package body Doraise is + + pragma Unsuppress (All_Checks); + + procedure Do_Raise (Rk : Raise_Kind) is + + -- This is the common procedure called to perform a raise to + -- be propagated. It is not called at all for Raise_Mode None, + -- so the "pre" or "run" anchors aren't appropriate here. + -- + -- do_raise-pre is introduced instead, needed at least for + -- the declarations below. + + -- Entities to help trigger specific kinds of occurrences + + R0 : Integer range 0 .. 0 := 0; -- # do_raise-pre + I1 : Integer := 1; -- # do_raise-pre + pragma Volatile (I1); + + Vint : Integer; -- # do_raise-pre + Vstr : String := "blue"; -- # do_raise-pre + pragma Volatile (Vstr); + + begin + X := X + 1; -- # do_raise-pre + if Rk = Implicit_CE then -- # ice-eval + R0 := I1; -- # ice-raise + + elsif Rk = Explicit_PE then -- # xpe-eval + raise Program_Error; -- # xpe-raise + + elsif Rk = Explicit_UE then -- # xue-eval + raise User_Error; -- # xue-raise + + elsif Rk = From_RTS then -- # rts-eval + Vint := Integer'Value(Vstr); -- # rts-raise + + end if; + X := X + 1; -- # do_raise-post + end; + + procedure Do_Reraise_One (Rk : Raise_Kind) is + begin + Do_Raise (Rk); -- # call_reraise_one + exception + when Constraint_Error => + Handled := Handled + 1; -- # reraise_one_ce_handler + raise; -- # reraise_one_ce_handler + when Program_Error => + Handled := Handled + 1; -- # reraise_one_pe_handler + raise; -- # reraise_one_pe_handler + when User_Error => + Handled := Handled + 1; -- # reraise_one_ue_handler + raise; -- # reraise_one_ue_handler + end; + + procedure Do_Reraise_Other (Rk : Raise_Kind) is + begin + Do_Raise (Rk); -- # call_reraise_other + exception + when others => + Handled := Handled + 1; -- # reraise_other_handler + raise; -- # reraise_other_handler + end; + + procedure Dispatch (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + case Rm is -- # pre + when Straight => + Do_Raise (Rk); -- # call_straight + when Reraise_Other => + Do_Reraise_Other (Rk); -- # call_reraise_other + when Reraise_One => + Do_Reraise_One (Rk); -- # call_reraise_one + when None => + null; -- # rm_none + end case; + X := X + 1; -- # post + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads new file mode 100644 index 000000000..d69e36da0 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads @@ -0,0 +1,25 @@ +package Doraise is + + User_Error : exception; + + -- How a raise is to be propagated. If not None, this can be + -- either directly (Straight) or via an intermediate handler that + -- will re-raise (Reraise_One/Other). For Reraise_One, there is + -- a specific handler for each exception id (CE, PE, User). For + -- Reraise_Other, this would be a "when others": + + type Raise_Mode is + (Straight, Reraise_One, Reraise_Other, None); + + -- The kind of raise operation a testcase can request: + + type Raise_Kind is + (Implicit_CE, -- implicit Constraint_Error out of a range check + Explicit_PE, -- explicit raise Constraint_Error stmt + Explicit_UE, -- explicit raise User_Error stmt + From_RTS, -- a Constraint_Error out of a 'Valid call + None); -- a sensible choice to go with Raise_Mode None + + procedure Dispatch (Rk : Raise_Kind; Rm : Raise_Mode); + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb new file mode 100644 index 000000000..51bb7b631 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_ICE_R1 is +begin + Ctxt.Run (Rk => Implicit_CE, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l+ ## 0 +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l+ ## 0 +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb new file mode 100644 index 000000000..7a452a6b8 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_ICE_RO is +begin + Ctxt.Run (Rk => Implicit_CE, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l+ ## 0 +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb new file mode 100644 index 000000000..69b54979b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_ICE_ST is +begin + Ctxt.Run (Rk => Implicit_CE, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l+ ## 0 +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb new file mode 100644 index 000000000..51d9e6964 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_Noraise is +begin + Ctxt.Run (Rk => None, Rm => None); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l+ ## 0 +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l- ## s- +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l- ## s- +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l+ ## 0 +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb new file mode 100644 index 000000000..1e220918a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_RTS_R1 is +begin + Ctxt.Run (Rk => From_RTS, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l- ## s- +-- /rts-eval/ l+ ## 0 +-- /rts-raise/ l+ ## 0 + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l+ ## 0 +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb new file mode 100644 index 000000000..21ebd6c61 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_RTS_RO is +begin + Ctxt.Run (Rk => From_RTS, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l- ## s- +-- /rts-eval/ l+ ## 0 +-- /rts-raise/ l+ ## 0 + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb new file mode 100644 index 000000000..94c900543 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_RTS_ST is +begin + Ctxt.Run (Rk => From_RTS, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l- ## s- +-- /rts-eval/ l+ ## 0 +-- /rts-raise/ l+ ## 0 + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb new file mode 100644 index 000000000..586512ad7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XPE_R1 is +begin + Ctxt.Run (Rk => Explicit_PE, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l+ ## 0 +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l+ ## 0 +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l+ ## 0 +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb new file mode 100644 index 000000000..afc7ca339 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XPE_RO is +begin + Ctxt.Run (Rk => Explicit_PE, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l+ ## 0 +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l+ ## 0 +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb new file mode 100644 index 000000000..5d8b78340 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XPE_ST is +begin + Ctxt.Run (Rk => Explicit_PE, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l+ ## 0 +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l+ ## 0 +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb new file mode 100644 index 000000000..39bba1acf --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XUE_R1 is +begin + Ctxt.Run (Rk => Explicit_UE, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l+ ## 0 +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l+ ## 0 +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l+ ## 0 +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb new file mode 100644 index 000000000..f0313acfe --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XUE_RO is +begin + Ctxt.Run (Rk => Explicit_UE, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l+ ## 0 +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l+ ## 0 +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb new file mode 100644 index 000000000..7eec534b7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XUE_ST is +begin + Ctxt.Run (Rk => Explicit_UE, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l+ ## 0 +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l+ ## 0 +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst index b7647625a..7de51433f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst @@ -1,9 +1,6 @@ Check SC with exceptions propagating across subprograms ======================================================= -Verify the correctness of assessments in the current restricted -perimeter set by our parent requirement. - .. qmlink:: TCIndexImporter * diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst deleted file mode 100644 index 998393a41..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst +++ /dev/null @@ -1,3 +0,0 @@ -**Exercise SC with multiple kinds of raise operations, implicit or explicit** - -LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst index d70aeba10..f96aa9865 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst @@ -4,67 +4,84 @@ SC requirements for ARM chap. 11 : Exceptions ============================================= -%REQ_ID% +Statement Coverage assessments shall handle the Ada exceptions related +features described in Chapter 11 of the language Reference Manual. This +requires accounting for exception handlers, implicit or explicit raise +operations and the effects of their control flow transfers. More precisely: -For local exceptions, handled in the same subprogram as where it was raised, -Statement Coverage shall be assessed for Ada's exceptions mechanism as -described in Chapter 11 of the Ada Reference Manual. In particular: +====== ====================================================================== +Rule # Description +====== ====================================================================== +1 Explicit ``raise`` statements shall be handled as regular + statements, reported uncovered when not reached, -* ``raise`` statements shall be reported uncovered when unreached, +2 Statements never reached in a sequence because of implicit or explicit + raise(s) earlier in the sequence shall be reported uncovered, -* The control flow effects of implicit and explicit exception raises shall be - handled correctly: +3 The complete set of Statement Coverage requirements apply to statements + that constitute exception handlers, - * statements that do not execute because of a raise shall be reported - as uncovered, +4 Statements that execute only partially, interrupted by a raise + during an expression evaluation as part of the statement's operation, + shall *not* be reported as uncovered. - * statements that only execute partially because of an interrupted expression - evaluation shall *not* be reported as uncovered. - -* Statement coverage requirements apply to both predefined and - user-defined exceptions. - -* The full set of core SC requirements apply to all the statements within - exception handlers. - -The tool shall also produce correct Statement Coverage assessments for -subprogram bodies consisting of a call to subprogram which may raise an -exception followed by simple scalar assignments, all (call and assignments) -protected by a handler which only performs scalar assignments that never -raise. Statements never reached either because the outer subprogram isn't -called or because the inner subprogram raised, shall be reported uncovered. +5 Predefined and user-defined exceptions shall be handled in the same + manner. +====== ====================================================================== .. rubric:: Testing Strategy -For local exceptions, we validate the requirements through a set of testcases -that exercise implicit or explicit exceptions for purposes of control flow -transfer. All the tescases follow a common pattern, involving: +We first validate all the rules in contexts where handlers are within the +subprogram where the exceptions get raised, known as *local handers*. The set +of testcases exercise implicit or explicit exceptions for purposes of control +flow transfer, involving: * Explicit ``raise`` statements, executed or not, followed by other statements - or not + or not, * Variations of these in subprograms or package bodies, directly within the top-level sequence of statements, and within nested block, conditional or loop statements, -* With one or more candidate handlers at different levels of nesting, - within a single body. - -For exceptions that may propagate from a called subprogram as in the -conditions stated in the requirement, we exercise situations where: +* With one or more candidate handlers, possibly at different levels of + block nesting within a single function or procedure body. -* The outer subprogram isn't called at all, +.. qmlink:: TCIndexImporter -* The inner subprogram is called only in conditions so it raises, + LocalHandlers -* The inner subprogram is called only in conditions so it does not raise, -* The inner subprogram is called in conditions so it raises and in conditions - so it does not raise. +Rules #1, 2 and 5 are checked by variations in most testcases and verified +more specifically by the *Raise* testcase, dedicated to this purpose. -.. qmlink:: TCIndexImporter +Rule #3 is verified by the *Within* family of testcases, which exercise +conditional constructs within exception handlers in a variety of contexts +where such handlers may appear. - * +Rule #4 is verified by the dedicated *CutEvals* set of testcases. +When conditional guards are involved, the coverage outcome is always checked +at least for situations where a guard is tested True only and False only. Very +often, testcases also verify the outcome when a guard is tested both True and +False or not at all. +For exceptions that propagate across subprograms, we first verify all +the requirement rules in a single *Basics* testcase, then check more +elaborate situations with a family of tests involving: + +* Various exception kinds (implicit standard exception raised from a + language check, explicit raise of standard or user defined exception, + raise from a Ada runtime facility); + +* That propagate either directly or via an intermediate handler and + a "raise;" statement propagating the original exception further, from + either a specific handler for the particular exception or from a + "when others" handler; + +* That are eventually either unhandled or handled in a variety of contexts, + for example within a library level subprogram or within a handler for + another exception occurrence. + +.. qmlink:: TCIndexImporter + Propagation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_elab_only.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_elab_only.adb new file mode 100755 index 000000000..435740de5 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_elab_only.adb @@ -0,0 +1,31 @@ +-- Test driver for local generic instantiations. It only "with's" the +-- functional code and code that instantiates generics of interest, but does +-- not call anything from it. So the only code that shall be reported as being +-- covered is the elaboration code corresponding to package instantiations. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Elab_Only is +begin + Assert (Local_Instantiations.Pack_Instance.Var = 'A'); +end Test_Elab_Only; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_full.adb new file mode 100755 index 000000000..d4cd47969 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_full.adb @@ -0,0 +1,46 @@ +-- Test driver for library-level generic instantiations. It calls routines +-- from the local instantiations that cause all the code from generics to be +-- reported as covered + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Full is + Int1 : Integer := 1; + Int2 : Integer := 2; + + use Local_Instantiations.Stacks; + S : Stack := Default_Stack; +begin + Pack.Proc (Int1, Int2); + Assert (Int1 = 2 and then Int2 = 1); + + Assert (Local_Instantiations.New_Value (0) = 1); + + Pop (Int1, S); + Assert (Int1 = 1); + + Assert (N_Values (S) = 0); + + Local_Instantiations.Update (Int1); + Assert (Int1 = 2); + +end Test_Full; + +--# pack.adb +-- /new_value_g/ l+ ## 0 +-- /swap/ l+ ## 0 +-- /proc/ l+ ## 0 + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l+ ## 0 +-- /n_values/ l+ ## 0 +-- /default_stack/ l+ ## 0 +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_elab_only.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_elab_only.adb deleted file mode 100755 index e3b13e138..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_elab_only.adb +++ /dev/null @@ -1,31 +0,0 @@ --- Test driver for local generic instantiations. It only "with's" the --- functional code and code that instantiates generics of interest, but does --- not call anything from it. So the only code that shall be reported as being --- covered is the elaboration code corresponding to package instantiations. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Elab_Only is -begin - Assert (Local_Instantiations.Pack_Instance.Var = 'A'); -end Test_Instantiations_Elab_Only; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_full.adb deleted file mode 100755 index 8e5a160ac..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_full.adb +++ /dev/null @@ -1,46 +0,0 @@ --- Test driver for library-level generic instantiations. It calls routines --- from the local instantiations that cause all the code from generics to be --- reported as covered - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Full is - Int1 : Integer := 1; - Int2 : Integer := 2; - - use Local_Instantiations.Stacks; - S : Stack := Default_Stack; -begin - Pack.Proc (Int1, Int2); - Assert (Int1 = 2 and then Int2 = 1); - - Assert (Local_Instantiations.New_Value (0) = 1); - - Pop (Int1, S); - Assert (Int1 = 1); - - Assert (N_Values (S) = 0); - - Local_Instantiations.Update (Int1); - Assert (Int1 = 2); - -end Test_Instantiations_Full; - ---# pack.adb --- /new_value_g/ l+ ## 0 --- /swap/ l+ ## 0 --- /proc/ l+ ## 0 - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l+ ## 0 --- /n_values/ l+ ## 0 --- /default_stack/ l+ ## 0 --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_1.adb deleted file mode 100755 index 8b3942903..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_1.adb +++ /dev/null @@ -1,36 +0,0 @@ --- Test driver for local generic instantiations. It "with's" all the --- functional code, and it calls only (some of) the routines from the local --- instantiation of the package Stack_G. The code from all the other generics --- shall be reported as uncovered. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Part_1 is - use Local_Instantiations.Stacks; - S : Stack; - Int : Integer := 0; -begin - Push (13, S); - Pop (Int, S); - Assert (Int = 13); -end Test_Instantiations_Part_1; - ---# pack.adb --- /new_value_g/ ~l- ## ~s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l+ ## 0 --- /n_values/ ~l- ## ~s- --- /default_stack/ ~l- ## ~s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_2.adb deleted file mode 100755 index c141fe5cb..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_2.adb +++ /dev/null @@ -1,33 +0,0 @@ --- Test driver for local generic instantiations. It "with's" all the --- functional code, and it calls only the local instantiation of the procedure --- Update_G. The code from all the other generics shall be reported as --- uncovered. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Part_2 is - Int : Integer := 0; -begin - Local_Instantiations.Update (Int); - Assert (Int = 1); -end Test_Instantiations_Part_2; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_3.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_3.adb deleted file mode 100755 index 2e095ebe1..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_3.adb +++ /dev/null @@ -1,31 +0,0 @@ --- Test driver for local generic instantiations. It "with's" all the --- functional code, and it calls only the local instantiation of the function --- Pack.New_Value_G. The code from all the other generics shall be reported as --- uncovered. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Part_3 is -begin - Assert (Local_Instantiations.New_Value (0) = 1); -end Test_Instantiations_Part_3; - ---# pack.adb --- /new_value_g/ l+ ## 0 --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_4.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_4.adb deleted file mode 100755 index 1e0832a27..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_4.adb +++ /dev/null @@ -1,36 +0,0 @@ --- Test driver for local generic instantiations. It "with's" all the --- functional code, and it calls only routine Swap from the local --- instantiation of the package Pack.Pack_G. The code from all the other --- generics shall be reported as uncovered. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Part_4 is - use Local_Instantiations.Pack_Instance; - Char : Character := 'B'; -begin - Assert (Var = 'A'); - Swap (Var, Char); - Assert (Var = 'B'); - Assert (Char = 'A'); -end Test_Instantiations_Part_4; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l+ ## 0 --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_5.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_5.adb deleted file mode 100755 index 9dc2759fd..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_5.adb +++ /dev/null @@ -1,46 +0,0 @@ --- Test driver for local generic instantiations. It "with's" all the --- functional code, and it calls only routine --- Local_Instantiations.Proc_With_Instantiations that instantiates generic --- packages Pack.Pack_G and Stacks_G and calls some routines from the --- instantiations. The code from all the other generics shall be reported as --- uncovered. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Part_5 is - Int1 : Integer := 1; - Int2 : Integer := 2; - Bool1 : Boolean := True; - Bool2 : Boolean := False; -begin - Local_Instantiations.Proc_With_Instantiations - (I => Int1, - J => Int2, - B1 => Bool1, - B2 => Bool2); - - Assert (Int1 = 2); - Assert (Int2 = 1); - Assert (not Bool1); - Assert (Bool2); -end Test_Instantiations_Part_5; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l+ ## 0 --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l+ ## 0 --- /n_values/ l+ ## 0 --- /default_stack/ l+ ## 0 --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_6.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_6.adb deleted file mode 100755 index 487d2d03c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_6.adb +++ /dev/null @@ -1,33 +0,0 @@ --- Test driver for local generic instantiations. It "with's" all the --- functional code, and it calls only function --- Local_Instantiations.Fun_With_Instantiations that instantiates generic --- procedure Update_G and calls instantiation. The code from all the other --- generics shall be reported as uncovered. - -with Pack; -with Local_Instantiations; -with Support; use Support; -procedure Test_Instantiations_Part_6 is - Bool2 : Boolean := False; -begin - Assert (Local_Instantiations.Fun_With_Instantiations (0) = 1); -end Test_Instantiations_Part_6; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_1.adb new file mode 100755 index 000000000..9fc54a96b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_1.adb @@ -0,0 +1,36 @@ +-- Test driver for local generic instantiations. It "with's" all the +-- functional code, and it calls only (some of) the routines from the local +-- instantiation of the package Stack_G. The code from all the other generics +-- shall be reported as uncovered. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Part_1 is + use Local_Instantiations.Stacks; + S : Stack; + Int : Integer := 0; +begin + Push (13, S); + Pop (Int, S); + Assert (Int = 13); +end Test_Part_1; + +--# pack.adb +-- /new_value_g/ ~l- ## ~s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l+ ## 0 +-- /n_values/ ~l- ## ~s- +-- /default_stack/ ~l- ## ~s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_2.adb new file mode 100755 index 000000000..4b13b5ceb --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_2.adb @@ -0,0 +1,33 @@ +-- Test driver for local generic instantiations. It "with's" all the +-- functional code, and it calls only the local instantiation of the procedure +-- Update_G. The code from all the other generics shall be reported as +-- uncovered. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Part_2 is + Int : Integer := 0; +begin + Local_Instantiations.Update (Int); + Assert (Int = 1); +end Test_Part_2; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_3.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_3.adb new file mode 100755 index 000000000..f2b2ed8c1 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_3.adb @@ -0,0 +1,31 @@ +-- Test driver for local generic instantiations. It "with's" all the +-- functional code, and it calls only the local instantiation of the function +-- Pack.New_Value_G. The code from all the other generics shall be reported as +-- uncovered. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Part_3 is +begin + Assert (Local_Instantiations.New_Value (0) = 1); +end Test_Part_3; + +--# pack.adb +-- /new_value_g/ l+ ## 0 +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_4.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_4.adb new file mode 100755 index 000000000..ae2caa116 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_4.adb @@ -0,0 +1,36 @@ +-- Test driver for local generic instantiations. It "with's" all the +-- functional code, and it calls only routine Swap from the local +-- instantiation of the package Pack.Pack_G. The code from all the other +-- generics shall be reported as uncovered. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Part_4 is + use Local_Instantiations.Pack_Instance; + Char : Character := 'B'; +begin + Assert (Var = 'A'); + Swap (Var, Char); + Assert (Var = 'B'); + Assert (Char = 'A'); +end Test_Part_4; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l+ ## 0 +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_5.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_5.adb new file mode 100755 index 000000000..e3d52e38e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_5.adb @@ -0,0 +1,46 @@ +-- Test driver for local generic instantiations. It "with's" all the +-- functional code, and it calls only routine +-- Local_Instantiations.Proc_With_Instantiations that instantiates generic +-- packages Pack.Pack_G and Stacks_G and calls some routines from the +-- instantiations. The code from all the other generics shall be reported as +-- uncovered. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Part_5 is + Int1 : Integer := 1; + Int2 : Integer := 2; + Bool1 : Boolean := True; + Bool2 : Boolean := False; +begin + Local_Instantiations.Proc_With_Instantiations + (I => Int1, + J => Int2, + B1 => Bool1, + B2 => Bool2); + + Assert (Int1 = 2); + Assert (Int2 = 1); + Assert (not Bool1); + Assert (Bool2); +end Test_Part_5; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l+ ## 0 +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l+ ## 0 +-- /n_values/ l+ ## 0 +-- /default_stack/ l+ ## 0 +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_6.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_6.adb new file mode 100755 index 000000000..965f779f3 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_6.adb @@ -0,0 +1,33 @@ +-- Test driver for local generic instantiations. It "with's" all the +-- functional code, and it calls only function +-- Local_Instantiations.Fun_With_Instantiations that instantiates generic +-- procedure Update_G and calls instantiation. The code from all the other +-- generics shall be reported as uncovered. + +with Pack; +with Local_Instantiations; +with Support; use Support; +procedure Test_Part_6 is + Bool2 : Boolean := False; +begin + Assert (Local_Instantiations.Fun_With_Instantiations (0) = 1); +end Test_Part_6; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads index 6b49be98a..5be249f47 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads @@ -2,4 +2,3 @@ with Stacks_G; package Stacks is new Stacks_G (Value => Integer, Init_Val => 0); - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_elab_only.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_elab_only.adb new file mode 100755 index 000000000..c91829678 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_elab_only.adb @@ -0,0 +1,33 @@ +-- Test driver for library-level generic instantiations. It only "with's" the +-- functional code, including instantiations, but does not call anything from +-- it. So the only code that shall be reported as being covered is the +-- elaboration code corresponding to package instantiations. + +with New_Value; +with Pack_Instance_Lib_Level; +with Stacks; +with Update; +with Support; use Support; +procedure Test_Elab_Only is +begin + Assert (Pack_Instance_Lib_Level.Var = 0.0); +end Test_Elab_Only; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_full.adb new file mode 100755 index 000000000..ed8e7b02a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_full.adb @@ -0,0 +1,53 @@ +-- Test driver for library-level generic instantiations. It executes all the +-- functional code corresponding to library-level instantiations, so +-- everything is expected to be reported as covered except the code of +-- Pack.Proc. + +with New_Value; +with Pack_Instance_Lib_Level; +with Stacks; +with Update; +with Support; use Support; +procedure Test_Full is + S : Stacks.Stack := Stacks.Default_Stack; + + I : Integer := 1; + J : Integer := 2; + + F1 : Float := 1.0; + F2 : Float := 2.0; +begin + Assert (Pack_Instance_Lib_Level.Var = 0.0); + Assert (Stacks.N_Values (S) = 1); + + Stacks.Pop (J, S); + Assert (J = 0); + + Pack_Instance_Lib_Level.Swap (F1, F2); + Assert (F1 = 2.0 and then F2 = 1.0); + + Assert (New_Value (1) = 2); + + Update (J); + Assert (J = 1); + +end Test_Full; + +--# pack.adb +-- /new_value_g/ l+ ## 0 +-- /swap/ l+ ## 0 +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l+ ## 0 +-- /n_values/ l+ ## 0 +-- /default_stack/ l+ ## 0 +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_elab_only.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_elab_only.adb deleted file mode 100755 index 127c28a17..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_elab_only.adb +++ /dev/null @@ -1,33 +0,0 @@ --- Test driver for library-level generic instantiations. It only "with's" the --- functional code, including instantiations, but does not call anything from --- it. So the only code that shall be reported as being covered is the --- elaboration code corresponding to package instantiations. - -with New_Value; -with Pack_Instance_Lib_Level; -with Stacks; -with Update; -with Support; use Support; -procedure Test_Instantiations_Elab_Only is -begin - Assert (Pack_Instance_Lib_Level.Var = 0.0); -end Test_Instantiations_Elab_Only; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_full.adb deleted file mode 100755 index aa9761a2c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_full.adb +++ /dev/null @@ -1,53 +0,0 @@ --- Test driver for library-level generic instantiations. It exsecutes all the --- functional code corresponding to library-level instantiations, so --- everything is expected to be reported as covered except the code of --- Pack.Proc. - -with New_Value; -with Pack_Instance_Lib_Level; -with Stacks; -with Update; -with Support; use Support; -procedure Test_Instantiations_Full is - S : Stacks.Stack := Stacks.Default_Stack; - - I : Integer := 1; - J : Integer := 2; - - F1 : Float := 1.0; - F2 : Float := 2.0; -begin - Assert (Pack_Instance_Lib_Level.Var = 0.0); - Assert (Stacks.N_Values (S) = 1); - - Stacks.Pop (J, S); - Assert (J = 0); - - Pack_Instance_Lib_Level.Swap (F1, F2); - Assert (F1 = 2.0 and then F2 = 1.0); - - Assert (New_Value (1) = 2); - - Update (J); - Assert (J = 1); - -end Test_Instantiations_Full; - ---# pack.adb --- /new_value_g/ l+ ## 0 --- /swap/ l+ ## 0 --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l+ ## 0 --- /n_values/ l+ ## 0 --- /default_stack/ l+ ## 0 --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_no.adb deleted file mode 100755 index 54b41ca74..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_no.adb +++ /dev/null @@ -1,80 +0,0 @@ --- Test driver for library-level generic instantiations. It only "with's" the --- code with generic units, but does not with's any instantiation, and does --- not instantiate anything itself. Code from generic units is expected --- to be reported as no-code, which requires a compiler version > 17. - -with Pack; -with Stacks_G, Update_G; -with Support; use Support; -procedure Test_Instantiations_No is -begin - Assert (True); -end Test_Instantiations_No; - ---# pack.adb --- ---%opts: --trace-mode=bin --- /decl/ ~l- ## ~s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- ---%opts: --trace-mode=src --- /new_value_g/ l- ## s- --- /decl/ l- ## s- --- /swap/ l- ## s- --- /proc/ l- ## s- --- --- ---# stacks_g.ads --- ---%opts: --trace-mode=bin --- /decl/ l. ## 0 --- /elab/ l. ## 0 --- /line-elab/ l. ## 0c --- ---%opts: --trace-mode=src --- /decl/ l- ## s- --- /elab/ l- ## s- --- /line-elab/ l- ## 0 - --- %tags:(7.1.2|7.2.2|7.4.3) --- =/decl/ l- ## s- --- =/elab/ l- ## s- --- =/line-elab/ l- ## 0c --- --- ---# stacks_g.adb --- ---%opts: --trace-mode=bin --- /push/ l. ## 0 --- /pop/ l. ## 0 --- /n_values/ l. ## 0 --- /default_stack/ l. ## 0 --- /elab/ l. ## 0 --- ---%opts: --trace-mode=src --- /push/ l- ## s- --- /pop/ l- ## s- --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l- ## s- --- --- %tags:(7.1.2|7.2.2|7.4.3) --- --- =/push/ l- ## s- --- =/pop/ l- ## s- --- =/n_values/ l- ## s- --- =/default_stack/ l- ## s- --- =/elab/ l- ## s- --- --- ---# update_g.adb --- ---%opts: --trace-mode=bin --- /stmt/ l. ## 0 - ---%opts: --trace-mode=src --- /stmt/ l- ## s- - --- %tags:(7.1.2|7.2.2|7.4.3) --- =/stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_1.adb deleted file mode 100755 index 8252f0133..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_1.adb +++ /dev/null @@ -1,37 +0,0 @@ --- Test driver for library-level generic instantiations. It calls only a part --- of the code from instantiations, so only the corresponding part of the code --- from templates shall be reported as covered. - -with New_Value; -with Pack_Instance_Lib_Level; -with Stacks; -with Update; -with Support; use Support; -procedure Test_Instantiations_Part_1 is - S : Stacks.Stack := Stacks.Default_Stack; -begin - Assert (Pack_Instance_Lib_Level.Var = 0.0); - - Assert (New_Value (0) = 1); - - Assert (Stacks.N_Values (S) = 1); -end Test_Instantiations_Part_1; - ---# pack.adb --- /new_value_g/ l+ ## 0 --- /swap/ l- ## s- --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l- ## s- --- /n_values/ l+ ## 0 --- /default_stack/ l+ ## 0 --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_2.adb deleted file mode 100755 index 98d24aba7..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_2.adb +++ /dev/null @@ -1,45 +0,0 @@ --- Test driver for library-level generic instantiations. It calls only a part --- of the code from instantiations, so only the corresponding part of the code --- from templates shall be reported as covered. - -with New_Value; -with Pack_Instance_Lib_Level; -with Stacks; -with Update; -with Support; use Support; -procedure Test_Instantiations_Part_2 is - S : Stacks.Stack; - I : Integer := 1; - J : Integer := 2; - - F1 : Float := 1.0; - F2 : Float := 2.0; -begin - Assert (Pack_Instance_Lib_Level.Var = 0.0); - - Stacks.Push (I, S); - Stacks.Pop (J, S); - Assert (J = 1); - - Pack_Instance_Lib_Level.Swap (F1, F2); - Assert (F1 = 2.0 and then F2 = 1.0); -end Test_Instantiations_Part_2; - ---# pack.adb --- /new_value_g/ l- ## s- --- /swap/ l+ ## 0 --- /proc/ l- ## s- --- /decl/ ~l- ## ~s- - ---# stacks_g.ads --- /elab/ l+ ## 0 - ---# stacks_g.adb --- /push/ l+ ## 0 --- /pop/ l+ ## 0 --- /n_values/ l- ## s- --- /default_stack/ l- ## s- --- /elab/ l+ ## 0 - ---# update_g.adb --- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_no.adb new file mode 100755 index 000000000..61dd99ca0 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_no.adb @@ -0,0 +1,80 @@ +-- Test driver for library-level generic instantiations. It only "with's" the +-- code with generic units, but does not with's any instantiation, and does +-- not instantiate anything itself. Code from generic units is expected +-- to be reported as no-code, which requires a compiler version > 17. + +with Pack; +with Stacks_G, Update_G; +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# pack.adb +-- +--%opts: --trace-mode=bin +-- /decl/ ~l- ## ~s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- +--%opts: --trace-mode=src +-- /new_value_g/ l- ## s- +-- /decl/ l- ## s- +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- +-- +--# stacks_g.ads +-- +--%opts: --trace-mode=bin +-- /decl/ l. ## 0 +-- /elab/ l. ## 0 +-- /line-elab/ l. ## 0c +-- +--%opts: --trace-mode=src +-- /decl/ l- ## s- +-- /elab/ l- ## s- +-- /line-elab/ l- ## 0 + +-- %tags:(7.1.2|7.2.2|7.4.3) +-- =/decl/ l- ## s- +-- =/elab/ l- ## s- +-- =/line-elab/ l- ## 0c +-- +-- +--# stacks_g.adb +-- +--%opts: --trace-mode=bin +-- /push/ l. ## 0 +-- /pop/ l. ## 0 +-- /n_values/ l. ## 0 +-- /default_stack/ l. ## 0 +-- /elab/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /push/ l- ## s- +-- /pop/ l- ## s- +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l- ## s- +-- +-- %tags:(7.1.2|7.2.2|7.4.3) +-- +-- =/push/ l- ## s- +-- =/pop/ l- ## s- +-- =/n_values/ l- ## s- +-- =/default_stack/ l- ## s- +-- =/elab/ l- ## s- +-- +-- +--# update_g.adb +-- +--%opts: --trace-mode=bin +-- /stmt/ l. ## 0 + +--%opts: --trace-mode=src +-- /stmt/ l- ## s- + +-- %tags:(7.1.2|7.2.2|7.4.3) +-- =/stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_1.adb new file mode 100755 index 000000000..11fc42e73 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_1.adb @@ -0,0 +1,37 @@ +-- Test driver for library-level generic instantiations. It calls only a part +-- of the code from instantiations, so only the corresponding part of the code +-- from templates shall be reported as covered. + +with New_Value; +with Pack_Instance_Lib_Level; +with Stacks; +with Update; +with Support; use Support; +procedure Test_Part_1 is + S : Stacks.Stack := Stacks.Default_Stack; +begin + Assert (Pack_Instance_Lib_Level.Var = 0.0); + + Assert (New_Value (0) = 1); + + Assert (Stacks.N_Values (S) = 1); +end Test_Part_1; + +--# pack.adb +-- /new_value_g/ l+ ## 0 +-- /swap/ l- ## s- +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l- ## s- +-- /n_values/ l+ ## 0 +-- /default_stack/ l+ ## 0 +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_2.adb new file mode 100755 index 000000000..45c1044ef --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_2.adb @@ -0,0 +1,45 @@ +-- Test driver for library-level generic instantiations. It calls only a part +-- of the code from instantiations, so only the corresponding part of the code +-- from templates shall be reported as covered. + +with New_Value; +with Pack_Instance_Lib_Level; +with Stacks; +with Update; +with Support; use Support; +procedure Test_Part_2 is + S : Stacks.Stack; + I : Integer := 1; + J : Integer := 2; + + F1 : Float := 1.0; + F2 : Float := 2.0; +begin + Assert (Pack_Instance_Lib_Level.Var = 0.0); + + Stacks.Push (I, S); + Stacks.Pop (J, S); + Assert (J = 1); + + Pack_Instance_Lib_Level.Swap (F1, F2); + Assert (F1 = 2.0 and then F2 = 1.0); +end Test_Part_2; + +--# pack.adb +-- /new_value_g/ l- ## s- +-- /swap/ l+ ## 0 +-- /proc/ l- ## s- +-- /decl/ ~l- ## ~s- + +--# stacks_g.ads +-- /elab/ l+ ## 0 + +--# stacks_g.adb +-- /push/ l+ ## 0 +-- /pop/ l+ ## 0 +-- /n_values/ l- ## s- +-- /default_stack/ l- ## s- +-- /elab/ l+ ## 0 + +--# update_g.adb +-- /stmt/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst index e4579da5b..14c822fe6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst @@ -1,7 +1,7 @@ **Exercise aggregated SC on instances providing compilation units** Exercise aggregated (default mode) Statement Coverage on instances of generic -packages or subprograms, all provided as independant compilation units on +packages or subprograms, all provided as independent compilation units on their own. LRMREF: 12.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py index 4e6971e89..ed921d36f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py @@ -8,5 +8,7 @@ # of absolute paths for source files). TestCase().run( CovControl(covoptions="--source-search=../../src") - if thistest.options.trace_mode == 'bin' else None) + if thistest.options.trace_mode == "bin" + else None +) thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb deleted file mode 100644 index bb514d75b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb +++ /dev/null @@ -1,10 +0,0 @@ -package body Check_G is - procedure Test (Value : T) is - begin - if Low > Value or else High < Value then -- # test-out - Out_Of_Range_Count := Out_Of_Range_Count + 1; -- # out-range - else - In_Range_Count := In_Range_Count + 1; -- # in-range - end if; - end Test; -end Check_G; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads deleted file mode 100644 index 6c18d8129..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads +++ /dev/null @@ -1,10 +0,0 @@ -generic - type T is new Float; - Low, High : T; -package Check_G is - procedure Test (Value : T); - pragma Inline (Test); - - In_Range_Count : Natural := 0; - Out_Of_Range_Count : Natural := 0; -end Check_G; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb deleted file mode 100644 index 7bb9a328d..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb +++ /dev/null @@ -1,13 +0,0 @@ -package body Sensors is - - procedure Test (Value : Float; Unit : Temp_Unit) is - begin - if Unit = C then -- # check-test-c - N_Tests_C := N_Tests_C + 1; -- # check-do-c - RC.Test (Temp_C (Value)); -- # check-do-c - else - N_Tests_F := N_Tests_F + 1; -- # check-do-f - RF.Test (Temp_F (Value)); -- # check-do-f - end if; - end Test; -end Sensors; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads deleted file mode 100644 index ca588cbfc..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads +++ /dev/null @@ -1,15 +0,0 @@ -with Check_G; - -package Sensors is - type Temp_C is new Float range -273.15 .. Float'Last; - package RC is new Check_G (Temp_C, 0.0, 100.0); -- # i:RC - - type Temp_F is new Float range -459.67 .. Float'Last; - package RF is new Check_G (Temp_F, 32.0, 212.0);-- # i:RF - - type Temp_Unit is (C, F); - - procedure Test (Value : Float; Unit : Temp_Unit); - - N_Tests_C, N_Tests_F : Natural := 0; -end Sensors; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb deleted file mode 100644 index 71a01ddca..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb +++ /dev/null @@ -1,45 +0,0 @@ -with Sensors, Support; use Sensors, Support; - --- CBFN : Invoking Both in and out of range for unit "C". None for unit "F". - -procedure Test_CBFN is -begin - -- C in range (!low !high => Out-False) - - Sensors.Test (37.0, C); - - -- C out of range (!low, high => Out-True) - - Sensors.Test (200.0, C); - - Assert (Sensors.N_Tests_C = 2); - Assert (Sensors.N_Tests_F = 0); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 1); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 0); - -end Test_CBFN; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l+ ## 0 --- /in-range/ l+ ## 0 --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l! ## s-@(i:RF) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb deleted file mode 100644 index bc4f85e96..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb +++ /dev/null @@ -1,39 +0,0 @@ -with Support, Sensors; use Support, Sensors; - -procedure Test_CIFN is -begin - -- C in range - - Sensors.Test (37.0, C); - - Assert (Sensors.N_Tests_C = 1); - Assert (Sensors.N_Tests_F = 0); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 0); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 0); -end Test_CIFN; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l+ ## 0 --- /in-range/ l+ ## 0 --- /out-range/ l- ## s- - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb deleted file mode 100644 index 20c51400b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb +++ /dev/null @@ -1,44 +0,0 @@ -with Sensors, Support; use Sensors, Support; - -procedure Test_CIFO is -begin - -- C in range - - Sensors.Test (37.0, C); - - -- F out of range - - Sensors.Test (0.0, F); - - Assert (Sensors.N_Tests_C = 1); - Assert (Sensors.N_Tests_F = 1); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 0); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 1); - -end Test_CIFO; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l+ ## 0 - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- defaults, for instances conslidated: --- /test-out/ l+ ## 0 --- /in-range/ l+ ## 0 --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ s=>l+, dmu=>l! ## dT-@(i:RC), dF-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l! ## s-@(i:RC) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb deleted file mode 100644 index 691cf0bcf..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb +++ /dev/null @@ -1,28 +0,0 @@ -with Sensors; use Sensors; -procedure Test_CNFN is -begin - null; -end Test_CNFN; - ---# sensors.adb --- /check-test-c/ l- ## s- --- /check-do-c/ l- ## s- --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l- ## s- --- /in-range/ l- ## s- --- /out-range/ l- ## s- - --- %cov: -S instance --- =/test-out/ l- ## s-@(i:RF), s-@(i:RC) --- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb deleted file mode 100644 index 3d6063954..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb +++ /dev/null @@ -1,30 +0,0 @@ -with Sensors; use Sensors; -procedure Test_CNFO is -begin - -- F out of range - - Sensors.Test (0.0, F); -end Test_CNFO; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l- ## s- --- /check-do-f/ l+ ## 0 - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l+ ## 0 --- /in-range/ l- ## s- --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RC) --- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) --- =/out-range/ l! ## s-@(i:RC) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst deleted file mode 100644 index 7bd614eb1..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst +++ /dev/null @@ -1,9 +0,0 @@ -**Exercise SC on multiple generic instances, triggering different paths** - -Exercise aggregated and per-instance Statement Coverage on multiple instances -of generic packages provided either as local packages within another package -spec. Enforce coverage variations by calling subprograms with arguments values -controlling different paths within the subprograms thanks to conditional -constructs. - -LRMREF: 12.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt deleted file mode 100644 index 71da06bed..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -7.1.2 DEAD testing per-instance analysis of generics, implemented post 7.0.3 -src-traces XFAIL S628-011: src-traces and per-instance coverage of generics -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py deleted file mode 100644 index cc7812869..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py +++ /dev/null @@ -1,9 +0,0 @@ -from SCOV.tc import TestCase -from SCOV.tctl import CovControl -from SUITE.context import thistest - -tc = TestCase() -tc.run() -tc.run(covcontrol=CovControl(covoptions='-S instance'), - subdirhint='i_') -thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb deleted file mode 100644 index 44aba7c72..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb +++ /dev/null @@ -1,32 +0,0 @@ -with V5, V8; use V5, V8; -with Support; use Support; - --- Call inc only on the v5 instance and mult only on the v8 instance. - -procedure Test_5i_8m is - V5o : V5.Vector_Type := (others => 1); - V8o : V8.Vector_Type := (others => 2); -begin - V5.Inc (V5o, 3); - Assert (V5o(1) = 4); - - V8.Mult (V8o, 2); - Assert (V5o(2) = 4); -end; - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V5) --- =/inc/ l! ## s-@(i:V8) - --- -S instance needs to see the instantiation ALIs as well: - ---# v5.ads - ---# v8.ads - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb deleted file mode 100644 index cfc4b9fa9..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb +++ /dev/null @@ -1,32 +0,0 @@ -with V5, V8; use V5, V8; -with Support; use Support; - --- Call mult only on the v5 instance and inc only on the v8 instance. - -procedure Test_5m_8i is - V5o : V5.Vector_Type := (others => 1); - V8o : V8.Vector_Type := (others => 2); -begin - V5.Inc (V5o, 3); - Assert (V5o(1) = 4); - - V8.Mult (V8o, 2); - Assert (V5o(2) = 4); -end; - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V5) --- =/inc/ l! ## s-@(i:V8) - --- -S instance needs to see the instantiation ALIs as well: - ---# v5.ads - ---# v8.ads - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb deleted file mode 100644 index 527f89058..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb +++ /dev/null @@ -1,26 +0,0 @@ -with V6or9; - -procedure Test_6i_9i is -begin - V6or9.Check (V6inc => True, - V6mult => False, - V9inc => True, - V9mult => False); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l- ## s- --- /9i/ l+ ## 0 --- /9m/ l- ## s- - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l- ## s- --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l- ## s-@(i:V6), s-@(i:V9) --- =/inc/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb deleted file mode 100644 index 5e1e08ded..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb +++ /dev/null @@ -1,26 +0,0 @@ -with V6or9; - -procedure Test_6i_9m is -begin - V6or9.Check (V6inc => True, - V6mult => False, - V9inc => False, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l- ## s- --- /9i/ l- ## s- --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances consolidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V6) --- =/inc/ l! ## s-@(i:V9) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb deleted file mode 100644 index 66d450275..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb +++ /dev/null @@ -1,26 +0,0 @@ -with V6or9; - -procedure Test_6m_9i is -begin - V6or9.Check (V6inc => False, - V6mult => True, - V9inc => True, - V9mult => False); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l- ## s- --- /6m/ l+ ## 0 --- /9i/ l+ ## 0 --- /9m/ l- ## s- - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V9) --- =/inc/ l! ## s-@(i:V6) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb deleted file mode 100644 index f800d1eae..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb +++ /dev/null @@ -1,26 +0,0 @@ -with V6or9; - -procedure Test_6m_9m is -begin - V6or9.Check (V6inc => False, - V6mult => True, - V9inc => False, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l- ## s- --- /6m/ l+ ## 0 --- /9i/ l- ## s- --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l- ## s- - --- %cov: -S instance --- =/mult/ l+ ## 0 --- =/inc/ l- ## s-@(i:V6), s-@(i:V9) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb deleted file mode 100644 index c74a3b32a..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb +++ /dev/null @@ -1,26 +0,0 @@ -with V6or9; - -procedure Test_6mi_9m is -begin - V6or9.Check (V6inc => True, - V6mult => True, - V9inc => False, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l+ ## 0 --- /9i/ l- ## s- --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l+ ## 0 --- =/inc/ l! ## s-@(i:V9) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb deleted file mode 100644 index f8b8247e2..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb +++ /dev/null @@ -1,26 +0,0 @@ -with V6or9; - -procedure Test_6mi_9mi is -begin - V6or9.Check (V6inc => True, - V6mult => True, - V9inc => True, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l+ ## 0 --- /9i/ l+ ## 0 --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l+ ## 0 --- =/inc/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads deleted file mode 100644 index 567d5a77e..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads +++ /dev/null @@ -1,2 +0,0 @@ -with Vops; -package v5 is new Vops (Size => 5); -- # i:V5 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb deleted file mode 100644 index ec12bba31..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb +++ /dev/null @@ -1,32 +0,0 @@ -with Vops, Support; use Support; - -package body V6or9 is - - procedure Check (V6inc, V6mult, V9inc, V9mult : Boolean) is - package V6 is new Vops (Size => 6); -- # i:V6 - V6i : V6.Vector_Type := (others => 2); - V6m : V6.Vector_Type := (others => 2); - - package V9 is new Vops (Size => 9); -- # i:V9 - V9i : V9.Vector_Type := (others => 3); - V9m : V9.Vector_Type := (others => 3); - begin - if V6inc then -- # stmt - V6.Inc (V6i, 1); -- # 6i - Assert (V6i(1) = 3); -- # 6i - end if; - if V6mult then -- # stmt - V6.Mult (V6m, 2); -- # 6m - Assert (V6m(1) = 4); -- # 6m - end if; - if V9inc then -- # stmt - V9.Inc (V9i, 1); -- # 9i - Assert (V9i(1) = 4); -- # 9i - end if; - if V9mult then -- # stmt - V9.Mult (V9m, 2); -- # 9m - Assert (V9m(1) = 6); -- # 9m - end if; - end; -end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads deleted file mode 100644 index 6a8adb5a8..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads +++ /dev/null @@ -1,3 +0,0 @@ -package V6or9 is - procedure Check (V6inc, V6mult, V9inc, V9mult : Boolean); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads deleted file mode 100644 index 0b51f83ad..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads +++ /dev/null @@ -1,2 +0,0 @@ -with Vops; -package v8 is new Vops (Size => 8); -- # i:V8 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb deleted file mode 100644 index 9970f51a3..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb +++ /dev/null @@ -1,17 +0,0 @@ -package body Vops is - - procedure Inc (V : in out Vector_Type; Amount : Integer) is - begin - for I in V'Range loop -- # inc - V(I) := V(I) + Amount; -- # inc - end loop; - end; - - procedure Mult (V : in out Vector_Type; Amount : Integer) is - begin - for I in V'Range loop -- # mult - V(I) := V(I) * Amount; -- # mult - end loop; - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads deleted file mode 100644 index af21cdbb4..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads +++ /dev/null @@ -1,11 +0,0 @@ --- This can be instantiated multiple times e.g. for different vector sizes, --- and different instances may call different sets of subprograms. - -generic - Size : in Integer; -package Vops is - type Vector_Type is array (1 .. Size) of Integer; - - procedure Inc (V : in out Vector_Type; Amount : Integer); - procedure Mult (V : in out Vector_Type; Amount : Integer); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst deleted file mode 100644 index cb21cce5a..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst +++ /dev/null @@ -1,9 +0,0 @@ -**Exercise SC on multiple generic instances, triggering different subprograms** - -Exercise aggregated and per-instance Statement Coverage on multiple instances -of generic packages provided either as independant compilation units or as -local packages within a subprogram body. Enforce coverage variations by -calling different subsets of subprograms exposed by each instance and going -through different paths in each subprogram. - -LRMREF: 12.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt deleted file mode 100644 index 71da06bed..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -7.1.2 DEAD testing per-instance analysis of generics, implemented post 7.0.3 -src-traces XFAIL S628-011: src-traces and per-instance coverage of generics -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py deleted file mode 100644 index cc7812869..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py +++ /dev/null @@ -1,9 +0,0 @@ -from SCOV.tc import TestCase -from SCOV.tctl import CovControl -from SUITE.context import thistest - -tc = TestCase() -tc.run() -tc.run(covcontrol=CovControl(covoptions='-S instance'), - subdirhint='i_') -thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst index f36495a89..15073dad9 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst @@ -2,37 +2,23 @@ SC requirements for ARM chap. 12 : Generic Units ================================================ -%REQ_ID% +For a given `generic` source (package or subprogram), the tool +aggregates the coverage achieved by different instantiations of the +entities offered by this source. -Unless requested otherwise by a command line argument to `gnatcov coverage`, -the tool aggregates for a given generic source the coverage achieved by -different instantiations of the entities offered by this source. - -In this default mode, Statements or declarations within generic source code -shall only be reported uncovered when they are never executed at all, -regardless of the instantiations from which the execution might originate. - -Conversely, with `-S instance` on the `gnatcov coverage` command line, the -tool shall perform a separate assessment and report about coverage violations -for each instantiation independently from the others. +Statements or declarations within generic source code shall only be +reported uncovered when they are never executed at all, regardless of +the instantiations from which the execution might originate. .. rubric:: Testing Strategy We check a variety of statement constructs in different kinds of generic sources (packages and subprograms) through library-level and local -instantiations, some in default, aggregation, mode only, some both in -aggregation and per-instance modes. - -In aggregation mode, we verify that a statement in a generic source is -reported uncovered only if it is exercised through none of the instances. - -In per-instance mode, we exercise execution of a generic statement through -multiple combinations of instances and verify that the tool reports the -expected set of coverage violations for each distinct instance. Variations -within one instance is achieved by calling a particular set of subprograms -exposed by the instance, or by the use of conditional constructs within -subprograms. +instantiations. + +We verify that a statement in a generic source is reported uncovered +only if it is exercised through none of the instances. .. qmlink:: TCIndexImporter diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads index 1157a032d..a82e27e2d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads @@ -18,9 +18,9 @@ private -- We use a small static size here to prevent dragging dependencies to -- memcpy, malloc or secondary stack services, irrelevant to the purpose -- of the testcase family we serve. - + type Value_Array is array (1 .. 5) of Value; -- # elab - + type Stack is record -- # elab Store : Value_Array; -- # line-elab N_Values : Natural := 0; -- # line-elab diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb index 2fa1364d1..976e7d56a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb @@ -1,10 +1,10 @@ with System.Machine_Code; use System.Machine_Code; package body Data is - + function Id (X, Pathno: Integer) return Integer is Copy : Integer := X; - pragma Volatile (Copy); + pragma Volatile (Copy); begin if Pathno = 1 then Asm ("nop", Volatile => True); -- # asm_1 @@ -13,5 +13,5 @@ package body Data is end if; return Copy; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt new file mode 100644 index 000000000..531c42810 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt @@ -0,0 +1 @@ +c DEAD ASM inlining not supported by CCG diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst index 45e5d850d..1c1baa7d2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst @@ -1,8 +1,6 @@ Machine_Code insertions ======================= -%REQ_ID% - Machine code insertions shall be processed as simple statements. .. rubric:: Testing Strategy diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb index c14147f9b..b26c762c7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb @@ -1,6 +1,6 @@ package body Mystreams is - + procedure Sint_Read (S : not null access Root_Stream_Type'Class; Item : out Sint) is @@ -10,8 +10,8 @@ package body Mystreams is when Copy => Item.Value := Latch; -- # read_copy end case; end; - - procedure Sint_Write + + procedure Sint_Write (S : not null access Root_Stream_Type'Class; Item : in Sint) is begin @@ -20,9 +20,9 @@ package body Mystreams is when Copy => Latch := Item.Value; -- # write_copy end case; end; - + -- - + overriding procedure Read (Port : in out Port_T; Buffer : out Stream_Element_Array; @@ -31,7 +31,7 @@ package body Mystreams is begin null; -- # pread end Read; - + overriding procedure Write (Port : in out Port_T; Buffer : Stream_Element_Array) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads index e90b824e4..4fbb90c8d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads @@ -1,42 +1,42 @@ with Ada.Streams; use Ada.Streams; package Mystreams is - + type Port_T is new Root_Stream_Type with null record; - + overriding procedure Read (Port : in out Port_T; Buffer : out Stream_Element_Array; Last : out Stream_Element_Offset); - + overriding procedure Write (Port : in out Port_T; Buffer : Stream_Element_Array); - + -- - + type Sint_Mode_Type is (Copy, Double); -- When reading or writing integers from/into a stream, whether -- we should read/fetch the base values untouched or multiply them -- by two; - + Sint_Mode : Sint_Mode_Type := Copy; - + type Sint is record Value : Integer; end record; - + procedure Sint_Read (S : not null access Root_Stream_Type'Class; Item : out Sint); - - procedure Sint_Write + + procedure Sint_Write (S : not null access Root_Stream_Type'Class; Item : in Sint); - + for Sint'Read use Sint_Read; for Sint'Write use Sint_Write; - + Latch : Integer := 0; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb index cfe5aecd3..731ea504a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb index 8b41d6b25..3ff96a5e6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb index f56d76bfe..17ef634f1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Copy; Sint'Write (P'Access, X); Assert (Latch = 1); - + Sint'Read (P'Access, X); Assert (X.Value = 1); end; @@ -23,4 +23,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb index ee110151f..63207cde9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Double; Sint'Write (P'Access, X); Assert (Latch = 2); - + Sint'Read (P'Access, X); Assert (X.Value = 4); end; @@ -23,4 +23,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb index fb65c8f89..095d0299a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Copy; Sint'Write (P'Access, X); Assert (Latch = 1); - + Mystreams.Sint_Mode := Double; Sint'Read (P'Access, X); Assert (X.Value = 2); @@ -24,4 +24,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb index bd3ea4299..69cd74529 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Double; Sint'Write (P'Access, X); Assert (Latch = 2); - + Mystreams.Sint_Mode := Copy; Sint'Read (P'Access, X); Assert (X.Value = 2); @@ -24,4 +24,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb index 1f374cdb6..543559656 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb index f614dd34f..a0b65a695 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb index aaf9317c0..7fc5a6a9c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb @@ -1,11 +1,11 @@ with Mystreams; use Mystreams; package body Trigger is - + -- point here is to have calls via operational attributes -- conditioned, controlling that they are not marked covered -- just because they are special sorts of calls. - + procedure Run (Op : Opkind) is P : aliased Port_T; X : Sint := (Value => 1); @@ -16,4 +16,3 @@ package body Trigger is end case; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads index 0aac346f7..f4738acf2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads @@ -3,4 +3,3 @@ package Trigger is type Opkind is (Read, Write); procedure Run (Op : Opkind); end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt deleted file mode 100644 index de636efbf..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt +++ /dev/null @@ -1 +0,0 @@ -all-warnings XFAIL U916-020: bug in libadalang diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt index 54fba5f43..9fa5daf30 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt @@ -1 +1,2 @@ RTS_ZFP DEAD +RTS_LIGHT_TASKING DEAD Ada.Streams not available diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst index 7da1032ea..b5b26e14d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst @@ -1,8 +1,6 @@ Attribute Definition Clauses for Operational Attributes ======================================================= -%REQ_ID% - Subprogram calls issued through operational attributes shall be treated as regular subprogram calls, regarding both the call statement itself and the called subprogram code. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads index 1e0b54746..77a9d7847 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads @@ -1,13 +1,13 @@ with Data; package Global_Refs.Full is - + X : aliased Integer; -- # decl for X'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'First); -- # clause - + Y : aliased Integer; -- # decl for Y'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'Last+1); -- # clause - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads index c2dc60380..6819c0f04 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads @@ -1,9 +1,9 @@ with Data; package Global_Refs.Inrange is - + X : aliased Integer; -- # decl for X'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'First); -- # clause - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads index 6d4ac4ce1..719aa494c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads @@ -1,9 +1,9 @@ with Data; package Global_Refs.Outrange is - + X : aliased Integer; -- # decl for X'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'Last + 1); -- # clause - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb index cfb9fefdd..73c515bd1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb @@ -1,27 +1,26 @@ with Data, System, Support; use Support; package body Process is - + procedure Check_Inrange is - + V : aliased Integer; -- # in_decl for V'Address use -- # in_clause Data.Data_Address(Index => Data.Data_Array'First); -- # in_clause - + begin Assert (V = Data.Data_Array(Data.Data_Array'First)); -- # in_stmt end; - + procedure Check_Outrange is - + V : aliased Integer; -- # out_decl for V'Address use -- # out_clause Data.Data_Address(Index => Data.Data_Array'Last + 1); -- # out_clause - + use type System.Address; begin Assert (V'Address = System.Null_Address); -- # out_stmt end; - -end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads index 92a022ff7..167acd913 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads @@ -1,5 +1,4 @@ -package Process is +package Process is procedure Check_Inrange; procedure Check_Outrange; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst index f96bbadb4..690ecd062 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst @@ -5,8 +5,6 @@ Attribute definition clauses for representation attributes are of interest in that some of them allow the evaluation of expressions with possible side effects. -%REQ_ID% - Attribute definition clauses for representation attributes aren't statements in the language definition sense and shall not be considered as such by the tool. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb index 0fe7accd7..bcb458aa9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb @@ -9,4 +9,3 @@ package body Data is end if; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst index 53a8eed5c..a0b72209a 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst @@ -14,15 +14,15 @@ Manual (Ada LRM), commonly designated as the Ada Reference Manual, or *ARM*: Several chapters aren't included for reasons listed in the following table: - + .. tabularcolumns:: |p{0.3\textwidth}|p{0.65\textwidth}| -.. csv-table:: +.. csv-table:: ARM chapter exclusions :header: "Chapter", "Not included because ..." :widths: 28, 65 - :delim: | + :delim: | - ARM chap. 1 : General | No language construct described + ARM chap. 1 : General | No language construct described ARM chap. 4 : Names and Expressions | "The described constructs are not considered on their own for coverage analysis purposes. The coverage information is computed for enclosing statement or declaration constructs." @@ -32,4 +32,3 @@ Several chapters aren't included for reasons listed in the following table: .. qmlink:: SubsetIndexTocTree * - diff --git a/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb b/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb index 677b0c2b9..b4f836f4b 100644 --- a/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb +++ b/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb @@ -11,4 +11,3 @@ package body Ranges is end if; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/Consolidation/req.rst b/testsuite/Qualif/Ada/stmt/Consolidation/req.rst index c39d58d9d..b3e2a39f8 100644 --- a/testsuite/Qualif/Ada/stmt/Consolidation/req.rst +++ b/testsuite/Qualif/Ada/stmt/Consolidation/req.rst @@ -1,8 +1,6 @@ SC requirements for the combination of multiple execution traces ================================================================ -%REQ_ID% - When the coverage achieved by multiple execution traces is evaluated, a statement coverage violation shall only be reported when it would have been reported for all the traces individually. diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb index 3a2eb18af..c7f90cfaf 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb @@ -26,5 +26,3 @@ package body Counters is end; end; end; - - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb index db99734ff..a1a576353 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb @@ -10,4 +10,3 @@ begin end; --# counters.adb - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb index b5b942d1d..b9e82cd37 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb @@ -19,4 +19,3 @@ begin Assert (M = Natural'Min (X, 2)); -- # common return M; -- # common end; - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst b/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst index 7dfe664e0..44621e6d0 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst @@ -1,8 +1,6 @@ SC requirements for statement sequences and control-flow transfers ================================================================== -%REQ_ID% - Statement coverage shall be assessed correctly for straightline sequences (basic blocks) of statements, and combinations of such using jump-like control flow transfers (goto, return, raise, exit). diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads b/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads index e21c5deb3..ce0110498 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads @@ -1,4 +1,3 @@ function MinX2 (X : Natural) return Natural; -- Compute and return the minimum of X and 2. Feature flow control -- based on goto and return statements. - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb index 90a0e3580..a51c0cafe 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb @@ -15,5 +15,3 @@ end; -- /xgt0/ l+ ## 0 -- /xgt2/ l+ ## 0 -- /xle2/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb index ad88e4230..22db4d35d 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb @@ -14,5 +14,3 @@ end; -- /xgt0/ l+ ## 0 -- /xgt2/ l- ## s- -- /xle2/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/disabled.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/disabled.adb new file mode 100644 index 000000000..511254e20 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/disabled.adb @@ -0,0 +1,49 @@ +package body Disabled is + + function Complex_Identity (X : Integer) return Integer is + begin + + -- Nest a disable coverage region in an exemption region. + + pragma Annotate (Xcov, Exempt_On, "Exempted region"); -- # exempted + if X = 0 then -- # exempted + return X; -- # exempted + end if; -- # exempted + -- # exempted + pragma Annotate (Xcov, Cov_Off, "Disabled coverage region"); -- # disabled + if X = 1 then -- # disabled + return X; -- # disabled + end if; -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + -- # exempted + if X = 2 then -- # exempted + return X; -- # exempted + end if; -- # exempted + -- # exempted + -- End of the exemption region -- # exempted + -- # exempted + pragma Annotate (Xcov, Exempt_Off); -- # exempted + + -- Now do the opposite: nest the exemption region in the disable + -- coverage region. + + pragma Annotate (Xcov, Cov_Off, "Disabled coverage region"); -- # disabled + -- # disabled + if X = 3 then -- # disabled + return X; -- # disabled + end if; -- # disabled + -- # disabled + pragma Annotate (Xcov, Exempt_On, "Exempted region"); -- # dis-ex + if X = 4 then -- # dis-ex + return X; -- # dis-ex + end if; -- # dis-ex + pragma Annotate (Xcov, Exempt_Off); -- # dis-ex + -- # disabled + return X; -- # disabled + -- # disabled + -- End the disabled coverage region -- # disabled + -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + + end Complex_Identity; +end Disabled; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/disabled.ads b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/disabled.ads new file mode 100644 index 000000000..a0843be4a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/disabled.ads @@ -0,0 +1,3 @@ +package Disabled is + function Complex_Identity (X : Integer) return Integer; +end Disabled; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/test_all.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/test_all.adb new file mode 100644 index 000000000..7e3cbf836 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/src/test_all.adb @@ -0,0 +1,14 @@ +with Disabled; use Disabled; +with Support; use Support; + +procedure Test_All is +begin + Assert (Complex_Identity (0) = 0); + Assert (Complex_Identity (2) = 2); + Assert (Complex_Identity (6) = 6); +end Test_All; + +--# disabled.adb +-- /disabled/ lD ## 0 +-- /dis-ex/ lD ## x0 +-- /exempted/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/tc.rst b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/tc.rst new file mode 100644 index 000000000..60c5b6425 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/tc.rst @@ -0,0 +1,4 @@ +**Exercise disabled coverage and exemption annotations nesting** + +Exercise a package containing disabled coverage annotations in an exemption +region, and the opposite. The former shall take precedence over the latter. diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/test.opt b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/test.opt new file mode 100644 index 000000000..868cc6ecd --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/test.opt @@ -0,0 +1 @@ +gnatcov-25 XFAIL mixing exemptions and disable coverage annotation is not supported for release 25 diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/test.py b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixExemptions/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/disabled.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/disabled.adb new file mode 100755 index 000000000..02557a7a6 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/disabled.adb @@ -0,0 +1,79 @@ +package body Disabled is + + procedure Swap (I, J : in out Integer) is + + -- Disable coverage for a local declaration + + pragma Annotate -- # disabled + (Xcov, Cov_Off, "disable coverage on declarations"); -- # disabled + Tmp : Integer := J; -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + begin + J := I; -- # swap_stmt + I := Tmp; -- # swap_stmt + end Swap; + + function Factorial (X : Natural) return Positive is + begin + if X = 1 then -- # factorial + return 1; -- # 1_factorial + elsif X >= Positive'Last / 1000 then -- # elsif_factorial + + -- Disable coverage for a conditioned set of statements + + pragma Annotate -- # disabled + (Xcov, Cov_Off, -- # disabled + "disable coverage on statements in function"); -- # disabled + return Positive'Last; -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + else + return X * Factorial (X - 1); -- # rec_factorial + end if; + end Factorial; + + -- No disable coverage in the couple of subprograms below + + procedure Another_Swap (I, J : in out Integer) is + Tmp : Integer := J; -- # another_swap + begin + J := I; -- # another_swap + I := Tmp; -- # another_swap + end Another_Swap; + + function Another_Factorial (X : Natural) return Positive is + Result : Positive := 1; -- # another_factorial + begin + for J in 1 .. X loop -- # another_factorial + if Result > Positive'Last / J then -- # in_loop_a_f + raise Constraint_Error; -- # in_if_a_f + end if; + + Result := Result * J; -- # in_loop_a_f + end loop; + + return Result; -- # another_factorial + exception + when Constraint_Error => + return Positive'Last; -- # handler_a_f + end Another_Factorial; + + +begin + + -- Mix of disabled and non-disabled coverage regions for statements in the + -- package elaboration sequence. + + pragma Annotate -- # disabled + (Xcov, Cov_Off, -- # disabled + "disable coverage on elaboration code - 1"); -- # disabled + Z := Identity (3); -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + + Another_Swap (X, Y); -- # elab + + pragma Annotate -- # disabled + (Xcov, Cov_Off, -- # disabled + "disable coverage on elaboration code - 2"); -- # disabled + Another_Swap (Z, X); -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled +end Disabled; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/disabled.ads b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/disabled.ads new file mode 100755 index 000000000..5aaa8eb6b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/disabled.ads @@ -0,0 +1,26 @@ +with Support; use Support; +package Disabled is + + procedure Swap (I, J : in out Integer); + -- Body contains disabled coverage section for a declaration + + function Factorial (X : Natural) return Positive; + -- Body contains disabled coverage section for a statement + + procedure Another_Swap (I, J : in out Integer) ; + -- No disabled coverage section in the body + + function Another_Factorial (X : Natural) return Positive; + -- No disabled coverage section in the body + + -- Mix of disabled and non-disabled declarations + + X : Integer := Identity (1); -- # decl + + pragma Annotate -- # disabled + (Xcov, Cov_Off, "disable coverage on global declaration"); -- # disabled + Y : Integer := Identity (2); -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + + Z : Integer := 1; +end Disabled; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/test_all_disable.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/test_all_disable.adb new file mode 100755 index 000000000..d0344488c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/src/test_all_disable.adb @@ -0,0 +1,44 @@ +-- Test driver for disabled coverage regions. It calls subprograms from the +-- functional code, and it executes all the code in all the disabled coverage +-- regions. + +with Disabled; +with Support; use Support; + +procedure Test_All_Disable is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Disabled.X = 3); + Assert (Disabled.Y = 1); + Assert (Disabled.Z = 2); + + Disabled.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Disabled.Factorial (Positive'Last) = Positive'Last); + -- Code in disabled coverage region is executed + +end Test_All_Disable; + +--# disabled.ads +-- /disabled/ lD ## 0 +-- /negI/ l+ ## 0 + +--# disabled.adb +-- /disabled/ lD ## 0 +-- /swap_stmt/ l+ ## 0 +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /elab/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/tc.rst b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/tc.rst new file mode 100644 index 000000000..2bf185b9a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/tc.rst @@ -0,0 +1,7 @@ +**Exercise disabled coverage regions over a mix of statements and declarations in several units** + +Exercise a package that contains several disabled coverage regions regions, for +a combination of statements and declarations in subprogram bodies, in the +package specification, and in the package body, by disabling coverage in +disjoint regions in subprogram bodies, in elaboration code, and in variable +declaration sections. diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/test.py b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/MixInUnits/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/stacks.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/stacks.adb new file mode 100644 index 000000000..f41052f31 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/stacks.adb @@ -0,0 +1,57 @@ +package body Stacks is + + -- Single disable coverage region for a couple of entire subprogram + -- definitions. + + pragma Annotate -- # disabled + (Xcov, Cov_Off, "we only care about push and pop"); -- # disabled + -- # disabled + procedure On -- # disabled + (S : in out Stack; Op : Op_Kind; V : in out Integer) -- # disabled + is -- # disabled + begin -- # disabled + case Op is -- # disabled + when Push => -- # disabled + if S.Vcount = S.Size then -- # disabled + raise Constraint_Error; -- # disabled + end if; -- # disabled + -- # disabled + S.Vcount := S.Vcount + 1; -- # disabled + S.Values (S.Vcount) := V; -- # disabled + -- # disabled + when Pop => -- # disabled + if S.Vcount = 0 then -- # disabled + raise Constraint_Error; -- # disabled + end if; -- # disabled + -- # disabled + V := S.Values (S.Vcount); -- # disabled + S.Vcount := S.Vcount - 1; -- # disabled + end case; -- # disabled + exception -- # disabled + when Constraint_Error => -- # disabled + S.Ecount := S.Ecount + 1; -- # disabled + end; -- # disabled + -- # disabled + function Errcount (S : in Stack) return Natural is -- # disabled + begin -- # disabled + return S.Ecount; -- # disabled + end; -- # disabled + -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled + + -- Then a couple of subprograms without any disable coverage region + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + +end; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/stacks.ads b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/test_push_pop.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/test_push_pop.adb new file mode 100644 index 000000000..5fd3316a3 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/src/test_push_pop.adb @@ -0,0 +1,17 @@ +with Stacks, Support; use Stacks, Support; + +procedure Test_Push_Pop is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 2); + Pop (S, V); +end; + +--# stacks.adb +-- /disabled/ lD ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/tc.rst b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/tc.rst new file mode 100644 index 000000000..90a1761c1 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/tc.rst @@ -0,0 +1,4 @@ +**Exercise disabled coverage regions over groups of entire subprograms** + +Exercise a package that declares some subprogram bodies with coverage enabled as +well as a disabled coverage region encompassing several other subprograms. diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/test.py b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/SubprogsInUnit/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/test_tipos_all.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/test_tipos_all.adb new file mode 100644 index 000000000..c01901b5b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/test_tipos_all.adb @@ -0,0 +1,9 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_All is +begin + Assert (Tipos (5) = 5); +end; + +--# tipos.adb +-- /disabled/ lD ## 0 diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/tipos.adb b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/tipos.adb new file mode 100644 index 000000000..78d16d4e1 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/tipos.adb @@ -0,0 +1,9 @@ +function Tipos (X : Integer) return Integer is +begin + -- Full sequence exempted below + + pragma Annotate -- # disabled + (Xcov, Cov_Off, "test disabling all coverage"); -- # disabled + return X; -- # disabled + pragma Annotate (Xcov, Cov_On); -- # disabled +end; diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/tipos.ads b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/tipos.ads new file mode 100644 index 000000000..68d462531 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/src/tipos.ads @@ -0,0 +1,2 @@ +function Tipos (X : Integer) return Integer; +-- Twice_If_Pos: x * 2 if x positive, x otherwise. diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/tc.rst b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/tc.rst new file mode 100644 index 000000000..0c91f0a1f --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/tc.rst @@ -0,0 +1,5 @@ +**Exercise disable coverage region over entire subprogram bodies** + +Exercise a subprogram in which all the statements are part of a single +disable coverage region. + diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/test.py b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/WholeBody/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/extra.opt b/testsuite/Qualif/Ada/stmt/DisabledCov/extra.opt new file mode 100644 index 000000000..4a95f8262 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/extra.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +bin-traces DEAD binary traces do not support disabling coverage diff --git a/testsuite/Qualif/Ada/stmt/DisabledCov/req.rst b/testsuite/Qualif/Ada/stmt/DisabledCov/req.rst new file mode 100644 index 000000000..cef292520 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/DisabledCov/req.rst @@ -0,0 +1,49 @@ +SC requirements for disabled coverage regions +============================================= + +For proper behavior of the Coverage Disabling facility, the +following set of rules shall be obeyed: + +====== ====================================================================== +Rule # Description +====== ====================================================================== +1 Disabled regions shall all be synthesized in a distinct section of + the output report, with a single message per region. + +2 Each message describing a disabled region shall specify the range of + source locations covered by the region declaration. + +3 Disabled coverage regions shall not affect the diagnostics reported for + constructs outside of such regions. + +4 The report section dedicated to disabled coverage regions shall indicate + the total number of disabled coverage regions and shall not contain any + other kind of information. + +5 Disabled coverage regions may be declared to disable coverage over + various levels of syntactic constructs such as statements or subprograms, + and groups of such in all the contexts where they may appear. + +6 Disabled coverage annotations shall take precedence over exemption + annotations. +====== ====================================================================== + + +.. rubric:: Testing Strategy + +The following set of testcases checks compliance with this requirement. +The testcases are partitioned into sections +according to point #5 - demonstrate ability to disable coverage for +various groups of syntactic constructs: + + +.. qmlink:: TCIndexImporter + + * + + + +Each test contains a combination of disabled coverage regions and regular code, +exercised in several ways to cover well-identified sections of the program. +All the other aspects of the requirement (rules #1 to #4) are validated by +demonstrating that all the tests run as expected. diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb index c73bfe348..e13aed29f 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb @@ -6,7 +6,7 @@ package body Exemptions is pragma Annotate -- # xswap (Xcov, Exempt_On, "exemption on declarations"); -- # xswap - Tmp : Integer := J; -- # xswap + Tmp : Integer := J; -- # xswap_vio pragma Annotate (Xcov, Exempt_Off); -- # xswap begin J := I; -- # swap_stmt @@ -24,7 +24,7 @@ package body Exemptions is pragma Annotate -- # xfactorial (Xcov, Exempt_On, -- # xfactorial "exemption on statements in function"); -- # xfactorial - return Positive'Last; -- # xfactorial + return Positive'Last; -- # xfactorial_vio pragma Annotate (Xcov, Exempt_Off); -- # xfactorial else return X * Factorial (X - 1); -- # rec_factorial @@ -66,14 +66,14 @@ begin pragma Annotate -- # xelab_1 (Xcov, Exempt_On, -- # xelab_1 "exemption on elaboration code - 1"); -- # xelab_1 - Z := Identity (3); -- # xelab_1 + Z := Identity (3); -- # xelab_1_vio pragma Annotate (Xcov, Exempt_Off); -- # xelab_1 Another_Swap (X, Y); -- # elab pragma Annotate -- # xelab_2 (Xcov, Exempt_On, -- # xelab_2 - "exemption on elaboration code - 2"); -- # xelab_2 + "exemption on elaboration code - 2"); -- # xelab_2_vio Another_Swap (Z, X); -- # xelab_2 pragma Annotate (Xcov, Exempt_Off); -- # xelab_2 end Exemptions; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads index e8ef3f37d..e65c7b770 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads @@ -15,11 +15,11 @@ package Exemptions is -- Mix of exempted and non-exempted declarations - X : Integer := Identity (1); -- # decl + X : Integer := Identity (1); -- # decl pragma Annotate -- # xdecl (Xcov, Exempt_On, "exemption on global declaration"); -- # xdecl - Y : Integer := Identity (2); -- # xdecl + Y : Integer := Identity (2); -- # xdecl_vio pragma Annotate (Xcov, Exempt_Off); -- # xdecl Z : Integer := 1; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_exempted.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_exempted.adb new file mode 100755 index 000000000..a6ecbe190 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_exempted.adb @@ -0,0 +1,48 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, and it executes all the code in all the exempted sections. + +with Exemptions; +with Support; use Support; + +procedure Test_All_Exempted is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Exemptions.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); + -- Code in exemption section is executed + +end Test_All_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l# ## x0 +-- /swap_stmt/ l+ ## 0 + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /xfactorial/ l# ## x0 +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_non_exempted.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_non_exempted.adb new file mode 100755 index 000000000..ea83b13b3 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_non_exempted.adb @@ -0,0 +1,54 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, but these calls do not execute/elaborate exempted code. So the only +-- exempted construct that are expected to be reported as covered are those +-- that are executed/elaborated when the spec and body of the package +-- Exemptions are elaborated +-- +-- This driver executes all the non-exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_All_Non_Exempted is + I, J, K : Integer := 1; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Assert (Exemptions.Factorial (3) = 6); + -- No exempted code is executed + + Assert (Exemptions.Another_Factorial (3) = 6); + Assert (Exemptions.Another_Factorial (Positive'Last) = Positive'Last); + -- No exempted code in this function + +end Test_All_Non_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l+ ## 0 +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l+ ## 0 + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l+ ## 0 +-- /in_loop_a_f/ l+ ## 0 +-- /in_if_a_f/ l+ ## 0 +-- /handler_a_f/ l+ ## 0 + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exempted.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exempted.adb new file mode 100755 index 000000000..424491b5a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exempted.adb @@ -0,0 +1,51 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, and it executes a part of the code in a part of the exempted +-- sections. +-- +-- This driver executes not all but only a part of exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_Exempted is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Exemptions.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); + -- Code in exemption section is executed + +end Test_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l# ## x0 +-- /swap_stmt/ l+ ## 0 + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /xfactorial/ l# ## x0 +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb deleted file mode 100755 index d2c290228..000000000 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb +++ /dev/null @@ -1,61 +0,0 @@ --- Test driver for exemptions. It calls subprograms from the functional --- code, and it executes all the code in all the exempted sections. - -with Exemptions; -with Support; use Support; - -procedure Test_Exemptions_All_Exempted_Code_Call is - I : Integer := 1; - J : Integer := 2; - K : Integer := 3; -begin - Assert (Exemptions.X = 3); - Assert (Exemptions.Y = 1); - Assert (Exemptions.Z = 2); - - Exemptions.Swap (I, J); - Assert (I = 2 and then J = 1); - - Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); - -- Code in exemption section is executed - -end Test_Exemptions_All_Exempted_Code_Call; - ---# exemptions.ads --- /decl/ l+ ## 0 --- /xdecl/ l# ## x0 --- /negI/ l+ ## 0 - ---# exemptions.adb --- /xswap/ l# ## x0 --- /swap_stmt/ l+ ## 0 - --- /factorial/ l+ ## 0 --- /1_factorial/ l- ## s- --- /xfactorial/ l# ## x0 --- /elsif_factorial/ l+ ## 0 --- /rec_factorial/ l- ## s- - --- /another_swap/ l+ ## 0 - --- /another_factorial/ l- ## s- --- /in_loop_a_f/ l- ## s- --- /in_if_a_f/ l- ## s- --- /handler_a_f/ l- ## s- - --- /xelab_1/ l# ## x0 --- /elab/ l+ ## 0 --- /xelab_2/ l# ## x0 - - - - - - - - - - - - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb deleted file mode 100755 index 94ec629cd..000000000 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb +++ /dev/null @@ -1,52 +0,0 @@ --- Test driver for exemptions. It calls subprograms from the functional --- code, but these calls do not execute/elaborate exempted code. So the only --- exempted construct that are expected to be reported as covered are those --- that are executed/elaborated when the spec and body of the package --- Exemptions are elaborated --- --- This driver executes all the non-exempted code. - -with Exemptions; -with Support; use Support; - -procedure Test_Exemptions_All_Non_Exempted_Code_Call is - I, J, K : Integer := 1; -begin - Assert (Exemptions.X = 3); - Assert (Exemptions.Y = 1); - Assert (Exemptions.Z = 2); - - Assert (Exemptions.Factorial (3) = 6); - -- No exempted code is executed - - Assert (Exemptions.Another_Factorial (3) = 6); - Assert (Exemptions.Another_Factorial (Positive'Last) = Positive'Last); - -- No exempted code in this function - -end Test_Exemptions_All_Non_Exempted_Code_Call; - ---# exemptions.ads --- /decl/ l+ ## 0 --- /xdecl/ l# ## x0 --- /negI/ l+ ## 0 - ---# exemptions.adb --- /xswap/ l* ## x+ --- /swap_stmt/ l- ## s- - --- /factorial/ l+ ## 0 --- /1_factorial/ l+ ## 0 --- /xfactorial/ l* ## x+ --- /elsif_factorial/ l+ ## 0 --- /rec_factorial/ l+ ## 0 - --- /another_swap/ l+ ## 0 - --- /another_factorial/ l+ ## 0 --- /in_loop_a_f/ l+ ## 0 --- /in_if_a_f/ l+ ## 0 --- /handler_a_f/ l+ ## 0 - --- /xelab_1/ l# ## x0 --- /elab/ l+ ## 0 --- /xelab_2/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb deleted file mode 100755 index a45c71ea0..000000000 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb +++ /dev/null @@ -1,52 +0,0 @@ --- Test driver for exemptions. It calls subprograms from the functional --- code, and it executes a part of the code in a part of the exempted --- sections. --- --- This driver executes not all but only a part of exempted code. - -with Exemptions; -with Support; use Support; - -procedure Test_Exemptions_Exempted_Code_Call is - I : Integer := 1; - J : Integer := 2; - K : Integer := 3; -begin - Assert (Exemptions.X = 3); - Assert (Exemptions.Y = 1); - Assert (Exemptions.Z = 2); - - Exemptions.Swap (I, J); - Assert (I = 2 and then J = 1); - - Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); - -- Code in exemption section is executed - -end Test_Exemptions_Exempted_Code_Call; - ---# exemptions.ads --- /decl/ l+ ## 0 --- /xdecl/ l# ## x0 --- /negI/ l+ ## 0 - ---# exemptions.adb --- /xswap/ l# ## x0 --- /swap_stmt/ l+ ## 0 - --- /factorial/ l+ ## 0 --- /1_factorial/ l- ## s- --- /xfactorial/ l# ## x0 --- /elsif_factorial/ l+ ## 0 --- /rec_factorial/ l- ## s- - --- /another_swap/ l+ ## 0 - --- /another_factorial/ l- ## s- --- /in_loop_a_f/ l- ## s- --- /in_if_a_f/ l- ## s- --- /handler_a_f/ l- ## s- - --- /xelab_1/ l# ## x0 --- /elab/ l+ ## 0 --- /xelab_2/ l# ## x0 - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb deleted file mode 100755 index 3ed02f507..000000000 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb +++ /dev/null @@ -1,41 +0,0 @@ --- Test driver for exemptions. It only "withes" the functional code, so the --- only constructs that are expected to be reported as covered are those that --- are executed/elaborated when the spec and body of the package Exemptions --- are elaborated - -with Exemptions; -with Support; use Support; - -procedure Test_Exemptions_No_Call is -begin - Assert (Exemptions.X = 3); - Assert (Exemptions.Y = 1); - Assert (Exemptions.Z = 2); -end Test_Exemptions_No_Call; - ---# exemptions.ads --- /decl/ l+ ## 0 --- /xdecl/ l# ## x0 --- /negI/ l+ ## 0 - ---# exemptions.adb --- /xswap/ l* ## x+ --- /swap_stmt/ l- ## s- - --- /factorial/ l- ## s- --- /1_factorial/ l- ## s- --- /xfactorial/ l* ## x+ --- /elsif_factorial/ l- ## s- --- /rec_factorial/ l- ## s- - --- /another_swap/ l+ ## 0 - --- /another_factorial/ l- ## s- --- /in_loop_a_f/ l- ## s- --- /in_if_a_f/ l- ## s- --- /handler_a_f/ l- ## s- - --- /xelab_1/ l# ## x0 --- /elab/ l+ ## 0 --- /xelab_2/ l# ## x0 - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb deleted file mode 100755 index 060b67906..000000000 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb +++ /dev/null @@ -1,52 +0,0 @@ --- Test driver for exemptions. It calls subprograms from the functional --- code, but these calls do not execute/elaborate exempted code. So the only --- exempted construct that are expected to be reported as covered are those --- that are executed/elaborated when the spec and body of the package --- Exemptions are elaborated --- --- This driver executes not all but only a part of non-exempted code. - -with Exemptions; -with Support; use Support; - -procedure Test_Exemptions_Non_Exempted_Code_Call is - I, J, K : Integer := 1; -begin - Assert (Exemptions.X = 3); - Assert (Exemptions.Y = 1); - Assert (Exemptions.Z = 2); - - Assert (Exemptions.Factorial (3) = 6); - -- No exempted code is executed - - Assert (Exemptions.Another_Factorial (3) = 6); - -- No exempted code in this function - -end Test_Exemptions_Non_Exempted_Code_Call; - ---# exemptions.ads --- /decl/ l+ ## 0 --- /xdecl/ l# ## x0 --- /negI/ l+ ## 0 - ---# exemptions.adb --- /xswap/ l* ## x+ --- /swap_stmt/ l- ## s- - --- /factorial/ l+ ## 0 --- /1_factorial/ l+ ## 0 --- /xfactorial/ l* ## x+ --- /elsif_factorial/ l+ ## 0 --- /rec_factorial/ l+ ## 0 - --- /another_swap/ l+ ## 0 - --- /another_factorial/ l+ ## 0 --- /in_loop_a_f/ l+ ## 0 --- /in_if_a_f/ l- ## s- --- /handler_a_f/ l- ## s- - --- /xelab_1/ l# ## x0 --- /elab/ l+ ## 0 --- /xelab_2/ l# ## x0 - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_no.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_no.adb new file mode 100755 index 000000000..06125fd6b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_no.adb @@ -0,0 +1,42 @@ +-- Test driver for exemptions. It only "withes" the functional code, so the +-- only constructs that are expected to be reported as covered are those that +-- are executed/elaborated when the spec and body of the package Exemptions +-- are elaborated + +with Exemptions; +with Support; use Support; + +procedure Test_No is +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); +end Test_No; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l- ## s- +-- /1_factorial/ l- ## s- +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l- ## s- +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_non_exempted.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_non_exempted.adb new file mode 100755 index 000000000..0f7bc7b5e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_non_exempted.adb @@ -0,0 +1,53 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, but these calls do not execute/elaborate exempted code. So the only +-- exempted construct that are expected to be reported as covered are those +-- that are executed/elaborated when the spec and body of the package +-- Exemptions are elaborated +-- +-- This driver executes not all but only a part of non-exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_Non_Exempted is + I, J, K : Integer := 1; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Assert (Exemptions.Factorial (3) = 6); + -- No exempted code is executed + + Assert (Exemptions.Another_Factorial (3) = 6); + -- No exempted code in this function + +end Test_Non_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l+ ## 0 +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l+ ## 0 + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l+ ## 0 +-- /in_loop_a_f/ l+ ## 0 +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb index 865f35ead..4739b87f8 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb @@ -6,8 +6,8 @@ package body Stacks is when Push => pragma Annotate -- # op_oflow (Xcov, Exempt_On, "no overflow"); -- # op_oflow - if S.Vcount = S.Size then -- # op_oflow - raise Constraint_Error; -- # op_oflow + if S.Vcount = S.Size then -- # op_oflow_v1 + raise Constraint_Error; -- # op_oflow_v2 end if; -- # op_oflow pragma Annotate (Xcov, Exempt_Off); -- # op_oflow @@ -17,8 +17,8 @@ package body Stacks is when Pop => pragma Annotate -- # op_uflow (Xcov, Exempt_On, "no underflow"); -- # op_uflow - if S.Vcount = 0 then -- # op_uflow - raise Constraint_Error; -- # op_uflow + if S.Vcount = 0 then -- # op_uflow_v1 + raise Constraint_Error; -- # op_uflow_v2 end if; -- # op_uflow pragma Annotate (Xcov, Exempt_Off); -- # op_uflow diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb index 932227699..9867b0aca 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb @@ -8,12 +8,16 @@ begin end; --# stacks.adb --- /op_case/ l- ## s- --- /op_push/ l- ## s- --- /op_pop/ l- ## s- --- /op_oflow/ l* ## x+ --- /op_uflow/ l* ## x+ --- /op_handler/ l- ## s- +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb index 8928f37f1..c77127091 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb @@ -12,14 +12,16 @@ begin end; --# stacks.adb --- /op_push/ l- ## s- --- /op_pop/ l- ## s- --- /op_oflow/ l* ## x+ --- /op_uflow/ l# ## x0 --- /op_handler/ l+ ## 0 +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 --- /push_decl/ l- ## s- --- /push_body/ l- ## s- --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb index db054a9e5..353642beb 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb @@ -11,14 +11,17 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l- ## s- --- /op_oflow/ l* ## x+ --- /op_uflow/ l* ## x+ --- /op_handler/ l- ## s- +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb index 67d18c8d2..8bb76caf7 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb @@ -9,20 +9,22 @@ begin Push (S, 1); Push (S, 3); Assert (Errcount (S) = 0); - + Push (S, 4); Assert (Errcount (S) = 1); end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l- ## s- --- /op_oflow/ l# ## x0 --- /op_uflow/ l* ## x+ --- /op_handler/ l+ ## 0 +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb index 716f9c59b..249586671 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb @@ -6,27 +6,29 @@ procedure Test_PushPop_0 is S : Stack (Size => 2); V : Integer; begin - Push (S, 1); - Push (S, 2); - + Push (S, 1); + Push (S, 2); + Pop (S, V); Assert (V = 2); - + Pop (S, V); Assert (V = 1); - + Assert (Errcount (S) = 0); end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /op_oflow/ l* ## x+ --- /op_uflow/ l* ## x+ --- /op_handler/ l- ## s- +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb index c3c0ef250..373cceb08 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb @@ -9,23 +9,24 @@ begin Push (S, 1); Push (S, 2); Assert (Errcount (S) = 0); - + Push (S, 3); Assert (Errcount (S) = 1); - + Pop (S, V); Assert (V = 2); end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /op_oflow/ l# ## x0 --- /op_uflow/ l* ## x+ --- /op_handler/ l+ ## 0 +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb index a05421256..5469640b3 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb @@ -6,19 +6,19 @@ procedure Test_PushPop_OU is S : Stack (Size => 2); V : Integer; begin - Push (S, 1); - Push (S, 2); + Push (S, 1); + Push (S, 2); Assert (Errcount (S) = 0); - + Push (S, 3); Assert (Errcount (S) = 1); Pop (S, V); Assert (V = 2); - + Pop (S, V); Assert (V = 1); - + Pop (S, V); Assert (Errcount (S) = 2); end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb index 6ba181281..9c50e1bab 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb @@ -6,24 +6,25 @@ procedure Test_PushPop_U is S : Stack (Size => 2); V : Integer; begin - Push (S, 1); + Push (S, 1); Pop (S, V); Assert (V = 1); Assert (Errcount (S) = 0); - + Pop (S, V); Assert (Errcount (S) = 1); end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /op_oflow/ l* ## x+ --- /op_uflow/ l# ## x0 --- /op_handler/ l+ ## 0 +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb index eb897d474..f505aaed2 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb @@ -18,7 +18,7 @@ begin pragma Annotate -- # init_call (Xcov, Exempt_On, "auto init off"); -- # init_call - Initialize; -- # init_call + Initialize; -- # init_call_violation pragma Annotate (Xcov, Exempt_Off); -- # init_call end if; end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads index b3bb7b247..825492be4 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads @@ -14,4 +14,3 @@ package Com is -- The package elaboration body calls Initialize if Auto_Initialize -- is True, which can never happen. end; - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads index 32a5a28ca..6ec75025a 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads @@ -4,4 +4,3 @@ with Support, Gcom; use Support; package Comi_NoInit is new Gcom (Auto_Init => Identity(False)); - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb index 34a429409..33be8e459 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb @@ -15,7 +15,7 @@ begin pragma Annotate -- # init_call (Xcov, Exempt_On, "auto init off"); -- # init_call - Initialize; -- # init_call + Initialize; -- # init_call_violation pragma Annotate (Xcov, Exempt_Off); -- # init_call end if; end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb index 2eb75e790..d1c453f5d 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb @@ -10,5 +10,6 @@ begin end; --# com.adb --- /init_body/ l- ## s- --- /init_call/ l* ## x+ +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb index 6e6523495..eaaed1e0a 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb @@ -8,5 +8,6 @@ begin end; --# gcom.adb --- /init_body/ l- ## s- --- /init_call/ l* ## x+ +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb index fcbcbc478..bb1693137 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb @@ -26,7 +26,7 @@ package body Stacks is pragma Annotate -- # op_handler (Xcov, Exempt_On, "exception handler"); -- # op_handler - S.Ecount := S.Ecount + 1; -- # op_handler + S.Ecount := S.Ecount + 1; -- # op_handler_stmt pragma Annotate (Xcov, Exempt_Off); -- # op_handler end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb index d0a9511dc..50faca385 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb @@ -8,17 +8,18 @@ begin end; --# stacks.adb --- /op_case/ l- ## s- --- /op_push/ l- ## s- --- /op_pop/ l- ## s- --- /test_oflow/ l- ## s- --- /op_oflow/ l- ## s- --- /test_uflow/ l- ## s- --- /op_uflow/ l- ## s- --- /op_handler/ l* ## x+ +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /test_oflow/ l- ## s- +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- --- /push_decl/ l- ## s- --- /push_body/ l- ## s- --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l- ## s- +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb index d98c992e8..347eee539 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb @@ -11,16 +11,17 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l- ## s- --- /test_oflow/ l+ ## 0 --- /op_oflow/ l- ## s- --- /test_uflow/ l- ## s- --- /op_uflow/ l- ## s- --- /op_handler/ l* ## x+ +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb index dfabd1777..2a09c98fa 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb @@ -19,16 +19,17 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /test_oflow/ l+ ## 0 --- /op_oflow/ l- ## s- --- /test_uflow/ l+ ## 0 --- /op_uflow/ l- ## s- --- /op_handler/ l* ## x+ +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb index ebe44229c..f2dc62257 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb @@ -25,7 +25,7 @@ begin Xf.X1 := True; -- # 1_flag pragma Annotate -- # 1_exem (Xcov, Exempt_On, "exemption section #1"); -- # 1_exem - raise Constraint_Error; -- # 1_exem + raise Constraint_Error; -- # 1_exem_v1 pragma Annotate (Xcov, Exempt_Off); -- # 1_exem end if; @@ -35,7 +35,7 @@ begin Xf.X2 := True; -- # 2_flag pragma Annotate -- # 2_exem (Xcov, Exempt_On, "exemption section #2"); -- # 2_exem - J := -J; -- # 2_exem + J := -J; -- # 2_exem_v1 pragma Annotate (Xcov, Exempt_Off); -- # 2_exem end if; I := Tmp; -- # 2_if @@ -47,7 +47,7 @@ begin Xf.X3 := True; -- # 3_flag pragma Annotate -- # 3_exem (Xcov, Exempt_On, "exemption section #3"); -- # 3_exem - J := 1; -- # 3_exem + J := 1; -- # 3_exem_v1 pragma Annotate (Xcov, Exempt_Off); -- # 3_exem end if; K := K + I; -- # 3_if @@ -61,9 +61,9 @@ exception pragma Annotate -- # h_exem (Xcov, Exempt_On, "exemption section in handler"); -- # h_exem - Tmp := I + J + K; -- # h_exem - I := Tmp; -- # h_exem - J := Tmp + 1; -- # h_exem - K := Tmp + 2; -- # h_exem + Tmp := I + J + K; -- # h_exem_v1 + I := Tmp; -- # h_exem_v2 + J := Tmp + 1; -- # h_exem_v3 + K := Tmp + 2; -- # h_exem_v4 pragma Annotate (Xcov, Exempt_Off); -- # h_exem end Multiple_Exemptions; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb index 6a7e8bf5c..d40658d42 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb @@ -13,13 +13,19 @@ end Test_0; -- /1_if/ l- ## s- -- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l- ## s- -- /2_if/ l- ## s- -- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l- ## s- -- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- -- /h_flag/ l- ## s- -- /h_exem/ l* ## x+ - +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb index c9401e6e9..08e0e68c1 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb @@ -24,15 +24,3 @@ end; -- /3_exem/ l# ## x0 -- /h_flag/ l+ ## 0 -- /h_exem/ l# ## x0 - - - - - - - - - - - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb index d408d7cd1..632346ad6 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb @@ -11,14 +11,21 @@ end; --# multiple_exemptions.adb -- /dcl/ l+ ## 0 -- /1_if/ l+ ## 0 --- /1_flag/ l- ## s- +-- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l+ ## 0 -- /2_if/ l+ ## 0 --- /2_flag/ l- ## s- +-- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l- ## s- --- /3_flag/ l- ## s- +-- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ --- /h_flag/ l- ## s- --- /h_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb index 5d88edf76..a6088e071 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb @@ -13,12 +13,18 @@ end; -- /1_if/ l+ ## 0 -- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l+ ## 0 -- /2_if/ l+ ## 0 -- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l+ ## 0 -- /3_flag/ l+ ## 0 -- /3_exem/ l# ## x0 -- /h_flag/ l- ## s- -- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb index 36f3b5b5f..174224dba 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb @@ -13,6 +13,7 @@ end; -- /1_if/ l+ ## 0 -- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l+ ## 0 -- /2_if/ l+ ## 0 -- /2_flag/ l+ ## 0 @@ -20,5 +21,10 @@ end; -- /3_if/ l- ## s- -- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- -- /h_flag/ l- ## s- -- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb index c8a6741f8..72be78090 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb @@ -6,10 +6,10 @@ with MX; use MX; procedure Test_Exempt_XR23 is begin Trigger_XR1; - + -- Region 1 raises an exception, force running the other blocks -- without the exempted regions. - + Trigger_0XR; end; @@ -22,8 +22,10 @@ end; -- /2_if/ l+ ## 0 -- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l- ## s- -- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- -- /h_flag/ l+ ## 0 -- /h_exem/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb index ab6aae143..39493b7ae 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb @@ -9,31 +9,31 @@ package body Stacks is (S : in out Stack; Op : Op_Kind; V : in out Integer) -- # xregion is -- # xregion begin -- # xregion - case Op is -- # xregion + case Op is -- # xregion_01 when Push => -- # xregion - if S.Vcount = S.Size then -- # xregion - raise Constraint_Error; -- # xregion + if S.Vcount = S.Size then -- # xregion_02 + raise Constraint_Error; -- # xregion_03 end if; -- # xregion -- # xregion - S.Vcount := S.Vcount + 1; -- # xregion - S.Values (S.Vcount) := V; -- # xregion + S.Vcount := S.Vcount + 1; -- # xregion_04 + S.Values (S.Vcount) := V; -- # xregion_05 -- # xregion when Pop => -- # xregion - if S.Vcount = 0 then -- # xregion - raise Constraint_Error; -- # xregion + if S.Vcount = 0 then -- # xregion_06 + raise Constraint_Error; -- # xregion_07 end if; -- # xregion -- # xregion - V := S.Values (S.Vcount); -- # xregion - S.Vcount := S.Vcount - 1; -- # xregion + V := S.Values (S.Vcount); -- # xregion_08 + S.Vcount := S.Vcount - 1; -- # xregion_09 end case; -- # xregion exception -- # xregion when Constraint_Error => -- # xregion - S.Ecount := S.Ecount + 1; -- # xregion + S.Ecount := S.Ecount + 1; -- # xregion_10 end; -- # xregion -- # xregion function Errcount (S : in Stack) return Natural is -- # xregion begin -- # xregion - return S.Ecount; -- # xregion + return S.Ecount; -- # xregion_11 end; -- # xregion -- # xregion pragma Annotate (Xcov, Exempt_Off); -- # xregion diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb index 23dca794c..3186da809 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb @@ -8,7 +8,18 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_01/ l= ## Xs- +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- +-- /xregion_11/ l= ## Xs- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb index b355ecc28..02a4911e0 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb @@ -11,7 +11,13 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb index 2d4c818ae..54f9fed66 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb @@ -11,7 +11,13 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb index 5ee282008..6d871a716 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb @@ -15,7 +15,11 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb index 3673fce4f..af94531be 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb @@ -19,7 +19,10 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_10/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb index 857e36a97..9f37a886d 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb @@ -18,7 +18,8 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_07/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb index 395db953a..0d0c5cef3 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb @@ -16,7 +16,8 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb index 871a749ce..c4c40190a 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb @@ -6,4 +6,7 @@ begin end; --# tipos.adb --- /xblock/ l* ## x+:"test exempting all" +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_if/ l= ## Xs- +-- /xblock_r1/ l= ## Xs- +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb index 4de6b5f30..7e377b1f7 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb @@ -6,4 +6,5 @@ begin end; --# tipos.adb --- /xblock/ l* ## x+:"test exempting all" +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r1/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb index 534e1ebc4..c3b785427 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb @@ -6,4 +6,5 @@ begin end; --# tipos.adb --- /xblock/ l* ## x+:"test exempting all" +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb index 7f9acb915..5ab7cc62b 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb @@ -4,10 +4,10 @@ begin pragma Annotate (Xcov, Exempt_On, -- # xblock "test exempting all"); -- # xblock - if X > 0 then -- # xblock - return X * 2; -- # xblock + if X > 0 then -- # xblock_if + return X * 2; -- # xblock_r1 else -- # xblock - return X; -- # xblock + return X; -- # xblock_r2 end if; -- # xblock pragma Annotate (Xcov, Exempt_Off); -- # xblock end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads index 64576eb46..68d462531 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads @@ -1,4 +1,2 @@ function Tipos (X : Integer) return Integer; -- Twice_If_Pos: x * 2 if x positive, x otherwise. - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt b/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt +++ b/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/req.rst b/testsuite/Qualif/Ada/stmt/Exemptions/req.rst index 90a53fada..dd00e70d5 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/Exemptions/req.rst @@ -1,8 +1,6 @@ SC requirements for exemption regions ===================================== -%REQ_ID% - For proper behavior of the Coverage Exemptions facility, the following set of rules shall be obeyed: @@ -12,17 +10,21 @@ Rule # Description 1 Exempted regions shall all be synthesized in a distinct section of the output report, with a single message per region. -2 Each exemption message shall specify the range of source locations - covered by the region declaration, and indicate whether 0 or more - coverage violations were actually exempted within this range. +2 Each message describing an exempted region shall specify the range of + source locations covered by the region declaration, and indicate whether + 0 or more coverage violations were actually exempted within this range. + +3 The type and location of exempted violations shall be displayed under + the corresponding exempted region message. -3 Exemption regions shall not affect the diagnostics reported for +4 Exemption regions shall not affect the diagnostics reported for constructs outside of such regions. -4 The report section dedicated to exemption regions shall not contain - any other kind of information. +5 The report section dedicated to exemption regions shall indicate the + total number of exemption regions and total number of exempted + violations, and shall not contain any other kind of information. -5 Exemption regions may be declared to exempt various levels of +6 Exemption regions may be declared to exempt various levels of syntactic constructs such as statements or subprograms, and groups of such in all the contexts where they may appear. ====== ====================================================================== @@ -32,7 +34,7 @@ Rule # Description The following set of testcases checks compliance with this requirement. The testcases are partitioned into sections -according to point #5 - demonstrate ability to exempt +according to point #6 - demonstrate ability to exempt various groups of syntactic constructs: @@ -44,10 +46,10 @@ various groups of syntactic constructs: Each test contains a combination of exempted regions and regular code, exercised in several ways to cover well-identified sections of the program. -All the other aspects of the requirement (rules #1 to #4) are validated by +All the other aspects of the requirement (rules #1 to #5) are validated by demonstrating that all the tests run as expected. -For each stated expectation, exempted region, or non-exempted -violation, the testsuite driver checks if it appears in the expected report -section (in addition to its regular checks). +For each stated expectation, exempted region, exempted violation and +non-exempted violation, the testsuite driver checks if it appears in the +expected report section (in addition to its regular checks). diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb index 3b5b4b2a2..fdd37df89 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb @@ -34,4 +34,3 @@ package body Sensors.Status is end; end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb index 7ed58c3f1..d3ba4b9b4 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb @@ -3,24 +3,24 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Broken is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Two history entries, both out of range - - S.V := 15; + + S.V := 15; Sample (S); Sample (S); - + Assert (Status_Of (S) = Broken); - + -- A third entry, in range. Still two out of range. - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Broken); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb index 182ff8b10..8155e3ca4 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb @@ -3,23 +3,23 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Single history entry, out of range - - S.V := 15; + + S.V := 15; Sample (S); - + Assert (Status_Of (S) = Check); - + -- Two history entries, only one out of range - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb index b25045422..f059116ab 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb @@ -4,15 +4,15 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 15; Sample (S); Assert (Status_Of (S) = Check); - + Sample (S); Assert (Status_Of (S) = Broken); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb index 41f130fb0..25da1cff6 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_OK is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb index b5d53ffe8..1a32eb2e2 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Sample (S); Assert (Status_Of (S) = Broken); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb index d25eb08eb..b51c551af 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb index dc9ce0599..14e2b25be 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb @@ -4,19 +4,19 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb index 61d041b89..0dee6dae7 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb @@ -4,18 +4,18 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 1; Sample (S); Sample (S); Assert (Status_Of (S) = Broken); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb index c69010279..87286041a 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb @@ -4,21 +4,21 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb index c66ff198b..39350b815 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); - + Sample (S); Assert (Status_Of (S) = Ok); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb index b3f615ea2..aa3c5b380 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb index 3b4c5e5a5..3e50f7c12 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb index 31c0335c9..bcea68f69 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Undecide is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads index be1a4bef4..7dfcde28c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads @@ -6,4 +6,3 @@ package Slists.Count is SP : SP_Access := Pass'Access; NT, NF : out Natural); end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb index ae80f0d75..bae3dea63 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb @@ -26,4 +26,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb index 76fca9e16..48bc0ae73 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb @@ -27,4 +27,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l- ## s- -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb index 76312d21b..91786e246 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb @@ -10,22 +10,22 @@ procedure Test_Iftf is Sin : aliased Sensor (Hist_Size => 5); -- in range sensor Sout : aliased Sensor (Hist_Size => 5); -- out of range sensor SL : Sensor_List; - + Nt, Nf : Natural; begin - + Sin.V := 5; Sin.ALB := 1; Sin.AHB := 10; - + Prepend (Sin'Unchecked_Access, SL); - + Sout.V := 5; Sout.ALB := 1; Sout.AHB := 3; - + Prepend (Sout'Unchecked_Access, SL); - + Count_In (Sl, Inrange'Access, Nt, Nf); Assert (Nt = 1); Assert (Nf = 1); @@ -40,4 +40,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb index 449ff9419..347619b89 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb @@ -21,4 +21,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l- ## s- -- /CO_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb index d4d9e1dd3..b18e47280 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb @@ -6,14 +6,14 @@ procedure Test_If_FFT is S : aliased Sensor (Hist_Size =>5); begin Prepend (S'Unchecked_Access, SL); - + -- Arrange to 'ok' only - + S.ALB := 1; S.AHB := 1; S.V := 1; S.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -36,4 +36,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb index 3911c8b85..34ad6c442 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb @@ -6,14 +6,14 @@ procedure Test_If_FTF is S : aliased Sensor (Hist_Size =>5); begin Prepend (S'Unchecked_Access, SL); - + -- Arrange to 'fault' only - + S.ALB := 1; S.AHB := 1; S.V := 5; S.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -36,4 +36,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb index 70b0551cd..9f222f822 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb @@ -5,21 +5,21 @@ procedure Test_If_FTT is SL : Sensor_List; S1, S2 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + -- Arrange to 'fault' and 'ok' only - + S1.ALB := 1; S1.AHB := 1; S1.V := 1; S1.Active := True; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -42,4 +42,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb index c3d1e3612..d8852b924 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb @@ -6,11 +6,11 @@ procedure Test_If_TFF is S : aliased Sensor (Hist_Size =>5); begin Prepend (S'Unchecked_Access, SL); - + -- Arrange to 'skip' only - + S.Active := False; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -33,4 +33,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb index 0096a384c..4791c1af0 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb @@ -5,21 +5,21 @@ procedure Test_If_TFT is SL : Sensor_List; S1, S2 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + -- Arrange to 'skip' and 'ok' only - + S1.ALB := 1; S1.AHB := 1; S1.V := 1; S1.Active := True; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := False; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -42,4 +42,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb index f82455733..975edbb76 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb @@ -5,21 +5,21 @@ procedure Test_If_TTF is SL : Sensor_List; S1, S2 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + -- Arrange to 'skip' and 'fault' only - + S1.ALB := 1; S1.AHB := 1; S1.V := 0; S1.Active := True; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := False; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -42,4 +42,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb index 4396abf40..96dfeb04c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb @@ -5,27 +5,27 @@ procedure Test_If_TTT is SL : Sensor_List; S1, S2, S3 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); Prepend (S3'Unchecked_Access, SL); - + -- Arrange to 'skip', 'fault' and 'ok' - + S1.ALB := 1; S1.AHB := 1; S1.V := 3; S1.Active := False; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := True; - + S3.ALB := 1; S3.AHB := 1; S3.V := 1; S3.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -48,4 +48,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb index a7bbb75c4..aa779903c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb @@ -24,4 +24,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt new file mode 100644 index 000000000..510071fba --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt @@ -0,0 +1 @@ +morello DEAD The test uses memory tricks that are prohibited on CHERI platforms diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb index dd2dd3ea3..f734bf26f 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb @@ -26,4 +26,3 @@ package body Slists.Forall is end; end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads index d1d942c70..5d475d37b 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads @@ -3,4 +3,3 @@ package Slists.Forall is procedure ForAll_In (SL : Sensor_List; Op : Sensor_Op; Active_Only : Boolean := False); end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb index a28cdb8f6..877455f3a 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb @@ -8,7 +8,7 @@ begin S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range - + S2.ALB := 5; S2.AHB := 15; S2.V := 1; -- # < low bound @@ -20,10 +20,10 @@ begin Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); Prepend (S3'Unchecked_Access, SL); - + Forall_In (SL, Activate); Assert (S1.Active and then S2.Active and then S3.Active); - + Forall_In (SL, Inhibit); Assert (S1.Active and then (not S2.Active) and then (not S3.Active)); end; @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb index c1fdc00c6..08ab934fb 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb @@ -7,16 +7,16 @@ procedure Test_Activate is begin S1.ALB := 1; S1.AHB := 10; - + S2.ALB := 5; S2.AHB := 15; Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + Forall_In (SL, Activate, Active_Only => True); Assert ((not S1.Active) and then (not S2.Active)); - + Forall_In (SL, Activate); Assert (S1.Active and then S2.Active); end; @@ -32,4 +32,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb index 8d2160933..4886c1134 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb @@ -9,7 +9,7 @@ begin S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + S2.ALB := 5; S2.AHB := 15; S2.V := 1; -- # < low bound @@ -23,7 +23,7 @@ begin Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); Prepend (S3'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active and then (not S2.Active) and then (not S3.Active)); end; @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb index ca014d18c..31e7aef65 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb @@ -24,4 +24,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb index bd7f368c4..bf9f04fc7 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb @@ -18,4 +18,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb index f98bb9a1a..88a2d7093 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb @@ -7,14 +7,14 @@ procedure Test_Noinhibit is begin -- get into the inhibit case selection, arranging for the -- if statement there to always evaluate false - + S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + Prepend (S1'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst b/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst index aebf2ef76..4ccf4678e 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst @@ -1,8 +1,6 @@ SC requirements for mixed statement constructs ============================================== -%REQ_ID% - Correct coverage shall be reported for programs that use combinations of Ada constructs with arbitrary levels of syntactic nesting, for example on statements nested within LOOPs within IF constructs within subprograms. diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb index 404de97f8..a4f0b96fc 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb @@ -5,5 +5,3 @@ package body Sensors is Vbufs.Push (S.V, S.History); end; end; - - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads index 97d448e97..f7f589942 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads @@ -14,4 +14,3 @@ package Sensors is -- latch current sensor value for S in its history buffer end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb index dfbefee80..a3d2aa1ee 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb @@ -2,10 +2,10 @@ with Vbufs; use Vbufs; with Simple_Pools; package body Slists is - + package Sensor_Nodes_Pool is new Simple_Pools.Basic_Pool (Data_Type => Sensor_Node, Capacity => 20); - + procedure Prepend (S : Sensor_Access; SL : in out Sensor_List) is NA : constant Sensor_Nodes_Pool.Data_Access := Sensor_Nodes_Pool.Allocate; begin diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads index 1e5ad1b18..49646f52c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads @@ -13,4 +13,3 @@ package Vbufs is procedure Push (V : Value; VB : in out Vbuffer); end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt b/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt +++ b/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb new file mode 100644 index 000000000..784ff7331 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb @@ -0,0 +1,15 @@ +package body Pkg is + + function Or_Else (L, R : New_Bool) return Boolean is + use type New_Bool; + begin + if L then -- # if-stmt + return True; -- # ret-if + elsif R then -- # elsif-stmt + return True; -- # ret-elsif + else + return False; -- # ret-else + end if; + end Or_Else; + +end Pkg; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads new file mode 100644 index 000000000..ee3026e42 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + type New_Bool is new Boolean; + + function Or_Else (L, R : New_Bool) return Boolean; + +end Pkg; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb new file mode 100644 index 000000000..1971dc325 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Else is +begin + Support.Assert (not Or_Else (False, False)); +end Test_Else; + +--# pkg.adb +-- +-- /if-stmt/ l+ ## 0 +-- /ret-if/ l- ## s- +-- /elsif-stmt/ l+ ## 0 +-- /ret-elsif/ l- ## s- +-- /ret-else/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb new file mode 100644 index 000000000..87ea64162 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Elsif is +begin + Support.Assert (Or_Else (False, True)); +end Test_Elsif; + +--# pkg.adb +-- +-- /if-stmt/ l+ ## 0 +-- /ret-if/ l- ## s- +-- /elsif-stmt/ l+ ## 0 +-- /ret-elsif/ l+ ## 0 +-- /ret-else/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb new file mode 100644 index 000000000..1caac11f8 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_If is +begin + Support.Assert (Or_Else (True, False)); +end Test_If; + +--# pkg.adb +-- +-- /if-stmt/ l+ ## 0 +-- /ret-if/ l+ ## 0 +-- /elsif-stmt/ l- ## s- +-- /ret-elsif/ l- ## s- +-- /ret-else/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb new file mode 100644 index 000000000..c606e05b9 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb @@ -0,0 +1,13 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_No is +begin + null; +end Test_No; + +--# pkg.adb +-- +-- /.*-stmt/ l- ## s- +-- /ret-.*/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst new file mode 100644 index 000000000..7b3c56a0c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst @@ -0,0 +1,4 @@ +**Exercise SC on ELSIF stmt with derived boolean types** + +Check that statement coverage of elsif statements for which +the decision is of a type derived from boolean works as intended. diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py new file mode 100644 index 000000000..74a224f6c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py @@ -0,0 +1,12 @@ +""" +Check that statement coverage of ELSIF statements works as intended +when the decision is of a type derived from Standard.Boolean +(and not a subtype of Standard.Boolean). Gnatcov used to produce +illegal code in this case. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb index 4ee3767ad..e7f9936df 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb @@ -3,4 +3,3 @@ procedure FlipB (B : in out Boolean) is begin B := not B; -- # flipb end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb index b394e5909..711ca6746 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb @@ -3,4 +3,3 @@ procedure FlipX (X : in out Integer) is begin X := -X; -- # flipx end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb index caf3118c4..c442f6695 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb @@ -7,8 +7,16 @@ end; --# ops.adb -- /incOp/ l- ## s- +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l- ## s- +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb index 8383e906d..5d61738de 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb @@ -9,8 +9,16 @@ end; --# ops.adb -- /incOp/ l+ ## 0 +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l+ ## 0 +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt deleted file mode 100644 index f10d6338c..000000000 --- a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-012: src-traces and inhibited code diff --git a/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb b/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb index 54c7296c0..b1456198b 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb @@ -1100,4 +1100,3 @@ begin X := X + 1; -- # bump X := X + 1; -- # bump end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb b/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb index a0ab5cb14..963089274 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb @@ -5,4 +5,3 @@ begin S := X + Y; P := X * Y; -- # compute end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt b/testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt new file mode 100644 index 000000000..531c42810 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt @@ -0,0 +1 @@ +c DEAD ASM inlining not supported by CCG diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads index 442b6bb71..07519dec3 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads @@ -3,4 +3,3 @@ pragma Restrictions (No_Elaboration_Code); package Bar is Z : Integer := 12; -- # decl end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads index c3b31d30e..e65ac8cc0 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads @@ -5,4 +5,3 @@ package Foo is X : Myint := 12; -- # decl procedure Set_X (V : Myint); -- # decl end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr index 8355f531b..156a94465 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr @@ -4,7 +4,16 @@ library project mylib is for library_kind use "static"; for library_name use project'name; for library_dir use "lib"; + + type Trace_Mode_Enum is ("src", "bin"); + Trace_Mode : Trace_Mode_Enum := external ("TRACE_MODE"); package compiler is - for switches("ada") use ("-fpreserve-control-flow", "-fdump-scos", "-g"); + case Trace_Mode is + when "bin" => + for switches("ada") use + ("-fpreserve-control-flow", "-fdump-scos", "-g"); + when "src" => + null; + end case; end compiler; -end mylib; \ No newline at end of file +end mylib; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py index 224a6a72f..d38517cd8 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py @@ -5,9 +5,15 @@ from SUITE.context import thistest from SUITE.gprutils import GPRswitches -libdep = os.path.abspath('mylib/mylib.gpr') -TestCase().run(covcontrol=CovControl( - deps=[libdep], - gprsw=GPRswitches(root_project='gen.gpr', - units=['foo', 'bar', 'klunk']))) +libdep = os.path.abspath("mylib/mylib.gpr") +TestCase().run( + covcontrol=CovControl( + deps=[libdep], + gprsw=GPRswitches( + root_project="gen.gpr", + units=["foo", "bar", "klunk"], + xvars=[("TRACE_MODE", thistest.options.trace_mode)], + ), + ) +) thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb b/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb index b22a23696..4bf065e23 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb @@ -10,4 +10,3 @@ end; --# andthen.adb -- /andthen/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb index 1664c15bc..760b9d148 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb @@ -1,20 +1,20 @@ pragma Ada_2012; package body Ops is - + function V_Indexing (X : aliased in out Composite_V; Op : Op_Name) return Integer_Ref - is + is begin case Op is -- # indexing when OP_A => return (Ref => X.A'Access); -- # op_a when Op_B => return (Ref => X.B'Access); -- # op_b end case; end; - + function C_Indexing (X : aliased Composite_C'Class; Op : Op_Name) return Integer - is + is begin case Op is -- # indexing when OP_A => return X.A; -- # op_a @@ -22,5 +22,3 @@ package body Ops is end case; end; end; - - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads index 95a22acac..a0d9a7061 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads @@ -1,29 +1,28 @@ pragma Ada_2012; package Ops is - - type Op_Name is (Op_A, Op_B); - + + type Op_Name is (Op_A, Op_B); + type Composite_V is tagged record A, B : aliased Integer; end record with Variable_Indexing => V_Indexing; - + type Composite_C is tagged record A, B : aliased Integer; end record with Constant_Indexing => C_Indexing; - + type Integer_Ref (Ref : access Integer) is null record with Implicit_Dereference => Ref; - + function V_Indexing (X : aliased in out Composite_V; Op : Op_Name) return Integer_Ref; - + function C_Indexing (X : aliased Composite_C'Class; Op : Op_Name) return Integer; - + end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb index 547125249..ac9bee9ae 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb @@ -8,13 +8,13 @@ procedure Test_OPAB is begin CV(Op_A) := 12; Assert (CV.A = 12); - + CV.B := 5; Assert (CV(Op_B) = 5); - + CC.A := 12; Assert (CC(Op_A) = 12); - + CC.B := 5; Assert (CC(Op_B) = 5); end; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb index 50bad10d1..ce395bad7 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb @@ -8,9 +8,9 @@ procedure Test_OPB is begin CV.B := 5; Assert (CV(Op_B) = 5); - + CC.B := 12; - Assert (CC(Op_B) = 12); + Assert (CC(Op_B) = 12); end; --# ops.adb diff --git a/testsuite/Qualif/Ada/stmt/Robustness/req.rst b/testsuite/Qualif/Ada/stmt/Robustness/req.rst index d1f776a9d..63af6eab3 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/req.rst +++ b/testsuite/Qualif/Ada/stmt/Robustness/req.rst @@ -5,8 +5,6 @@ SC requirements regarding potentially confusing constructs, e.g. multiple statements sharing a line. -%REQ_ID% - Statement Coverage assessment is correct in the presence of code diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt new file mode 100644 index 000000000..916096d15 --- /dev/null +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt @@ -0,0 +1 @@ +native,RTS_ZFP DEAD Test assumes bin file available on native platform diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py index c07142685..5e5d4b466 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py @@ -4,7 +4,9 @@ HarnessTestCase( - expected_diags=[HarnessDiagnostic( - text="exception raised while running 'test_afail'")], - category=CAT.stmt).run() + expected_diags=[ + HarnessDiagnostic(text="exception raised while running 'test_afail'") + ], + category=CAT.stmt, +).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py index 44183c3b8..d663c372f 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py @@ -6,11 +6,12 @@ # The =report diags we always expect. The =xcov diags we only expect in # !qualif runs as these don't produce the =xcov outputs. expected_diags = [ - HarnessDiagnostic(text='Missing expected sNoCov mark at line 3')] + HarnessDiagnostic(text="Missing expected sNoCov mark at line 3") +] if not thistest.options.qualif_level: expected_diags.append( - HarnessDiagnostic(text='Missing expected lNoCov mark at line 3')) + HarnessDiagnostic(text="Missing expected lNoCov mark at line 3") + ) -HarnessTestCase(expected_diags=expected_diags, - category=CAT.stmt).run() +HarnessTestCase(expected_diags=expected_diags, category=CAT.stmt).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst b/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst index 6898460b6..83fda58c2 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst @@ -24,3 +24,6 @@ The test harness shall comply to the following requirements: * Presence in the output report of violations not applicable to the test category shall be ignored +.. qmlink:: TCIndexImporter + + * diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb b/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb deleted file mode 100644 index e7e059c05..000000000 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb +++ /dev/null @@ -1,20 +0,0 @@ - -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - - function Identity (X : Integer) return Integer is - begin - return X; - end; - - function Identity (B : Boolean) return Boolean is - begin - return B; - end; -end; diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads b/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads deleted file mode 100644 index f7482f2e1..000000000 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads +++ /dev/null @@ -1,6 +0,0 @@ - -package Support is - procedure Assert (Cond : Boolean); - function Identity (X : Integer) return Integer; - function Identity (B : Boolean) return Boolean; -end; diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb index 516ce9972..a448df957 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb @@ -8,4 +8,3 @@ begin end; --# inc.adb - diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py index 210a744e1..bf3b34c31 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py @@ -5,11 +5,13 @@ # The =report diags we always expect. The =xcov diags we only expect in # !qualif runs as these don't produce the =xcov outputs. -expected_diags = [HarnessDiagnostic(text='Unexpected sNoCov mark at sloc 3:4')] +expected_diags = [HarnessDiagnostic(text="Unexpected sNoCov mark at sloc 3:4")] if not thistest.options.qualif_level: - expected_diags.append(HarnessDiagnostic( - text='(inc.adb.xcov) Unexpected lNoCov mark at line 3')) + expected_diags.append( + HarnessDiagnostic( + text="(inc.adb.xcov) Unexpected lNoCov mark at line 3" + ) + ) -HarnessTestCase(expected_diags=expected_diags, - category=CAT.stmt).run() +HarnessTestCase(expected_diags=expected_diags, category=CAT.stmt).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py index ba68b763f..d6a1c8574 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py @@ -5,6 +5,8 @@ HarnessTestCase( expected_diags=[ - HarnessDiagnostic(text='Unexpected sNoCov mark at sloc 3:4')], - category=CAT.stmt).run() + HarnessDiagnostic(text="Unexpected sNoCov mark at sloc 3:4") + ], + category=CAT.stmt, +).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/app.rst b/testsuite/Qualif/Appendix/Testsuite/app.rst index 2516783a0..d0c6bc758 100644 --- a/testsuite/Qualif/Appendix/Testsuite/app.rst +++ b/testsuite/Qualif/Appendix/Testsuite/app.rst @@ -1,13 +1,13 @@ .. _testsuite-overview: -|testproc_section_title| -************************ +Overview of the Test Procedures Organization +******************************************** The GNATcoverage *testsuite* consists of the set of executable *tests* that implement *Testcases*, driven by an execution and control harness to validate part or all of a *Tool Operational Requirement*. Each test involves sources and a description of expected results, which, in association with the harness -operation, consitutes a *test procedure*. +operation, constitutes a *test procedure*. Very broadly, the testsuite harness builds executables from the sources, executes the resulting programs, invokes GNATcoverage to perform some coverage @@ -394,5 +394,3 @@ with the test category to prevent FAILures from violations of stricter criteria. In our example test of statement category, the ``0`` expectations are meant to convey that we expect no *statement coverage* violation on the lines, and violations of stricter criteria there ought to be ignored. - - diff --git a/testsuite/Qualif/C/.tor_ignore b/testsuite/Qualif/C/.tor_ignore new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c index a54eee59a..1d5a9ebc8 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c @@ -1,8 +1,9 @@ -char andeqor (char A, char B, char C, char D) +char +andeqor (char A, char B, char C, char D) { if ((A && B) == (C || D)) // # eval - return (char) 1; // # true + return (char) 1; // # true else return (char) 0; // # false } diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb index c251d49c3..5ff7faf25 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", eF-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c index 2281abbfa..a32b397c9 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c @@ -1,5 +1,6 @@ -char oreqandnot (char A, char B, char C, char D) +char +oreqandnot (char A, char B, char C, char D) { return ((A || B) == (C && !D)); // # eval } diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb index d3aefc918..9ce9d4532 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb @@ -4,7 +4,7 @@ procedure Test_AC_T is begin Assert -- or-1, and-2 (Or_Eq_And_Not (False, False, False, False) = True); - + Assert -- or-3, and-1 (Or_Eq_And_Not (True, False, True, False) = True); end; diff --git a/testsuite/Qualif/C/src/support.adb b/testsuite/Qualif/C/src/support.adb deleted file mode 100644 index 06edf576c..000000000 --- a/testsuite/Qualif/C/src/support.adb +++ /dev/null @@ -1,10 +0,0 @@ -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - -end; diff --git a/testsuite/Qualif/C/src/support.ads b/testsuite/Qualif/C/src/support.ads deleted file mode 100644 index 69581ba52..000000000 --- a/testsuite/Qualif/C/src/support.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Support is - procedure Assert (Cond : Boolean); - Pragma Export(C, Assert, "assert"); -end; diff --git a/testsuite/Qualif/C/src/support.h b/testsuite/Qualif/C/src/support.h index 73c084827..052a658b8 100644 --- a/testsuite/Qualif/C/src/support.h +++ b/testsuite/Qualif/C/src/support.h @@ -1,14 +1,10 @@ #ifndef SUPPORT_H -# define SUPPORT_H +#define SUPPORT_H -# define NULL ((void *) 0) -# define false 0 -# define true 1 +#define NULL ((void *) 0) +#define false 0 +#define true 1 -extern void -assert (char cond); - -extern int -identity (char value); +extern void assert (char cond); #endif diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c index cfd185063..3126f898e 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int full, int arg) { - arg; // # statements-all - if (full) // # statements-aux-all + arg; // # statements-all + if (full) // # statements-aux-all { - arg; // # statements-cond + arg; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c index 336ab3e41..c1bb8fdfd 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int full, int arg) { - 0x80; // # statements-all - if (full) // # statements-aux-all + 0x80; // # statements-all + if (full) // # statements-aux-all { - 0xff; // # statements-cond + 0xff; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ arg += 1; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c index 1ee588c00..71ff7e11f 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int full, int arg) { - "Hello, "; // # statements-all - if (full) // # statements-aux-all + "Hello, "; // # statements-all + if (full) // # statements-aux-all { "world!"; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond }; - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c index 91f215b2d..c8e54d306 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c @@ -3,17 +3,17 @@ int num (int *arg) { - return ++*arg; // # statements-aux-all + return ++*arg; // # statements-aux-all } int run_statements (int full, int arg) { - int a[2] = { 0, 1, 2 }; // # statements-aux-all + int a[2] = { 0, 1, 2 }; // # statements-aux-all - a[num (&arg)]; // # statements-all - if (full) // # statements-aux-all - a[num (&arg)]; // # statements-cond + a[num (&arg)]; // # statements-all + if (full) // # statements-aux-all + a[num (&arg)]; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c index 50550ef51..77d11437a 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c @@ -3,7 +3,7 @@ static void nop (int *arg) { - ++*arg; // # statements-aux-all + ++*arg; // # statements-aux-all } int @@ -13,5 +13,5 @@ run_statements (int full, int arg) if (full) // # statements-aux-all nop (&arg); // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c index 51547d969..5775d22fe 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c @@ -5,40 +5,34 @@ struct foo int bar; }; -static struct foo foo_objects[5] = -{ - { 1 }, - { 2 }, - { 3 }, - { 4 }, - { 5 }, +static struct foo foo_objects[5] = { + { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, }; struct foo get_foo (int arg) { - foo_objects[arg].bar += 1; // # statements-aux-all - return foo_objects[arg]; // # statements-aux-all + foo_objects[arg].bar += 1; // # statements-aux-all + return foo_objects[arg]; // # statements-aux-all } struct foo * get_foo_p (int arg) { - foo_objects[arg].bar += 1; // # statements-aux-all - return &foo_objects[arg]; // # statements-aux-all + foo_objects[arg].bar += 1; // # statements-aux-all + return &foo_objects[arg]; // # statements-aux-all } - int run_statements (int full, int arg) { - get_foo (++arg).bar; // # statements-all - if (full) // # statements-aux-all - get_foo (++arg).bar; // # statements-cond + get_foo (++arg).bar; // # statements-all + if (full) // # statements-aux-all + get_foo (++arg).bar; // # statements-cond - get_foo_p (++arg)->bar; // # statements-all - if (full) // # statements-aux-all - get_foo_p (++arg)->bar; // # statements-cond + get_foo_p (++arg)->bar; // # statements-all + if (full) // # statements-aux-all + get_foo_p (++arg)->bar; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c index 3c4182444..0a257627e 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c @@ -3,12 +3,12 @@ int run_statements (int full, int arg) { - arg++; // # statements-all - if (full) // # statements-aux-all - arg++; // # statements-cond + arg++; // # statements-all + if (full) // # statements-aux-all + arg++; // # statements-cond - arg--; // # statements-all - if (full) // # statements-aux-all - arg--; // # statements-cond - return arg; // # statements-aux-all + arg--; // # statements-all + if (full) // # statements-aux-all + arg--; // # statements-cond + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c index ec7c388ee..b77051372 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c @@ -2,30 +2,30 @@ struct complex_number { - int real; - int imag; + int real; + int imag; }; int run_statements (int full, int arg) { - (char *) {"Hello, world!"}; // # statements-all - if (full) // # statements-aux-all + (char *){ "Hello, world!" }; // # statements-all + if (full) // # statements-aux-all { - (char *) {"Hello, world!"}; // # statements-cond - ++arg; // # statements-aux-cond + (char *){ "Hello, world!" }; // # statements-cond + ++arg; // # statements-aux-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ } - (struct complex_number) { 1, 2 }; // # statements-all - if (full) // # statements-aux-all + (struct complex_number){ 1, 2 }; // # statements-all + if (full) // # statements-aux-all { - (struct complex_number) { 1, 2 }; // # statements-cond - ++arg; // # statements-aux-cond + (struct complex_number){ 1, 2 }; // # statements-cond + ++arg; // # statements-aux-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c index f3dddb0bf..b38a77de5 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int full, int arg) { - ++arg; // # statements-all - if (full) // # statements-aux-all - ++arg; // # statements-cond + ++arg; // # statements-all + if (full) // # statements-aux-all + ++arg; // # statements-cond - --arg; // # statements-all - if (full) // # statements-aux-all - --arg; // # statements-cond + --arg; // # statements-all + if (full) // # statements-aux-all + --arg; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c index dc7b94d00..01fe3088d 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c @@ -3,27 +3,27 @@ int run_statements (int full, int arg) { - int *b = &arg; // # statements-aux-all + int *b = &arg; // # statements-aux-all - &arg; // # statements-all - *b; // # statements-all - +arg; // # statements-all - -arg; // # statements-all - ~arg; // # statements-all - !arg; // # statements-all + &arg; // # statements-all + *b; // # statements-all + +arg; // # statements-all + -arg; // # statements-all + ~arg; // # statements-all + !arg; // # statements-all - if (full) // # statements-aux-all + if (full) // # statements-aux-all { - &arg; // # statements-cond - *b; // # statements-cond - +arg; // # statements-cond - -arg; // # statements-cond - ~arg; // # statements-cond - !arg; // # statements-cond + &arg; // # statements-cond + *b; // # statements-cond + +arg; // # statements-cond + -arg; // # statements-cond + ~arg; // # statements-cond + !arg; // # statements-cond /* The following statement is needed so that the previous statements are considered as covered even if they generate no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c index 329da57e7..5a0bc84ac 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int foo, int arg) { - sizeof (arg); // # statements-all - if (foo) // # statements-aux-all - { + sizeof (arg); // # statements-all + if (foo) // # statements-aux-all + { sizeof (arg); // # statements-cond ++arg; // # statements-aux-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - } + } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c index 50ab477c7..b3da7b170 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int foo, int arg) { - sizeof (int); // # statements-all - if (foo) // # statements-aux-all + sizeof (int); // # statements-all + if (foo) // # statements-aux-all { sizeof (int); // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - arg += 1; // # statements-aux-cond + arg += 1; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c index ad231ad9a..53787a879 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c @@ -3,12 +3,12 @@ int run_statements (int full, int arg) { - if (full) // # statements-aux-all + if (full) // # statements-aux-all { - (void) arg; // # statements-cond + (void) arg; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c index 1136a85dd..317732b6b 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg * 0; // # statements-all - if (full) // # statements-aux-all - ++arg * 0; // # statements-cond + ++arg * 0; // # statements-all + if (full) // # statements-aux-all + ++arg * 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c index 4fbfc6f7d..ab64b75b4 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg + 0; // # statements-all - if (full) // # statements-aux-all - ++arg + 0; // # statements-cond + ++arg + 0; // # statements-all + if (full) // # statements-aux-all + ++arg + 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c index 04aa32ff8..e84035a98 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int full, int arg) { - ++arg << 1; // # statements-all - if (full) // # statements-aux-all - ++arg << 1; // # statements-cond + ++arg << 1; // # statements-all + if (full) // # statements-aux-all + ++arg << 1; // # statements-cond - ++arg >> 1; // # statements-all - if (full) // # statements-aux-all - ++arg >> 1; // # statements-cond + ++arg >> 1; // # statements-all + if (full) // # statements-aux-all + ++arg >> 1; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c index 8a358de15..4b00a5713 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c @@ -3,21 +3,21 @@ int run_statements (int full, int arg) { - ++arg < 0; // # statements-all - if (full) // # statements-aux-all - ++arg < 0; // # statements-cond + ++arg < 0; // # statements-all + if (full) // # statements-aux-all + ++arg < 0; // # statements-cond - ++arg > 0; // # statements-all - if (full) // # statements-aux-all - ++arg > 0; // # statements-cond + ++arg > 0; // # statements-all + if (full) // # statements-aux-all + ++arg > 0; // # statements-cond - ++arg <= 0; // # statements-all - if (full) // # statements-aux-all - ++arg <= 0; // # statements-cond + ++arg <= 0; // # statements-all + if (full) // # statements-aux-all + ++arg <= 0; // # statements-cond - ++arg >= 0; // # statements-all - if (full) // # statements-aux-all - ++arg >= 0; // # statements-cond + ++arg >= 0; // # statements-all + if (full) // # statements-aux-all + ++arg >= 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c index 811d04152..7392a3c13 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int full, int arg) { - ++arg == 0; // # statements-all - if (full) // # statements-aux-all - ++arg == 0; // # statements-cond + ++arg == 0; // # statements-all + if (full) // # statements-aux-all + ++arg == 0; // # statements-cond - ++arg != 0; // # statements-all - if (full) // # statements-aux-all - ++arg != 0; // # statements-cond + ++arg != 0; // # statements-all + if (full) // # statements-aux-all + ++arg != 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c index 13aaa9846..be3e9efa9 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg & 0; // # statements-all - if (full) // # statements-aux-all - ++arg & 0; // # statements-cond + ++arg & 0; // # statements-all + if (full) // # statements-aux-all + ++arg & 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c index a53e532fd..61148d5ae 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg ^ 0; // # statements-all - if (full) // # statements-aux-all - ++arg ^ 0; // # statements-cond + ++arg ^ 0; // # statements-all + if (full) // # statements-aux-all + ++arg ^ 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c index 7a40bc253..1337a6987 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg | 0; // # statements-all - if (full) // # statements-aux-all - ++arg | 0; // # statements-cond + ++arg | 0; // # statements-all + if (full) // # statements-aux-all + ++arg | 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c index 8e7b743fc..3ba34e146 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg && 0; // # statements-all - if (full) // # statements-aux-all - ++arg && 0; // # statements-cond + ++arg && 0; // # statements-all + if (full) // # statements-aux-all + ++arg && 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c index c74c64aa2..f0bace27a 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c @@ -3,10 +3,10 @@ int run_statements (int full, int arg) { - ++arg || 0; // # statements-all + ++arg || 0; // # statements-all if (full) // # statements-aux-all ++arg || 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c index bec83fc09..552626a51 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c @@ -3,13 +3,13 @@ static int incr (int *arg) { - return ++*arg; // # statements-aux-all + return ++*arg; // # statements-aux-all } static int decr (int *arg) { - return --*arg; // # statements-aux-all + return --*arg; // # statements-aux-all } int @@ -17,12 +17,12 @@ run_statements (int full, int arg) { /* Call zero and one so that they are covered iff. statements-aux-all must be covered. */ - incr (&arg); // # statements-aux-all - decr (&arg); // # statements-aux-all + incr (&arg); // # statements-aux-all + decr (&arg); // # statements-aux-all - full ? incr (&arg) : decr (&arg); // # statements-all - if (full) // # statements-aux-all - full ? incr (&arg) : decr (&arg); // # statements-cond + full ? incr (&arg) : decr (&arg); // # statements-all + if (full) // # statements-aux-all + full ? incr (&arg) : decr (&arg); // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c index 888cb09b5..fc2b28934 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c @@ -3,31 +3,31 @@ int run_statements (int full, int arg) { - arg = arg + 1; // # statements-all - arg *= 2; // # statements-all - arg /= 1; // # statements-all - arg %= 0xff; // # statements-all - arg += 1; // # statements-all - arg -= 1; // # statements-all - arg <<= 1; // # statements-all - arg >>= 1; // # statements-all - arg &= 0xff; // # statements-all - arg ^= 1; // # statements-all - arg |= 1; // # statements-all - if (full) // # statements-aux-all + arg = arg + 1; // # statements-all + arg *= 2; // # statements-all + arg /= 1; // # statements-all + arg %= 0xff; // # statements-all + arg += 1; // # statements-all + arg -= 1; // # statements-all + arg <<= 1; // # statements-all + arg >>= 1; // # statements-all + arg &= 0xff; // # statements-all + arg ^= 1; // # statements-all + arg |= 1; // # statements-all + if (full) // # statements-aux-all { - arg = arg + 1; // # statements-cond - arg *= 2; // # statements-cond - arg /= 1; // # statements-cond - arg %= 0xff; // # statements-cond - arg += 1; // # statements-cond - arg -= 1; // # statements-cond - arg <<= 1; // # statements-cond - arg >>= 1; // # statements-cond - arg &= 0xff; // # statements-cond - arg ^= 1; // # statements-cond - arg |= 1; // # statements-cond + arg = arg + 1; // # statements-cond + arg *= 2; // # statements-cond + arg /= 1; // # statements-cond + arg %= 0xff; // # statements-cond + arg += 1; // # statements-cond + arg -= 1; // # statements-cond + arg <<= 1; // # statements-cond + arg >>= 1; // # statements-cond + arg &= 0xff; // # statements-cond + arg ^= 1; // # statements-cond + arg |= 1; // # statements-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c index 169e1ab73..c0a371188 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c @@ -7,5 +7,5 @@ run_statements (int full, int arg) if (full) // # statements-aux-all arg -= 1, arg += 2; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst b/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst index a8c56ced9..fb761b24b 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst @@ -4,8 +4,6 @@ SC requirements for chapter 6, section 5: Expressions SC requirements regarding chapter 6, section 5: Expressions -%REQ_ID% - All C expressions can be used as a statement. diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h b/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h index d3bf61595..128183ee5 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h @@ -1,11 +1,10 @@ #ifndef STATEMENTS_H -# define STATEMENTS_H +#define STATEMENTS_H -/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or just - "statement-all" ones otherwise. - Auxillary "statement-aux-all" tagged statements are executed if and only if - "statement-all" are executed, and "statement-aux-cond" ones are too iff. - "statement-cond" ones are executed.*/ +/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or + just "statement-all" ones otherwise. Auxillary "statement-aux-all" tagged + statements are executed if and only if "statement-all" are executed, and + "statement-aux-cond" ones are too iff. "statement-cond" ones are executed.*/ int run_statements (int full, int a); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c index 522974ebc..1889a5ab3 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c @@ -4,25 +4,25 @@ int run_statements (int full, int arg) { { - if (!full) // # statements-aux-all + if (!full) // # statements-aux-all { - --arg; // # statements-not-cond - goto middle; // # statements-not-cond + --arg; // # statements-not-cond + goto middle; // # statements-not-cond } - ++arg; // # statements-cond + ++arg; // # statements-cond } middle: - if (!full) // # statements-aux-all + if (!full) // # statements-aux-all { - --arg; // # statements-not-cond - goto end; // # statements-not-cond + --arg; // # statements-not-cond + goto end; // # statements-not-cond } { - ++arg; // # statements-cond + ++arg; // # statements-cond } end: - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c index e62610d9f..c58640253 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c @@ -3,16 +3,16 @@ int run_statements (int full, int arg) { - if (full) // # statements-aux-all + if (full) // # statements-aux-all { goto compound_in; // # statements-cond { - arg = 1; // # statement-non-coverable + arg = 1; // # statement-non-coverable -compound_in: ; - ++arg; // # statements-cond + compound_in:; + ++arg; // # statements-cond } } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c index 928f6e9d0..6aa236643 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c @@ -4,15 +4,15 @@ int run_statements (int full, int arg) { { - if (!full) // # statements-aux-all + if (!full) // # statements-aux-all { - ++arg; // # statements-not-cond - goto compound_out; // # statements-not-cond + ++arg; // # statements-not-cond + goto compound_out; // # statements-not-cond } - --arg; // # statements-cond + --arg; // # statements-cond } compound_out: - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h index 1741ccee3..5bae7a388 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h @@ -1,11 +1,10 @@ #ifndef STATEMENTS_H -# define STATEMENTS_H +#define STATEMENTS_H -/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or just - "statement-all" ones otherwise. - Auxillary "statement-aux-all" tagged statements are executed if and only if - "statement-all" are executed, and "statement-aux-cond" ones are too iff. - "statement-cond" ones are executed.*/ +/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or + just "statement-all" ones otherwise. Auxillary "statement-aux-all" tagged + statements are executed if and only if "statement-all" are executed, and + "statement-aux-cond" ones are too iff. "statement-cond" ones are executed.*/ int run_statements (int full, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c index 301c2e63c..24358ca23 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c @@ -1,10 +1,11 @@ #include "doif.h" -void doif (int cond, int * xstatus) +void +doif (int cond, int *xstatus) { - *xstatus = 0; // # body - if (cond) // # eval - *xstatus |= XST_IF; // # if + *xstatus = 0; // # body + if (cond) // # eval + *xstatus |= XST_IF; // # if else *xstatus |= XST_ELSE; // # else } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h index 466f769bf..e2646062b 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h @@ -1,4 +1,4 @@ -#define XST_IF (0x1 << 0) +#define XST_IF (0x1 << 0) #define XST_ELSE (0x1 << 1) -void doif (int cond, int * xstatus); +void doif (int cond, int *xstatus); diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c index ba1b414c4..7bb259b1a 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c @@ -1,31 +1,31 @@ #include "doswitch.h" void -doswitch (int input, int * xstatus) +doswitch (int input, int *xstatus) { - *xstatus = 0; // # body + *xstatus = 0; // # body - if (input == 0) // # body + if (input == 0) // # body { - *xstatus &= ~XST_INPUT_WAS_ZERO; // # zero - goto zero; // # zero + *xstatus &= ~XST_INPUT_WAS_ZERO; // # zero + goto zero; // # zero } - switch (input) // # eval + switch (input) // # eval { -zero: - *xstatus |= XST_ZERO; // # zero - break; // # zero + zero: + *xstatus |= XST_ZERO; // # zero + break; // # zero case 1: - *xstatus |= XST_ONE; // # one + *xstatus |= XST_ONE; // # one case 2: - *xstatus |= XST_TWO; // # two - break; // # two + *xstatus |= XST_TWO; // # two + break; // # two default: - *xstatus |= XST_DEFAULT; // # default - break; // # default + *xstatus |= XST_DEFAULT; // # default + break; // # default } } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h index 00bc1afc3..1105e0138 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h @@ -1,12 +1,12 @@ #ifndef DOSWITCH_H -# define DOSWITCH_H +#define DOSWITCH_H -#define XST_ZERO (0x1 << 0) -#define XST_ONE (0x1 << 1) -#define XST_TWO (0x1 << 2) -#define XST_DEFAULT (0x1 << 3) -#define XST_INPUT_WAS_ZERO (0x1 << 4) +#define XST_ZERO (0x1 << 0) +#define XST_ONE (0x1 << 1) +#define XST_TWO (0x1 << 2) +#define XST_DEFAULT (0x1 << 3) +#define XST_INPUT_WAS_ZERO (0x1 << 4) -void doswitch (int input, int * xstatus); +void doswitch (int input, int *xstatus); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c index d53a4a18d..ac981e8a0 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c @@ -3,26 +3,26 @@ int dowhile (int start, int behavior) { - int a = start; // # body + int a = start; // # body - if (behavior & GOTO_IN) // # body + if (behavior & GOTO_IN) // # body { - ++a; // # goto-in - goto in_while; // # goto-in + ++a; // # goto-in + goto in_while; // # goto-in } - while (a < 10) // # eval + while (a < 10) // # eval { - ++a; // # while-eval -in_while: - ++a; // # while-in - if (behavior & GOTO_OUT) // # while-in + ++a; // # while-eval + in_while: + ++a; // # while-in + if (behavior & GOTO_OUT) // # while-in { - ++a; // # goto-out - goto out_while; // # goto-out + ++a; // # goto-out + goto out_while; // # goto-out } } out_while: - return a; // # body + return a; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h index 02dd66b3e..2d8b9d077 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h @@ -1,8 +1,8 @@ #ifndef DOWHILE_H -# define DOWHILE_H +#define DOWHILE_H -# define GOTO_IN (0x01 << 0) -# define GOTO_OUT (0x01 << 1) +#define GOTO_IN (0x01 << 0) +#define GOTO_OUT (0x01 << 1) int dowhile (int start, int behavior); diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c index c6f04b67a..047d7faad 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c @@ -3,27 +3,29 @@ int dowhile (int start, int behavior) { - int a = start; // # body + int a = start; // # body - if (behavior & GOTO_IN) // # body + if (behavior & GOTO_IN) // # body { - ++a; // # goto-in - goto in_while; // # goto-in + ++a; // # goto-in + goto in_while; // # goto-in } /* Without the following statement, the goto-in is pointless. */ - ++a; // # pre-while + ++a; // # pre-while - do { -in_while: - ++a; // # while - if (behavior & GOTO_OUT) // # while + do + { + in_while: + ++a; // # while + if (behavior & GOTO_OUT) // # while { - ++a; // # goto-out - goto out_while; // # goto-out + ++a; // # goto-out + goto out_while; // # goto-out } - } while (a < 10); // # eval + } + while (a < 10); // # eval out_while: - return a; // # body + return a; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h index 02dd66b3e..2d8b9d077 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h @@ -1,8 +1,8 @@ #ifndef DOWHILE_H -# define DOWHILE_H +#define DOWHILE_H -# define GOTO_IN (0x01 << 0) -# define GOTO_OUT (0x01 << 1) +#define GOTO_IN (0x01 << 0) +#define GOTO_OUT (0x01 << 1) int dowhile (int start, int behavior); diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoin.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gi.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoin.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gi.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoinout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gio.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoinout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gio.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_go.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_go.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_no.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_no.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_no.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_no.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoin.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gi.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoin.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gi.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoinout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gio.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoinout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gio.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_go.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_go.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c index f424e9649..48c810172 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c @@ -3,16 +3,16 @@ int dofor (int start, int behavior) { - int a = start; // # body - int i; // # body + int a = start; // # body + int i; // # body - if (behavior & GOTO_IN) // # body + if (behavior & GOTO_IN) // # body { - ++a; // # goto-in - goto in_for; // # goto-in + ++a; // # goto-in + goto in_for; // # goto-in } - --a; // # pre-for + --a; // # pre-for // For binary traces, we will have two coverage obligations here: // - The initialization statement and the test expression @@ -23,16 +23,16 @@ dofor (int start, int behavior) // for the update statement). This means the coverage expectations will be // different. - for (i = start; i < 10; ++i) // # eval + for (i = start; i < 10; ++i) // # eval { -in_for: - if (behavior & GOTO_OUT) // # for + in_for: + if (behavior & GOTO_OUT) // # for { - ++a; // # goto-out - goto out_for; // # goto-out + ++a; // # goto-out + goto out_for; // # goto-out } } out_for: - return a + i; // # return + return a + i; // # return } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h index cab3a2162..429095828 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h @@ -1,10 +1,9 @@ #ifndef DOFOR_H -# define DOFOR_H +#define DOFOR_H -#define GOTO_IN (0x01 << 0) -#define GOTO_OUT (0x01 << 1) +#define GOTO_IN (0x01 << 0) +#define GOTO_OUT (0x01 << 1) -int -dofor (int start, int behavior); +int dofor (int start, int behavior); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c index 92994493d..54137663f 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c @@ -3,20 +3,20 @@ int dogoto (int full, int arg) { - if (full != -1) // # body + if (full != -1) // # body { - --arg; // # body - goto test; // # body + --arg; // # body + goto test; // # body } - ++arg; // # unreachable + ++arg; // # unreachable test: - if (full) // # body - { - ++arg; // # cond - goto end; // # cond - } + if (full) // # body + { + ++arg; // # cond + goto end; // # cond + } end: - return arg; // # body + return arg; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h index 302fab915..d02883e51 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h @@ -1,7 +1,6 @@ #ifndef DOGOTO_H -# define DOGOTO_H +#define DOGOTO_H -int -dogoto (int full, int arg); +int dogoto (int full, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c index 4d030aa70..54a2e0acf 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c @@ -5,19 +5,20 @@ docontinue (int limit, int arg) { do { - ++arg; // # while - if (arg > limit) // # while + ++arg; // # while + if (arg > limit) // # while { - arg += 2; // # continue-soft - continue; // # continue-soft + arg += 2; // # continue-soft + continue; // # continue-soft } - if (arg >= 10) // # while + if (arg >= 10) // # while { - arg += 3; // # continue-hard - continue; // # continue-hard + arg += 3; // # continue-hard + continue; // # continue-hard } - ++arg; // # not-continue - } while (0 < arg && arg <= 10); // # eval + ++arg; // # not-continue + } + while (0 < arg && arg <= 10); // # eval - return arg; // # body + return arg; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h index 6636c2121..1f821f649 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h @@ -1,7 +1,6 @@ #ifndef DOCONTINUE_H -# define DOCONTINUE_H +#define DOCONTINUE_H -int -docontinue (int limit, int arg); +int docontinue (int limit, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c index 2fd939e66..951a56ce2 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c @@ -3,22 +3,23 @@ int dobreak (int limit, int arg) { - int loop = 1; // # body + int loop = 1; // # body do { - ++arg; // # while - if (arg > limit) // # while + ++arg; // # while + if (arg > limit) // # while { - --arg; // # break-soft - break; // # break-soft + --arg; // # break-soft + break; // # break-soft } - if (arg > 10) // # while + if (arg > 10) // # while { - --arg; // # break-hard - break; // # break-hard + --arg; // # break-hard + break; // # break-hard } - } while (++loop); // # body + } + while (++loop); // # body - return arg; // # body + return arg; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h index 1de5b4147..d147f1ca2 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h @@ -1,7 +1,6 @@ #ifndef DOBREAK_H -# define DOBREAK_H +#define DOBREAK_H -int -dobreak (int limit, int arg); +int dobreak (int limit, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c index a70f1be59..c0b465343 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c @@ -3,8 +3,8 @@ int doreturn (int cond) { - if (cond) // # body - return 1; // # cond-true + if (cond) // # body + return 1; // # cond-true else - return 0; // # cond-false + return 0; // # cond-false } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h index ee8515c0b..bd2193b05 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h @@ -1,5 +1,5 @@ #ifndef DORETURN_H -# define DORETURN_H +#define DORETURN_H int doreturn (int cond); diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c index ec687d9a7..fed3583ef 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c @@ -7,35 +7,35 @@ sensor_get_status (struct sensor *s) enum sensor_status status; int i; - if (s->history.len == 0) // # SO_t0 - status = SENSOR_UNDECIDABLE; // # SO_undecide + if (s->history.len == 0) // # SO_t0 + status = SENSOR_UNDECIDABLE; // # SO_undecide else { - status = SENSOR_OK; // # SO_decide + status = SENSOR_OK; // # SO_decide - i = 0; // # SO_init - while (i < s->history.len) // # SO_loop + i = 0; // # SO_init + while (i < s->history.len) // # SO_loop { - if (s->history.store[i] < s->lower_bound // # SO_tfaultLB - || s->history.store[i] > s->upper_bound) // # SO_tfaultUB + if (s->history.store[i] < s->lower_bound // # SO_tfaultLB + || s->history.store[i] > s->upper_bound) // # SO_tfaultUB { - switch (status) // # SO_fault + switch (status) // # SO_fault { case SENSOR_OK: - status = SENSOR_CHECK; // # SO_check - break; // # SO_check + status = SENSOR_CHECK; // # SO_check + break; // # SO_check case SENSOR_CHECK: case SENSOR_BROKEN: - status = SENSOR_BROKEN; // # SO_broken - break; // # SO_broken + status = SENSOR_BROKEN; // # SO_broken + break; // # SO_broken default: - assert (false); // # SO_PE - break; // # SO_unreachable + assert (false); // # SO_PE + break; // # SO_unreachable } } - ++i; // # SO_iter + ++i; // # SO_iter } } - return status; // # SO_ret + return status; // # SO_ret } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h index 030d8c773..5e2dc14ad 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h @@ -1,5 +1,5 @@ #ifndef SENSORS_STATUS_H -# define SENSORS_STATUS_H +#define SENSORS_STATUS_H #include "sensors.h" @@ -11,7 +11,6 @@ enum sensor_status SENSOR_BROKEN }; -extern enum sensor_status -sensor_get_status (struct sensor *s); +extern enum sensor_status sensor_get_status (struct sensor *s); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c index 3f1e86963..77a8ec167 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c @@ -15,6 +15,5 @@ sensor_pass (struct sensor *s) bool sensor_inrange (struct sensor *s) { - return s->lower_bound <= s->value - && s->value <= s->upper_bound; + return s->lower_bound <= s->value && s->value <= s->upper_bound; } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h index 352254b68..5738d5b68 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h @@ -1,17 +1,14 @@ #ifndef SENSORS_PREDICATES_H -# define SENSORS_PREDICATES_H +#define SENSORS_PREDICATES_H -# include "sensors.h" +#include "sensors.h" -extern bool -sensor_nopass (struct sensor *s); +extern bool sensor_nopass (struct sensor *s); -extern bool -sensor_pass (struct sensor *s); +extern bool sensor_pass (struct sensor *s); -extern bool -sensor_inrange (struct sensor *s); +extern bool sensor_inrange (struct sensor *s); -typedef bool (*sensor_predicate)(struct sensor *s); +typedef bool (*sensor_predicate) (struct sensor *s); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c index fed5d257c..b3c266222 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c @@ -2,19 +2,18 @@ #include "support.h" void -slist_count_in (struct sensor_list *l, - sensor_predicate p, +slist_count_in (struct sensor_list *l, sensor_predicate p, unsigned *count_true, unsigned *count_false) { - struct sensor_node *node = l->head; // # CO_decl + struct sensor_node *node = l->head; // # CO_decl - *count_true = *count_false = 0; // # CO_init - while (node != NULL) // # CO_while + *count_true = *count_false = 0; // # CO_init + while (node != NULL) // # CO_while { - if (p (node->s)) // # CO_test - ++*count_true; // # CO_incT + if (p (node->s)) // # CO_test + ++*count_true; // # CO_incT else - ++*count_false; // # CO_incF - node = node->next; // # CO_next + ++*count_false; // # CO_incF + node = node->next; // # CO_next } } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h index 6c07da74e..533793c24 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h @@ -1,13 +1,11 @@ #ifndef SLISTS_COUNT_H -# define SLISTS_COUNT_H +#define SLISTS_COUNT_H #include "sensors.h" -#include "slists.h" #include "sensors_predicates.h" +#include "slists.h" -extern void -slist_count_in (struct sensor_list *l, - sensor_predicate p, - unsigned *count_true, unsigned *count_false); +extern void slist_count_in (struct sensor_list *l, sensor_predicate p, + unsigned *count_true, unsigned *count_false); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c index 9c2eb7088..c47bcdb89 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c @@ -3,21 +3,20 @@ void slist_control (struct sensor_list *l, bool active_only, - struct sensor_list *skipped, - struct sensor_list *fault, + struct sensor_list *skipped, struct sensor_list *fault, struct sensor_list *ok) { - struct sensor_node *node = l->head; // # AF_init + struct sensor_node *node = l->head; // # AF_init - while (node != NULL) // # AF_while - { - if (active_only && !node->s->active) // # AF_evA - slist_prepend (node->s, skipped); // # AF_skip - else if (node->s->value < node->s->lower_bound // # AF_evLB - || node->s->value > node->s->upper_bound) // # AF_evHB - slist_prepend (node->s, fault); // # AF_fault - else - slist_prepend (node->s, ok); // # AF_ok - node = node->next; // # AF_next - } + while (node != NULL) // # AF_while + { + if (active_only && !node->s->active) // # AF_evA + slist_prepend (node->s, skipped); // # AF_skip + else if (node->s->value < node->s->lower_bound // # AF_evLB + || node->s->value > node->s->upper_bound) // # AF_evHB + slist_prepend (node->s, fault); // # AF_fault + else + slist_prepend (node->s, ok); // # AF_ok + node = node->next; // # AF_next + } } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h index c25f87c15..cc9abb26f 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h @@ -1,14 +1,12 @@ #ifndef SLISTS_FAULT -# define SLISTS_FAULT +#define SLISTS_FAULT #include "slists.h" #include -extern void -slist_control (struct sensor_list *s, bool active_only, - struct sensor_list *skipped, - struct sensor_list *fault, - struct sensor_list *ok); +extern void slist_control (struct sensor_list *s, bool active_only, + struct sensor_list *skipped, + struct sensor_list *fault, struct sensor_list *ok); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c index bed3982ac..2bb86f7e3 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c @@ -4,22 +4,22 @@ void slist_forall_in (struct sensor_list *l, enum sensor_op op, bool active_only) { - struct sensor_node *node = l->head; // # FA_init + struct sensor_node *node = l->head; // # FA_init - while (node != NULL) // # FA_while + while (node != NULL) // # FA_while { - if (node->s->active || !active_only) // # FA_tactive - switch (op) // # FA_case - { - case SENSOR_ACTIVATE: - node->s->active = true; // # FA_activate - break; // # FA_activate - case SENSOR_INHIBIT: - if (node->s->value < node->s->lower_bound // # FA_tinhibitLB - || node->s->value > node->s->upper_bound) // # FA_tinhibitHB - node->s->active = false; // # FA_do_inhibit - break; // # FA_inhibit_end - } - node = node->next; // # FA_next + if (node->s->active || !active_only) // # FA_tactive + switch (op) // # FA_case + { + case SENSOR_ACTIVATE: + node->s->active = true; // # FA_activate + break; // # FA_activate + case SENSOR_INHIBIT: + if (node->s->value < node->s->lower_bound // # FA_tinhibitLB + || node->s->value > node->s->upper_bound) // # FA_tinhibitHB + node->s->active = false; // # FA_do_inhibit + break; // # FA_inhibit_end + } + node = node->next; // # FA_next } } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h index cc5082e25..945c5785b 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h @@ -1,7 +1,7 @@ #ifndef SLISTS_FORALL_H -# define SLISTS_FORALL_H +#define SLISTS_FORALL_H -# include "slists.h" +#include "slists.h" enum sensor_op { @@ -9,7 +9,7 @@ enum sensor_op SENSOR_INHIBIT }; -extern void -slist_forall_in (struct sensor_list *l, enum sensor_op op, bool active_only); +extern void slist_forall_in (struct sensor_list *l, enum sensor_op op, + bool active_only); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c index 2d4992f75..ea9c4a0be 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c @@ -10,11 +10,11 @@ main (void) struct sensor_list l; sensor_init (1, 10, &s1); - s1.value = 5; /* in range */ + s1.value = 5; /* in range */ sensor_init (5, 15, &s2); - s2.value = 1; /* < low bound */ + s2.value = 1; /* < low bound */ sensor_init (5, 15, &s3); - s3.value = 45; /* > high bound */ + s3.value = 45; /* > high bound */ slist_init (&l); slist_prepend (&s1, &l); @@ -22,12 +22,12 @@ main (void) slist_prepend (&s3, &l); slist_forall_in (&l, SENSOR_ACTIVATE, false); - assert ( s1.active); - assert ( s2.active); - assert ( s3.active); + assert (s1.active); + assert (s2.active); + assert (s3.active); slist_forall_in (&l, SENSOR_INHIBIT, false); - assert ( s1.active); + assert (s1.active); assert (!s2.active); assert (!s3.active); return 0; diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c index 50bfc0c65..acd4b4ce9 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c @@ -21,8 +21,8 @@ main (void) assert (!s2.active); slist_forall_in (&l, SENSOR_ACTIVATE, false); - assert ( s1.active); - assert ( s2.active); + assert (s1.active); + assert (s2.active); return 0; } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c index 0a823078f..a53861472 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c @@ -10,13 +10,13 @@ main (void) struct sensor_list l; sensor_init (1, 10, &s1); - s1.value = 5; /* in range */ + s1.value = 5; /* in range */ s1.active = true; sensor_init (5, 15, &s2); - s2.value = 1; /* < low bound */ + s2.value = 1; /* < low bound */ s2.active = true; sensor_init (5, 15, &s3); - s3.value = 45; /* > high bound */ + s3.value = 45; /* > high bound */ s3.active = true; slist_init (&l); @@ -25,7 +25,7 @@ main (void) slist_prepend (&s3, &l); slist_forall_in (&l, SENSOR_INHIBIT, false); - assert ( s1.active); + assert (s1.active); assert (!s2.active); assert (!s3.active); return 0; diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h index 2c3aca3c8..9c60f6e88 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h @@ -1,9 +1,9 @@ #ifndef SENSORS_H -# define SENSORS_H +#define SENSORS_H -# include "vbufs.h" +#include "vbufs.h" -# include +#include struct sensor { @@ -14,11 +14,9 @@ struct sensor struct vbuffer history; }; -extern void -sensor_init (int lower_bound, int upper_bound, struct sensor *s); +extern void sensor_init (int lower_bound, int upper_bound, struct sensor *s); /* Latch current sensor value for S in its history buffer. */ -extern void -sensor_sample (struct sensor *s); +extern void sensor_sample (struct sensor *s); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h index 0c524bee8..adc477ebd 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h @@ -1,9 +1,8 @@ #ifndef SIMPLE_POOLS_H -# define SIMPLE_POOLS_H +#define SIMPLE_POOLS_H -# include "slists.h" +#include "slists.h" -extern struct sensor_node * -pool_allocate (void); +extern struct sensor_node *pool_allocate (void); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c index 1474da99e..6caa1d80f 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c @@ -12,7 +12,7 @@ slist_init (struct sensor_list *l) void slist_prepend (struct sensor *s, struct sensor_list *l) { - struct sensor_node * const node = pool_allocate (); + struct sensor_node *const node = pool_allocate (); node->s = s; node->next = l->head; l->head = node; diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h index 336f40d1e..66895103e 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h @@ -1,8 +1,8 @@ #ifndef SLISTS_H -# define SLISTS_H +#define SLISTS_H -# include "vbufs.h" -# include "sensors.h" +#include "sensors.h" +#include "vbufs.h" struct sensor_node; @@ -18,10 +18,8 @@ struct sensor_list unsigned len; }; -extern void -slist_init (struct sensor_list *l); +extern void slist_init (struct sensor_list *l); -extern void -slist_prepend (struct sensor *s, struct sensor_list *l); +extern void slist_prepend (struct sensor *s, struct sensor_list *l); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c index e07355d54..713fa1dab 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c @@ -14,11 +14,12 @@ vbuffer_push (int value, struct vbuffer *vbuf) /* Shift right, insert at first position the given VALUE and adjust length. */ - for (i = vbuf->size - 1; i > 0; --i) // # PU_loop0 + for (i = vbuf->size - 1; i > 0; --i) // # PU_loop0 { - if (i < vbuf->size - 1) // # PU_tshift - vbuf->store[i] = vbuf->store[i - 1]; // # PU_shift + if (i < vbuf->size - 1) // # PU_tshift + vbuf->store[i] = vbuf->store[i - 1]; // # PU_shift } - vbuf->store[0] = value; // # PU_update - vbuf->len = (vbuf->len < vbuf->size) ? (vbuf->len + 1) : vbuf->len; // # PU_update + vbuf->store[0] = value; // # PU_update + vbuf->len + = (vbuf->len < vbuf->size) ? (vbuf->len + 1) : vbuf->len; // # PU_update } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h index 3ffb9e2e3..396da43bf 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h @@ -1,7 +1,7 @@ #ifndef VBUFS_H -# define VBUFS_H +#define VBUFS_H -# define HIST_SIZE 10 +#define HIST_SIZE 10 struct vbuffer { @@ -10,10 +10,8 @@ struct vbuffer unsigned len; /* Number of filled entries. */ }; -extern void -vbuffer_init (struct vbuffer *vbuf); +extern void vbuffer_init (struct vbuffer *vbuf); -extern void -vbuffer_push (int value, struct vbuffer *vbuf); +extern void vbuffer_push (int value, struct vbuffer *vbuf); #endif diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt index c0edc3122..141860657 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt @@ -1,2 +1,2 @@ -src-traces,native DEAD Binary traces specific testcase -7.1.2 DEAD test GPR file attributes that were not supported in 7.1.2 \ No newline at end of file +src-traces DEAD Binary traces specific testcase +7.1.2 DEAD test GPR file attributes that were not supported in 7.1.2 diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py index c1ee12eab..6b40c6be2 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py @@ -11,42 +11,54 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xrun, - xcov) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xrun, + xcov, +) -gprname = 'p' -mainbase = 'foo' -mainunit = mainbase + '.adb' +gprname = "p" +mainbase = "foo" +mainunit = mainbase + ".adb" env = Env() target = env.target.triplet -Wdir('wd_') +Wdir("tmp_") # Get a template for the project file. -gpr_filename = gprfor(prjid=gprname, mains=[mainunit], - srcdirs=['../..'], - langs=["Ada"], - extra='for Target use "%TARGET%"; %RUNTIME%') +gpr_filename = gprfor( + prjid=gprname, + mains=[mainunit], + srcdirs=["../.."], + langs=["Ada"], + extra='for Target use "%TARGET%"; %RUNTIME%', +) gpr_filename = os.path.abspath(gpr_filename) gpr_basename = os.path.basename(gpr_filename) gpr_content = contents_of(gpr_filename) def instantiate_gpr(target): - with open(gpr_basename, 'w') as f: - content = gpr_content.replace('%TARGET%', target) + with open(gpr_basename, "w") as f: + content = gpr_content.replace("%TARGET%", target) content = content.replace( - '%RUNTIME%', - 'for Runtime ("Ada") use "{}";'.format(thistest.options.RTS) - if thistest.options.RTS else '' + "%RUNTIME%", + ( + 'for Runtime ("Ada") use "{}";'.format(thistest.options.RTS) + if thistest.options.RTS + else "" + ), ) f.write(content) -for mode in ('no_arg', 'with_arg'): - wd = Wdir('wd_{}'.format(mode)) +for mode in ("no_arg", "with_arg"): + wd = Wdir("tmp_{}".format(mode)) exe = exepath_to(mainbase) trace = tracename_for(mainbase) @@ -55,28 +67,26 @@ def instantiate_gpr(target): instantiate_gpr(target) gprbuild(os.path.abspath(gpr_basename)) - argv = ['-P{}'.format(gprname), '-o', trace, exe] + argv = ["-P{}".format(gprname), "-o", trace, exe] # Run with a bad target as the Target attribute in order to check that the # --target argument actually takes precedence. - with_target_arg = mode == 'with_arg' + with_target_arg = mode == "with_arg" if with_target_arg: - instantiate_gpr('this_target_does_not_exist') + instantiate_gpr("this_target_does_not_exist") # Force the passing of --target in the native case, as xrun() does not # pass it when it is the default. if not env.is_cross: - argv.append('--target={}'.format(target)) + argv.append("--target={}".format(target)) - xrun(argv, - auto_config_args=False, - auto_target_args=with_target_arg) + xrun(argv, auto_config_args=False, auto_target_args=with_target_arg) - dump = 'dump.txt' - xcov('dump-trace {}'.format(trace), out=dump) + dump = "dump.txt" + xcov("dump-trace {}".format(trace), out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with exe, no block execution trace found in {}'.format(trace) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with exe, no block execution trace found in {}".format(trace), ) wd.to_homedir() diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst index 656225b46..a0dd90ef8 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst @@ -1,8 +1,6 @@ Requirements for Target and Runtime attributes ==================================================== -%REQ_ID% - For cross configurations, unless an explicit :option:`--target` or :option:`--RTS` option is provided on the command line, the tool shall assume their respective values from a :option:`Target` or a diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb index 02ee09365..6714556e2 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb @@ -12,4 +12,3 @@ begin Assert (N_LT0 = 1); Assert (N_GE0 = 0); end; - diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py index cf59bede7..ce18e2547 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import gprfor, xcov -pgm = 'test_lt0' +pgm = "test_lt0" def run(subdir, extra_args, covlevel=None): @@ -19,17 +19,23 @@ def run(subdir, extra_args, covlevel=None): dirname = f"tmp_{subdir}" wd = Wdir(dirname) - gpr = gprfor(mains=[pgm + '.adb'], - srcdirs=['../src'], - extra=gprcov_for(switches=[ - Csw('*', ['--level=stmt']), - Csw('coverage', ['--annotate=report'])])) + gpr = gprfor( + mains=[pgm + ".adb"], + srcdirs=["../src"], + extra=gprcov_for( + switches=[ + Csw("*", ["--level=stmt"]), + Csw("coverage", ["--annotate=report"]), + ] + ), + ) xcov_args = build_and_run( gprsw=GPRswitches(root_project=gpr), covlevel=covlevel, mains=[pgm], - extra_coverage_args=[] if covlevel is None else ['--level', covlevel]) + extra_coverage_args=[] if covlevel is None else ["--level", covlevel], + ) xcov(xcov_args + extra_args) wd.to_homedir() @@ -39,44 +45,58 @@ def run(subdir, extra_args, covlevel=None): def check_report(label, filename, pattern, check_present=True): report = contents_of(filename) matched = re.search(pattern, report) - thistest.fail_if(not matched if check_present else matched, - label) + thistest.fail_if(not matched if check_present else matched, label) # Check that we get results corresponding to the project file # defaults if we don't tell anything otherwise. -subdir = run("default", ['-o', 'def.rep']) +subdir = run("default", ["-o", "def.rep"]) def_rep = os.path.join(subdir, "def.rep") # Check that we have the output report, that it does contain at least a stmt # coverage violation note, and that it doesn't contain any DC related note. -check_report('missing expected stmt coverage failure indication', - def_rep, 'statement not executed') -check_report('unexpected decision coverage failure indication', - def_rep, 'decision outcome .* never exercised', - check_present=False) +check_report( + "missing expected stmt coverage failure indication", + def_rep, + "statement not executed", +) +check_report( + "unexpected decision coverage failure indication", + def_rep, + "decision outcome .* never exercised", + check_present=False, +) # Override --level up to DC. Check that we now find the DC violations we # expect. -subdir = run("lev", ['-o', 'lev.rep'], covlevel='stmt+decision') +subdir = run("lev", ["-o", "lev.rep"], covlevel="stmt+decision") lev_rep = os.path.join(subdir, "lev.rep") -check_report('missing expected decision coverage failure indication', - lev_rep, 'decision outcome .* never exercised') +check_report( + "missing expected decision coverage failure indication", + lev_rep, + "decision outcome .* never exercised", +) # Override --annotate only. Expect full coverage on the "if" # statement. -subdir = run("ann", ['--annotate=xcov']) -check_report('missing expected full coverage indication', - os.path.join(subdir, "obj", "values.adb.xcov"), r'\+:.*if') +subdir = run("ann", ["--annotate=xcov"]) +check_report( + "missing expected full coverage indication", + os.path.join(subdir, "obj", "values.adb.xcov"), + r"\+:.*if", +) # Override --annotate and --level. Expect partial coverage on the "if" # statement. -subdir = run("lev-ann", ['--annotate=xcov'], covlevel='stmt+decision') -check_report('missing expected partial decision coverage indication', - os.path.join(subdir, "obj", "values.adb.xcov"), '!:.*if') +subdir = run("lev-ann", ["--annotate=xcov"], covlevel="stmt+decision") +check_report( + "missing expected partial decision coverage indication", + os.path.join(subdir, "obj", "values.adb.xcov"), + "!:.*if", +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py index a6c95a448..0ca37d0b5 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py @@ -9,21 +9,24 @@ # Check correctness of transmission from Switches to commands for a few # particular commands. Check that Switches ("*") comes before Switches (cmd). -wd = Wdir('wd_') +wd = Wdir("tmp_") # We will be exercising combinations of run/coverage operations with option # variations controlled via Coverage attributes in an otherwise common project # file for a simple program. -def gprvariant(id, extra): - return gprfor(prjid=id, srcdirs=['../src'], mains=['p.adb'], extra=extra) +def gprvariant(prjid, extra): + return gprfor( + prjid=prjid, srcdirs=["../src"], mains=["p.adb"], extra=extra + ) -exe = exepath_to('p') + +exe = exepath_to("p") # Build once -gprbuild(gprvariant(id='bld', extra='')) +gprbuild(gprvariant(prjid="bld", extra="")) # ------------------------------------------------ # -- Simple helpers for coverage/run variations -- @@ -33,114 +36,145 @@ def gprvariant(id, extra): # --annotate, valid only for gnatcov coverage. -def tag_for(id): - return 'tag-%s' % id +def tag_for(prjid): + return "tag-%s" % prjid -def tagopt_for(id): - return ['--tag=%s' % tag_for(id)] +def tagopt_for(prjid): + return ["--tag=%s" % tag_for(prjid)] -def rep_for(id): - return '%s.rep' % id +def rep_for(prjid): + return "%s.rep" % prjid -def annopt_for(id): - return ['--annotate=report'] +def annopt_for(prjid): + return ["--annotate=report"] # level expected to be assessed eventually, always -lev = 'stmt+decision' +lev = "stmt+decision" -def levopt_for(id): - return ['--level=%s' % lev] +def levopt_for(prjid): + return ["--level=%s" % lev] -def try_run(id, gpr): +def try_run(prjid, gpr): """gnatcov run with common set of options & variations via gpr.""" - log = id + '.rlog' - xrun(['-P%s' % gpr, exe, '-o', '%s.trace' % id], - out=log, register_failure=False) + log = prjid + ".rlog" + xrun( + ["-P%s" % gpr, exe, "-o", "%s.trace" % prjid], + out=log, + register_failure=False, + ) return contents_of(log) -def try_cov(id, gpr): +def try_cov(prjid, gpr): """ gnatcov coverage with common set of options & variations via gpr. Expect valid options and check for commonly expected outcome """ - log = id + '.clog' - xcov(['coverage', '-P%s' % gpr, '%s.trace' % id, '-o', rep_for(id)], - out=log, register_failure=False) + log = prjid + ".clog" + xcov( + ["coverage", "-P%s" % gpr, "%s.trace" % prjid, "-o", rep_for(prjid)], + out=log, + register_failure=False, + ) # Check that we get a report with expected contents wrt options # eventually. The tag & level checks make sure that # # * options intended for run do get there and not to coverage # * options intended for coverage do get there and not to run - thistest.fail_if(not empty(log), 'unexpected contents in %s' % log) + thistest.fail_if(not empty(log), "unexpected contents in %s" % log) - rep = contents_of(rep_for(id)) - thistest.fail_if('level: %s' % lev not in rep, - 'missing expected level indication in %s' % rep_for(id)) + rep = contents_of(rep_for(prjid)) + thistest.fail_if( + "level: %s" % lev not in rep, + "missing expected level indication in %s" % rep_for(prjid), + ) - thistest.fail_if(not re.search('tag.*: %s' % tag_for(id), rep), - 'missing expected tag indication in %s' % rep_for(id)) + thistest.fail_if( + not re.search("tag.*: %s" % tag_for(prjid), rep), + "missing expected tag indication in %s" % rep_for(prjid), + ) -def check_valid_sequence_for(id, gprcov): +def check_valid_sequence_for(prjid, gprcov): """ Common checking sequence for a specific gpr coverage package with valid options for both run and coverage. """ - gpr = gprvariant(id=id, extra=gprcov) - try_run(id, gpr) - try_cov(id, gpr) + gpr = gprvariant(prjid=prjid, extra=gprcov) + try_run(prjid, gpr) + try_cov(prjid, gpr) # Basic check for starters. No "*". -id = 'basic' +prjid = "basic" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('run', tagopt_for(id)), - Csw('coverage', levopt_for(id) + annopt_for(id)) - ])) + prjid=prjid, + gprcov=gprcov_for( + switches=[ + Csw("run", tagopt_for(prjid)), + Csw("coverage", levopt_for(prjid) + annopt_for(prjid)), + ] + ), +) # Check that "*" applies to all. Pass --level there. -id = 'star_valid' +prjid = "star_valid" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('*', levopt_for(id)), - Csw('run', tagopt_for(id)), - Csw('coverage', annopt_for(id)) - ])) + prjid=prjid, + gprcov=gprcov_for( + switches=[ + Csw("*", levopt_for(prjid)), + Csw("run", tagopt_for(prjid)), + Csw("coverage", annopt_for(prjid)), + ] + ), +) # Check that command specific args prevail over "*", with "*" placed # before in the gpr file. -id = 'star_postover' +prjid = "star_postover" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('*', ['--level=stmt+mcdc']), - Csw('run', tagopt_for(id)), - Csw('coverage', levopt_for(id) + annopt_for(id))])) + prjid=prjid, + gprcov=gprcov_for( + switches=[ + Csw("*", ["--level=stmt+mcdc"]), + Csw("run", tagopt_for(prjid)), + Csw("coverage", levopt_for(prjid) + annopt_for(prjid)), + ] + ), +) # Likewise, with "*" placed after in the gpr file. -id = 'star_preover' +prjid = "star_preover" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('run', tagopt_for(id)), - Csw('coverage', levopt_for(id) + annopt_for(id)), - Csw('*', ['--level=stmt+mcdc'])])) + prjid=prjid, + gprcov=gprcov_for( + switches=[ + Csw("run", tagopt_for(prjid)), + Csw("coverage", levopt_for(prjid) + annopt_for(prjid)), + Csw("*", ["--level=stmt+mcdc"]), + ] + ), +) # Check that "*" applies to all. Pass invalid for run, check failure. -id = 'star_invalid' -gpr = gprvariant(id=id, extra=gprcov_for(switches=[Csw('*', annopt_for(id))])) -rlog = try_run(id, gpr) +prjid = "star_invalid" +gpr = gprvariant( + prjid=prjid, extra=gprcov_for(switches=[Csw("*", annopt_for(prjid))]) +) +rlog = try_run(prjid, gpr) thistest.fail_if( '--annotate is not valid with the "run" command.' not in rlog, - 'missing expected failure indication in run log for %s' % id) + "missing expected failure indication in run log for %s" % prjid, +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb index 02ee09365..6714556e2 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb @@ -12,4 +12,3 @@ begin Assert (N_LT0 = 1); Assert (N_GE0 = 0); end; - diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py index 0ea9858a0..2a28a1b94 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py @@ -8,43 +8,52 @@ from SUITE.tutils import gprfor -pgm = 'test_lt0' -wd = Wdir('wd_') +pgm = "test_lt0" +wd = Wdir("tmp_") # Build and run the single test program, which volontarily performs stmt and # decision coverage violations. # # Enforce --level=stmt+decision here. Check that Default_Switches in # subprojects are ignored -gpr = gprfor(mains=[pgm + '.adb'], - srcdirs=['../src'], - deps=['../App/app'], - extra=gprcov_for(switches=[ - Csw('*', ['--level=stmt+decision']), - Csw('coverage', ['--annotate=report'])])) +gpr = gprfor( + mains=[pgm + ".adb"], + srcdirs=["../src"], + deps=["../App/app"], + extra=gprcov_for( + switches=[ + Csw("*", ["--level=stmt+decision"]), + Csw("coverage", ["--annotate=report"]), + ] + ), +) build_run_and_coverage( gprsw=GPRswitches(root_project=gpr, no_subprojects=False), covlevel=None, mains=[pgm], - extra_coverage_args=['-o', 'def.rep']) + extra_coverage_args=["-o", "def.rep"], +) # Check that we get results corresponding to the root project file despite # "overrides" (other Switches) in subprojects. -rep = contents_of('def.rep') +rep = contents_of("def.rep") -thistest.fail_if(not os.path.exists('def.rep'), - "couldn't find default report") +thistest.fail_if(not os.path.exists("def.rep"), "couldn't find default report") -thistest.fail_if(not re.search('statement not executed', rep), - 'missing expected stmt coverage failure indication') +thistest.fail_if( + not re.search("statement not executed", rep), + "missing expected stmt coverage failure indication", +) thistest.fail_if( - not re.search(r'test.*\.adb:.*: decision outcome .* never exercised', rep), - 'missing expected decision coverage failure indication') + not re.search(r"test.*\.adb:.*: decision outcome .* never exercised", rep), + "missing expected decision coverage failure indication", +) thistest.fail_if( - not re.search('values.adb:.*: decision outcome .* never exercised', rep), - 'missing expected decision coverage failure indication') + not re.search("values.adb:.*: decision outcome .* never exercised", rep), + "missing expected decision coverage failure indication", +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst index 06afe0b77..d8c4d1831 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst @@ -1,8 +1,6 @@ Requirements for gnatcov command switches in project files ================================================================ -%REQ_ID% - The tool shall handle *Switches* attributes in the Coverage package of the root project file, indexed by gnatcov command name and where the value is a list of switch strings that could be passed to the gnatcov diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py index f4d98a17b..7970a2a79 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py @@ -5,38 +5,44 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir('wd_') +wd = Wdir("tmp_") # GPR with multiple mains -gprname = 'gen' -mainbases = ['test_tt', 'test_tf'] -mainunits = [base + '.adb' for base in mainbases] +gprname = "gen" +mainbases = ["test_tt", "test_tf"] +mainunits = [base + ".adb" for base in mainbases] -gprbuild(gprfor(prjid=gprname, - srcdirs=['../../../../src', '../../src'], - mains=mainunits)) +gprbuild( + gprfor( + prjid=gprname, + srcdirs=["../../../../src", "../../src"], + mains=mainunits, + ) +) # We expect this to work. The multiple mains in the gpr file are just ignored # when there is an exe on the command line. -exe = exepath_to('test_tt') -trace = 'tt.trace0' -dump = 'tt.dump0' +exe = exepath_to("test_tt") +trace = "tt.trace0" +dump = "tt.dump0" -xrun(['-P', gprname, '-o', trace, exe]) -xcov(['dump-trace', trace], out=dump) +xrun(["-P", gprname, "-o", trace, exe]) +xcov(["dump-trace", trace], out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with exe, no block execution trace found in %s' % trace) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with exe, no block execution trace found in %s" % trace, +) # Again, _not_ providing the executable. Expected to fail # from missing command line argument. -trace = 'oops.trace0' -dump = 'oops.dump' -xrun(['-P', gprname, '-o', trace], out=dump, register_failure=False) +trace = "oops.trace0" +dump = "oops.dump" +xrun(["-P", gprname, "-o", trace], out=dump, register_failure=False) thistest.fail_if( - not match(': Please specify an executable to run', dump), - 'missing expected error diag on main-less invocation of gnatcov run') + not match(": Please specify an executable to run", dump), + "missing expected error diag on main-less invocation of gnatcov run", +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py index 2f4fffadf..ba1f22dd2 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py @@ -5,22 +5,20 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir('wd_') +wd = Wdir("tmp_") # We have two candidate main drivers. Craft a gpr # with a Main attribute listing only the first one. -mainbase1 = 'test_tt' -mainunit1 = mainbase1 + '.adb' +mainbase1 = "test_tt" +mainunit1 = mainbase1 + ".adb" exe1 = exepath_to(mainbase1) -mainbase2 = 'test_tf' -mainunit2 = mainbase2 + '.adb' +mainbase2 = "test_tf" +mainunit2 = mainbase2 + ".adb" exe2 = exepath_to(mainbase2) -gprname = gprfor( - srcdirs=['../../../../src', '../../src'], - mains=[mainunit1]) +gprname = gprfor(srcdirs=["../../../../src", "../../src"], mains=[mainunit1]) # Build both executables, passing both main unit # names on the command line: @@ -32,22 +30,23 @@ # at least an entry showing actual execution of something # for this particular case. -def check(explicit_exe): +def check(explicit_exe): outbase = explicit_exe if explicit_exe else "noexe" - trace = '%s.trace' % outbase - dump = '%s.dt' % outbase + trace = "%s.trace" % outbase + dump = "%s.dt" % outbase - runcmd = ['-P', gprname, '-o', trace] + runcmd = ["-P", gprname, "-o", trace] if explicit_exe: runcmd.append(explicit_exe) xrun(runcmd) - xcov(['dump-trace', trace], out=dump) + xcov(["dump-trace", trace], out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with %s, no block trace entry found in %s' % (outbase, trace)) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with %s, no block trace entry found in %s" % (outbase, trace), + ) # With an explicit exe1, we just confirm what the Main attribute diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py index 615dd6301..c74718e87 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py @@ -5,28 +5,33 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir('wd_') +wd = Wdir("tmp_") # GPR without a main. # # We must provide the main executable on the command line. -gprname = 'tt_nomain' -mainbase = 'test_tf' -mainunit = mainbase + '.adb' +gprname = "tt_nomain" +mainbase = "test_tf" +mainunit = mainbase + ".adb" exe = exepath_to(mainbase) -gprbuild(gprfor(prjid=gprname, - srcdirs=['../../../../src', '../../src'], - mains='', - langs=['Ada']), - gargs=[mainunit]) +gprbuild( + gprfor( + prjid=gprname, + srcdirs=["../../../../src", "../../src"], + mains="", + langs=["Ada"], + ), + gargs=[mainunit], +) -trace = 'tf.trace0' -dump = 'tf.dump0' -xrun(['-P', gprname, exe, '-o', trace]) -xcov(['dump-trace', trace], out=dump) +trace = "tf.trace0" +dump = "tf.dump0" +xrun(["-P", gprname, exe, "-o", trace]) +xcov(["dump-trace", trace], out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with exe, no block execution trace found in %s' % trace) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with exe, no block execution trace found in %s" % trace, +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt b/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt index 1eff4a74a..4b804ae79 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt @@ -1 +1 @@ -src-traces,native DEAD Binary traces specific testcase +src-traces DEAD Binary traces specific testcase diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst b/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst index 530a6b606..86f2e64a9 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst @@ -1,8 +1,6 @@ Requirements for Main attributes in project files ======================================================= -%REQ_ID% - The gnatcov run command shall handle a Main attribute in the root project file. diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb b/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb index 22090ac7b..49cba2788 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb @@ -2,4 +2,3 @@ function Andthen (A, B : Boolean) return Boolean is begin return A and then B; end; - diff --git a/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py b/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py index a26aaad47..a331e1a0d 100644 --- a/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py +++ b/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py @@ -9,28 +9,31 @@ from SUITE.tutils import gprfor -wd = Wdir('wd_') +wd = Wdir("tmp_") -gprname = 'p' -mainunit = 'foo.adb' -subdir = 'gnatcov' -mainunit_xcov = os.path.join('obj', subdir, mainunit + '.xcov') +gprname = "p" +mainunit = "foo.adb" +subdir = "gnatcov" +mainunit_xcov = os.path.join("obj", subdir, mainunit + ".xcov") # Arrange to build, run and perform coverage analysis passing # --subdirs to all gprbuild and gnatcov commands, then verify that # we find a report in the designated subdir afterwards. build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(prjid=gprname, mains=[mainunit], - srcdirs=['..']), - subdirs=subdir), - covlevel='stmt', - mains=['foo'], - extra_coverage_args=['-a', 'xcov']) + gprsw=GPRswitches( + root_project=gprfor(prjid=gprname, mains=[mainunit], srcdirs=[".."]), + subdirs=subdir, + ), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["-a", "xcov"], +) thistest.fail_if( not os.path.exists(mainunit_xcov), - 'The coverage report is missing: {}'.format(mainunit_xcov)) + "The coverage report is missing: {}".format(mainunit_xcov), +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst b/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst index 86aae778d..d145efd77 100644 --- a/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst @@ -1,8 +1,6 @@ Requirements for the :option:`--subdirs` switch ===================================================== -%REQ_ID% - The tool shall handle the :option:`--subdirs` command line switch, following similar semantics as for gprbuild: with :option:`--subdir=`, everything which should normally be performed within a project's diff --git a/testsuite/Qualif/Common/GprFacilities/req_set.rst b/testsuite/Qualif/Common/GprFacilities/req_set.rst index 0f8d7bb5a..8bf6ade2e 100644 --- a/testsuite/Qualif/Common/GprFacilities/req_set.rst +++ b/testsuite/Qualif/Common/GprFacilities/req_set.rst @@ -21,5 +21,5 @@ This incurs a set of related requirements summarized in the following table: GnatcovSwitches MainAttr ConfigAttr - SubdirsSwitch + Subdirs diff --git a/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb b/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb index 57b0f1030..2140d4ff9 100644 --- a/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb +++ b/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb @@ -4,30 +4,30 @@ with Support, Expr; use Support, Expr; procedure Test_Expr_Full is begin -- cover and-then - + If_Andthen (True, False, 5); Assert (Expr.Value = 0); - + If_Andthen (False, True, 6); Assert (Expr.Value = 0); - + If_Andthen (False, False, 7); Assert (Expr.Value = 0); - + If_Andthen (True, True, 9); Assert (Expr.Value = 9); - + -- cover or-else - + If_Orelse (True, False, 5); Assert (Expr.Value = 5); - + If_Orelse (False, True, 6); Assert (Expr.Value = 6); - + If_Orelse (False, False, 7); Assert (Expr.Value = 6); - + If_Orelse (True, True, 9); Assert (Expr.Value = 9); end; diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb b/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb index 92ed7ac63..94885d748 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb @@ -15,9 +15,9 @@ package body Ranges is begin pragma Annotate -- # preValid (Xcov, Exempt_On, "expect no invalid ranges"); -- # preValid - if not (R1.Valid and then R2.Valid) then -- # preValid - N_Invalid_Inputs := N_Invalid_Inputs + 1; -- # preValid - return True; -- # preValid + if not (R1.Valid and then R2.Valid) then -- # preValid_if + N_Invalid_Inputs := N_Invalid_Inputs + 1; -- # preValid_inc + return True; -- # preValid_ret end if; -- # preValid pragma Annotate (Xcov, Exempt_Off); -- # preValid diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb index 5dfa0dfc9..8a2196429 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb @@ -17,7 +17,9 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ s=>l#, dum=>l* ## s=>x0, dum=>x+ +-- /preValid_if/ s=>l=, dum=>l= ## s=>X0, dum=>XoF- +-- /preValid_inc/ s=>l=, dum=>l= ## s=>X0, dum=>X0 +-- /preValid_ret/ s=>l=, dum=>l= ## s=>X0, dum=>X0 -- /checkOverlap/ l- ## s- -- /overlapTrue/ l- ## s- -- /overlapFalse/ l- ## s- - diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb index fa751f210..a1dfce5dc 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb @@ -40,7 +40,9 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_inc/ l= ## Xs- +-- /preValid_ret/ l= ## Xs- -- /checkOverlap/ l! ## dF- -- /overlapTrue/ l+ ## 0 -- /overlapFalse/ l- ## s- - diff --git a/testsuite/Qualif/Common/Report/Exemptions/test.opt b/testsuite/Qualif/Common/Report/Exemptions/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/test.opt +++ b/testsuite/Qualif/Common/Report/Exemptions/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Common/Report/req.rst b/testsuite/Qualif/Common/Report/req.rst index 1843edf34..8706fd4e5 100644 --- a/testsuite/Qualif/Common/Report/req.rst +++ b/testsuite/Qualif/Common/Report/req.rst @@ -1,8 +1,6 @@ Output report format ==================== -%REQ_ID% - The tool qualified output is the synthetic report produced by the :literal:`--annotate=report` command line option. The output report shall: diff --git a/testsuite/Qualif/Common/Report/src/expr.adb b/testsuite/Qualif/Common/Report/src/expr.adb index 7fa6f98bc..2536890b8 100644 --- a/testsuite/Qualif/Common/Report/src/expr.adb +++ b/testsuite/Qualif/Common/Report/src/expr.adb @@ -18,5 +18,3 @@ package body Expr is end; end; - - diff --git a/testsuite/Qualif/Common/Report/src/support.adb b/testsuite/Qualif/Common/Report/src/support.adb deleted file mode 100644 index e7e059c05..000000000 --- a/testsuite/Qualif/Common/Report/src/support.adb +++ /dev/null @@ -1,20 +0,0 @@ - -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - - function Identity (X : Integer) return Integer is - begin - return X; - end; - - function Identity (B : Boolean) return Boolean is - begin - return B; - end; -end; diff --git a/testsuite/Qualif/Common/Report/src/support.ads b/testsuite/Qualif/Common/Report/src/support.ads deleted file mode 100644 index f7482f2e1..000000000 --- a/testsuite/Qualif/Common/Report/src/support.ads +++ /dev/null @@ -1,6 +0,0 @@ - -package Support is - procedure Assert (Cond : Boolean); - function Identity (X : Integer) return Integer; - function Identity (B : Boolean) return Boolean; -end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst new file mode 100644 index 000000000..f794510eb --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst @@ -0,0 +1 @@ +**Check use of globbing patterns for unit names in external unit lists** diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py new file mode 100644 index 000000000..47a045d41 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py @@ -0,0 +1,17 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_file + +wd = Wdir() + +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops*"]), + units_out=["ops.orelse"], + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) + +thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst new file mode 100644 index 000000000..4ef7e27be --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst @@ -0,0 +1 @@ +**Check use of globbing patterns for unit names in Coverage attributes** diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py new file mode 100644 index 000000000..ad2099faf --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py @@ -0,0 +1,48 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.cutils import Wdir + + +wd = Wdir() + +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops*"], + xreports=[ + "ops.ads", + "ops.adb", + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) + +wd.to_subdir("tmp_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=["test*"], + xreports=[ + "ops.ads", + "ops.adb", + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) + +wd.to_subdir("tmp_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops*"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], + ) +) + +thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py index 19c8bfce6..44be424a9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py @@ -7,22 +7,30 @@ # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( - covcontrol=CovControl(ulist_in="../" + list_to_file(["ops"]), - xreports=["ops.ads", "ops.adb"])) + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops"]), xreports=["ops.ads", "ops.adb"] + ) +) # Check on lone node + child unit -wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - ulist_in="../" + list_to_file(["ops", "ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) +wd.to_subdir("tmp_2") +TestCase(category=None).run( + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops", "ops.andthen"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) # Check on lone child unit only -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( - covcontrol=CovControl(ulist_in="../" + list_to_file(["ops.andthen"]), - xreports=["ops-andthen.adb"])) + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops.andthen"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py index 7b12008d3..dfcf8bc81 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py @@ -7,24 +7,33 @@ wd = Wdir() # Remove a parent unit -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( - covcontrol=CovControl(ulist_in=list_to_tmp(["ops", "ops.andthen"]), - ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.adb"])) + covcontrol=CovControl( + ulist_in=list_to_tmp(["ops", "ops.andthen"]), + ulist_out=list_to_tmp(["ops"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) # Remove a child unit -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( - covcontrol=CovControl(ulist_in=list_to_tmp(["ops", "ops.andthen"]), - ulist_out=list_to_tmp(["ops.andthen"]), - xreports=["ops.ads", "ops.adb"])) + covcontrol=CovControl( + ulist_in=list_to_tmp(["ops", "ops.andthen"]), + ulist_out=list_to_tmp(["ops.andthen"]), + xreports=["ops.ads", "ops.adb"], + ) +) # Remove one that's not in -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( - covcontrol=CovControl(ulist_in=list_to_tmp(["ops", "ops.andthen"]), - ulist_out=list_to_tmp(["ops.orelse"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) + covcontrol=CovControl( + ulist_in=list_to_tmp(["ops", "ops.andthen"]), + ulist_out=list_to_tmp(["ops.orelse"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py index c3cebaf70..5b2e3d2d9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py @@ -3,26 +3,41 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, list_to_file -base_out = ["support", "test_or_ft", "test_and_tt", "test_and_tf"] +base_out = ["test_or_ft", "test_and_tt", "test_and_tf"] wd = Wdir() # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( - covcontrol=CovControl(ulist_out="../" + list_to_file(base_out + ["ops"]), - xreports=["ops-andthen.adb", "ops-orelse.adb"])) + covcontrol=CovControl( + ulist_out="../" + list_to_file(base_out + ["ops"]), + xreports=[ + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) # Check on child units only -wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - ulist_out="../" + list_to_file(base_out + ["ops.orelse", "ops.andthen"]), - xreports=["ops.ads", "ops.adb"])) +wd.to_subdir("tmp_2") +TestCase(category=None).run( + covcontrol=CovControl( + ulist_out="../" + + list_to_file(base_out + ["ops.orelse", "ops.andthen"]), + xreports=["ops.ads", "ops.adb"], + ) +) # Check on root + child unit -wd.to_subdir("wd_3") -TestCase(category=None).run(covcontrol=CovControl( - ulist_out="../" + list_to_file(base_out + ["ops", "ops.andthen"]), - xreports=["ops-orelse.adb"])) +wd.to_subdir("tmp_3") +TestCase(category=None).run( + covcontrol=CovControl( + ulist_out="../" + list_to_file(base_out + ["ops", "ops.andthen"]), + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py index 191ebc8e8..c24c71588 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py @@ -6,10 +6,13 @@ # Mixing units and lists to include wd = Wdir() -wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops"], - ulist_in=list_to_tmp(["ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops"], + ulist_in=list_to_tmp(["ops.andthen"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py index 23c892224..c4ba3b654 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py @@ -6,15 +6,21 @@ # Mixing units and lists to include / exclude wd = Wdir() -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( - covcontrol=CovControl(units_in=["ops", "ops.andthen"], - ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.adb"])) + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + ulist_out=list_to_tmp(["ops"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) TestCase(category=None).run( - covcontrol=CovControl(units_in=["ops", "ops.andthen"], - units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb"])) + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py index dafdda2f3..f8dade53e 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py @@ -5,29 +5,43 @@ # Mixing units and lists to exclude -base_out = ["support", "test_or_ft", "test_and_tt", "test_and_tf"] +base_out = ["test_or_ft", "test_and_tt", "test_and_tf"] wd = Wdir() # Check on lone node unit only -wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out, - ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.adb", "ops-orelse.adb"])) +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out, + ulist_out=list_to_tmp(["ops"]), + xreports=[ + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) # Check on child units only -wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out, - ulist_out=list_to_tmp(["ops.orelse", "ops.andthen"]), - xreports=["ops.ads", "ops.adb"])) +wd.to_subdir("tmp_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out, + ulist_out=list_to_tmp(["ops.orelse", "ops.andthen"]), + xreports=["ops.ads", "ops.adb"], + ) +) # Check on root + child unit -wd.to_subdir("wd_3") -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out, - ulist_out=list_to_tmp(["ops", "ops.andthen"]), - xreports=["ops-orelse.adb"])) +wd.to_subdir("tmp_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out, + ulist_out=list_to_tmp(["ops", "ops.andthen"]), + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py index e434a639d..357a2791f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py @@ -7,21 +7,27 @@ wd = Wdir() # Check on lone node unit only -wd.to_subdir('wd_1') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops'], - xreports=['ops.ads', 'ops.adb'])) +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl(units_in=["ops"], xreports=["ops.ads", "ops.adb"]) +) # Check on lone node + child unit -wd.to_subdir('wd_2') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops', 'ops.andthen'], - xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb'])) +wd.to_subdir("tmp_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) # Check on lone child unit only -wd.to_subdir('wd_3') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops.andthen'], - xreports=['ops-andthen.adb'])) +wd.to_subdir("tmp_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops.andthen"], + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py index d366c4ea8..9e3b726b4 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py @@ -12,23 +12,32 @@ # Out empty (In only) out is another testcase # Out overlaps In -wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops", "ops.andthen"], - units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb"])) - -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops", "ops.andthen", "ops.orelse"], - units_out=["ops", "ops.andthen"], - xreports=["ops-orelse.adb"])) +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb"], + ) +) + +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.andthen", "ops.orelse"], + units_out=["ops", "ops.andthen"], + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) # Out does not overlap In -wd.to_subdir("wd_2") - -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops", "ops.orelse"], - units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb", "ops-orelse.adb"])) +wd.to_subdir("tmp_2") + +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.orelse"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py index cabb34f9b..9942bc17e 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py @@ -4,25 +4,39 @@ from SUITE.cutils import Wdir -base_out = ['support', 'test_or_ft', 'test_and_tt', 'test_and_tf'] +base_out = ["test_or_ft", "test_and_tt", "test_and_tf"] wd = Wdir() # Check on lone node unit only -wd.to_subdir('wd_1') -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out + ['ops'], - xreports=['ops-andthen.adb', 'ops-orelse.adb'])) +wd.to_subdir("tmp_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out + ["ops"], + xreports=[ + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) # Check on child units only -wd.to_subdir('wd_2') -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out + ['ops.orelse', 'ops.andthen'], - xreports=['ops.ads', 'ops.adb'])) +wd.to_subdir("tmp_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out + ["ops.orelse", "ops.andthen"], + xreports=["ops.ads", "ops.adb"], + ) +) # Check on root + child unit -wd.to_subdir('wd_3') -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out + ['ops', 'ops.andthen'], - xreports=['ops-orelse.adb'])) +wd.to_subdir("tmp_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out + ["ops", "ops.andthen"], + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb index b9e6640a9..d3e0403ad 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb @@ -15,5 +15,3 @@ end; --# ops-orelse.adb -- /eval/ l- ## s- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb index 5239647fa..d53965446 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb @@ -15,5 +15,3 @@ end; --# ops-orelse.adb -- /eval/ l- ## s- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb index 7292a72f8..6d428f3ec 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb @@ -15,5 +15,3 @@ end; --# ops-orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py index c960dc87f..b74ff2ee0 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py @@ -10,9 +10,10 @@ # expect intops, boolops and conters related reports check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=None, - xreports=['intops', 'boolops', 'counters']) + xreports=["intops", "boolops", "counters"], +) # -Pgen, non recursive would yield an empty set of # units of interest, so try another level first: @@ -21,18 +22,20 @@ # expect intops and counters related reports check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=None, - xreports=['intops', 'counters']) + xreports=["intops", "counters"], +) # -Pgen --projects=intops --no-subprojects # expect intops related report only check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=False, - xreports=['intops']) + xreports=["intops"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py index 210645f48..4cf1d3770 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py @@ -5,26 +5,29 @@ # expect intops, boolops & counters reports check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - xreports=['intops', 'boolops', 'counters']) + xreports=["intops", "boolops", "counters"], +) # -Pgen --projects=intops.gpr, recursive, # expect intops & counters reports check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=True, - xreports=['intops', 'counters']) + xreports=["intops", "counters"], +) # -Pgen --projects=boolops.gpr, recursive, # expect boolops & counters reports check( - root_project='gen.gpr', - projects=['boolops'], + root_project="gen.gpr", + projects=["boolops"], recurse=True, - xreports=['boolops', 'counters']) + xreports=["boolops", "counters"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py index 2ec633226..cf7be0892 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py @@ -5,36 +5,40 @@ # expect intops related reports only check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=False, - xreports=['intops']) + xreports=["intops"], +) # -Pgen --projects=boolops.gpr, not recursive, # expect boolops related reports only check( - root_project='gen.gpr', - projects=['boolops'], + root_project="gen.gpr", + projects=["boolops"], recurse=False, - xreports=['boolops']) + xreports=["boolops"], +) -# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recusrive +# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recursive # expect boolops & intops related reports check( - root_project='gen.gpr', - projects=['boolops', 'intops'], + root_project="gen.gpr", + projects=["boolops", "intops"], recurse=False, - xreports=['boolops', 'intops']) + xreports=["boolops", "intops"], +) -# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recusrive +# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recursive # expect boolops & counters related reports check( - root_project='gen.gpr', - projects=['boolops', 'counters'], + root_project="gen.gpr", + projects=["boolops", "counters"], recurse=False, - xreports=['boolops', 'counters']) + xreports=["boolops", "counters"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py index d072808be..0c1744977 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py @@ -9,7 +9,7 @@ # Create a directory to hold temporary files, so that we do not accumulate # uncleaned temporary files across testsuite runs. -temp_file_dir = Wdir('tmp_files') +temp_file_dir = Wdir("tmp_files") temp_file_dir.to_homedir() # Note that intops involves sub-units while boolops involves child-units, @@ -17,42 +17,53 @@ # Lone unit, with sub units, in closure check( - root_project='gen.gpr', - units=['intops'], + root_project="gen.gpr", + units=["intops"], recurse=True, - xreports=['intops.ads', 'intops.adb', - 'intops-add.adb', 'intops-sub.adb']) + xreports=[ + "intops.ads", + "intops.adb", + "intops-add.ads", + "intops-add.adb", + "intops-sub.ads", + "intops-sub.adb", + ], +) # Lone unit, with child units, in closure check( - root_project='../boolops/boolops', - units=['boolops'], + root_project="../boolops/boolops", + units=["boolops"], recurse=True, - xreports=['boolops.ads', 'boolops.adb']) + xreports=["boolops.ads", "boolops.adb"], +) # Likewise, using a response file to convey the units. check( - root_project='../boolops/boolops', - units=['@%s' % list_to_tmp(['boolops'], dir='tmp_files')], + root_project="../boolops/boolops", + units=["@%s" % list_to_tmp(["boolops"], dirname="tmp_files")], recurse=True, - xreports=['boolops.ads', 'boolops.adb']) + xreports=["boolops.ads", "boolops.adb"], +) # Lone child unit from single project, either from -P + --projects # or from a -P designating the subproject directly check( - root_project='../boolops/boolops', - units=['boolops.andthen'], + root_project="../boolops/boolops", + units=["boolops.andthen"], recurse=False, - xreports=['boolops.ads', 'boolops-andthen.adb']) + xreports=["boolops.ads", "boolops-andthen.ads", "boolops-andthen.adb"], +) check( - root_project='gen.gpr', - projects=['boolops'], - units=['boolops.andthen'], + root_project="gen.gpr", + projects=["boolops"], + units=["boolops.andthen"], recurse=False, - xreports=['boolops.ads', 'boolops-andthen.adb']) + xreports=["boolops.ads", "boolops-andthen.ads", "boolops-andthen.adb"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py index 3d120959a..4fab73d96 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py @@ -11,26 +11,29 @@ # Without --units, on closure -> everything check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - xreports=['intops', 'boolops', 'counters']) + xreports=["intops", "boolops", "counters"], +) # --units=boolops.andthen in closure, andthen and parent # spec reports only, despite the attribute in boolops.gpr check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - units=['boolops.andthen'], - xreports=['boolops.ads', 'boolops-andthen.adb']) + units=["boolops.andthen"], + xreports=["boolops.ads", "boolops-andthen.ads", "boolops-andthen.adb"], +) # --units=counters in closure, counters reports only # despite the attribute in boolops.gpr check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - units=['counters'], - xreports=['counters.ads', 'counters.adb']) + units=["counters"], + xreports=["counters.ads", "counters.adb"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb index de7eb6836..1d86e07e1 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb @@ -26,4 +26,3 @@ end; --# ../../intops/src/intops-sub.adb -- /eval/ l+ ## 0 - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py index e7dae6a78..02667dad6 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py @@ -8,7 +8,7 @@ from SCOV.tc import TestCase from SCOV.tctl import CovControl -from SUITE.control import env +from SUITE.control import env, gnatemu_board_name from SUITE.cutils import to_list, Wdir from SUITE.gprutils import GPRswitches @@ -17,11 +17,23 @@ # The set of source file names with coverage obligations attached to # each project, designated by project short name. _xreports = { - 'boolops': ['boolops.ads', 'boolops.adb', - 'boolops-andthen.adb', 'boolops-orelse.adb'], - 'intops': ['intops.ads', 'intops.adb', - 'intops-add.adb', 'intops-sub.adb'], - 'counters': ['counters.ads', 'counters.adb'], + "boolops": [ + "boolops.ads", + "boolops.adb", + "boolops-andthen.ads", + "boolops-andthen.adb", + "boolops-orelse.ads", + "boolops-orelse.adb", + ], + "intops": [ + "intops.ads", + "intops.adb", + "intops-add.ads", + "intops-add.adb", + "intops-sub.ads", + "intops-sub.adb", + ], + "counters": ["counters.ads", "counters.adb"], } all_projects = list(_xreports) @@ -59,25 +71,25 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): # Append the first letter of each project name will pass through # --project, if any: if projects: - label += '-' + ''.join(prj[0] for prj in projects) + label += "-" + "".join(prj[0] for prj in projects) # Append indication on recursion request: if recurse: - label += '-rt' + label += "-rt" elif recurse is None: - label += '-rn' + label += "-rn" else: - label += '-rf' + label += "-rf" # Arrange to execute each check in its own temporary directory and copying # shared projects in that directory prevent mixups across test variants. - tmpdir = f'wd_{label}' + tmpdir = f"tmp_{label}" wd = Wdir(tmpdir) # Copy shared projects in the temporary directory and create their object # directory to avoid spurious warnings. for p in all_projects: - sync_tree(os.path.join(wd.homedir, '..', p), p) + sync_tree(os.path.join(wd.homedir, "..", p), p) mkdir(os.path.join(p, "obj")) # If a list of expected reports is provided, convert into list of @@ -85,8 +97,7 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): if xreports is not None: ctl_xreports = [] for xr in xreports: - ctl_xreports.extend( - _xreports[xr] if xr in _xreports else [xr]) + ctl_xreports.extend(_xreports[xr] if xr in _xreports else [xr]) else: ctl_xreports = None @@ -96,23 +107,19 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): TestCase(category=None).run( covcontrol=CovControl( - # The programs we build and exercise always depend on the three # subprojects (copied above in the parent directory relative to the # TestCase temporary directory). - deps=[f'../{p}/{p}' for p in all_projects], - + deps=[f"../{p}/{p}" for p in all_projects], # What we analyse and check depends on our arguments: gprsw=GPRswitches( root_project=root_project, projects=projects, units=units, no_subprojects=no_subprojects, - xvars=[('BOARD', env.target.machine)], + xvars=[("BOARD", gnatemu_board_name(env.target.machine))], ), - xreports=ctl_xreports, - # The test driver and the likes are never of interest units_in=[], ), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads index 7cedd5bd6..6044b2e46 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads @@ -2,5 +2,3 @@ package Values is N_GE0, N_LT0 : Integer := 0; procedure Scan (X : Integer); end; - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb index 02ee09365..6714556e2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb @@ -12,4 +12,3 @@ begin Assert (N_LT0 = 1); Assert (N_GE0 = 0); end; - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py index 675277b1d..7fdcbe2c5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py @@ -1,4 +1,3 @@ - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.gprutils import GPRswitches @@ -6,21 +5,30 @@ from SUITE.tutils import gprfor -wd = Wdir('wd_') +wd = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=['test_lt0.adb'], - srcdirs=['../src'], - deps=['../App/app'])), - covlevel='stmt', - mains=['test_lt0'], - extra_args=['--projects=app_base'], - extra_coverage_args=['-axcov']) + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_lt0.adb"], srcdirs=["../src"], deps=["../App/app"] + ) + ), + covlevel="stmt", + mains=["test_lt0"], + extra_args=["--projects=app_base"], + extra_coverage_args=["-axcov"], +) # App_Base is extended by App; App overrides Coverage'Units so that only Values # (not Values.Aux) is selected. -check_xcov_reports('obj/*.xcov', { - 'obj/values.ads.xcov': {}, - 'obj/values.adb.xcov': {'+': {5, 6}, '-': {8}}}) +check_xcov_reports( + "obj", + { + "values.ads.xcov": {}, + "values.adb.xcov": {"+": {5, 6}, "-": {8}}, + }, + # See eng/das/cov/gnatcoverage#245 + discard_empty=False, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst index a64538622..88d3b5c5d 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst @@ -1,2 +1 @@ -**Check that sources in extended projects are considered when looking for -mains** +**Check that sources in extended projects are considered when looking for mains** diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py index 5f18ec6d4..5a3d14755 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py @@ -10,35 +10,45 @@ from SUITE.tutils import gprfor -wd = Wdir('wd_') +wd = Wdir("tmp_") # Prepare the two project files -p = gprfor(prjid='p', mains=['main1.adb'], srcdirs=['../src'], - objdir='obj-p') -ext_p = 'ext_p.gpr' -with open(ext_p, 'w') as f: - f.write(""" +p = gprfor(prjid="p", mains=["main1.adb"], srcdirs=["../src"], objdir="obj-p") +ext_p = "ext_p.gpr" +with open(ext_p, "w") as f: + f.write( + """ project Ext_P extends "{}" is for Source_Dirs use ("../ext-src"); for Object_Dir use "ext-obj"; for Exec_Dir use "."; for Main use ("main1.adb", "main2.adb"); end Ext_P; - """.format(p)) + """.format( + p + ) + ) build_run_and_coverage( gprsw=GPRswitches(root_project=ext_p), - covlevel='stmt', - mains=['main1', 'main2'], - gpr_obj_dir='ext-obj', - extra_coverage_args=['-axcov']) + covlevel="stmt", + mains=["main1", "main2"], + gpr_obj_dir="ext-obj", + extra_coverage_args=["-axcov"], +) # In blob.ads, we expect either '+' or '.' on everything, depending # on the toolchain. Let check_xcov_reports refine that. -check_xcov_reports('ext-obj/*.xcov', { - 'ext-obj/blob.ads.xcov': {}, - 'ext-obj/main1.adb.xcov': {'+': {5}}, - 'ext-obj/main2.adb.xcov': {'+': {5, 6}}}) +check_xcov_reports( + "ext-obj", + { + "blob.ads.xcov": {}, + "main1.adb.xcov": {"+": {5}}, + "main2.adb.xcov": {"+": {5, 6}}, + }, + # See eng/das/cov/gnatcoverage#245 + discard_empty=False, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py index e2c14694e..52fc4c43b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py @@ -12,34 +12,45 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("tmp_") # The "orig" project contains two units: "main" and "helper". The "ext" project # extends "orig" and overrides only the "helper" unit. # # Previously, gnatcov used to consider that the only unit of interest was # "helper". It now also consider that "main" is a unit of interest. -orig_prj = gprfor(prjid='orig', mains=['main.adb'], srcdirs='..') -ext_prj = 'ext.gpr' -with open(ext_prj, 'w') as f: - f.write(""" +orig_prj = gprfor(prjid="orig", mains=["main.adb"], srcdirs="..") +ext_prj = "ext.gpr" +with open(ext_prj, "w") as f: + f.write( + """ project Ext extends "{}" is for Source_Dirs use ("../src-ext"); for Object_Dir use "obj-ext"; end Ext; -""".format(orig_prj)) +""".format( + orig_prj + ) + ) build_run_and_coverage( gprsw=GPRswitches(root_project=ext_prj), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov'], - gpr_obj_dir='obj-ext', - gpr_exe_dir='obj-ext') - -check_xcov_reports('obj-ext/*.xcov', { - 'obj-ext/main.adb.xcov': {'+': {5}}, - 'obj-ext/helper.ads.xcov': {}, - 'obj-ext/helper.adb.xcov': {'+': {4}}}) + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + gpr_obj_dir="obj-ext", + gpr_exe_dir="obj-ext", +) + +check_xcov_reports( + "obj-ext", + { + "main.adb.xcov": {"+": {5}}, + "helper.ads.xcov": {}, + "helper.adb.xcov": {"+": {4}}, + }, + # See eng/das/cov/gnatcoverage#245 + discard_empty=False, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py index 6cabb480b..6c12ca7ce 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py @@ -5,7 +5,7 @@ from SCOV.minicheck import build_and_run from SUITE.context import thistest -from SUITE.control import env +from SUITE.control import env, gnatemu_board_name from SUITE.cutils import Wdir, lines_of from SUITE.gprutils import GPRswitches from SUITE.tutils import xcov @@ -14,9 +14,10 @@ import e3.fs -root_project = os.path.abspath('root.gpr') -board_arg = '-XBOARD={}'.format(env.target.machine) -wd = Wdir('wd_') +root_project = os.path.abspath("root.gpr") +board = gnatemu_board_name(env.target.machine) +board_arg = "-XBOARD={}".format(board) +wd = Wdir("tmp_") # Every project of interest is setup to feature a single unit named after the # project. Dumping the units of interest for a given analysis, with @@ -27,13 +28,17 @@ # --dump-units-to tests we need. cov_cmdline = build_and_run( - gprsw=GPRswitches(root_project=root_project), - mains=['root'], - covlevel='stmt', - gpr_obj_dir='../obj', - gpr_exe_dir='../obj', + gprsw=GPRswitches( + root_project=root_project, + xvars=[("BOARD", board)], + ), + mains=["root"], + covlevel="stmt", + gpr_obj_dir="../obj", + gpr_exe_dir="../obj", extra_args=[board_arg], - extra_coverage_args=[]) + extra_coverage_args=[], +) trace = cov_cmdline[-1] @@ -48,25 +53,35 @@ def check(options, xunits): # Compute the name of a unique output dir for the reports, # based on the options. - opt_str = ''.join( - [opt. - replace('--projects=', ''). - replace('root', 'r'). - replace('../', ''). - replace('.gpr', ''). - replace('_X=True', ''). - replace('--no-subprojects', 'ns'). - strip('-') - for opt in options]) - - odir = 'tmp_' + opt_str - ofile = os.path.join(odir, 'dump-units') - - xcov(['coverage', trace, '--level=stmt', '--annotate=xcov', - '--output-dir={}'.format(odir), - '--dump-units-to={}'.format(ofile), - board_arg] + options, - out='cov-' + opt_str + '.log') + opt_str = "".join( + [ + opt.replace("--projects=", "") + .replace("root", "r") + .replace("../", "") + .replace(".gpr", "") + .replace("_X=True", "") + .replace("--no-subprojects", "ns") + .strip("-") + for opt in options + ] + ) + + odir = "tmp_" + opt_str + ofile = os.path.join(odir, "dump-units") + + xcov( + [ + "coverage", + trace, + "--level=stmt", + "--annotate=xcov", + "--output-dir={}".format(odir), + "--dump-units-to={}".format(ofile), + board_arg, + ] + + options, + out="cov-" + opt_str + ".log", + ) # Primary check, from the list of units reported by --dump-units-to @@ -77,7 +92,8 @@ def check(options, xunits): runits != xunits, "for options '{}', reported list of units not as expected:\n" "expected: {}\n" - "obtained: {}".format(' '.join(options), xunits, runits)) + "obtained: {}".format(" ".join(options), xunits, runits), + ) # Secondary check, from the set of generated reports @@ -87,15 +103,17 @@ def check(options, xunits): # Map the report files to a set of units by stripping both the leading # subdir part and the extension. - runits = set( - os.path.basename(r).split('.')[0] for r in - e3.fs.ls(os.path.join(odir, '*.xcov'))) + runits = { + os.path.basename(r).split(".")[0] + for r in e3.fs.ls(os.path.join(odir, "*.xcov")) + } thistest.fail_if( runits != xunits, "for options '{}', list of units from reports not as expected:\n" "expected: {}\n" - "obtained: {}".format(' '.join(options), xunits, runits)) + "obtained: {}".format(" ".join(options), xunits, runits), + ) # -P alone, recursive or not @@ -103,22 +121,23 @@ def check(options, xunits): # No externally built -check(options=['-P', '../root.gpr'], - xunits=['root', 'ssa', 'a1', 'ssb', 'b1', 'common']) +check( + options=["-P", "../root.gpr"], + xunits=["root", "ssa", "a1", "ssb", "b1", "common"], +) -check(options=['-P', '../root.gpr', '--no-subprojects'], - xunits=['root']) +check(options=["-P", "../root.gpr", "--no-subprojects"], xunits=["root"]) -check(options=['-P', '../ssa.gpr'], - xunits=['ssa', 'a1', 'common']) +check(options=["-P", "../ssa.gpr"], xunits=["ssa", "a1", "common"]) -check(options=['-P', '../ssa.gpr', '--no-subprojects'], - xunits=['ssa']) +check(options=["-P", "../ssa.gpr", "--no-subprojects"], xunits=["ssa"]) # ssa externally built -check(options=['-P', '../root.gpr', '-XSSA_X=True'], - xunits=['root', 'a1', 'ssb', 'b1', 'common']) +check( + options=["-P", "../root.gpr", "-XSSA_X=True"], + xunits=["root", "a1", "ssb", "b1", "common"], +) # -P --projects, recursive or not @@ -127,40 +146,67 @@ def check(options, xunits): # No externally built # Recursive from single child of root, not including root -check(options=['-P', '../root.gpr', '--projects=ssa'], - xunits=['ssa', 'a1', 'common']) +check( + options=["-P", "../root.gpr", "--projects=ssa"], + xunits=["ssa", "a1", "common"], +) -check(options=['-P', '../root.gpr', '--projects=ssb'], - xunits=['ssb', 'b1', 'common']) +check( + options=["-P", "../root.gpr", "--projects=ssb"], + xunits=["ssb", "b1", "common"], +) # Non recursive from single child of root, not including root -check(options=['-P', '../root.gpr', '--projects=ssa', '--no-subprojects'], - xunits=['ssa']) +check( + options=["-P", "../root.gpr", "--projects=ssa", "--no-subprojects"], + xunits=["ssa"], +) -check(options=['-P', '../root.gpr', '--projects=ssb', '--no-subprojects'], - xunits=['ssb']) +check( + options=["-P", "../root.gpr", "--projects=ssb", "--no-subprojects"], + xunits=["ssb"], +) # Non recursive from multiple children of root, not including root -check(options=['-P', '../root.gpr', - '--projects=ssa', '--projects=ssb', - '--no-subprojects'], - xunits=['ssa', 'ssb']) - -check(options=['-P', '../root.gpr', - '--projects=ssa', '--projects=b1', - '--no-subprojects'], - xunits=['ssa', 'b1']) +check( + options=[ + "-P", + "../root.gpr", + "--projects=ssa", + "--projects=ssb", + "--no-subprojects", + ], + xunits=["ssa", "ssb"], +) + +check( + options=[ + "-P", + "../root.gpr", + "--projects=ssa", + "--projects=b1", + "--no-subprojects", + ], + xunits=["ssa", "b1"], +) # Non recursive including root -check(options=['-P', '../root.gpr', - '--projects=root', '--projects=ssb', - '--no-subprojects'], - xunits=['root', 'ssb']) +check( + options=[ + "-P", + "../root.gpr", + "--projects=root", + "--projects=ssb", + "--no-subprojects", + ], + xunits=["root", "ssb"], +) # ssb externally built -check(options=['-P', '../root.gpr', - '--projects=ssb', '-XSSB_X=True'], - xunits=['b1', 'common']) +check( + options=["-P", "../root.gpr", "--projects=ssb", "-XSSB_X=True"], + xunits=["b1", "common"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb new file mode 100644 index 000000000..0910aec41 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb @@ -0,0 +1,6 @@ +package body Ops.Andthen is + function Eval (A, B : Boolean) return Boolean is + begin + return A and then B; -- # eval + end; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads new file mode 100644 index 000000000..e947bdf97 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads @@ -0,0 +1,3 @@ +package Ops.Andthen is + function Eval (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb new file mode 100644 index 000000000..8c4df1b7e --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb @@ -0,0 +1,6 @@ +package body Ops.Orelse is + function Eval (A, B : Boolean) return Boolean is + begin + return A or else B; -- # eval + end; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads new file mode 100644 index 000000000..0720cc3c6 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads @@ -0,0 +1,3 @@ +package Ops.Orelse is + function Eval (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb new file mode 100644 index 000000000..51f3391b5 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb @@ -0,0 +1,13 @@ +with Ops.Andthen; with Ops.Orelse; + +package body Ops is + + function Eval (Op: Opkind; A, B : Boolean) return Boolean is + begin + case Op is + when Op_Andthen => return Ops.Andthen.Eval (A, B); -- # eval_and + when Op_Orelse => return Ops.Orelse.Eval (A, B); -- # eval_or + end case; + end; + +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads new file mode 100644 index 000000000..7d4925214 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads @@ -0,0 +1,5 @@ +package Ops is + type Opkind is (Op_Andthen, Op_Orelse); + + function Eval (Op: Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb new file mode 100644 index 000000000..ead063806 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb @@ -0,0 +1,17 @@ + +with Support, Ops; use Ops, Support; + +procedure Test_And_TF is +begin + Assert (Ops.Eval (Op_Andthen, True, False) = False); +end; + +--# ops/ops.adb +-- /eval_and/ l+ ## 0 +-- /eval_or/ l- ## s- + +--# ops/ops-andthen.adb +-- /eval/ l! ## eT- + +--# ops/ops-orelse.adb +-- /eval/ l- ## s- diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb new file mode 100644 index 000000000..b47b81e31 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb @@ -0,0 +1,17 @@ + +with Support, Ops; use Ops, Support; + +procedure Test_And_TT is +begin + Assert (Ops.Eval (Op_Andthen, True, True) = True); +end; + +--# ops/ops.adb +-- /eval_and/ l+ ## 0 +-- /eval_or/ l- ## s- + +--# ops/ops-andthen.adb +-- /eval/ l! ## eF- + +--# ops/ops-orelse.adb +-- /eval/ l- ## s- diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb new file mode 100644 index 000000000..f9ae2f35b --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb @@ -0,0 +1,17 @@ + +with Support, Ops; use Ops, Support; + +procedure Test_Or_FT is +begin + Assert (Ops.Eval (Op_Orelse, False, True) = True); +end; + +--# ops/ops.adb +-- /eval_and/ l- ## s- +-- /eval_or/ l+ ## 0 + +--# ops/ops-andthen.adb +-- /eval/ l- ## s- + +--# ops/ops-orelse.adb +-- /eval/ l! ## eF- diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst new file mode 100644 index 000000000..8c4defe4d --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst @@ -0,0 +1,21 @@ +**Check unit selection attributes in a non-root project** + +From a test dir where we have + + src/ops/ops.ad? + ops-andthen.ad? + ops-orelse.ad? + /test_*.adb + +Verify that the proper set of units is examined for +a variety of subtests for which we + +- Create an ops.gpr project with attributes to include + or exclude some of the units in src/ops, + +- Launch a testcase which will create it's own working dir and + it's own root project there, for which we setup an empty set of + units of interest. + +Check the selection of units in ops.gpr with a lone Units attribute, a +lone Excluded_Units attribute or a mix of the two. diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py new file mode 100644 index 000000000..4d93e1281 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -0,0 +1,63 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import gprcov_for + +wd = Wdir() + + +def check(subdir, opspkg, xreports): + wd.to_subdir(subdir) + + ops_gpr = gprfor(mains=[], prjid="ops", srcdirs="../src/ops", extra=opspkg) + + TestCase(category=None).run( + covcontrol=CovControl(deps=[ops_gpr], units_in=[], xreports=xreports) + ) + + +# ops.gpr: no attribute + +check( + opspkg="", + xreports=[ + "ops.adb", + "ops.ads", + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + subdir="tmp_1", +) + +# ops.gpr: for Units use ... + +check( + opspkg=gprcov_for(units_in=["ops.andthen"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + subdir="tmp_2", +) + +# ops.gpr: for Excluded_Units use ... + +check( + opspkg=gprcov_for(units_out=["ops.andthen"]), + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], + subdir="tmp_3", +) + +# ops.gpr: for Units use ... for Excluded_Units use ... + +check( + opspkg=gprcov_for( + units_in=["ops", "ops.orelse", "ops.andthen"], units_out=["ops.orelse"] + ), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + subdir="tmp_3", +) + + +thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index 1ecc98509..0e68908fb 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -9,25 +9,34 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor( - 'main.adb', - srcdirs='..', - extra=gprcov_for(units_in=['no_such_unit', 'main']))), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov']) + gprsw=GPRswitches( + root_project=gprfor( + "main.adb", + srcdirs="..", + extra=gprcov_for(units_in=["no_such_unit", "main"]), + ) + ), + covlevel="stmt", + mains=["main"], + tolerate_instrument_messages="no unit .* in project", + extra_coverage_args=["-axcov"], + tolerate_coverage_messages="no unit .* in project", +) -log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') +log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no unit no_such_unit in project gen (coverage.units attribute)', - contents_of(log_file).strip()) + "gnatcov output", + "warning: no unit no_such_unit in project gen (coverage.units attribute)", + contents_of(log_file).strip(), +) -check_xcov_reports('obj/*.xcov', {'obj/main.adb.xcov': {'+': {5}}}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index c4f1eecc6..a867d739b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -9,33 +9,41 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor('main.adb', srcdirs='..'), - units=['no_such_unit', 'main', 'helper.say_hello']), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov']) - -log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') + gprsw=GPRswitches( + root_project=gprfor("main.adb", srcdirs=".."), + units=["no_such_unit", "main", "helper.say_hello"], + ), + covlevel="stmt", + mains=["main"], + tolerate_instrument_messages="no unit .* in the projects of interest", + extra_coverage_args=["-axcov"], + tolerate_coverage_messages="no unit .* in the projects of interest", +) + +log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) # Split and re-join lines to avoid spurious CR/LF diffs on Windows. Also sort # lines, as the order in which these warnings is emitted is not deterministic. -log_lines = '\n'.join( +log_lines = "\n".join( sorted(line.rstrip() for line in contents_of(log_file).splitlines()) ).rstrip() thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no unit helper.say_hello (from --units) in the projects of' - ' interest' - '\nwarning: no unit no_such_unit (from --units) in the projects of' - ' interest', - log_lines) - -check_xcov_reports('obj/*.xcov', {'obj/main.adb.xcov': {'+': {5}}}) + "gnatcov output", + "warning: no unit helper.say_hello (from --units) in the projects of" + " interest" + "\nwarning: no unit no_such_unit (from --units) in the projects of" + " interest", + log_lines, +) + +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py index e24935c2b..ec9e513d5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py @@ -22,30 +22,32 @@ from SUITE.tutils import gprfor, xcov -tmp = Wdir('wd_') +tmp = Wdir("tmp_") xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor('main.adb', srcdirs='..')), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov']) + gprsw=GPRswitches(root_project=gprfor("main.adb", srcdirs="..")), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) # Unlike the compiler, "gnatcov instrument" processes source files in projects, # even when they are not in the closure of the main. Yet, we want to check that # gnatcov complains when the SID file is missing, so manually remove it, here. -if thistest.options.trace_mode == 'src': - rm(os.path.join('obj', 'helper.sid')) - what = 'SID' +if thistest.options.trace_mode == "src": + rm(os.path.join("obj", "helper.sid")) + what = "SID" else: - what = 'ALI' + what = "ALI" -log_file = 'coverage.log' -xcov(xcov_args, out=log_file) +log_file = "coverage.log" +xcov(xcov_args, out=log_file, tolerate_messages=".") thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no {} file found for unit helper'.format(what), - contents_of(log_file).strip()) + "gnatcov output", + "warning: no {} file found for unit helper".format(what), + contents_of(log_file).strip(), +) -check_xcov_reports('obj/*.xcov', {'obj/main.adb.xcov': {'+': {3}}}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {3}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index f468949a8..12ca54a28 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -3,6 +3,9 @@ of interest are emitted when expected. """ +import os.path +import glob + from e3.fs import mkdir from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -12,7 +15,7 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("tmp_") class ProjectConfig(object): @@ -22,21 +25,33 @@ class ProjectConfig(object): Coverage package must contain, and the rest (project name, dependencies and mains) is determined during the generation (see the generate method below). """ + def __init__(self, units_in=None, units_out=None): self.units_in = units_in self.units_out = units_out def generate(self, name, deps=(), mains=()): return gprfor( - prjid=name, mains=mains, langs=['Ada'], deps=deps, - srcdirs=['../../src-{}'.format(name)], - objdir='obj-{}'.format(name), - extra=gprcov_for(units_in=self.units_in, - units_out=self.units_out)) - - -def run_test(label, slug, main, helper, recursive, projects=[], units=[], - projects_warned=[], expected_cov_list=[]): + prjid=name, + mains=mains, + deps=deps, + srcdirs=["../../src-{}".format(name)], + objdir="obj-{}".format(name), + extra=gprcov_for(units_in=self.units_in, units_out=self.units_out), + ) + + +def run_test( + label, + slug, + main, + helper, + recursive, + projects=None, + units=None, + projects_warned=None, + expected_cov_list=None, +): """ Produce a coverage report for the given parameters and check the emitted warnings. @@ -47,52 +62,80 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], :param ProjectConfig main: Configuration for the "main" project. :param ProjectConfig helper: Configuration for the "helper" project. :param bool recursive: Whether to not pass --no-subprojects. - :param list[str] projects: List of projects to pass with --projects. - :param list[str] units: List of units to pass with --units. - :param list[str] projects_warned: List of projects for which we expected - warnings. + :param list[str] | None projects: List of projects to pass with --projects. + :param list[str] | None units: List of units to pass with --units. + :param list[str] | None projects_warned: List of projects for which we + expected warnings. :param expected_cov: List of expected coverage reports. """ - thistest.log('== [{}] {} =='.format(slug, label)) - tmp.to_subdir('wd_/{}'.format(slug)) + projects = projects or [] + units = units or [] + projects_warned = projects_warned or [] + expected_cov_list = expected_cov_list or [] - expected_output = '\n'.join( - 'warning: project {} provides no unit of interest' - .format(project) for project in projects_warned) + thistest.log("== [{}] {} ==".format(slug, label)) + tmp.to_subdir("tmp_/{}".format(slug)) + + expected_output = "\n".join( + "warning: project {} provides no unit of interest".format(project) + for project in projects_warned + ) # Generate projects for this test (see below for the description of each # project). - ProjectConfig().generate('empty') - helper.generate('helper') - main_prj = main.generate('main', deps=['empty', 'helper'], - mains=['main.adb']) - mkdir('obj-empty') - mkdir('obj-helper') - mkdir('obj-main') + ProjectConfig().generate("empty") + helper.generate("helper") + main_prj = main.generate( + "main", deps=["empty", "helper"], mains=["main.adb"] + ) + mkdir("obj-empty") + mkdir("obj-helper") + mkdir("obj-main") # Generate a coverage report for them build_run_and_coverage( - gprsw=GPRswitches(root_project=main_prj, - projects=projects, - units=units, - no_subprojects=not recursive), - covlevel='stmt', - mains=['main'], - gpr_obj_dir='obj-main', - extra_coverage_args=['-axcov']) - - log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') + gprsw=GPRswitches( + root_project=main_prj, + projects=projects, + units=units, + no_subprojects=not recursive, + ), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-main", + tolerate_instrument_messages="project .* provides no unit", + extra_coverage_args=["-axcov"], + tolerate_coverage_messages="project .* provides no unit", + ) + + log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" + ) thistest.fail_if_not_equal( - '[{}/{}] gnatcov output'.format(label, slug), + "[{}/{}] gnatcov output".format(label, slug), expected_output, - contents_of(log_file).strip()) + contents_of(log_file).strip(), + ) expected_cov = {} - for c in expected_cov_list: - expected_cov.update(c) - check_xcov_reports('obj-*/*.xcov', expected_cov) + if expected_cov_list: + for c in expected_cov_list: + expected_cov.update(c) + check_xcov_reports("obj-main", expected_cov) + + # Check that all xcov report files are created in obj-main (i.e. the root + # project). + xcov_files = glob.glob("obj-*/*.xcov") + extra_xcov_files = [ + f for f in xcov_files if os.path.dirname(f) != "obj-main" + ] + thistest.fail_if_not_equal( + "misplaced xcov report files", + "", + "\n".join(extra_xcov_files), + ) # For all testcases, we set up three projects: @@ -108,47 +151,56 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], # project of interest (--projects) unless not recursive (no warnings # are expected in this mode). The point of having this project loaded is to # check that indeed gnatcov does not warn about "empty". -main = {'obj-main/main.adb.xcov': {'+': {6, 7}}} -main_support = {'obj-main/main_support.adb.xcov': {'+': {3}}} -helper = {'obj-main/helper.adb.xcov': {'+': {5}}} -helper_support = {'obj-main/helper_support.adb.xcov': {'+': {3}}} +main = {"main.adb.xcov": {"+": {6, 7}}} +main_support = {"main_support.adb.xcov": {"+": {3}}} +helper = {"helper.adb.xcov": {"+": {5}}} +helper_support = {"helper_support.adb.xcov": {"+": {3}}} # Check when --units is passed # Pass both projects to --projects and only "main" to --units so that the # "helper" project has no unit of interest: gnatcov must warn about it. -run_test(label='--units present, no UoI in helper', slug='up1', - main=ProjectConfig(), - helper=ProjectConfig(), - projects=['main', 'helper'], - units=['main'], - projects_warned=['helper'], - expected_cov_list=[main], - recursive=False) +run_test( + label="--units present, no UoI in helper", + slug="up1", + main=ProjectConfig(), + helper=ProjectConfig(), + projects=["main", "helper"], + units=["main"], + projects_warned=["helper"], + expected_cov_list=[main], + recursive=False, +) # Pass both projects to --projects and both "main" and "h[ea]lper*" to --units. # The globbing pattern should match helper and helper_support. Both projects # have at least one unit of interest, so we expect no warning. -run_test(label='--units present, all projects have UoI', slug='up2', - main=ProjectConfig(), - helper=ProjectConfig(), - projects=['main', 'helper'], - units=['main', 'h[ea]lper*'], - projects_warned=[], - expected_cov_list=[main, helper, helper_support], - recursive=False) +run_test( + label="--units present, all projects have UoI", + slug="up2", + main=ProjectConfig(), + helper=ProjectConfig(), + projects=["main", "helper"], + units=["main", "h[ea]lper*"], + projects_warned=[], + expected_cov_list=[main, helper, helper_support], + recursive=False, +) # Only pass the root project (-P) in recursive mode and pass # "main" to --units. Even though "helper" is a project of interest, it does not # contain any unit of interest, yet we expect no warning in recursive mode. -run_test(label='--units present, no UoI in helper, recursive', slug='up3', - main=ProjectConfig(), - helper=ProjectConfig(), - units=['main'], - projects_warned=[], - expected_cov_list=[main], - recursive=True) +run_test( + label="--units present, no UoI in helper, recursive", + slug="up3", + main=ProjectConfig(), + helper=ProjectConfig(), + units=["main"], + projects_warned=[], + expected_cov_list=[main], + recursive=True, +) # Check when we don't pass --units @@ -156,35 +208,43 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], # Pass both projects to --projects, no --units argument and make "helper" have # an empty Coverage'Units attribute. "helper" has no unit of interest, but it # has an attribute, se we should not warn about it. -run_test(label='--units absent, no UoI in helper with Units', slug='ua1', - main=ProjectConfig(), - helper=ProjectConfig(units_in=[]), - projects=['main', 'helper'], - projects_warned=[], - expected_cov_list=[main, main_support], - recursive=False) +run_test( + label="--units absent, no UoI in helper with Units", + slug="ua1", + main=ProjectConfig(), + helper=ProjectConfig(units_in=[]), + projects=["main", "helper"], + projects_warned=[], + expected_cov_list=[main, main_support], + recursive=False, +) # Pass both projects to --projects, no --units argument and make "helper" have # one unit pattern in its Coverage'Units attribute. All projects have units of # interest, so no warning expected. -run_test(label='--units absent, no UoI in helper with Excluded_Units', - slug='ua2', - main=ProjectConfig(), - helper=ProjectConfig(units_out=['helper*']), - projects=['main', 'helper'], - projects_warned=[], - expected_cov_list=[main, main_support], - recursive=False) +run_test( + label="--units absent, no UoI in helper with Excluded_Units", + slug="ua2", + main=ProjectConfig(), + helper=ProjectConfig(units_out=["helper*"]), + projects=["main", "helper"], + projects_warned=[], + expected_cov_list=[main, main_support], + recursive=False, +) # Pass both projects to --projects in recursive mode, no --units # argument. All projects have units of interest and we are in recursive mode # anyway, so no warning expected. -run_test(label='--units absent, no UoI in helper, recursive', slug='ua3', - main=ProjectConfig(), - helper=ProjectConfig(), - projects_warned=[], - expected_cov_list=[main, main_support, helper, helper_support], - recursive=True) +run_test( + label="--units absent, no UoI in helper, recursive", + slug="ua3", + main=ProjectConfig(), + helper=ProjectConfig(), + projects_warned=[], + expected_cov_list=[main, main_support, helper, helper_support], + recursive=True, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb index be364586a..53d54bb47 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb @@ -4,4 +4,3 @@ begin exception when others => null; end; - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py index 7b0dfc039..b0846b6ac 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py @@ -13,46 +13,59 @@ def try_one_gpr(gpr, no_such): label = os.path.basename(os.getcwd()) - dump = 'xcov.out' + dump = "xcov.out" build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - covlevel='stmt', - mains=['p'], - extra_coverage_args=['-axcov'], + covlevel="stmt", + mains=["p"], + extra_coverage_args=["-axcov"], out=dump, - register_failure=False + register_failure=False, ) dump = contents_of(dump) expected_warning = ( - 'no unit {} in project gen (coverage.units attribute)'.format(no_such) - if no_such else 'no unit of interest') + "no unit {} in project gen (coverage.units attribute)".format(no_such) + if no_such + else "no unit of interest" + ) thistest.fail_if( expected_warning not in dump, - '[{}] missing warning on absence of specified unit'.format(label)) + "[{}] missing warning on absence of specified unit".format(label), + ) # Empty by specifying a single, non-existing unit in only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") try_one_gpr( - gpr=gprfor(srcdirs="../src", mains="p.adb", - extra=CovControl(units_in=["no_such_unit"]).gpr()), - no_such="no_such_unit") + gpr=gprfor( + srcdirs="../src", + mains="p.adb", + extra=CovControl(units_in=["no_such_unit"]).gpr(), + ), + no_such="no_such_unit", +) # Empty by excluding the only candidate unit -wd.to_subdir("wd_2") -try_one_gpr(gpr=gprfor(srcdirs="../src", mains="p.adb", - extra=CovControl(units_out=["p"]).gpr()), - no_such=None) +wd.to_subdir("tmp_2") +try_one_gpr( + gpr=gprfor( + srcdirs="../src", + mains="p.adb", + extra=CovControl(units_out=["p"]).gpr(), + ), + no_such=None, +) # Empty by including the empty set explicitly -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") try_one_gpr( gpr=gprfor( - srcdirs="../src", mains="p.adb", - extra=CovControl(units_in=[]).gpr()), - no_such=None) + srcdirs="../src", mains="p.adb", extra=CovControl(units_in=[]).gpr() + ), + no_such=None, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py index 0570c58f1..74f9a663b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py @@ -28,40 +28,52 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): """ wd.to_subdir(subdir) - gpr = gprfor(srcdirs="../src", mains="test_t.adb", - extra='\n'.join( - ['for Source_Files use', - ' ("test_t.adb","flip.ads", "flip.adb");'])) + gpr = gprfor( + srcdirs="../src", + mains="test_t.adb", + extra="\n".join( + [ + "for Source_Files use", + ' ("test_t.adb","flip.ads", "flip.adb");', + ] + ), + ) build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - covlevel='stmt', - mains=['test_t'], - extra_coverage_args=['--annotate=xcov'] + extra_covargs) + covlevel="stmt", + mains=["test_t"], + extra_coverage_args=["--annotate=xcov"] + extra_covargs, + tolerate_coverage_messages=".", + ) - check_xcov_reports('obj/*.xcov', xreports) + check_xcov_reports("obj", xreports) - wlog = contents_of('coverage.log') + wlog = contents_of("coverage.log") for xw in xwarnings: thistest.fail_if( - xw not in wlog, - 'expected warning "%s" not found in log' % xw) + xw not in wlog, 'expected warning "%s" not found in log' % xw + ) wd.to_homedir() try_one( - subdir="wd_1", + subdir="tmp_1", extra_covargs=[], xreports={ - 'obj/flip.adb.xcov': {'+': {3}}, - 'obj/test_t.adb.xcov': {'+': {4, 6}}}, - xwarnings=[]) + "flip.adb.xcov": {"+": {3}}, + "flip.ads.xcov": {}, + "test_t.adb.xcov": {"+": {4, 6}}, + }, + xwarnings=[], +) try_one( - subdir="wd_2", - extra_covargs=['--units=flop'], + subdir="tmp_2", + extra_covargs=["--units=flop"], xreports={}, - xwarnings=['no unit flop (from --units) in the projects of interest']) + xwarnings=["no unit flop (from --units) in the projects of interest"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index 30e41e757..fd84c6be2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -4,6 +4,9 @@ reported. """ +import os.path +import glob + from e3.fs import mkdir from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -13,32 +16,59 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') -mkdir('obj-helper') -mkdir('obj-main') +tmp = Wdir("tmp_") +mkdir("obj-helper") +mkdir("obj-main") -helper_prj = gprfor(prjid='helper', mains=[], langs=['Ada'], - srcdirs='../src-helper', objdir='obj-helper') -main_prj = gprfor(prjid='main', mains=['main.adb'], langs=['Ada'], - deps=['helper'], srcdirs='../src-main', objdir='obj-main') +helper_prj = gprfor( + prjid="helper", + mains=[], + langs=["Ada"], + srcdirs="../src-helper", + objdir="obj-helper", +) +main_prj = gprfor( + prjid="main", + mains=["main.adb"], + langs=["Ada"], + deps=["helper"], + srcdirs="../src-main", + objdir="obj-main", +) build_run_and_coverage( - gprsw=GPRswitches(root_project=main_prj, - projects=['helper'], - units=['helper', 'main']), - covlevel='stmt', - mains=['main'], - gpr_obj_dir='obj-main', - extra_coverage_args=['-axcov']) - -log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') + gprsw=GPRswitches( + root_project=main_prj, projects=["helper"], units=["helper", "main"] + ), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-main", + tolerate_instrument_messages="no unit .* in the projects", + extra_coverage_args=["-axcov"], + tolerate_coverage_messages="no unit .* in the projects", +) + +log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no unit main (from --units) in the projects of interest', - contents_of(log_file).strip()) + "gnatcov output", + "warning: no unit main (from --units) in the projects of interest", + contents_of(log_file).strip(), +) -check_xcov_reports('obj-*/*.xcov', {'obj-main/helper.adb.xcov': {'+': {3}}}) +check_xcov_reports("obj-main", {"helper.adb.xcov": {"+": {3}}}) + +# Check that all xcov report files are created in obj-main (i.e. the root +# project). +xcov_files = glob.glob("obj-*/*.xcov") +extra_xcov_files = [f for f in xcov_files if os.path.dirname(f) != "obj-main"] +thistest.fail_if_not_equal( + "misplaced xcov report files", + "", + "\n".join(extra_xcov_files), +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst index 5927de5ff..3ba0cc91f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst @@ -1,8 +1,6 @@ Use of GPR project files to state Units Of Interest =================================================== -%REQ_ID% - The tool shall support the use of project file facilities to let users designate Units Of Interest for an analysis, as a replacement of the mechanism where users would instead provide an explicit list diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py index 04c20260f..56e1ca078 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py @@ -4,15 +4,18 @@ from test_support import check -wd = Wdir('wd_') +wd = Wdir("tmp_") gprbuild( - gprfor(srcdirs=['../src', # For the test sources - '../../../../src'], # For the support sources - deps=['../Mon/mon.gpr'], - mains=['test_ab.adb'])) + gprfor( + srcdirs=[ + "../src", # For the test sources + "../../../../src", + ], # For the support sources + deps=["../Mon/mon.gpr"], + mains=["test_ab.adb"], + ) +) -check( - test_ali='obj/test_ab.ali', - mon_ali='../Mon/obj/monitor.ali') +check(test_ali="obj/test_ab.ali", mon_ali="../Mon/obj/monitor.ali") thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py index c3bab76da..ce4cd44c2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py @@ -4,14 +4,17 @@ from test_support import check -wd = Wdir('wd_') +wd = Wdir("tmp_") gprbuild( - gprfor(srcdirs=['../src', # For the test sources - '../../../../src'], # For the support sources - mains=['test_ab.adb'])) + gprfor( + srcdirs=[ + "../src", # For the test sources + "../../../../src", + ], # For the support sources + mains=["test_ab.adb"], + ) +) -check( - test_ali='obj/test_ab.ali', - mon_ali='obj/monitor.ali') +check(test_ali="obj/test_ab.ali", mon_ali="obj/monitor.ali") thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst index 4f50ad640..c20e2a240 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst @@ -1,8 +1,6 @@ Use of SCO files to state Units Of Interest =========================================== -%REQ_ID% - As an alternative to the use of project file facilities to designate Units Of Interest for an analysis, the tool shall let users specify those units by listing their corresponding .ali files with a set of diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py index c5c85b477..254183e69 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py @@ -20,12 +20,12 @@ def _run_and_cov(pgm, level, sco_args): if we are doing mcdc. """ - level_arg = '--level=%s' % level + level_arg = "--level=%s" % level # gnatcov run run_args = [exepath_to(pgm), level_arg] - if 'mcdc' in level_arg: + if "mcdc" in level_arg: run_args.extend(sco_args) xrun(run_args) @@ -33,11 +33,12 @@ def _run_and_cov(pgm, level, sco_args): # gnatcov coverage cov_args = [ - '--annotate=xcov', - '--trace=%s' % tracename_for(os.path.basename(pgm)), - level_arg] + sco_args + "--annotate=xcov", + "--trace=%s" % tracename_for(os.path.basename(pgm)), + level_arg, + ] + sco_args - xcov(['coverage'] + cov_args) + xcov(["coverage"] + cov_args) def _tryone(sco_args, odir): @@ -51,27 +52,31 @@ def _tryone(sco_args, odir): wsd = Wdir(subdir=odir) - _run_and_cov(pgm='../test_ab', level='stmt+mcdc', sco_args=sco_args) + _run_and_cov(pgm="../test_ab", level="stmt+mcdc", sco_args=sco_args) # Check report contents - args = 'stmt+mcdc / ' + ' '.join(sco_args) + args = "stmt+mcdc / " + " ".join(sco_args) - test_xcov = contents_of('test_ab.adb.xcov') + test_xcov = contents_of("test_ab.adb.xcov") thistest.fail_if( - not re.search(r'\+: Monitor.Diamond', test_xcov), - 'failure on check for %s' % args) + not re.search(r"\+: Monitor.Diamond", test_xcov), + "failure on check for %s" % args, + ) - mon_xcov = contents_of('monitor.adb.xcov') + mon_xcov = contents_of("monitor.adb.xcov") thistest.fail_if( - not re.search(r'\!:.*and then', mon_xcov), - 'failure on Decision monitor check for %s' % args) + not re.search(r"\!:.*and then", mon_xcov), + "failure on Decision monitor check for %s" % args, + ) thistest.fail_if( - not re.search(r'\+:.*Hit := Hit \+ 1;', mon_xcov), - 'failure on Hit monitor check for %s' % args) + not re.search(r"\+:.*Hit := Hit \+ 1;", mon_xcov), + "failure on Hit monitor check for %s" % args, + ) thistest.fail_if( - not re.search(r'\+:.*Miss := Miss \+ 1;', mon_xcov), - 'failure on Miss monitor check for %s' % args) + not re.search(r"\+:.*Miss := Miss \+ 1;", mon_xcov), + "failure on Miss monitor check for %s" % args, + ) wsd.to_homedir() @@ -87,18 +92,20 @@ def check(test_ali, mon_ali): # To prevent mixups and facilitate investigation in case # of failure, we execute each sequence of commands from within # a separate subdir. Adjust the paths to ali files accordingly. - test_ali = os.path.join('..', test_ali) - mon_ali = os.path.join('..', mon_ali) + test_ali = os.path.join("..", test_ali) + mon_ali = os.path.join("..", mon_ali) # Check with response file only - _tryone(sco_args=['--scos=@' + list_to_tmp([test_ali, mon_ali])], - odir='response') + _tryone( + sco_args=["--scos=@" + list_to_tmp([test_ali, mon_ali])], + odir="response", + ) # Check with --scos only - _tryone(sco_args=['--scos=' + f for f in [test_ali, mon_ali]], - odir='scos') + _tryone(sco_args=["--scos=" + f for f in [test_ali, mon_ali]], odir="scos") # Check with a mix of a response file and --scos - _tryone(sco_args=['--scos=@' + list_to_tmp([test_ali]), - '--scos=' + mon_ali], - odir='mix') + _tryone( + sco_args=["--scos=@" + list_to_tmp([test_ali]), "--scos=" + mon_ali], + odir="mix", + ) diff --git a/testsuite/Qualif/Common/src/support.adb b/testsuite/Qualif/Common/src/support.adb deleted file mode 100644 index 624900713..000000000 --- a/testsuite/Qualif/Common/src/support.adb +++ /dev/null @@ -1,8 +0,0 @@ -package body Support is - procedure Assert (T : Boolean) is - begin - if not T then - raise Program_Error; - end if; - end; -end; diff --git a/testsuite/Qualif/Common/src/support.ads b/testsuite/Qualif/Common/src/support.ads deleted file mode 100644 index 15de51aa4..000000000 --- a/testsuite/Qualif/Common/src/support.ads +++ /dev/null @@ -1,3 +0,0 @@ -package Support is - procedure Assert (T : Boolean); -end; diff --git a/testsuite/Qualif/Environment/content.rst b/testsuite/Qualif/Environment/content.rst index 6ec9e1c5c..d011b2e93 100644 --- a/testsuite/Qualif/Environment/content.rst +++ b/testsuite/Qualif/Environment/content.rst @@ -1,11 +1,11 @@ .. _operational-conditions: -|opcond_section_title| -====================== +Operational Conditions of Use +============================= This chapter describes rules on which the correctness of the source coverage assessments performed by GNATcoverage depends. This instance of the document -is valid for use in a certification context no stricter than DAL |dolevel|. +is valid for use in a certification context no stricter than DAL |prj_DAL|. .. _operational-context: @@ -22,16 +22,19 @@ matching process. .. tabularcolumns:: |p{0.06\textwidth}|p{0.30\textwidth}|p{0.60\textwidth}| -.. csv-table:: +.. csv-table:: Expected verification Environment values :header: "Item #", "Description", "Expected value" :widths: 5, 30, 60 - :delim: | + :delim: / + + e1 / Host Operating System name and version / |prj_host_platform| + e2 / GNATcoverage executable name and version / |gnatcov_version| + e3 / GNAT Pro compiler executable name and version / |gnatpro_version| + s1 / GNAT Pro compilation switches / |prj_switches| + s2 / GNAT Pro Runtime Library Profile / |prj_RTS| + s3 / GNATcov dump trigger switch value / |prj_dump_trigger| + s4 / GNATcov dump channel switch value / |prj_dump_channel| - e1 | Host Operating System name and version | Linux Redhat 7 - e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) - e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] - s1 | GNAT Pro compilation switches | -g -fpreserve-control-flow -fdump-scos -gnat12 - s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless. For the GNAT Pro compilation switches, additional options which do not influence code generation are allowed. This may, for example, include options @@ -46,6 +49,12 @@ delivered with the GNAT Pro toolchain. Tool Users shall have their toolchain setup to compile programs with a :literal:`--RTS` switch as well, designating a runtime with a ``system.ads`` identical to the qualification one. +The indications for the GNATcov dump trigger and GNATcov dump channel switch +values represent the retained values for the corresponding switches, required +as part of the :literal:`gnatcov instrument` command, in accordance to the +restrictions imposed by the GNATPro runtime library profile and execution host +capabilities defined above, as described in the tool's User Manual. + Installation, Documentation and Qualified Interface --------------------------------------------------- @@ -66,7 +75,7 @@ General use of the tool is described in the Tool User's Guide document, which can be found in the subdirectory :literal:`share/doc` of the tool installation. For qualified use more specifically, the Tool User shall also conform to the rules described in the *Qualified Interface* section of the -qualification |plans_doc| document. + |plans_doc| document. .. _language-scope: @@ -100,23 +109,6 @@ In addition: pragma Restriction_Warnings (No_Finalization); pragma Restriction_Warnings (No_Implicit_Dynamic_Code); -* The tool is only partially qualified for analysis in presence of exceptions - which propagate across subprograms, when the runtime library profile - supports this at all. - - One possible way to ensure that the code subject to analysis conforms to - what this qualification material encompasses is to verify that it compiles - without error under control of a Zero Footprint Runtime Library Profile, or - free of warnings out of the following set of configuration pragmas:: - - pragma Restriction_Warnings (No_Exception_Registration); - pragma Restriction_Warnings (No_Exception_Handlers); - - Otherwise, for all uses (in subprograms subject to the analysis) of handlers - for exceptions not raised by the subprogram itself, users shall verify - conformance to what the Operational Requirements specifically prescribe for - such cases (:ref:`exceptions`). - * For mcdc assessments, the tool requires the use of short-circuit variants for the Boolean binary operators composing decisions: ``&&`` or ``||`` in C, ``and then`` or ``or else`` in Ada. diff --git a/testsuite/Qualif/Index/content.rst b/testsuite/Qualif/Index/content.rst index 312f9506c..fb37991c3 100644 --- a/testsuite/Qualif/Index/content.rst +++ b/testsuite/Qualif/Index/content.rst @@ -19,6 +19,3 @@ directions: .. qmlink:: IndexImporter - - :allclass:TORReq - diff --git a/testsuite/Qualif/Introduction/content.rst b/testsuite/Qualif/Introduction/content.rst index 4ec1863e9..b333fa613 100644 --- a/testsuite/Qualif/Introduction/content.rst +++ b/testsuite/Qualif/Introduction/content.rst @@ -1,5 +1,5 @@ -|torintro_section_title| -************************ +Document Purpose and Organization +********************************* Document Purpose ================ @@ -45,7 +45,7 @@ for this requirement. Each line in such a table designates a particular testcase, requirement or group artifact, with an abbreviation denoting the kind of artifact in the first column, the artifact local name in the second column and a short description of the artifact contents in the third. See the -:ref:`abbrevs` section later in this chapter for the list of abbrevations used +:ref:`abbrevs` section later in this chapter for the list of abbreviations used in the first column. At the top of the hierarchy, collections of high level requirement groups are @@ -71,7 +71,7 @@ requirement groups, addressing: tool behavior with respect to the stated requirements, testcases in this category are also typically designed to exercise multiple kinds of language constructs mixed together. They represent a good opportunity to do so as - they are not directed to focus on specific contructs by the nature of the + they are not directed to focus on specific constructs by the nature of the requirements to exercise, unlike a core requirement on, say, *If* statements for example. @@ -85,16 +85,16 @@ testsuite harness to search for criteria violation messages. Every requirement is assigned a unique **Requirement Identifier** computed from its local name and position in the hierarchy of chapters and groups. This identifier is denoted as a path with slashes between each intermediate -level, for example `/TOR/Ada/stmt/Core/CompoudStatements/Loop`. +level, for example `/TOR/Ada/stmt/Core/CompoundStatements/Loop`. Likewise, each Testcase is assigned a unique **Testcase Identifier**, computed from its local name and position in the hierarchy of requirements and testcases. Each testcase or group is always attached to a single requirement, so testcase identifiers are continuations of the parent requirement's identifier, for example -`/TOR/Ada/stmt/Core/CompoudStatements/Loop/Incomplete_Iteration`. +`/TOR/Ada/stmt/Core/CompoundStatements/Loop/Incomplete_Iteration`. -These identifiers are used to denote individual testcases in the |str_doc| +These identifiers are used to denote individual testcases in the |str_abb| report produced out of testuite runs for qualification. For a more detailed description of how testscase sources are organized and how @@ -108,7 +108,7 @@ Abbreviations The following abbreviations are used throughout this document: -.. csv-table:: +.. csv-table:: Abbreviation definitions :delim: | :widths: 30, 40 :header: "Abbreviation", "Meaning" @@ -124,4 +124,3 @@ The following abbreviations are used throughout this document: rqg|requirement group tc|test case tcg|test case group - diff --git a/testsuite/Qualif/content.rst b/testsuite/Qualif/content.rst index bdac324ad..2f3b01870 100644 --- a/testsuite/Qualif/content.rst +++ b/testsuite/Qualif/content.rst @@ -1,27 +1,20 @@ -GNATcoverage - |standard| Qualification Material: |tor_doc_title| -################################################################# +GNATcoverage - |tool_standard| Qualification Material: |doc_title| +################################################################## .. rubric:: List of referenced documents .. tabularcolumns:: |p{0.20\textwidth}|p{0.80\textwidth}| -.. csv-table:: +.. csv-table:: Reference documents :delim: ; :widths: 10, 90 :header: "Designation", "Referenced document" - |plans_doc| ; |project_name_it| - |plans_doc_title| (|plans_doc_id|) + |plans_abb| ; |prj_toolset| - |plans_doc| (|plans_id|) Ada 2012 LRM ; Ada 2012 Reference Manual. Language and Standard Libraries, ISO/IEC 8652:2012(E) Ada 2005 LRM ; Ada 2005 Reference Manual. Language and Standard Libraries. International Standard ISO/IEC 8652/1995(E) with Technical Corrigendum 1 and Amendment 1. Ada 95 LRM ; Ada 1995 Reference Manual. Language and Standard Libraries. International Standard ISO/IEC 8652:1995 Technical Corrigendum 1 (ISO/IEC 8652:1995:TC1:2000) - Tool User's Guide ; *GNATcoverage User's Guide*, part of the GNATcoverage 19.3 release documentation - -.. rubric:: Revision History -.. csv-table:: - :delim: | - :header: "Version #", "Date", "Comment" - - DRAFT 0.0 | | Draft for interim delivery, pre internal QA + Tool User's Guide ; *GNATcoverage User's Guide*, part of the GNATcoverage |gnatcov_version| release documentation .. only:: html @@ -46,6 +39,10 @@ GNATcoverage - |standard| Qualification Material: |tor_doc_title| Ada Common +.. raw:: latex + + \appendix + .. only:: html @@ -57,4 +54,3 @@ GNATcoverage - |standard| Qualification Material: |tor_doc_title| Index Appendix - diff --git a/testsuite/Qualif/qmconf.py b/testsuite/Qualif/qmconf.py deleted file mode 100644 index bbaa070a4..000000000 --- a/testsuite/Qualif/qmconf.py +++ /dev/null @@ -1,29 +0,0 @@ -import os.path - -latex_show_pagerefs = True - -common_file = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__))))), - "common_conf.py") - -if os.path.isfile(common_file): - execfile(common_file) - execfile(os.path.join( - os.path.dirname(common_file), - "qm_prolog.py")) -else: - print "Couldn't find common configuration file" - print common_file - print "from: %s" % __file__ - -rst_prolog += writer.define_role('raw-html(raw)', {'format': 'html'}) - -doc_id = tor_doc_id - -html_sidebars = { - '**': ['localtoc.html', 'sourcelink.html', 'searchbox.html'] -} diff --git a/testsuite/README.md b/testsuite/README.md index ccb8fdce4..d7e235c5f 100644 --- a/testsuite/README.md +++ b/testsuite/README.md @@ -8,13 +8,9 @@ This is a Python driven testsuite for GNATcoverage. Most tests use gprbuild to build programs for run/analysis by gnatcov/gnatemu. -The testsuite driver is `/testsuite.py`. It scans the following -subdirectories for `test.py` instances and runs every one it finds after -switching to where it was found: - -* `Qualif/` (DO-178 qualification testsuite) -* `../extra/tests/` (other testcases) - +The testsuite driver is `/testsuite.py`. It scans the subdirectories +provided as arguments for `test.py` instances and runs every one it finds after +switching the current directory to where it was found. Prerequisites ------------- @@ -23,18 +19,10 @@ You need, on your `PATH`: * The gnatcov binary that you wish to exercise -* gprbuild >= 1.3.0 - -* GNATpython and rlimit. If you don't have a binary package at hand, you may - install the necessary subset with: +* gprbuild version >= 22 - ```shell - git clone https://forge.open-do.org/anonscm/git/gnatpython/gnatpython.git - ``` - - Add the extracted directory to your `PYTHONPATH`, then compile rlimit and add - it to your `PATH`. Or run `./setup.py` install to install the GNATpython - package in your Python distribution. +* The [e3-core](https://github.com/AdaCore/e3-core/) and + [e3-testsuite](https://github.com/adacore/e3-testsuite/) Python packages. * The GNAT toolchain that you wish be used to compile the tests (recent enough wrt `-fpreserve-control-flow`). @@ -42,28 +30,16 @@ You need, on your `PATH`: * The `-gnatemu` binaries you wish to exercise if you are willing to run tests for a cross target. -Native runs are supported on x86 and x86_64-linux, using an instrumented -version of Valgrind. An instrumented Valgrind is bundled in recent binary -packages of GNATcoverage. If you are building from sources, you need to -install the GNATcoverage trace adapter into your Valgrind distrib. See the -Makefiles for this particular purpose. - -If you are running tests for a ZFP or Ravenscar configuration (not a full -runtime), you also need at the toplevel, together with this README: a `support` -subdirectory corresponding to the one in the gnatcov examples. - -If you retrieved this testsuite subdir as part of a full GNATcoverage tree, you -have the gnatcov sources in `../tools` and may for example do: - -```shell -ln -s ../tools/gnatcov/examples/support support -``` +* An e3-testsuite distribution, https://github.com/AdaCore/e3-testsuite -Otherwise, you might just checkout the relevant subdir from the scm repo, for -example with: +If you are running tests for a light (formerly ZFP)s or Ravenscar configuration +(not a full runtime), you also need at the toplevel, together with this +README: a `support` subdirectory corresponding to the one in the gnatcov +examples. Assuming you have the GNATcoverage source repository at hand in +$gnatcov-src-dir, this could be setup with a mere symbolic link like: ```shell -svn co svn+ssh://$OPENDO_ROOT/tools/gnatcov/examples/support +ln -s $gnatcov-src-dir/tools/gnatcov/examples/support support ``` @@ -81,13 +57,12 @@ Note the use of target _product_ names here, not GCC target triplets. For example: ```shell -# Cross configurations, using GNATemulator: -./testsuite.py --target=ppc-elf --RTS=powerpc-elf/ravenscar-sfp-prep -./testsuite.py --target=leon-elf --RTS=ravenscar -./testsuite.py --target=ppc-vx6 --RTS=kernel --kernel=tests/kernels/vx6.8-fastsbc +# Cross configurations, using binary traces or source instrumentation: +./testsuite.py --target=ppc-elf --RTS=light-mpc8641 --trace-mode=src +./testsuite.py --target=leon3-elf --RTS=embedded-leon3 --trace-mode=bin -# Native configuration, using an instrumented valgrind (x86-linux or x86_64-linux): -./testsuite.py +# Windows or Linux native configuration, using source instrumentation: +./testsuite.py --trace-mode=src ``` The optional `regexp` at the end instructs the driver to run only those tests diff --git a/testsuite/REST/rest.py b/testsuite/REST/rest.py index 8f412eafe..4e691f46b 100644 --- a/testsuite/REST/rest.py +++ b/testsuite/REST/rest.py @@ -1,41 +1,49 @@ +def isolate(text, pre, post): + return "\n" * pre + text + "\n" * post -def isolate (text, pre, post): - return '\n' * pre + text + '\n' * post def heading(title, char, pre=2, post=1): - return isolate ( - pre = pre, - text = '\n'.join ( - (char * len(title), title, char * len(title))), - post = post) + return isolate( + pre=pre, + text="\n".join((char * len(title), title, char * len(title))), + post=post, + ) + def part(title): - return heading(title, '#') + return heading(title, "#") + def chapter(title): - return heading(title, '*') + return heading(title, "*") + def section(title): - return heading(title, '=') + return heading(title, "=") + def emph(content): return "*" + content + "*" + def strong(content): return "**" + content + "**" -def list(content, pre=1, post=1): - return isolate ( - pre = pre, - text = '\n'.join([' * %s' % l for l in content]), - post = post) - -def toctree(l, depth=2): - return isolate ( - pre = 1, - text = '\n'.join ( - [".. toctree::", - " :maxdepth: %s\n" % depth] - + [" %s" % item for item in l]), - post = 1) +def list(content, pre=1, post=1): # noqa: A001 + return isolate( + pre=pre, + text="\n".join([" * %s" % line for line in content]), + post=post, + ) + + +def toctree(lines, depth=2): + return isolate( + pre=1, + text="\n".join( + [".. toctree::", " :maxdepth: %s\n" % depth] + + [" %s" % item for item in lines] + ), + post=1, + ) diff --git a/testsuite/SCOV/expgen/__init__.py b/testsuite/SCOV/expgen/__init__.py index 3543ec32b..3346078a4 100644 --- a/testsuite/SCOV/expgen/__init__.py +++ b/testsuite/SCOV/expgen/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +""" TODO -''' +""" diff --git a/testsuite/SCOV/expgen/ast.py b/testsuite/SCOV/expgen/ast.py deleted file mode 100644 index 2ec22f09b..000000000 --- a/testsuite/SCOV/expgen/ast.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -Expose various construct that can be used to build abstract trees. Those trees -can then be used to generate programs. - -The idea is not to reimplement a full AST for both C and Ada, but rather focus -on an interesting common set of constructs for tests. When too specific -constructs are needed, just use the X* node kinds: XType, XOperand, etc. -""" - -from collections import namedtuple - - -class RelOp(object): - """Available relational operators.""" - GT = '>' - GE = '>=' - LT = '<' - LE = '<=' - EQ = '==' - NE = '!=' - - -class Types(object): - """Available basic types for local variable declarations.""" - BOOLEAN = 'boolean' - INTEGER = 'integer' - - -class TagTypes(object): - """Available decision context types for tags.""" - DECISION = ':d:' - EXPRESSION = ':e:' - - -Program = namedtuple('program', 'local_vars statements') - - -# Types: used for both declarations and usages -BuiltinType = namedtuple('builtin_type', 'name') -RecordType = namedtuple('record_type', 'name members') -MemberDecl = namedtuple('member_decl', 'type name') - -# ... and some regularly used ones. Note that builtin types must not be -# declared -BooleanType = BuiltinType(Types.BOOLEAN) -IntegerType = BuiltinType(Types.INTEGER) - - -# Expressions: when adding nodes to these or to topology ones, do not forget to -# update the `utils.is_expr` function. -VariableUsage = namedtuple('variable_usage', 'name') -LitteralInteger = namedtuple('litteral_integer', 'value') -LitteralBoolean = namedtuple('litteral_boolean', 'value') -LitteralRecord = namedtuple('litteral_record', 'type members') -Comparison = namedtuple('comparison', 'operator left right') -Call = namedtuple('call', 'function arguments') - -# Topology expressions -And = namedtuple('and_expr', 'left right') -Or = namedtuple('or_expr', 'left right') -Not = namedtuple('not_expr', 'expr') - - -# Statements -If = namedtuple('if_stmt', 'condition true_stmt false_stmt') -While = namedtuple('while_stmt', 'condition stmt') -Return = namedtuple('return_stmt', 'expr') -Assign = namedtuple('assign', 'variable expr') - -# Language-specific constructs: -# - Type -XType = namedtuple('language_specific_type', - 'language declaration usage') -# - Litteral (for actuals, mostly) -XLitteral = namedtuple('language_specific_litteral', - 'language format') -# - Operand -XOperand = namedtuple('language_specific_operand', - 'language format formal_name') -# - Context -XContext = namedtuple('language_specific_context', - 'language format decision_expr') - -# Tag -# Used to tag lines, so that test drivers can reference the correct lines for -# expectations. -# - Custom tags may only define the `name` attribute, leaving `operand` and -# `context` as None. -# - If name is `eval`, `operand` must be the formal name that is used in the -# tagged operand, or `all` if all operands are on the same line. In both -# cases, `context` must be `TagTypes.(DECISION or EXPRESSION)` depending on -# the context of the tagged decision. -Tag = namedtuple('tag', 'name operand context') -TaggedNode = namedtuple('tagged_node', 'tag node') diff --git a/testsuite/SCOV/expgen/context.py b/testsuite/SCOV/expgen/context.py index b6fe52da6..bb6c673bd 100644 --- a/testsuite/SCOV/expgen/context.py +++ b/testsuite/SCOV/expgen/context.py @@ -3,7 +3,7 @@ """Expose contexts suitable for decisions.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax class Context(object): @@ -39,15 +39,15 @@ def __init__(self): self.language = self.LANGUAGE def get_program(self, decision_expr): - return ast.Program( - [], [ast.XContext(self.LANGUAGE, self.FORMAT, decision_expr)] + return syntax.Program( + [], [syntax.XContext(self.LANGUAGE, self.FORMAT, decision_expr)] ) # Tag for statements whose execution depends on the outcome of the decision # expression. -ON_TRUE_TAG = ast.Tag('on-true', None, None) -ON_FALSE_TAG = ast.Tag('on-false', None, None) +ON_TRUE_TAG = syntax.Tag("on-true", None, None) +ON_FALSE_TAG = syntax.Tag("on-false", None, None) class Call(Context): @@ -56,23 +56,25 @@ class Call(Context): function, and return the result of this call. The user must provide an implementation for this function. - """'' + """ "" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION def get_program(self, param): - temp_name = 'result' - temp_usage = ast.VariableUsage(temp_name) + temp_name = "result" + temp_usage = syntax.VariableUsage(temp_name) - return ast.Program( - [(temp_name, ast.BooleanType), ], + return syntax.Program( [ - ast.Assign( + (temp_name, syntax.BooleanType), + ], + [ + syntax.Assign( temp_usage, - ast.Call(ast.VariableUsage('identity'), [param]) + syntax.Call(syntax.VariableUsage("identity"), [param]), ), - ast.Return(temp_usage), - ] + syntax.Return(temp_usage), + ], ) @@ -82,18 +84,24 @@ class If(Context): statement. """ - TAG_CONTEXT = ast.TagTypes.DECISION + TAG_CONTEXT = syntax.TagTypes.DECISION def get_program(self, condition): - return ast.Program( + return syntax.Program( [], # No local variable - [ast.If( - condition, - ast.TaggedNode(ON_TRUE_TAG, - ast.Return(ast.LitteralBoolean(True))), - ast.TaggedNode(ON_FALSE_TAG, - ast.Return(ast.LitteralBoolean(False))) - )] + [ + syntax.If( + condition, + syntax.TaggedNode( + ON_TRUE_TAG, + syntax.Return(syntax.LitteralBoolean(True)), + ), + syntax.TaggedNode( + ON_FALSE_TAG, + syntax.Return(syntax.LitteralBoolean(False)), + ), + ) + ], ) @@ -103,29 +111,33 @@ class While(Context): statement. """ - TAG_CONTEXT = ast.TagTypes.DECISION + TAG_CONTEXT = syntax.TagTypes.DECISION def get_program(self, condition): - return ast.Program( + return syntax.Program( [], # No local variable [ - ast.While( + syntax.While( condition, - ast.TaggedNode(ON_TRUE_TAG, - ast.Return(ast.LitteralBoolean(True))) + syntax.TaggedNode( + ON_TRUE_TAG, + syntax.Return(syntax.LitteralBoolean(True)), + ), ), - ast.TaggedNode(ON_FALSE_TAG, - ast.Return(ast.LitteralBoolean(False))) - ] + syntax.TaggedNode( + ON_FALSE_TAG, syntax.Return(syntax.LitteralBoolean(False)) + ), + ], ) class Return(Context): - - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION def get_program(self, condition): - return ast.Program( + return syntax.Program( [], - [ast.Return(condition), ] + [ + syntax.Return(condition), + ], ) diff --git a/testsuite/SCOV/expgen/generator/__init__.py b/testsuite/SCOV/expgen/generator/__init__.py index 3543ec32b..3346078a4 100644 --- a/testsuite/SCOV/expgen/generator/__init__.py +++ b/testsuite/SCOV/expgen/generator/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +""" TODO -''' +""" diff --git a/testsuite/SCOV/expgen/generator/composition.py b/testsuite/SCOV/expgen/generator/composition.py index b9bad46eb..930997e45 100644 --- a/testsuite/SCOV/expgen/generator/composition.py +++ b/testsuite/SCOV/expgen/generator/composition.py @@ -3,7 +3,7 @@ """Set of composition elements.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context import SCOV.expgen.language as language import SCOV.expgen.language.ada.context as ada_context @@ -13,13 +13,11 @@ import SCOV.expgen.operand as operand -languages = [lang_mod.Language() - for lang_mod in (language.ada, language.c)] +languages = [lang_mod.Language() for lang_mod in (language.ada, language.c)] operand_kinds = [ operand.Variable(), - operand.IntegerComparison(ast.RelOp.GT, 1), - + operand.IntegerComparison(syntax.RelOp.GT, 1), # Ada-specific operands ada_operand.Aggregate(), ada_operand.Component(), @@ -31,7 +29,6 @@ # TODO: find how to make coverage expectation match the whole expression # (including the Boolean conversion operator). # -> ada_operand.DerivedType(), - # C-specific operands c_operand.Component(), c_operand.Modulo(), @@ -42,7 +39,6 @@ context.If(), context.While(), context.Return(), - # Ada-specific contexts ada_context.Case(), ada_context.DeclarationInitializer(), @@ -50,7 +46,6 @@ ada_context.ExitWhen(), ada_context.For(), ada_context.Index(), - # C-specific contexts c_context.DeclarationInitializer(), ] diff --git a/testsuite/SCOV/expgen/generator/engine.py b/testsuite/SCOV/expgen/generator/engine.py index 67e9171a2..fd6e297c5 100644 --- a/testsuite/SCOV/expgen/generator/engine.py +++ b/testsuite/SCOV/expgen/generator/engine.py @@ -39,15 +39,15 @@ def run(group_py): with env.get_dir(group_py_dir): generate_all(env) except GenerationError as e: - sys.stderr.write('{}: error: {}\n'.format(e.context, e.message)) + sys.stderr.write("{}: error: {}\n".format(e.context, e.message)) sys.exit(1) def generate_all(env): """Generate code for all topology directories in the current directory.""" # Each directory contains drivers for a given topology. - for topo_dir in os.listdir('.'): - if not os.path.isdir(topo_dir) or topo_dir == 'src': + for topo_dir in os.listdir("."): + if not os.path.isdir(topo_dir) or topo_dir == "src": continue with env.get_dir(topo_dir): generate_topology(topo_dir, env) @@ -60,27 +60,28 @@ def generate_topology(topo_dir, env): # Look at all drivers to collect the truth vectors involved. Extract the # topology used and check that each driver use the same one. - with env.get_dir('src'): - for driver in os.listdir('.'): - if not driver.startswith('test_') or not driver.endswith('.adb'): + with env.get_dir("src"): + for driver in os.listdir("."): + if not driver.startswith("test_") or not driver.endswith(".adb"): continue - drv_topo = parsing.parse_driver( - topo_dir, driver, truth_vectors - ) + drv_topo = parsing.parse_driver(topo_dir, driver, truth_vectors) # Check that this driver has a topology and that its topology is # not different from others. if drv_topo is None: raise DriverError( - topo_dir, driver, None, 'This driver has no topology') - elif ( - topo is not None - and not utils.is_topology_equal(topo.expression, drv_topo) + topo_dir, driver, None, "This driver has no topology" + ) + elif topo is not None and not utils.is_topology_equal( + topo.expression, drv_topo ): raise DriverError( - topo_dir, driver, None, - 'This driver has a different topology from other one') + topo_dir, + driver, + None, + "This driver has a different topology from other one", + ) topo = topology.Topology(drv_topo) # If we happen to get here for subdirectories that are not aimed at @@ -116,7 +117,7 @@ def generate_language(env, topo, truth_vectors, lang): ] first_unused_op_kind = i + topo.arity - with env.get_dir('Op{}'.format(i)): + with env.get_dir("Op{}".format(i)): generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds) # If some operand kinds were not used in the previous combination, use them @@ -140,15 +141,12 @@ def generate_language(env, topo, truth_vectors, lang): operand_kinds_to_test[(k + j) % len(operand_kinds_to_test)] for j in range(topo.arity) ] - with env.get_dir('Op{}'.format(i)): + with env.get_dir("Op{}".format(i)): generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds) def generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds): - formal_names = [ - 'X{}'.format(i + 1) - for i in range(topo.arity) - ] + formal_names = ["X{}".format(i + 1) for i in range(topo.arity)] operands = [ op_kind.get_operand(name) for name, op_kind in zip(formal_names, op_kinds) @@ -159,26 +157,25 @@ def generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds): program = ctx.get_program(decision) # Generate the needed type declarations in the TYPES module. - used_types = utils.make_type_set(sum( - (tuple(op_kind.used_types) for op_kind in op_kinds), - () - )) + used_types = utils.make_type_set( + sum((tuple(op_kind.used_types) for op_kind in op_kinds), ()) + ) - with env.get_dir('src'): + with env.get_dir("src"): # First generate types needed by operands. with open( - lang.get_specification_filename(lang.TYPES_MODULE), 'w' + lang.get_specification_filename(lang.TYPES_MODULE), "w" ) as types_fp: lang.serialize_specification_types(types_fp, used_types) # Then generate the ADA binding for the run module... with open( - ada.get_specification_filename(ada.RUN_MODULE), 'w' + ada.get_specification_filename(ada.RUN_MODULE), "w" ) as run_fp: ada.serialize_run_module_interface(run_fp, lang, truth_vectors) # ... and the run module itself, in the decided language. with open( - lang.get_implementation_filename(lang.RUN_MODULE), 'w' + lang.get_implementation_filename(lang.RUN_MODULE), "w" ) as run_fp: lang.serialize_run_module_implementation( run_fp, op_kinds, truth_vectors @@ -187,59 +184,59 @@ def generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds): # And finally generate the specification and the implementation for the # computing module. with open( - lang.get_specification_filename(lang.COMPUTING_MODULE), 'w' + lang.get_specification_filename(lang.COMPUTING_MODULE), "w" ) as comp_fp: lang.serialize_specification_program( comp_fp, program, formal_names, formal_types ) with open( - lang.get_implementation_filename(lang.COMPUTING_MODULE), 'w' + lang.get_implementation_filename(lang.COMPUTING_MODULE), "w" ) as comp_fp: - # Prepend the "computing" module implementation with some comments # documenting the operands usage and the target of the context. def get_doc(instance): - text = type(instance).__doc__ or '' - text = ' '.join(text.split()) + text = type(instance).__doc__ or "" + text = " ".join(text.split()) return textwrap.wrap(text, 72) lines = [] - lines.append('Operands:') + lines.append("Operands:") for name, op_kind in zip(formal_names, op_kinds): - lines.append(' - {}: {}'.format(name, type(op_kind).__name__)) + lines.append(" - {}: {}".format(name, type(op_kind).__name__)) lines.extend( - ' {}'.format(line) - for line in get_doc(op_kind) + " {}".format(line) for line in get_doc(op_kind) ) - lines.append('Context: {}'.format(type(ctx).__name__)) - lines.extend( - ' {}'.format(line) - for line in get_doc(ctx) - ) + lines.append("Context: {}".format(type(ctx).__name__)) + lines.extend(" {}".format(line) for line in get_doc(ctx)) # Serialize the implementation code itself. for line in lines: comp_fp.write(lang.format_comment(line)) - comp_fp.write('\n') - comp_fp.write('\n') + comp_fp.write("\n") + comp_fp.write("\n") lang.serialize_implementation( - comp_fp, program, formal_names, formal_types, - one_operand_per_line + comp_fp, + program, + formal_names, + formal_types, + one_operand_per_line, ) # The "test.py" testcase file is hardcoded... - with open('test.py', 'w') as test_fp: - test_fp.write("""\ + with open("test.py", "w") as test_fp: + test_fp.write( + """\ from SCOV.tc import * from SCOV.tctl import CAT [TestCase(category=cat).run() for cat in CAT.critcats] thistest.result() -""") +""" + ) # Properly tag it as generated, so that the testsuite framework does not # treat it as a regular testcase next time. - with open('.generated', 'w'): + with open(".generated", "w"): pass diff --git a/testsuite/SCOV/expgen/generator/errors.py b/testsuite/SCOV/expgen/generator/errors.py index 381c048db..4df678214 100644 --- a/testsuite/SCOV/expgen/generator/errors.py +++ b/testsuite/SCOV/expgen/generator/errors.py @@ -1,7 +1,8 @@ class GenerationError(Exception): def __init__(self, context, message): super(GenerationError, self).__init__( - '{}: {}'.format(context, message)) + "{}: {}".format(context, message) + ) self.context = context self.message = message @@ -9,10 +10,13 @@ def __init__(self, context, message): class DriverError(GenerationError): def __init__(self, topo_dir, test_driver, line_no, message): super(DriverError, self).__init__( - '{}/{}{}'.format(topo_dir, test_driver, - ':{}'.format(line_no) - if line_no is not None else ''), - message) + "{}/{}{}".format( + topo_dir, + test_driver, + ":{}".format(line_no) if line_no is not None else "", + ), + message, + ) self.test_driver = test_driver self.line_no = line_no @@ -20,5 +24,5 @@ def __init__(self, topo_dir, test_driver, line_no, message): class BadTopologyError(DriverError): def __init__(self, topo_dir, test_driver, line_no, message): super(BadTopologyError, self).__init__( - topo_dir, test_driver, line_no, 'Bad topology: {}'.format(message) + topo_dir, test_driver, line_no, "Bad topology: {}".format(message) ) diff --git a/testsuite/SCOV/expgen/generator/parsing.py b/testsuite/SCOV/expgen/generator/parsing.py index c8660af15..f8dfd5fa2 100644 --- a/testsuite/SCOV/expgen/generator/parsing.py +++ b/testsuite/SCOV/expgen/generator/parsing.py @@ -5,7 +5,7 @@ module provides various helpers to parse them. """ -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.topology as topology from SCOV.expgen.generator.errors import DriverError, BadTopologyError @@ -31,57 +31,62 @@ def error(message): def check_eof(i): if i >= len(tokens): - raise error('unexpected end of line') + raise error("unexpected end of line") def parse_or(i): check_eof(i) left, i = parse_and(i) while i < len(tokens): - if tokens[i:i + 2] != ['or', 'else']: + if tokens[i : i + 2] != ["or", "else"]: raise error( - 'expected "or else" but found {}'.format(tokens[i])) + 'expected "or else" but found {}'.format(tokens[i]) + ) i += 2 right, i = parse_and(i) - left = ast.And(left, right) + left = syntax.And(left, right) return left, i def parse_and(i): check_eof(i) left, i = parse_not(i) while i < len(tokens): - if tokens[i:i + 2] != ['and', 'then']: + if tokens[i : i + 2] != ["and", "then"]: raise error( - 'expected "and then" but found {}'.format(tokens[i])) + 'expected "and then" but found {}'.format(tokens[i]) + ) i += 2 right, i = parse_not(i) - left = ast.And(left, right) + left = syntax.And(left, right) return left, i def parse_not(i): check_eof(i) - if tokens[i] == 'not': + if tokens[i] == "not": expr, i = parse_not(i + 1) - return ast.Not(expr), i - elif tokens[i] == '_': + return syntax.Not(expr), i + elif tokens[i] == "_": return (topology.OperandPlaceholder(), i + 1) - elif tokens[i] == '(': + elif tokens[i] == "(": result, i = parse_or(i + 1) if i >= len(tokens): raise error('expected ")" but found end of line') - elif tokens[i] != ')': + elif tokens[i] != ")": raise error('expected ")" but found {}'.format(tokens[i])) return (result, i + 1) else: raise error( 'expected "not", "(" or a placeholder but found ' - '{}'.format(tokens[i])) + "{}".format(tokens[i]) + ) # Check that all tokens have been consumed. topo, next_token = parse_or(0) if next_token < len(tokens): - raise error('Too much operands (parsed {})'.format( - ' '.join(tokens[:next_token]) - )) + raise error( + "Too much operands (parsed {})".format( + " ".join(tokens[:next_token]) + ) + ) return topo @@ -91,13 +96,14 @@ def parse_truth(topo_dir, driver, line_no, c): Parse a truth character ('F' or 'T') and return the corresponding truth value, or raise an error. """ - if c == 'F': + if c == "F": return False - elif c == 'T': + elif c == "T": return True else: - raise DriverError(topo_dir, driver, line_no, - 'Invalid truth character: {}'.format(c)) + raise DriverError( + topo_dir, driver, line_no, "Invalid truth character: {}".format(c) + ) def parse_driver(topo_dir, driver, truth_vectors): @@ -107,42 +113,47 @@ def parse_driver(topo_dir, driver, truth_vectors): """ drv_topo = None - for line_no, line in enumerate(open(driver, 'r'), 1): - + for line_no, line in enumerate(open(driver, "r"), 1): # Parse a topology declaration - if line.startswith('-- Topology: '): + if line.startswith("-- Topology: "): if drv_topo is not None: raise DriverError( - topo_dir, driver, line_no, - 'There is more than one topology' + topo_dir, + driver, + line_no, + "There is more than one topology", ) - _, topo_str = line.split(': ', 1) + _, topo_str = line.split(": ", 1) drv_topo = parse_topology( topo_dir, driver, line_no, topo_str.split() ) # Parse a run procedure call, extract a truth vector from it. - elif line.startswith(' Run_'): - + elif line.startswith(" Run_"): if drv_topo is None: raise DriverError( - topo_dir, driver, line_no, - 'A topology is needed before a run procedure is called') + topo_dir, + driver, + line_no, + "A topology is needed before a run procedure is called", + ) - chunks = line.split('_', 2) - assert chunks[0] == ' Run' + chunks = line.split("_", 2) + assert chunks[0] == " Run" if len(chunks) != 3: raise DriverError( - topo_dir, driver, line_no, - 'Invalid run invokation: {}'.format(line.strip())) + topo_dir, + driver, + line_no, + "Invalid run invokation: {}".format(line.strip()), + ) operands_truth = tuple( - parse_truth(topo_dir, driver, line_no, c) - for c in chunks[1] + parse_truth(topo_dir, driver, line_no, c) for c in chunks[1] ) expected_truth = parse_truth( topo_dir, driver, line_no, chunks[2][0] ) - truth_vectors.add(operands_truth + (expected_truth, )) + truth_vectors.add(operands_truth + (expected_truth,)) return drv_topo diff --git a/testsuite/SCOV/expgen/generator/utils.py b/testsuite/SCOV/expgen/generator/utils.py index 17e1e0ce2..7e46388c4 100644 --- a/testsuite/SCOV/expgen/generator/utils.py +++ b/testsuite/SCOV/expgen/generator/utils.py @@ -22,16 +22,14 @@ def __init__(self, env, subdir): def __enter__(self): self.env.push_dir(self.subdir) - def __exit__(self, type, value, traceback): + def __exit__(self, exctype, value, traceback): self.env.pop_dir() def __init__(self): - self.dir_stack = [ - os.getcwd() - ] + self.dir_stack = [os.getcwd()] def get_dir(self, subdir): - """ Return a new directory guard for `subdir`.""" + """Return a new directory guard for `subdir`.""" return self.DirectoryGuard(self, subdir) def push_dir(self, subdir): diff --git a/testsuite/SCOV/expgen/language/__init__.py b/testsuite/SCOV/expgen/language/__init__.py index 34bf390bb..ea3b3260d 100644 --- a/testsuite/SCOV/expgen/language/__init__.py +++ b/testsuite/SCOV/expgen/language/__init__.py @@ -6,7 +6,7 @@ import io -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context import SCOV.expgen.operand as operand import SCOV.expgen.utils as utils @@ -33,21 +33,21 @@ class Language(object): NAME = None - SUPPORT_MODULE = 'support' + SUPPORT_MODULE = "support" # The "types" module is used to define types used by operands. - TYPES_MODULE = 'types' + TYPES_MODULE = "types" # The "run" module contains all "run_*" procedures called by test drivers. - RUN_MODULE = 'run' + RUN_MODULE = "run" # These "run_*" functions call the "compute" function in the "computing" # module. - COMPUTING_MODULE = 'computing' - ENTRY_POINT_NAME = 'compute' - ASSERT_PROC_NAME = 'assert' + COMPUTING_MODULE = "computing" + ENTRY_POINT_NAME = "compute" + ASSERT_PROC_NAME = "assert" # Used to format the name of the test procedures. BOOL_TO_CHAR = { - False: 'F', - True: 'T', + False: "F", + True: "T", } def __init__(self): @@ -82,9 +82,7 @@ def serialize_run_module_implementation( """ raise NotImplementedError() - def serialize_specification_types( - self, stream, types - ): + def serialize_specification_types(self, stream, types): """ Output a specification source that contains declarations for the given `types`. The name of the module for these specification is @@ -103,9 +101,7 @@ def serialize_specification_program( raise NotImplementedError() def serialize_implementation( - self, stream, - program, formal_names, formal_types, - one_operand_per_line + self, stream, program, formal_names, formal_types, one_operand_per_line ): """ Output an implementation source that contain the "compute" function, @@ -120,7 +116,7 @@ def handle(self, expr, *args, **kwargs): handling method, passing it the *args and **kwargs arguments. """ arg_type = type(expr).__name__ - arg_handler = getattr(self, 'handle_{}'.format(arg_type)) + arg_handler = getattr(self, "handle_{}".format(arg_type)) return arg_handler(expr, *args, **kwargs) def format_tree(self, tree, *args, **kwargs): @@ -181,11 +177,9 @@ def check_language(self, xnode): this instance. """ assert xnode.language == self.NAME, ( - '{} construct is specific to {} ' - 'but is used with language {}'.format( - type(xnode).__name__, - xnode.language, - self.NAME + "{} construct is specific to {} " + "but is used with language {}".format( + type(xnode).__name__, xnode.language, self.NAME ) ) @@ -203,12 +197,11 @@ def handle_tagged_node(self, tagged_node): self.handle(tagged_node.node) def get_run_procedure_name(self, truth_vector): - return 'run_{}_{}'.format( - ''.join( - self.BOOL_TO_CHAR[b] - for b in truth_vector[:-1] + return "run_{}_{}".format( + "".join( + self.BOOL_TO_CHAR[b] for b in truth_vector[:-1] ), # Actuals - self.BOOL_TO_CHAR[truth_vector[-1]] # Result + self.BOOL_TO_CHAR[truth_vector[-1]], # Result ) # @@ -234,7 +227,7 @@ def handle_language_specific_operand(self, xoperand): self.check_language(xoperand) # Languages can process identifiers in a specific way. formal_name, remaining_tag = self.format_tree( - ast.VariableUsage(xoperand.formal_name) + syntax.VariableUsage(xoperand.formal_name) ) if remaining_tag: self.add_tag(remaining_tag) @@ -244,7 +237,7 @@ def handle_language_specific_context(self, xcontext): self.check_language(xcontext) for line in xcontext.format: try: - index = line.index('{decision_expr}') + index = line.index("{decision_expr}") except ValueError: self.write(line) else: @@ -298,17 +291,19 @@ def filter_types(self, types): """ Return the subset of `types` that can be used with this language. """ - return self._filter_nodes(ast.XType, types) + return self._filter_nodes(syntax.XType, types) # # Formatting helper classes # + class IndentationGuard(object): """ Increment the indentation level on entry and decrement it when leaving. """ + def __init__(self, formatter, addend): self.formatter = formatter self.addend = addend @@ -316,7 +311,7 @@ def __init__(self, formatter, addend): def __enter__(self): self.formatter.push_indent(self.addend) - def __exit__(self, type, value, traceback): + def __exit__(self, exptype, value, traceback): self.formatter.pop_indent() @@ -355,7 +350,7 @@ def write(self, string): """ if self.current_column == 0: self.current_column = self.indent_stack[-1] - self.stream.write(' ' * self.indent_stack[-1]) + self.stream.write(" " * self.indent_stack[-1]) self.stream.write(string) self.current_column += len(string) @@ -378,7 +373,7 @@ def indent(self, addend=0): def newline(self): """Flush any tag and insert a new line character.""" self.flush_tags() - self.stream.write('\n') + self.stream.write("\n") self.current_column = 0 def add_tag(self, tag): @@ -387,15 +382,15 @@ def add_tag(self, tag): if self.line_tag: if tag.name != self.line_tag.name: raise ValueError( - 'Trying to insert a `{}` tag on a line where there is a ' - '`{}` tag'.format(tag.name, self.line_tag.name) + "Trying to insert a `{}` tag on a line where there is a " + "`{}` tag".format(tag.name, self.line_tag.name) ) if tag.context != self.line_tag.context: raise ValueError( - 'Trying to insert a `{}` tag on a line where there is a ' - '`{}` tag'.format(tag.context, self.line_tag.context) + "Trying to insert a `{}` tag on a line where there is a " + "`{}` tag".format(tag.context, self.line_tag.context) ) - tag = tag._replace(operand='all') + tag = tag._replace(operand="all") self.line_tag = tag def flush_tags(self): @@ -406,5 +401,5 @@ def flush_tags(self): comment = self.language.format_comment( utils.format_tag(self.line_tag) ) - self.stream.write(' {}'.format(comment)) + self.stream.write(" {}".format(comment)) self.line_tag = None diff --git a/testsuite/SCOV/expgen/language/ada/__init__.py b/testsuite/SCOV/expgen/language/ada/__init__.py index 5255c6f46..427fb1d9c 100644 --- a/testsuite/SCOV/expgen/language/ada/__init__.py +++ b/testsuite/SCOV/expgen/language/ada/__init__.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.utils as utils import SCOV.expgen.language as language # Serialization of relational operators REL_OP = { - ast.RelOp.GT: '>', - ast.RelOp.GE: '>=', - ast.RelOp.LT: '>', - ast.RelOp.LE: '>=', - ast.RelOp.EQ: '=', - ast.RelOp.NE: '/=', + syntax.RelOp.GT: ">", + syntax.RelOp.GE: ">=", + syntax.RelOp.LT: ">", + syntax.RelOp.LE: ">=", + syntax.RelOp.EQ: "=", + syntax.RelOp.NE: "/=", } # Serialization for builtin types BUILTIN_TYPES = { - ast.Types.BOOLEAN: 'Boolean', - ast.Types.INTEGER: 'Integer', + syntax.Types.BOOLEAN: "Boolean", + syntax.Types.INTEGER: "Integer", } @@ -31,10 +31,10 @@ def conv_name(name): up_next = False result.append(c.upper()) continue - if c == '_': + if c == "_": up_next = True result.append(c) - return ''.join(result) + return "".join(result) class PackageGuard(object): @@ -47,24 +47,22 @@ def __init__(self, language, is_spec, module_name): self.indent_guard = language.indent(language.INDENT) def __enter__(self): - self.language.write('package {}{} is'.format( - '' if self.is_spec else 'body ', - conv_name(self.module_name) - )) + self.language.write( + "package {}{} is".format( + "" if self.is_spec else "body ", conv_name(self.module_name) + ) + ) self.language.newline() self.indent_guard.__enter__() - def __exit__(self, type, value, traceback): - self.indent_guard.__exit__(type, value, traceback) - self.language.write( - 'end {};'.format(conv_name(self.module_name)) - ) + def __exit__(self, exctype, value, traceback): + self.indent_guard.__exit__(exctype, value, traceback) + self.language.write("end {};".format(conv_name(self.module_name))) self.language.newline() class Language(language.Language): - - NAME = 'Ada' + NAME = "Ada" INDENT = 3 # @@ -72,10 +70,10 @@ class Language(language.Language): # def get_specification_filename(self, module_name): - return '{}.ads'.format(module_name) + return "{}.ads".format(module_name) def get_implementation_filename(self, module_name): - return '{}.adb'.format(module_name) + return "{}.adb".format(module_name) # # Serialization entry points @@ -101,28 +99,33 @@ def serialize_run_module_implementation( self.add_subprogram_signature( procedure_name, None, [], [], False ) - self.write('begin') + self.write("begin") self.newline() with self.indent(self.INDENT): - call_to_run = ast.Call( - ast.VariableUsage(self.ENTRY_POINT_NAME), + call_to_run = syntax.Call( + syntax.VariableUsage(self.ENTRY_POINT_NAME), [ op_kind.actuals[op_truth] - for op_kind, op_truth - in zip(operand_kinds, truth_vector) - ] + for op_kind, op_truth in zip( + operand_kinds, truth_vector + ) + ], + ) + self.handle( + syntax.Call( + syntax.VariableUsage(self.ASSERT_PROC_NAME), + [ + syntax.Comparison( + syntax.RelOp.EQ, + call_to_run, + syntax.LitteralBoolean(truth_vector[-1]), + ) + ], + ) ) - self.handle(ast.Call( - ast.VariableUsage(self.ASSERT_PROC_NAME), - [ast.Comparison( - ast.RelOp.EQ, - call_to_run, - ast.LitteralBoolean(truth_vector[-1]) - )] - )) - self.write(';') + self.write(";") self.newline() - self.write('end {};'.format(conv_name(procedure_name))) + self.write("end {};".format(conv_name(procedure_name))) self.newline() # This one is specific to the Ada language, since this is the main @@ -149,18 +152,18 @@ def serialize_run_module_interface( # If the target language is not Ada, use the C # calling/mangling/whatever... convention. if target_language.NAME != self.NAME: - self.write('Pragma Import(C, {}, "{}");'.format( - conv_name(procedure_name), procedure_name - )) + self.write( + 'Pragma Import(C, {}, "{}");'.format( + conv_name(procedure_name), procedure_name + ) + ) self.newline() - def serialize_specification_types( - self, stream, types - ): + def serialize_specification_types(self, stream, types): self.set_stream(stream) with PackageGuard(self, True, self.TYPES_MODULE): for type_decl in types: - if not isinstance(type_decl, ast.BuiltinType): + if not isinstance(type_decl, syntax.BuiltinType): self.handle(type_decl, declaration=True) def serialize_specification_program( @@ -173,15 +176,15 @@ def serialize_specification_program( with PackageGuard(self, True, self.COMPUTING_MODULE): self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - True + self.ENTRY_POINT_NAME, + syntax.BooleanType, + formal_names, + formal_types, + True, ) def serialize_implementation( - self, stream, - program, formal_names, formal_types, - one_operand_per_line + self, stream, program, formal_names, formal_types, one_operand_per_line ): self.set_stream(stream) @@ -191,9 +194,11 @@ def serialize_implementation( with PackageGuard(self, False, self.COMPUTING_MODULE): self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - False + self.ENTRY_POINT_NAME, + syntax.BooleanType, + formal_names, + formal_types, + False, ) self.handle(program) @@ -203,75 +208,76 @@ def serialize_implementation( def add_use(self, module_name): self.write( - 'with {name}; use {name};'.format(name=conv_name(module_name)) + "with {name}; use {name};".format(name=conv_name(module_name)) ) self.newline() - def add_subprogram_signature(self, name, return_type, formal_names, - formal_types, declaration): + def add_subprogram_signature( + self, name, return_type, formal_names, formal_types, declaration + ): """Add a subprogram signature to the output. If `return_type` is None, the subprogram is considered as a procedure. It is a function otherwise. """ # Add the type of subprogram and its name. - self.write('{} {}'.format( - 'function' if return_type else 'procedure', - conv_name(name), - )) + self.write( + "{} {}".format( + "function" if return_type else "procedure", + conv_name(name), + ) + ) # Add the list of formals. if len(formal_names) > 0: - self.write(' (') - for i, (name, type_) in enumerate( - zip(formal_names, formal_types) - ): + self.write(" (") + for i, (name, type_) in enumerate(zip(formal_names, formal_types)): if i > 0: - self.write('; ') - self.write('{} : '.format(conv_name(name))) + self.write("; ") + self.write("{} : ".format(conv_name(name))) self.handle(type_) - self.write(')') + self.write(")") # Add the return type, if any if return_type: - self.write(' return ') + self.write(" return ") self.handle(return_type) - self.write(';' if declaration else ' is') + self.write(";" if declaration else " is") self.newline() def handle_parent(self, expr): - self.write('(') + self.write("(") with self.indent(): self.handle(expr) - self.write(')') + self.write(")") def helper_binop(self, op, left, right): self.handle_composite_expr(left) if self.one_operand_per_line and utils.contains_tag(left): self.newline() else: - self.write(' ') - self.write('{} '.format(op)) + self.write(" ") + self.write("{} ".format(op)) self.handle_composite_expr(right) def format_comment(self, string): - return '-- {}'.format(string) + return "-- {}".format(string) def handle_program(self, program, declaration=False): with self.indent(self.INDENT): for name, type_ in program.local_vars: - self.write('{} : '.format(conv_name(name))) + self.write("{} : ".format(conv_name(name))) self.handle(type_) - self.write(';') + self.write(";") self.newline() - self.write('begin') + self.write("begin") self.newline() with self.indent(self.INDENT): for stmt in program.statements: self.handle(stmt) - self.write('end;') + self.write("end;") self.newline() # @@ -281,27 +287,27 @@ def handle_program(self, program, declaration=False): def handle_builtin_type(self, builtin_type, declaration=False): if declaration: raise ValueError( - 'Cannot output a type declaration for a builtin type' + "Cannot output a type declaration for a builtin type" ) else: self.write(BUILTIN_TYPES[builtin_type.name]) def handle_record_type(self, record_type, declaration=False): if declaration: - self.write('type {} is record'.format(conv_name(record_type.name))) + self.write("type {} is record".format(conv_name(record_type.name))) self.newline() with self.indent(self.INDENT): for member in record_type.members: self.handle(member) - self.write('end record;') + self.write("end record;") self.newline() else: self.write(conv_name(record_type.name)) def handle_member_decl(self, member_decl): - self.write('{} : '.format(conv_name(member_decl.name))) + self.write("{} : ".format(conv_name(member_decl.name))) self.handle(member_decl.type) - self.write(';') + self.write(";") self.newline() # @@ -309,10 +315,10 @@ def handle_member_decl(self, member_decl): # def handle_variable_usage(self, var): - self.write('{}'.format(conv_name(var.name))) + self.write("{}".format(conv_name(var.name))) def handle_litteral_integer(self, integer): - self.write('{}'.format(integer.value)) + self.write("{}".format(integer.value)) def handle_litteral_boolean(self, boolean): # Python and Ada happen to share the same syntax for litteral @@ -320,15 +326,15 @@ def handle_litteral_boolean(self, boolean): self.write(str(boolean.value)) def handle_litteral_record(self, record): - self.write('(') + self.write("(") for i, (member, decl) in enumerate( zip(record.members, record.type.members) ): if i > 0: - self.write(', ') - self.write('{} => '.format(conv_name(decl.name))) + self.write(", ") + self.write("{} => ".format(conv_name(decl.name))) self.handle(member) - self.write(')') + self.write(")") def handle_comparison(self, comp): self.helper_binop(REL_OP[comp.operator], comp.left, comp.right) @@ -336,86 +342,90 @@ def handle_comparison(self, comp): def handle_call(self, expr): self.handle_composite_expr(expr.function) if len(expr.arguments) > 0: - self.write('(') + self.write("(") with self.indent(): for i, arg in enumerate(expr.arguments): self.handle(arg) if i + 1 < len(expr.arguments): - self.write(',') + self.write(",") self.newline() - self.write(')') + self.write(")") # # Serialization for topology expressions # def handle_and_expr(self, expr): - self.helper_binop('and then', expr.left, expr.right) + self.helper_binop("and then", expr.left, expr.right) def handle_or_expr(self, expr): - self.helper_binop('or else', expr.left, expr.right) + self.helper_binop("or else", expr.left, expr.right) def handle_not_expr(self, expr): - self.write('not ') + self.write("not ") self.handle_composite_expr(expr.expr) def handle_composite_expr(self, expr): - is_composite = isinstance(expr, ( - ast.Comparison, - ast.And, ast.Or, - )) + is_composite = isinstance( + expr, + ( + syntax.Comparison, + syntax.And, + syntax.Or, + ), + ) if is_composite: - self.write('(') + self.write("(") with self.indent(): self.handle(expr) if is_composite: - self.write(')') + self.write(")") # # Serialization for statements # def handle_if_stmt(self, stmt): - self.write('if ') + self.write("if ") with self.indent(): self.handle(stmt.condition) - self.write(' then') + self.write(" then") self.newline() with self.indent(self.INDENT): self.handle(stmt.true_stmt) - self.write('else') + self.write("else") self.newline() with self.indent(self.INDENT): self.handle(stmt.false_stmt) - self.write('end if;') + self.write("end if;") self.newline() def handle_while_stmt(self, stmt): - self.write('while ') + self.write("while ") with self.indent(): self.handle(stmt.condition) - self.write(' loop') + self.write(" loop") self.newline() with self.indent(self.INDENT): self.handle(stmt.stmt) - self.write('end loop;') + self.write("end loop;") self.newline() def handle_return_stmt(self, stmt): - self.write('return ') + self.write("return ") with self.indent(): self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() def handle_assign(self, stmt): self.handle(stmt.variable) - self.write(' := ') + self.write(" := ") self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() diff --git a/testsuite/SCOV/expgen/language/ada/context.py b/testsuite/SCOV/expgen/language/ada/context.py index 164619fab..aee22cec9 100644 --- a/testsuite/SCOV/expgen/language/ada/context.py +++ b/testsuite/SCOV/expgen/language/ada/context.py @@ -2,7 +2,7 @@ """Ada-specific contexts.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context @@ -11,42 +11,44 @@ class Case(context.LanguageSpecific): The decision expression is used as the controlling expression of a case statement. """ - LANGUAGE = 'Ada' - TAG_CONTEXT = ast.TagTypes.EXPRESSION + + LANGUAGE = "Ada" + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ - 'case {decision_expr} is', - ' when True =>', - ' return True; -- # on-true', - ' when False =>', - ' return False; -- # on-false', - 'end case;', + "case {decision_expr} is", + " when True =>", + " return True; -- # on-true", + " when False =>", + " return False; -- # on-false", + "end case;", ] class DeclarationInitializer(context.LanguageSpecific): """The decision expression is used as a local boolean initializer.""" - LANGUAGE = 'Ada' - TAG_CONTEXT = ast.TagTypes.EXPRESSION + + LANGUAGE = "Ada" + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' E : Boolean := {decision_expr};' - 'begin', - ' return E;', - 'end;', + "declare", + " E : Boolean := {decision_expr};" "begin", + " return E;", + "end;", ] class Discriminant(context.LanguageSpecific): """The decision expression is used as a record discriminant.""" - LANGUAGE = 'Ada' - TAG_CONTEXT = ast.TagTypes.EXPRESSION + + LANGUAGE = "Ada" + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' type My_Type (Value : Boolean) is null record;', - ' R : My_Type (Value => {decision_expr});', - 'begin', - ' return R.Value;', - 'end;', + "declare", + " type My_Type (Value : Boolean) is null record;", + " R : My_Type (Value => {decision_expr});", + "begin", + " return R.Value;", + "end;", ] @@ -55,14 +57,15 @@ class ExitWhen(context.LanguageSpecific): The decision expression is used as the condition for an EXIT WHEN statement. """ - LANGUAGE = 'Ada' - TAG_CONTEXT = ast.TagTypes.DECISION + + LANGUAGE = "Ada" + TAG_CONTEXT = syntax.TagTypes.DECISION FORMAT = [ - 'loop', - ' exit when {decision_expr};', - ' return False; -- # on-false', - 'end loop;', - 'return True; -- # on-true', + "loop", + " exit when {decision_expr};", + " return False; -- # on-false", + "end loop;", + "return True; -- # on-true", ] @@ -71,31 +74,33 @@ class For(context.LanguageSpecific): The decision expression is used as the controlling expression of a for statement. """ - LANGUAGE = 'Ada' - TAG_CONTEXT = ast.TagTypes.EXPRESSION + + LANGUAGE = "Ada" + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' E : Boolean := False;', - 'begin', - ' for Value in False .. ({decision_expr}) loop', - ' E := Value;', - ' end loop;', - ' return E;', - 'end;', + "declare", + " E : Boolean := False;", + "begin", + " for Value in False .. ({decision_expr}) loop", + " E := Value;", + " end loop;", + " return E;", + "end;", ] class Index(context.LanguageSpecific): """The decision expression is used as an array subscript.""" - LANGUAGE = 'Ada' - TAG_CONTEXT = ast.TagTypes.EXPRESSION + + LANGUAGE = "Ada" + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' Values : array (Boolean) of Boolean := (', - ' False => False,', - ' True => True', - ' );', - 'begin', - ' return Value ({decision_expr});', - 'end;', + "declare", + " Values : array (Boolean) of Boolean := (", + " False => False,", + " True => True", + " );", + "begin", + " return Value ({decision_expr});", + "end;", ] diff --git a/testsuite/SCOV/expgen/language/ada/operand.py b/testsuite/SCOV/expgen/language/ada/operand.py index ef754e928..952f5767a 100644 --- a/testsuite/SCOV/expgen/language/ada/operand.py +++ b/testsuite/SCOV/expgen/language/ada/operand.py @@ -10,158 +10,168 @@ # # Bultin ones -INTEGER = ([], 'Integer') -STRING = ([], 'String') +INTEGER = ([], "Integer") +STRING = ([], "String") BOOLEAN_SUBTYPE = ( - ['subtype Bool_Subtype is Boolean;'], # Type declaration - 'Bool_Subtype' # Type usage + ["subtype Bool_Subtype is Boolean;"], # Type declaration + "Bool_Subtype", # Type usage ) BOOLEAN_TYPE = ( - ['type Bool_Type is new Boolean;'], # Type declaration - 'Bool_Type' # Type usage + ["type Bool_Type is new Boolean;"], # Type declaration + "Bool_Type", # Type usage ) -BOOLEAN_ACTUALS = {False: 'False', True: 'True'} +BOOLEAN_ACTUALS = {False: "False", True: "True"} SLOC_RECORD = ( [ # Type declaration - 'type Sloc is record', - ' Line : Integer;', - ' Column : Integer;', - 'end record;', + "type Sloc is record", + " Line : Integer;", + " Column : Integer;", + "end record;", ], - 'Sloc' # Type usage + "Sloc", # Type usage ) TWO_STRINGS = ( [ # Type declaration - 'type Two_Strings (L1, L2 : Integer) is record', - ' First : String (1 .. L1);', - ' Second : String (1 .. L2);', - 'end record;', + "type Two_Strings (L1, L2 : Integer) is record", + " First : String (1 .. L1);", + " Second : String (1 .. L2);", + "end record;", ], - 'Two_Strings' # Type usage + "Two_Strings", # Type usage ) SENSOR = ( [ # Type declaration - 'type Sensor is record', - ' Low, High : Integer;', - ' Value : Integer;', - 'end record;', + "type Sensor is record", + " Low, High : Integer;", + " Value : Integer;", + "end record;", ], - 'Sensor' # Type usage + "Sensor", # Type usage ) class Aggregate(operand.LanguageSpecific): """Compare the argument with some litteral aggregate.""" - LANGUAGE = 'Ada' - USED_TYPES = (SLOC_RECORD, ) + + LANGUAGE = "Ada" + USED_TYPES = (SLOC_RECORD,) PARAM_TYPE = SLOC_RECORD - FORMAT = '{formal_name} = (Line => 1, Column => 2)' + FORMAT = "{formal_name} = (Line => 1, Column => 2)" ACTUALS = { - False: '(Line => 1, Column => 3)', - True: '(Line => 1, Column => 2)', + False: "(Line => 1, Column => 3)", + True: "(Line => 1, Column => 2)", } class Component(operand.LanguageSpecific): """Compare the member of a structure with a litteral integer.""" - LANGUAGE = 'Ada' - USED_TYPES = (SLOC_RECORD, ) + + LANGUAGE = "Ada" + USED_TYPES = (SLOC_RECORD,) PARAM_TYPE = SLOC_RECORD - FORMAT = '{formal_name}.Line = 1' + FORMAT = "{formal_name}.Line = 1" ACTUALS = { - False: '(Line => 2, Column => 1)', - True: '(Line => 1, Column => 1)', + False: "(Line => 2, Column => 1)", + True: "(Line => 1, Column => 1)", } class LengthAttribute(operand.LanguageSpecific): """Compare the length of the argument with a constant.""" - LANGUAGE = 'Ada' - USED_TYPES = (STRING, ) + + LANGUAGE = "Ada" + USED_TYPES = (STRING,) PARAM_TYPE = STRING FORMAT = "{formal_name}'Length > 0" ACTUALS = { - False: '""', - True: '"Hello, world!"', + False: '""', + True: '"Hello, world!"', } class StringConcatenation(operand.LanguageSpecific): """Compare the concatenation of two strings with a litteral string.""" - LANGUAGE = 'Ada' - USED_TYPES = (STRING, TWO_STRINGS, ) + + LANGUAGE = "Ada" + USED_TYPES = ( + STRING, + TWO_STRINGS, + ) PARAM_TYPE = TWO_STRINGS FORMAT = ( - '({formal_name}.Second & {formal_name}.First)' - ' = "Hello, world!"' + "({formal_name}.Second & {formal_name}.First)" ' = "Hello, world!"' ) ACTUALS = { - False: '(Second => "I beg you", L2 => 9,' - ' First => "pardon?", L1 => 7)', - True: '(Second => "Hello, ", L2 => 7,' - ' First => "world!", L1 => 6)', + False: '(Second => "I beg you", L2 => 9,' + ' First => "pardon?", L1 => 7)', + True: '(Second => "Hello, ", L2 => 7,' + ' First => "world!", L1 => 6)', } class StringSlice(operand.LanguageSpecific): """Compare the slice of a string with a litteral string.""" - LANGUAGE = 'Ada' - USED_TYPES = (STRING, ) + + LANGUAGE = "Ada" + USED_TYPES = (STRING,) PARAM_TYPE = STRING FORMAT = ( - '{formal_name}( {formal_name}\'First .. {formal_name}\'Last - 1)' + "{formal_name}( {formal_name}'First .. {formal_name}'Last - 1)" ' = "Hell"' ) ACTUALS = { - False: '"World"', - True: '"Hello"', + False: '"World"', + True: '"Hello"', } class Modulo(operand.LanguageSpecific): """Compare the modulo of the argument with a litteral integer.""" - LANGUAGE = 'Ada' - USED_TYPES = (INTEGER, ) + + LANGUAGE = "Ada" + USED_TYPES = (INTEGER,) PARAM_TYPE = INTEGER - FORMAT = '{formal_name} mod 17 = 0' + FORMAT = "{formal_name} mod 17 = 0" ACTUALS = { - False: '18', - True: '34', + False: "18", + True: "34", } class Range(operand.LanguageSpecific): """Test whether an integer is in a range.""" - LANGUAGE = 'Ada' - USED_TYPES = (SENSOR, ) + + LANGUAGE = "Ada" + USED_TYPES = (SENSOR,) PARAM_TYPE = SENSOR FORMAT = ( - '{formal_name}.Value in ' - '{formal_name}.Low .. {formal_name}.High' + "{formal_name}.Value in " "{formal_name}.Low .. {formal_name}.High" ) ACTUALS = { - False: '(Low => 0, High => 10, Value => 15)', - True: '(Low => 0, High => 10, Value => 10)', + False: "(Low => 0, High => 10, Value => 15)", + True: "(Low => 0, High => 10, Value => 10)", } class Subtype(operand.LanguageSpecific): """Use a subtype of Boolean as an operand.""" - LANGUAGE = 'Ada' - USED_TYPES = (BOOLEAN_SUBTYPE, ) + + LANGUAGE = "Ada" + USED_TYPES = (BOOLEAN_SUBTYPE,) PARAM_TYPE = BOOLEAN_SUBTYPE - FORMAT = '{formal_name}' + FORMAT = "{formal_name}" ACTUALS = BOOLEAN_ACTUALS class DerivedType(operand.LanguageSpecific): """Use a derived type of Boolean as an operand.""" - LANGUAGE = 'Ada' - USED_TYPES = (BOOLEAN_TYPE, ) + + LANGUAGE = "Ada" + USED_TYPES = (BOOLEAN_TYPE,) PARAM_TYPE = BOOLEAN_TYPE - FORMAT = 'Boolean({formal_name})' + FORMAT = "Boolean({formal_name})" ACTUALS = BOOLEAN_ACTUALS diff --git a/testsuite/SCOV/expgen/language/c/__init__.py b/testsuite/SCOV/expgen/language/c/__init__.py index fc588fcb7..5dc3f4372 100644 --- a/testsuite/SCOV/expgen/language/c/__init__.py +++ b/testsuite/SCOV/expgen/language/c/__init__.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.utils as utils import SCOV.expgen.language as language # Serialization of relational operators REL_OP = { - ast.RelOp.GT: '>', - ast.RelOp.GE: '>=', - ast.RelOp.LT: '>', - ast.RelOp.LE: '>=', - ast.RelOp.EQ: '==', - ast.RelOp.NE: '!=', + syntax.RelOp.GT: ">", + syntax.RelOp.GE: ">=", + syntax.RelOp.LT: ">", + syntax.RelOp.LE: ">=", + syntax.RelOp.EQ: "==", + syntax.RelOp.NE: "!=", } # Serialization for builtin types BUILTIN_TYPES = { - ast.Types.BOOLEAN: 'int', - ast.Types.INTEGER: 'int', + syntax.Types.BOOLEAN: "int", + syntax.Types.INTEGER: "int", } @@ -30,32 +30,31 @@ def __init__(self, language, module_name): self.module_name = module_name def __enter__(self): - self.language.write('#ifndef {}_H'.format(self.module_name.upper())) + self.language.write("#ifndef {}_H".format(self.module_name.upper())) self.language.newline() - self.language.write('#define {}_H'.format(self.module_name.upper())) + self.language.write("#define {}_H".format(self.module_name.upper())) self.language.newline() - def __exit__(self, type, value, traceback): - self.language.write('#endif') + def __exit__(self, exctype, value, traceback): + self.language.write("#endif") self.language.newline() class Language(language.Language): - - NAME = 'C' + NAME = "C" INDENT = 2 - RUN_MODULE = 'run_body' + RUN_MODULE = "run_body" # # Filename generators # def get_specification_filename(self, module_name): - return '{}.h'.format(module_name) + return "{}.h".format(module_name) def get_implementation_filename(self, module_name): - return '{}.c'.format(module_name) + return "{}.c".format(module_name) # # Serialization entry points @@ -77,40 +76,42 @@ def serialize_run_module_implementation( self.newline() self.add_subprogram_signature( - self.get_run_procedure_name(truth_vector), - None, [], [], False + self.get_run_procedure_name(truth_vector), None, [], [], False ) - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): - call_to_run = ast.Call( - ast.VariableUsage(self.ENTRY_POINT_NAME), + call_to_run = syntax.Call( + syntax.VariableUsage(self.ENTRY_POINT_NAME), [ op_kind.actuals[op_truth] - for op_kind, op_truth - in zip(operand_kinds, truth_vector) - ] + for op_kind, op_truth in zip( + operand_kinds, truth_vector + ) + ], + ) + self.handle( + syntax.Call( + syntax.VariableUsage(self.ASSERT_PROC_NAME), + [ + syntax.Comparison( + syntax.RelOp.EQ, + call_to_run, + syntax.LitteralBoolean(truth_vector[-1]), + ) + ], + ) ) - self.handle(ast.Call( - ast.VariableUsage(self.ASSERT_PROC_NAME), - [ast.Comparison( - ast.RelOp.EQ, - call_to_run, - ast.LitteralBoolean(truth_vector[-1]) - )] - )) - self.write(';') + self.write(";") self.newline() - self.write('}') + self.write("}") self.newline() - def serialize_specification_types( - self, stream, types - ): + def serialize_specification_types(self, stream, types): self.set_stream(stream) with HeaderGuard(self, self.TYPES_MODULE): for type_decl in types: - if not isinstance(type_decl, ast.BuiltinType): + if not isinstance(type_decl, syntax.BuiltinType): self.handle(type_decl, declaration=True) def serialize_specification_program( @@ -122,15 +123,15 @@ def serialize_specification_program( self.newline() self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - True + self.ENTRY_POINT_NAME, + syntax.BooleanType, + formal_names, + formal_types, + True, ) def serialize_implementation( - self, stream, - program, formal_names, formal_types, - one_operand_per_line + self, stream, program, formal_names, formal_types, one_operand_per_line ): self.set_stream(stream) @@ -142,14 +143,16 @@ def serialize_implementation( self.newline() self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - False + self.ENTRY_POINT_NAME, + syntax.BooleanType, + formal_names, + formal_types, + False, ) - self.write('{') + self.write("{") self.newline() self.handle(program) - self.write('}') + self.write("}") self.newline() # @@ -160,8 +163,9 @@ def add_include(self, module_name): self.write('#include "{}.h"'.format(module_name)) self.newline() - def add_subprogram_signature(self, name, return_type, formal_names, - formal_types, declaration): + def add_subprogram_signature( + self, name, return_type, formal_names, formal_types, declaration + ): """Add a subprogram signature to the output. If `return_type` is None, the subprogram is considered as a procedure. @@ -169,53 +173,51 @@ def add_subprogram_signature(self, name, return_type, formal_names, """ # Add subprogram return type, prepend subprogram linkage if needed. if declaration: - self.write('extern ') + self.write("extern ") if return_type: self.handle(return_type) else: - self.write('void') + self.write("void") self.newline() # Then add the name of the subprogram and its arguments. - self.write('{} ('.format(name)) - for i, (name, type_) in enumerate( - zip(formal_names, formal_types) - ): + self.write("{} (".format(name)) + for i, (name, type_) in enumerate(zip(formal_names, formal_types)): if i > 0: - self.write(', ') + self.write(", ") self.handle(type_) - self.write(' {}'.format(name)) + self.write(" {}".format(name)) if len(formal_names) == 0: - self.write('void') - self.write(')') + self.write("void") + self.write(")") if declaration: - self.write(';') + self.write(";") self.newline() def handle_parent(self, expr): - self.write('(') + self.write("(") with self.indent(): self.handle(expr) - self.write(')') + self.write(")") def helper_binop(self, op, left, right): self.handle_composite_expr(left) if self.one_operand_per_line and utils.contains_tag(left): self.newline() else: - self.write(' ') - self.write('{} '.format(op)) + self.write(" ") + self.write("{} ".format(op)) self.handle_composite_expr(right) def format_comment(self, string): - return '// {}'.format(string) + return "// {}".format(string) def handle_program(self, program, declaration=False): with self.indent(self.INDENT): for name, type_ in program.local_vars: self.handle(type_) - self.write(' {};'.format(name)) + self.write(" {};".format(name)) self.newline() for stmt in program.statements: @@ -228,28 +230,28 @@ def handle_program(self, program, declaration=False): def handle_builtin_type(self, builtin_type, declaration=False): if declaration: raise ValueError( - 'Cannot output a type declaration for a builtin type' + "Cannot output a type declaration for a builtin type" ) else: self.write(BUILTIN_TYPES[builtin_type.name]) def handle_record_type(self, record_type, declaration=False): if declaration: - self.write('struct {}'.format(record_type.name)) + self.write("struct {}".format(record_type.name)) self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): for member in record_type.members: self.handle(member) - self.write('};') + self.write("};") self.newline() else: - self.write('struct {}'.format(record_type.name)) + self.write("struct {}".format(record_type.name)) def handle_member_decl(self, member_decl): self.handle(member_decl.type) - self.write(' {};'.format(member_decl.name)) + self.write(" {};".format(member_decl.name)) self.newline() # @@ -257,118 +259,120 @@ def handle_member_decl(self, member_decl): # def handle_variable_usage(self, var): - self.write('{}'.format(var.name)) + self.write("{}".format(var.name)) def handle_litteral_integer(self, integer): - self.write('{}'.format(integer.value)) + self.write("{}".format(integer.value)) def handle_litteral_boolean(self, boolean): - self.write('{}'.format( - {True: 1, False: 0}[boolean.value] - )) + self.write("{}".format({True: 1, False: 0}[boolean.value])) def handle_litteral_record(self, record): - self.write('(') + self.write("(") self.handle(record.type) - self.write(') {') + self.write(") {") for i, member in enumerate(record.members): if i > 0: - self.write(', ') + self.write(", ") self.handle(member) - self.write('}') + self.write("}") def handle_comparison(self, comp): self.helper_binop(REL_OP[comp.operator], comp.left, comp.right) def handle_call(self, expr): self.handle_composite_expr(expr.function) - self.write('(') + self.write("(") with self.indent(): for i, arg in enumerate(expr.arguments): self.handle(arg) if i + 1 < len(expr.arguments): - self.write(',') + self.write(",") self.newline() - self.write(')') + self.write(")") # # Serialization for topology expressions # def handle_and_expr(self, expr): - self.helper_binop('&&', expr.left, expr.right) + self.helper_binop("&&", expr.left, expr.right) def handle_or_expr(self, expr): - self.helper_binop('||', expr.left, expr.right) + self.helper_binop("||", expr.left, expr.right) def handle_not_expr(self, expr): - self.write('!') + self.write("!") self.handle_composite_expr(expr.expr) def handle_composite_expr(self, expr): - is_composite = isinstance(expr, ( - ast.Comparison, - ast.And, ast.Or, - )) + is_composite = isinstance( + expr, + ( + syntax.Comparison, + syntax.And, + syntax.Or, + ), + ) if is_composite: - self.write('(') + self.write("(") with self.indent(): self.handle(expr) if is_composite: - self.write(')') + self.write(")") # # Serialization for statements # def handle_if_stmt(self, stmt): - self.write('if (') + self.write("if (") with self.indent(): self.handle(stmt.condition) - self.write(')') + self.write(")") self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): self.handle(stmt.true_stmt) - self.write('}') + self.write("}") self.newline() - self.write('else') + self.write("else") self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): self.handle(stmt.false_stmt) - self.write('}') + self.write("}") self.newline() def handle_while_stmt(self, stmt): - self.write('while (') + self.write("while (") with self.indent(): self.handle(stmt.condition) - self.write(')') + self.write(")") self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): self.handle(stmt.stmt) - self.write('}') + self.write("}") self.newline() def handle_return_stmt(self, stmt): - self.write('return ') + self.write("return ") with self.indent(): self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() def handle_assign(self, stmt): self.handle(stmt.variable) - self.write(' = ') + self.write(" = ") self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() diff --git a/testsuite/SCOV/expgen/language/c/context.py b/testsuite/SCOV/expgen/language/c/context.py index 1b398a990..c97b41331 100644 --- a/testsuite/SCOV/expgen/language/c/context.py +++ b/testsuite/SCOV/expgen/language/c/context.py @@ -2,15 +2,16 @@ """C-specific contexts""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context class DeclarationInitializer(context.LanguageSpecific): """The decision expression is used as a local boolean initializer.""" - LANGUAGE = 'C' - TAG_CONTEXT = ast.TagTypes.EXPRESSION + + LANGUAGE = "C" + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ - 'int result = {decision_expr};', - 'return result;', + "int result = {decision_expr};", + "return result;", ] diff --git a/testsuite/SCOV/expgen/language/c/operand.py b/testsuite/SCOV/expgen/language/c/operand.py index 05ebbf6f9..7006ac50e 100644 --- a/testsuite/SCOV/expgen/language/c/operand.py +++ b/testsuite/SCOV/expgen/language/c/operand.py @@ -10,40 +10,42 @@ # # Builtin types -INTEGER = ([], 'int') +INTEGER = ([], "int") SLOC_STRUCT = ( [ # Type declaration - 'struct sloc', - '{', - ' int line;', - ' int column;', - '};' + "struct sloc", + "{", + " int line;", + " int column;", + "};", ], - 'struct sloc' # Type usage + "struct sloc", # Type usage ) class Component(operand.LanguageSpecific): """Compare a field of a structure with a litteral integer.""" - LANGUAGE = 'C' - USED_TYPES = (SLOC_STRUCT, ) + + LANGUAGE = "C" + USED_TYPES = (SLOC_STRUCT,) PARAM_TYPE = SLOC_STRUCT - FORMAT = '{formal_name}.line == 1' + FORMAT = "{formal_name}.line == 1" ACTUALS = { - False: '(struct sloc) {2, 1}', - True: '(struct sloc) {1, 1}', + False: "(struct sloc) {2, 1}", + True: "(struct sloc) {1, 1}", } class Modulo(operand.LanguageSpecific): """Compare the modulo of the arguent with a litteral integer.""" - LANGUAGE = 'C' - USED_TYPES = (INTEGER, ) + + LANGUAGE = "C" + USED_TYPES = (INTEGER,) PARAM_TYPE = INTEGER - FORMAT = '{formal_name} % 17 == 0' + FORMAT = "{formal_name} % 17 == 0" ACTUALS = { - False: '18', - True: '34', + False: "18", + True: "34", } diff --git a/testsuite/SCOV/expgen/operand.py b/testsuite/SCOV/expgen/operand.py index 204daa3df..2e12fe91e 100644 --- a/testsuite/SCOV/expgen/operand.py +++ b/testsuite/SCOV/expgen/operand.py @@ -2,7 +2,7 @@ """Expose operand kinds suitable for condition expressions.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax class Operand(object): @@ -67,20 +67,20 @@ def __init__(self): if type_ is self.PARAM_TYPE: param_type = xtype - assert param_type is not None, ( - 'PARAM_TYPE must be present in USED_TYPES' - ) + assert ( + param_type is not None + ), "PARAM_TYPE must be present in USED_TYPES" # Convert ACTUALS to ast.XLitteral nodes. actuals = { - False: ast.XLitteral(self.LANGUAGE, self.ACTUALS[False]), - True: ast.XLitteral(self.LANGUAGE, self.ACTUALS[True]), + False: syntax.XLitteral(self.LANGUAGE, self.ACTUALS[False]), + True: syntax.XLitteral(self.LANGUAGE, self.ACTUALS[True]), } super(LanguageSpecific, self).__init__(xtypes, param_type, actuals) def get_operand(self, param): - return ast.XOperand(self.LANGUAGE, self.FORMAT, param) + return syntax.XOperand(self.LANGUAGE, self.FORMAT, param) # Mapping: type_tuple id -> ast.XType # This is global since a type can be used in more than one operand kind, @@ -94,7 +94,7 @@ def convert_type(self, type_): xtype = self.converted_types[type_id] except KeyError: declaration, usage = type_ - xtype = ast.XType(self.LANGUAGE, declaration, usage) + xtype = syntax.XType(self.LANGUAGE, declaration, usage) self.converted_types[type_id] = xtype return xtype @@ -103,19 +103,17 @@ class Variable(Operand): """The operand is just the usage of a boolean argument.""" ACTUALS = { - False: ast.LitteralBoolean(False), - True: ast.LitteralBoolean(True), + False: syntax.LitteralBoolean(False), + True: syntax.LitteralBoolean(True), } def __init__(self): super(Variable, self).__init__( - (ast.BooleanType, ), - ast.BooleanType, - self.ACTUALS + (syntax.BooleanType,), syntax.BooleanType, self.ACTUALS ) def get_operand(self, param): - return ast.VariableUsage(param) + return syntax.VariableUsage(param) class IntegerComparison(Operand): @@ -125,36 +123,28 @@ class IntegerComparison(Operand): # Each factory takes the compared integer and returns (a false actual, a # true one). ACTUALS_MAKERS = { - ast.RelOp.GT: - lambda value: (value - 1, value + 1), - ast.RelOp.GE: - lambda value: (value - 1, value + 1), - ast.RelOp.LT: - lambda value: (value + 1, value - 2), - ast.RelOp.LE: - lambda value: (value + 1, value - 2), - ast.RelOp.EQ: - lambda value: (value + 1, value), - ast.RelOp.NE: - lambda value: (value, value + 1), + syntax.RelOp.GT: lambda value: (value - 1, value + 1), + syntax.RelOp.GE: lambda value: (value - 1, value + 1), + syntax.RelOp.LT: lambda value: (value + 1, value - 2), + syntax.RelOp.LE: lambda value: (value + 1, value - 2), + syntax.RelOp.EQ: lambda value: (value + 1, value), + syntax.RelOp.NE: lambda value: (value, value + 1), } def __init__(self, operator, value): actual_false, actual_true = self.ACTUALS_MAKERS[operator](value) super(IntegerComparison, self).__init__( - (ast.IntegerType, ), - ast.IntegerType, + (syntax.IntegerType,), + syntax.IntegerType, { - False: ast.LitteralInteger(actual_false), - True: ast.LitteralInteger(actual_true), - } + False: syntax.LitteralInteger(actual_false), + True: syntax.LitteralInteger(actual_true), + }, ) self.operator = operator - self.value = ast.LitteralInteger(value) + self.value = syntax.LitteralInteger(value) def get_operand(self, param): - return ast.Comparison( - self.operator, - ast.VariableUsage(param), - self.value + return syntax.Comparison( + self.operator, syntax.VariableUsage(param), self.value ) diff --git a/testsuite/SCOV/expgen/syntax.py b/testsuite/SCOV/expgen/syntax.py new file mode 100644 index 000000000..0a4d0000b --- /dev/null +++ b/testsuite/SCOV/expgen/syntax.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- + +""" +Expose various construct that can be used to build abstract trees. Those trees +can then be used to generate programs. + +The idea is not to reimplement a full AST for both C and Ada, but rather focus +on an interesting common set of constructs for tests. When too specific +constructs are needed, just use the X* node kinds: XType, XOperand, etc. +""" + +from collections import namedtuple + + +class RelOp(object): + """Available relational operators.""" + + GT = ">" + GE = ">=" + LT = "<" + LE = "<=" + EQ = "==" + NE = "!=" + + +class Types(object): + """Available basic types for local variable declarations.""" + + BOOLEAN = "boolean" + INTEGER = "integer" + + +class TagTypes(object): + """Available decision context types for tags.""" + + DECISION = ":d:" + EXPRESSION = ":e:" + + +Program = namedtuple("program", "local_vars statements") + + +# Types: used for both declarations and usages +BuiltinType = namedtuple("builtin_type", "name") +RecordType = namedtuple("record_type", "name members") +MemberDecl = namedtuple("member_decl", "type name") + +# ... and some regularly used ones. Note that builtin types must not be +# declared +BooleanType = BuiltinType(Types.BOOLEAN) +IntegerType = BuiltinType(Types.INTEGER) + + +# Expressions: when adding nodes to these or to topology ones, do not forget to +# update the `utils.is_expr` function. +VariableUsage = namedtuple("variable_usage", "name") +LitteralInteger = namedtuple("litteral_integer", "value") +LitteralBoolean = namedtuple("litteral_boolean", "value") +LitteralRecord = namedtuple("litteral_record", "type members") +Comparison = namedtuple("comparison", "operator left right") +Call = namedtuple("call", "function arguments") + +# Topology expressions +And = namedtuple("and_expr", "left right") +Or = namedtuple("or_expr", "left right") +Not = namedtuple("not_expr", "expr") + + +# Statements +If = namedtuple("if_stmt", "condition true_stmt false_stmt") +While = namedtuple("while_stmt", "condition stmt") +Return = namedtuple("return_stmt", "expr") +Assign = namedtuple("assign", "variable expr") + +# Language-specific constructs: +# - Type +XType = namedtuple("language_specific_type", "language declaration usage") +# - Litteral (for actuals, mostly) +XLitteral = namedtuple("language_specific_litteral", "language format") +# - Operand +XOperand = namedtuple( + "language_specific_operand", "language format formal_name" +) +# - Context +XContext = namedtuple( + "language_specific_context", "language format decision_expr" +) + +# Tag +# Used to tag lines, so that test drivers can reference the correct lines for +# expectations. +# - Custom tags may only define the `name` attribute, leaving `operand` and +# `context` as None. +# - If name is `eval`, `operand` must be the formal name that is used in the +# tagged operand, or `all` if all operands are on the same line. In both +# cases, `context` must be `TagTypes.(DECISION or EXPRESSION)` depending on +# the context of the tagged decision. +Tag = namedtuple("tag", "name operand context") +TaggedNode = namedtuple("tagged_node", "tag node") diff --git a/testsuite/SCOV/expgen/topology.py b/testsuite/SCOV/expgen/topology.py index 18071043c..ba6013c13 100644 --- a/testsuite/SCOV/expgen/topology.py +++ b/testsuite/SCOV/expgen/topology.py @@ -11,11 +11,12 @@ expression: to do so, placeholders are replaced by "operand" expressions. """ -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax class OperandPlaceholder(object): """Placeholder to be put in expressions to specify a topology.""" + pass @@ -36,10 +37,7 @@ def get_arity(self, expression): if isinstance(expression, OperandPlaceholder): return 1 else: - return sum( - self.get_arity(sub_expr) - for sub_expr in expression - ) + return sum(self.get_arity(sub_expr) for sub_expr in expression) def instanciate(self, operands, formal_names, context): """ @@ -58,9 +56,9 @@ def helper(expression, i): # If we find a placeholder, return the next operand after tagging # it. if isinstance(expression, OperandPlaceholder): - result = ast.TaggedNode( - ast.Tag('eval', formal_names[i], context.TAG_CONTEXT), - operands[i] + result = syntax.TaggedNode( + syntax.Tag("eval", formal_names[i], context.TAG_CONTEXT), + operands[i], ) return (result, i + 1) @@ -102,20 +100,20 @@ def helper(expression, i): return (operands[i], i + 1) # Otherwise, evaluate sub-expressions and return the result. - if isinstance(expression, ast.And): + if isinstance(expression, syntax.And): left, i = helper(expression.left, i) right, i = helper(expression.right, i) return (left and right, i) - elif isinstance(expression, ast.Or): + elif isinstance(expression, syntax.Or): left, i = helper(expression.left, i) right, i = helper(expression.right, i) return (left or right, i) - elif isinstance(expression, ast.Not): + elif isinstance(expression, syntax.Not): result, i = helper(expression.expr, i) return (not result, i) else: raise ValueError( - 'Invalid topology node: {}'.format(expression) + "Invalid topology node: {}".format(expression) ) # The number of operands must naturally match the number of @@ -130,21 +128,20 @@ def helper(expression, i): return result def __str__(self): - - placeholders = list(reversed('ABCDEFGHIJ')) + placeholders = list(reversed("ABCDEFGHIJ")) def helper(expr): if isinstance(expr, OperandPlaceholder): return placeholders.pop() - elif isinstance(expr, ast.And): - return '({} and {})'.format( + elif isinstance(expr, syntax.And): + return "({} and {})".format( helper(expr.left), helper(expr.right) ) - elif isinstance(expr, ast.Or): - return '({} or {})'.format( + elif isinstance(expr, syntax.Or): + return "({} or {})".format( helper(expr.left), helper(expr.right) ) else: - return 'not {}'.format(helper(expr.expr)) + return "not {}".format(helper(expr.expr)) return helper(self.expression) diff --git a/testsuite/SCOV/expgen/utils.py b/testsuite/SCOV/expgen/utils.py index b8725a131..a79764a89 100644 --- a/testsuite/SCOV/expgen/utils.py +++ b/testsuite/SCOV/expgen/utils.py @@ -2,13 +2,16 @@ """Various helpers used through the whole package.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax def check_tag(tag): """Assert whether the given `tag` is valid, or not.""" - if tag.name == 'eval': - assert tag.context in (ast.TagTypes.DECISION, ast.TagTypes.EXPRESSION) + if tag.name == "eval": + assert tag.context in ( + syntax.TagTypes.DECISION, + syntax.TagTypes.EXPRESSION, + ) assert tag.operand is not None else: assert tag.operand is None @@ -17,32 +20,38 @@ def check_tag(tag): def format_tag(tag): """Serialize the given `tag`.""" - if tag.name == 'eval': - return '# {}-{} {}'.format(tag.name, tag.operand, tag.context) + if tag.name == "eval": + return "# {}-{} {}".format(tag.name, tag.operand, tag.context) else: - return '# {}'.format(tag.name) + return "# {}".format(tag.name) def contains_tag(node): """Return if the given `node` tree contains a tagged node.""" - return ( - not isinstance(node, (str, bool, int)) and - ( - isinstance(node, ast.TaggedNode) or - any(contains_tag(subnode) for subnode in node) - ) + return not isinstance(node, (str, bool, int)) and ( + isinstance(node, syntax.TaggedNode) + or any(contains_tag(subnode) for subnode in node) ) def is_expr(node): """Return whether `node` is an expression.""" - return isinstance(node, ( - ast.VariableUsage, - ast.LitteralInteger, ast.LitteralBoolean, ast.LitteralRecord, - ast.Comparison, ast.Call, - ast.XLitteral, ast.XOperand, - ast.And, ast.Or, ast.Not, - )) + return isinstance( + node, + ( + syntax.VariableUsage, + syntax.LitteralInteger, + syntax.LitteralBoolean, + syntax.LitteralRecord, + syntax.Comparison, + syntax.Call, + syntax.XLitteral, + syntax.XOperand, + syntax.And, + syntax.Or, + syntax.Not, + ), + ) def make_type_set(types): @@ -58,18 +67,14 @@ def add_if_new(type_): else: return False - return [ - type_ - for type_ in types - if add_if_new(type_) - ] + return [type_ for type_ in types if add_if_new(type_)] def is_topology_equal(topo1, topo2): """Return whether two topologies are equal.""" - if type(topo1) != type(topo2): + if type(topo1) is not type(topo2): return False - elif isinstance(topo1, (ast.And, ast.Not, ast.Or)): + elif isinstance(topo1, (syntax.And, syntax.Not, syntax.Or)): return all( is_topology_equal(sub_topo1, sub_topo2) for sub_topo1, sub_topo2 in zip(topo1, topo2) diff --git a/testsuite/SCOV/htc.py b/testsuite/SCOV/htc.py index 5a96a6553..ef80dbe59 100644 --- a/testsuite/SCOV/htc.py +++ b/testsuite/SCOV/htc.py @@ -34,8 +34,9 @@ def match(self, reported): class HarnessTestCase(TestCase): - def __init__(self, expected_diags, extradrivers="", extracargs="", - category=CAT.auto): + def __init__( + self, expected_diags, extradrivers="", extracargs="", category=CAT.auto + ): TestCase.__init__(self, extradrivers, extracargs, category) # By default, these test cases expect failures from subprocesses @@ -58,7 +59,9 @@ def run(self): for errtext in re.findall( pattern=r"^ \* (?:exception|\(.*\)) .*", string=contents_of(thistest.report.report_file), - flags=re.M)] + flags=re.M, + ) + ] for reported in self.reported_diags: for expected in self.expected_diags: @@ -66,12 +69,16 @@ def run(self): self.__count_match_on(reported, expected) for expected in self.expected_diags: - thistest.fail_if(expected.nmatches != 1, - "expectation check failed - %s" % expected.text) + thistest.fail_if( + expected.nmatches != 1, + "expectation check failed - %s" % expected.text, + ) for i in self.reported_diags: print(i.__dict__) for reported in self.reported_diags: - thistest.fail_if(reported.nmatches != 1, - "reporting check failed - %s" % reported.text) + thistest.fail_if( + reported.nmatches != 1, + "reporting check failed - %s" % reported.text, + ) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index d6c4d78e8..7f77781c0 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -2,48 +2,79 @@ import os.path import re +import shutil -from e3.fs import mkdir +from e3.fs import mkdir, sync_tree from SUITE.context import thistest -from SUITE.cutils import contents_of, ext, indent -from SUITE.tutils import RUNTIME_INFO, xcov +from SUITE.control import env +from SUITE.cutils import contents_of, ext, copy_to_dir +from SUITE.tutils import ( + RUNTIME_INFO, + GNATCOV_INFO, + gpr_common_args, + locate_gpr_file, + xcov, +) def default_dump_trigger(mains): """Return the default dump trigger to use in testcases.""" - if RUNTIME_INFO.has_full_runtime: - return 'atexit' + if thistest.options.default_dump_trigger: + return thistest.options.default_dump_trigger + elif RUNTIME_INFO.has_full_runtime: + return "atexit" # It does not make sense to have a dump-trigger=ravenscar-task-termination # if the main is not an Ada program. - elif (all([ext(main) == 'adb' for main in mains]) - and RUNTIME_INFO.has_ravenscar_runtime): - return 'ravenscar-task-termination' + elif ( + all(ext(main) == "adb" for main in mains) + and RUNTIME_INFO.has_ravenscar_runtime + # TODO: There seems to be a problem with light-tasking runtimes and + # task-termination, so default back to main end in that case. + # See eng/cov/gnatcoverage#191 + and "light-tasking" not in RUNTIME_INFO.runtime_name + ): + return "ravenscar-task-termination" else: - return 'main-end' + return "main-end" def default_dump_channel(): """Return the default dump channel to use in testcases.""" - if RUNTIME_INFO.has_full_runtime: - return 'bin-file' + if thistest.options.default_dump_channel: + return thistest.options.default_dump_channel + elif RUNTIME_INFO.has_full_runtime: + return "bin-file" else: - return 'base64-stdout' - - -def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", - dump_channel="auto", gpr_obj_dir=None, - runtime_project=None, out=None, err=None, - warnings_as_errors=True, register_failure=True, - auto_languages=True): + return "base64-stdout" + + +def xcov_instrument( + gprsw, + covlevel, + quiet=True, + extra_args=None, + dump_trigger="auto", + dump_channel="auto", + gpr_obj_dir=None, + runtime_project=None, + out=None, + err=None, + tolerate_messages=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, +): """ Run "gnatcov instrument" on a project. :param GPRswitches gprsw: Project file command line switches to honor. :param None|str covlevel: Coverage level for the instrumentation (--level argument). Not passed if None. - :param list[str] extra_args: Extra arguments to append to the command line. + :param bool quiet: Whether to pass the "--quiet" flag. + :param list[str] | None extra_args: Extra arguments to append to the + command line. :param None|str dump_trigger: If None, do not pass the --dump-trigger argument. If "auto", pass the result of default_dump_trigger(). Otherwise, pass the given value. @@ -56,8 +87,12 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", :param None|str runtime_project: If None, use the default name for the instrumentation runtime project. Otherwise, use the name given for this option. - :param bool warnings_as_errors: Whether to make the test fail if there are - warnings in gnatcov's output. + :param None|str tolerate_messages: If not None, a re pattern of warning + or error messsages tolerated in the tool output. Messages not matching + this pattern will cause a test failure when register_failure is True. + :param bool register_failure: See SUITE.tutils.xcov. + :param bool auto_config_args: See SUITE.tutils.xcov. + :param bool auto_target_args: See SUITE.tutils.xcov. See SUITE.tutils.xcov for the other supported options. """ @@ -67,7 +102,7 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", if gpr_obj_dir: mkdir(gpr_obj_dir) - covlevel_args = [] if covlevel is None else ['--level', covlevel] + covlevel_args = [] if covlevel is None else ["--level", covlevel] # We want to get the mains to know which dump-trigger should be passed to # the instrumentation command. @@ -75,15 +110,18 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", # Capture the list of main file names, double quoted and comma separated. m = re.search( pattern=r"for Main use \((?P.*)\)", - string=contents_of(gprsw.root_project)) + string=contents_of(locate_gpr_file(gprsw)), + ) # If found, split then remove whitespaces and double quotes mains = [] if m: - mains = m.group('mains').split(',') + mains = m.group("mains").split(",") mains = [main.strip(' "') for main in mains] - args = ['instrument'] + covlevel_args + args = ["instrument"] + covlevel_args + if quiet: + args.append("--quiet") if dump_trigger: if dump_trigger == "auto": @@ -96,10 +134,41 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", if runtime_project: args += ["--runtime-project", runtime_project] - args += gprsw.cov_switches + extra_args + args += gprsw.cov_switches + (extra_args or []) if thistest.options.pretty_print: - args.append('--pretty-print') + args.append("--pretty-print") + + if thistest.options.block: + args.append("--instrument-block") + + # Get the Ada version from the test framework + if thistest.options.ada_version: + args += ["--ada", thistest.options.ada_version] + + # TODO (gpr-issues#241) temporary workaround. + # Since gpr2clean deletes .sid files for the moment, we need to + # clean the project before instrumenting (this used to be done before the + # invocation of gprbuild). + thistest.cleanup( + gprsw.root_project, + gpr_common_args(gprsw.root_project, auto_config_args), + ) + + # When no message is to be tolerated, fallback to an actual regexp + # that will never match: + re_tolerate_messages = tolerate_messages or "" + + # For qualification purposes, tolerate possible warnings about + # inexistant object dirs from older gnatcov versions, typically + # issued when instrumenting before building. Tests do a best + # effort attempt at creating objects dirs beforehand but doing + # that is cumbersome for some of the more convoluted tests. + if not GNATCOV_INFO.major_at_least(24): + re_tolerate_messages = "|".join( + "(?:{})".format(mre) + for mre in ["object directory.*not found", re_tolerate_messages] + ) out = out or "instrument.log" result = xcov( @@ -107,23 +176,17 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", out=out, err=err, register_failure=register_failure, - auto_languages=auto_languages, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, + tolerate_messages=re_tolerate_messages, ) - if warnings_as_errors: - output = contents_of(out) - - thistest.fail_if( - "***" in output, - f"Warnings detected in the output of 'gnatcov instrument':" - f"\n{indent(output)}" - ) - return result -def xcov_convert_base64(base64_file, output_trace_file, out=None, err=None, - register_failure=True): +def xcov_convert_base64( + base64_file, output_trace_file, out=None, err=None, register_failure=True +): """Extract a trace file out of a Base64 file. :param str base64_file: Name of the file to read. @@ -131,32 +194,18 @@ def xcov_convert_base64(base64_file, output_trace_file, out=None, err=None, See SUITE.tutils.xcov for the other supported options. """ - xcov(['extract-base64-trace', base64_file, output_trace_file], - out=out, err=err, register_failure=register_failure) + xcov( + ["extract-base64-trace", base64_file, output_trace_file], + out=out, + err=err, + register_failure=register_failure, + ) -def add_last_chance_handler(project, obj_dir, subdirs, main_unit, silent): +def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): """ - Add a unit to instrumented sources to hold a last chance handler. - - Several mechanisms provide last chance handlers in cross setups. First, - libsupport.gpr provides a last chance handler (last_chance.adb) that prints - a "!!! ERROR !!!"-like pattern that the testsuite will detect as an error, - and base.gpr makes sure that the __gnat_last_chance_handler is undefined so - that the linker picks last_chance.o even though it is not in the main - compilation closure. - - Second, some tests additionally provide a "silence_last_chance.adb" source - that defines this symbol, only this time, the handler prints no message. - Test drivers explicitly WITH this unit, so the linker will not pull - last_chance.o. - - In instrumentation mode, we need the last chance handler to dump coverage - buffers, and to do that we want to call the procedure that dumps coverage - for the test driver closure. So we generate in the actual project - instrumented source directory ($obj_dir/gnatcov-instr or - $obj_dir/$subdirs/gnatcov-instr) a last chance handler. Which one precisely - depends on the ``silent`` argument. + Add a unit to instrumented sources to hold a last chance handler + entry hook dumping the coverage buffers for the given main_unit. :param str project: Instrumented project. This can be either the name of the project file, or the name of the project. @@ -164,87 +213,172 @@ def add_last_chance_handler(project, obj_dir, subdirs, main_unit, silent): project. :param None|str subdirs: Value of --subdirs passed to gnatcov and gprbuild. None if this argument is not passed. - :param str main_unit: Name of the main unit for which the handler will call + :param str main_unit: Name of the main unit for which the hook will call the coverage buffers dump routine. - :param bool silent: Whether the last chance handler should be silent. If - not, it will print a "!!! ERROR !!!"-like pattern that the testsuite - will detect as an error. """ + # Isolate the dependency to the libadalang module. This means that a user + # testing natively (thus not needing the support for last chance handlers) + # will not need to install the libadalang python module. + import libadalang as lal + # Amend obj_dir according to subdirs, if applicable if subdirs: obj_dir = os.path.join(obj_dir, subdirs) # Make sure we have a lowe-cased project *name* (not a filename) project = os.path.basename(project).lower() - if project.endswith('.gpr'): + if project.endswith(".gpr"): project = project[:-4] - # Unit that contain helper routines to dump coverage bufers. There is one - # such unit per main. See instrument-common.ads to know more about the slug - # computation. - main_unit_slug = main_unit.replace('z', 'zz') - auto_dump_unit = 'GNATcov_RTS.Buffers.DB_{}'.format(main_unit_slug) - handler_unit = 'Silent_Last_Chance' if silent else 'Last_Chance' + # Unit that contain helper routines to dump coverage buffers. There is one + # such unit per main. The only differences between two such units of the + # same project is the name of the main unit which is encoded in the trace + # (in place of the actual executable name). This is not checked by the + # testsuite so there should be no problem using the helper unit of a + # different main. + + auto_dump_suffix = None + for _, _, files in os.walk( + os.path.join(obj_dir, f"{project}-gnatcov-instr") + ): + for file in files: + res = re.match(pattern="gcvrt-db_(.+).adb", string=file) + if res: + auto_dump_suffix = res.group(1) + break + if auto_dump_suffix: + break + + assert auto_dump_suffix is not None + + # Determine if the buffer dump helper unit corresponds to a manual buffer + # dump. If so, there is an extra parameter to pass to the call to the + # Dump_Buffers procedure. + is_manual_dump = not re.match("z[0-9a-f]+", auto_dump_suffix) + + auto_dump_unit = "GCVRT.DB_{}".format(auto_dump_suffix) + handler_unit = "Last_Chance_Dumper" def filename(prefix, ext): - return os.path.join(obj_dir, '{}-gnatcov-instr'.format(project), - '{}.{}'.format(prefix, ext)) + return os.path.join( + obj_dir, + "{}-gnatcov-instr".format(project), + "{}.{}".format(prefix, ext), + ) unit_prefix = handler_unit.lower() - with open(filename(unit_prefix, 'ads'), 'w') as f: - f.write(""" - with System; - + with open(filename(unit_prefix, "ads"), "w") as f: + f.write( + """ package {unit_name} is - procedure Last_Chance_Handler - (Msg : System.Address; Line : Integer); - pragma Export - (C, Last_Chance_Handler, "__gnat_last_chance_handler"); - pragma No_Return (Last_Chance_Handler); + procedure Lch_Enter; + pragma Export (Ada, Lch_Enter, "__lch_enter"); end {unit_name}; - """.format(unit_name=handler_unit)) - with open(filename(unit_prefix, 'adb'), 'w') as f: - f.write(""" - with System; - with GNAT.IO; + """.format( + unit_name=handler_unit + ) + ) + with open(filename(unit_prefix, "adb"), "w") as f: + f.write( + """ with {auto_dump_unit}; package body {unit_name} is - procedure Last_Chance_Handler - (Msg : System.Address; Line : Integer) - is - pragma Unreferenced (Msg, Line); - procedure C_abort; - pragma Import (C, C_abort, "abort"); - pragma No_Return (C_abort); + procedure Lch_Enter is begin - if not {silent} then - GNAT.IO.New_Line; - GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); - GNAT.IO.Put_Line ("!!! EXCEPTION RAISED !!!"); - GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); - end if; - {auto_dump_unit}.Dump_Buffers; - C_Abort; - end Last_Chance_Handler; + {auto_dump_unit}.Dump_Buffers{call_params}; + end; end {unit_name}; - """.format(unit_name=handler_unit, - auto_dump_unit=auto_dump_unit, - silent=silent)) - - # Add a "with" to this handler in the main to make sure the handler unit is - # included in the link. - main_file = filename(main_unit, 'adb') - with open(main_file, 'r') as f: - lines = f.read().splitlines() - - # Insert the "with" clause after all pragmas to keep the code valid - for i, line in enumerate(lines): - if not line.strip().lower().startswith('pragma'): - break + """.format( + unit_name=handler_unit, + auto_dump_unit=auto_dump_unit, + call_params=f' ("{main_unit}")' if is_manual_dump else "", + ) + ) + + # Amend the main unit to "with" the generated package so it gets + # included in the build. Insert the "with" clause after all pragmas + # to keep the code valid. + + main_file = filename(main_unit, "adb") + + context = lal.AnalysisContext() + unit = context.get_from_file(main_file) + + # Assume that the root node is a CompilationUnit. Then look for the token + # right before the start of the body node: this is where we will insert the + # with_handler clause. + assert not unit.diagnostics + assert isinstance(unit.root, lal.CompilationUnit) + after_body_token = unit.lookup_token(unit.root.f_body.sloc_range.start) + before_body_token = after_body_token.previous + + # build the new source + new_source = "".join( + [ + ( + "" + if before_body_token is None + else lal.Token.text_range(unit.first_token, before_body_token) + ), + "with {};".format(handler_unit), + lal.Token.text_range(after_body_token, unit.last_token), + ] + ) + with open(main_file, "w") as f: + f.write(new_source) + + +def available_ada_dump_triggers(): + """ + Return the list of dump triggers available for the current Ada runtime. + """ + if RUNTIME_INFO.has_full_runtime: + return ["main-end", "atexit"] + elif ( + RUNTIME_INFO.has_ravenscar_runtime + # TODO: remove once --dump-trigger=ravenscar-task-termination is + # fixed, see eng/das/cov/gnatcoverage#191. + and "light-tasking" not in RUNTIME_INFO.runtime_name + ): + return ["main-end", "ravenscar-task-termination"] else: - assert False, 'Could not find a non-pragma line' - lines.insert(i, 'with {};'.format(handler_unit)) + return ["main-end"] - with open(main_file, 'w') as f: - f.write('\n'.join(lines)) + +def maybe_relocate_binaries(object_dir, exe_dir, mains): + """ + Relocate binaries produced in the object_dir to the exe_dir for the AAMP + target. + + :param object_dir: object directory of the main project. + :param exe_dir: executable directory of the main project. + :param mains: main filenames. + """ + # The GNAAMP linker disregards the full name passed to the -o switch but + # only picks the simple name. Thus, the executable ends up in the object + # directory. + # + # Copy it to the executable directory so that the rest of the testsuite + # can assume executables are always there. + if "aamp" in env.target.platform: + for main in mains: + copy_to_dir(object_dir, exe_dir, main) + + +def maybe_copy_runtime(test_dir): + """ + Copy the Ada instrumentation runtime in test_dir for the AAMP target. + """ + if "aamp" in env.target.platform: + rts_path = os.path.join( + os.path.dirname(shutil.which("gnatcov")), + "..", + "share", + "gnatcoverage", + "gnatcov_ada_rts", + ) + rts_dest_path = os.path.join(test_dir, "rts") + mkdir(rts_dest_path) + sync_tree(rts_path, rts_dest_path) + env.add_search_path(env_var="GPR_PROJECT_PATH", path=rts_dest_path) diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index 183d07f71..6979577bc 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -93,12 +93,14 @@ # lNoCode : no code for line (=xcov) # lNotCoverable : no code but statement on line, hence not coverable (=xcov) # lUndetCov : scos present but could not determine coverage state (=xcov) +# lDisCov : coverage analysis disabled for the line (=xcov) # lFullCov : full coverage for line (=xcov) # r0 : expect empty set of violations (=report) # r0c : like r0, on a statement continuation line (=report) # lx0 : line part of exempted block, 0 deviations (=xcov) # lx1 : line part of exempted block, >0 deviations (=xcov) # lx2 : line part of exempted block, >0 undet. cov. items (=xcov) +# lx : line part of exempted block, do not check deviations (=xcov) # lNoCov : line not covered (=xcov) # lPartCov : line partially covered (=xcov) @@ -125,10 +127,25 @@ # cPartCov : independent effect of condition not demonstrated (=report) +# aNoCov : assertion never evaluated (=report) +# atNoCov : assertion expression outcome TRUE never evaluated (=report) +# acPartCov : assertion condition was never evaluated during an evaluation of +# the decision to True (=report) + +# fNoCov : subprogram never entered (=report) +# cNoCov : call statement or expression never evaluated (=report) +# fUndetCov : subprogram with undetermined coverage state (=report) +# cUndetCov : call with undetermined coverage state (=report) + +# gNoCov : guarded expression never evaluated (=report) +# gUndetCov : guarded expression with undetermined coverage state (=state) + # xBlock0 : exempted block, 0 deviations (=report) # xBlock1 : exempted block, >0 deviations (=report) # xBlock2 : exempted block, >0 undetermined coverage items (=report) +# dBlock : disabled block + # Transient kinds: these may be used in expectations and should always be # subject to substitution rules mapping them to other kinds. No emitted note # will ever match them. These are useful for shared drivers when the actual @@ -141,39 +158,144 @@ # oPartCov : one outcome not covered (=report) # oNoCov : outcome never evaluated (=report) +# Exempted violations. These are a subset of the violations described above +# that are possible to find in exempted blocks. They have the same meaning but +# are simply prefixed by an uppercase 'X' to express that they can only be +# found in exempted regions. The relevant notes are: +# +# XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, XofNoCov, +# XoPartCov, XoNoCov, XcPartCov, r0, r0c + # Annotations lower than strictNote won't trigger an unexpected annotation # failure if they appear in a place where they are not explicitly expected. -(lNoCode, lFullCov, - strictNote, - r0, r0c, lx0, lx1, lx2, - deviationNote, - lNoCov, lPartCov, lNotCoverable, lUndetCov, - sNoCov, sPartCov, sNotCoverable, sUndetCov, - dtAlways, dfAlways, - dtNoCov, dfNoCov, dNoCov, dPartCov, dUndetCov, - etNoCov, efNoCov, eNoCov, ePartCov, eUndetCov, - otNoCov, ofNoCov, oNoCov, oPartCov, - cPartCov, - blockNote, - xBlock0, xBlock1, xBlock2) = range(38) - -NK_image = {None: "None", - lNoCode: "lNoCode", lNotCoverable: "lNotCoverable", - lUndetCov: "lUndetCov", - lFullCov: "lFullCov", lNoCov: "lNoCov", lPartCov: "lPartCov", - r0: "r0", r0c: "r0c", lx0: "lx0", lx1: "lx1", lx2: "lx2", - sNoCov: "sNoCov", sPartCov: "sPartCov", - sNotCoverable: "sNotCoverable", sUndetCov: "sUndetCov", - dtAlways: "dtAlways", dfAlways: "dfAlways", - dtNoCov: "dtNoCov", dfNoCov: "dfNoCov", dNoCov: "dNoCov", - dPartCov: "dPartCov", dUndetCov: "dUndetCov", - etNoCov: "etNoCov", efNoCov: "efNoCov", eNoCov: "eNoCov", - ePartCov: "ePartCov", eUndetCov: " eUndetCov", - otNoCov: "otNoCov", ofNoCov: "ofNoCov", oNoCov: "oNoCov", - oPartCov: "oPartCov", - xBlock0: "xBlock0", xBlock1: "xBlock1", xBlock2: "xBlock2", - cPartCov: "cPartCov"} +( + lNoCode, + lFullCov, + lx, + strictNote, + r0, + r0c, + lx0, + lx1, + lx2, + deviationNote, + lNoCov, + lPartCov, + lNotCoverable, + lUndetCov, + lDisCov, + sNoCov, + sPartCov, + sNotCoverable, + sUndetCov, + dtAlways, + dfAlways, + dNotCoverable, + dtNoCov, + dfNoCov, + dNoCov, + dPartCov, + dUndetCov, + etNoCov, + efNoCov, + eNoCov, + ePartCov, + eUndetCov, + otNoCov, + ofNoCov, + oNoCov, + oPartCov, + cPartCov, + XsNoCov, + XsPartCov, + XsNotCoverable, + XsUndetCov, + XotNoCov, + XofNoCov, + XoPartCov, + XoNoCov, + XcPartCov, + Xr0, + Xr0c, + aNoCov, + atNoCov, + acPartCov, + fNoCov, + cNoCov, + fUndetCov, + cUndetCov, + gNoCov, + gUndetCov, + blockNote, + xBlock0, + xBlock1, + xBlock2, + dBlock, +) = range(62) + +NK_image = { + None: "None", + lNoCode: "lNoCode", + lNotCoverable: "lNotCoverable", + lUndetCov: "lUndetCov", + lDisCov: "lDisCov", + lFullCov: "lFullCov", + lNoCov: "lNoCov", + lPartCov: "lPartCov", + r0: "r0", + r0c: "r0c", + lx0: "lx0", + lx1: "lx1", + lx2: "lx2", + lx: "lx", + sNoCov: "sNoCov", + sPartCov: "sPartCov", + sNotCoverable: "sNotCoverable", + sUndetCov: "sUndetCov", + dtAlways: "dtAlways", + dfAlways: "dfAlways", + dNotCoverable: "dNotCoverable", + dtNoCov: "dtNoCov", + dfNoCov: "dfNoCov", + dNoCov: "dNoCov", + dPartCov: "dPartCov", + dUndetCov: "dUndetCov", + etNoCov: "etNoCov", + efNoCov: "efNoCov", + eNoCov: "eNoCov", + ePartCov: "ePartCov", + eUndetCov: " eUndetCov", + otNoCov: "otNoCov", + ofNoCov: "ofNoCov", + oNoCov: "oNoCov", + oPartCov: "oPartCov", + xBlock0: "xBlock0", + xBlock1: "xBlock1", + xBlock2: "xBlock2", + cPartCov: "cPartCov", + XsNoCov: "XsNoCov", + XsPartCov: "XsPartCov", + XsNotCoverable: "XsNotCoverable", + XsUndetCov: "XsUndetCov", + XotNoCov: "XotNoCov", + XofNoCov: "XofNoCov", + XoPartCov: "XoPartCov", + XoNoCov: "XoNoCov", + XcPartCov: "XcPartCov", + Xr0: "Xr0", + Xr0c: "Xr0c", + aNoCov: "aNoCov", + atNoCov: "atNoCov", + acPartCov: "acPartCov", + fNoCov: "fNoCov", + cNoCov: "cNoCov", + fUndetCov: "fUndetCov", + cUndetCov: "cUndetCov", + gNoCov: "gNoCov", + gUndetCov: "gUndetCov", + dBlock: "dBlock", +} # =============================== @@ -183,9 +305,22 @@ # Line notes (=xcov); the set of possible expectations matches the # set of possible emitted indications -elNoteKinds = (lNoCode, lNotCoverable, lUndetCov, lNoCov, lPartCov, lFullCov, - lx0, lx1, lx2) -xlNoteKinds = elNoteKinds +elNoteKinds = ( + lNoCode, + lNotCoverable, + lUndetCov, + lDisCov, + lNoCov, + lPartCov, + lFullCov, + lx0, + lx1, + lx2, +) + +xlTransparentKinds = (lx,) + +xlNoteKinds = elNoteKinds + xlTransparentKinds # Report notes (=report), which feature anti-expectations that # explicitely state expection of absence of emitted notes @@ -194,14 +329,49 @@ sNoteKinds = (sNoCov, sPartCov, sNotCoverable, sUndetCov) # DC indications -dNoteKinds = (dtNoCov, dfNoCov, dPartCov, dNoCov, dtAlways, dfAlways, dUndetCov) +dNoteKinds = ( + dtNoCov, + dfNoCov, + dPartCov, + dNoCov, + dtAlways, + dfAlways, + dNotCoverable, + dUndetCov, +) # MCDC violations -cNoteKinds = (etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, eUndetCov) +cNoteKinds = (etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, eUndetCov) + +# Assertion violations +atcNoteKinds = (aNoCov, atNoCov) +atccNoteKinds = acPartCov +aNoteKinds = (aNoCov, atNoCov, atccNoteKinds) + +# Function and call coverage violations +fNoteKinds = (fNoCov, cNoCov, fUndetCov, cUndetCov) + +# Guarded expression coverage violations +gNoteKinds = (gNoCov, gUndetCov) # Exemption regions xNoteKinds = (xBlock0, xBlock1, xBlock2) + +# Exempted violations +XsNoteKinds = (XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov) + +XoNoteKinds = (XotNoCov, XofNoCov, XoPartCov, XoNoCov) + +XcNoteKinds = (XcPartCov,) + +XrAntiKinds = (Xr0, Xr0c) + +XNoteKinds = XsNoteKinds + XoNoteKinds + XcNoteKinds + +# Disabled coverage regions +disabledNoteKinds = (dBlock,) + # Anti-expectations rAntiKinds = (r0, r0c) @@ -212,14 +382,24 @@ # kinds in the Emitted Report Notes set because we do want to handle them as # if they could be emitted and report them as unmatched. -erNoteKinds = sNoteKinds+dNoteKinds+cNoteKinds+xNoteKinds+tNoteKinds -xrNoteKinds = erNoteKinds+rAntiKinds +erNoteKinds = ( + sNoteKinds + + dNoteKinds + + cNoteKinds + + xNoteKinds + + tNoteKinds + + XNoteKinds + + disabledNoteKinds +) +erNoteKinds += aNoteKinds + fNoteKinds + gNoteKinds +xrNoteKinds = erNoteKinds + rAntiKinds + XrAntiKinds # ========================== # == Note Kind Predicates == # ========================== + def deviation_p(nkind): """ DEVIATION notes are those representing violations of a coverage mandate @@ -265,10 +445,57 @@ def anti_p(nkind): return nkind in rAntiKinds +def transparent_p(nkind): + """ + TRANSPARENT expectations are those that should not produce an expected note + to be matched. It is relevant for exempted regions. For an exempted region, + we have one _line_ note emitted for each line of the block, one _report_ + block note emitted for the entire region and one _report_ note for each + exempted violation within the region. For example: + + foo.adb.xcov: + 2 *: pragma Annotate (Exempt_On, "comment"); -- # ex-region + 3 *: if Debug then -- # ex-region-test + 4 *: Count := Count + 1; -- # ex-region-bump + 5 *: end if; -- # ex-region + 6 *: pragma Annotate (Exempt_Off); -- # ex-region + + report: + -- Exempted Regions -- + foo.adb:2:4-6:4: 2 exempted violations, justification: + "comment" + foo.adb:3:7 decision outcome True never exercised + foo.adb:4:7 statement not executed + + In expectation blocks, the line intended to match the emitted report block + note for the entire region is typically designed to match on all the lines + of the region to capture the sloc range. For example: + + --# foo.adb + --# /ex-region/ l* ## x1 + + This matches all the lines, from 2 to 6, and creates a "l*" line note + expectation for each line that is indeed discharged by the .xcov output. + + Now we need additional expectations for the emitted violation _report_ + notes, and we need to prevent these from creating new line notes + expectations that would never be discharged. On our example, this would be + achieved with: + + --# /ex-region-test l= ## dT- + --# /ex-region-bump l= ## s- + + where the "l=" expectation is "transparent". + """ + + return nkind in xlTransparentKinds + + # =========================== # == Coverage Note Classes == # =========================== + class Block: """ Source regions to which expected coverage note instances belong. @@ -277,6 +504,7 @@ class Block: processed. Our purpose is only to associate notes with regions, for which an object id is enough + a parent link to represent nesting trees. """ + def __init__(self, parent): self.parent = parent @@ -303,7 +531,7 @@ def image(self): return "%s%s mark at %s" % ( NK_image[self.kind], "(from %s)" % self.stag.text if self.stag else "", - self.segment + self.segment, ) @@ -344,10 +572,10 @@ class Enote(Cnote): """Emitted note, as extracted from an xcov report.""" def __init__(self, kind, segment, source, stag=None): - self.kind = kind # The kind of emitted note + Cnote.__init__(self, kind) self.segment = segment # The line segment it designates - self.source = source # The corresponding source name - self.stag = stag # The separation tag it contains + self.source = source # The corresponding source name + self.stag = stag # The separation tag it contains self.discharges = None # The Xnote it discharges diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index cbe22ae4b..85682af2a 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -28,24 +28,48 @@ from SCOV.tctl import CAT, CovControl -from SCOV.instr import (add_last_chance_handler, default_dump_channel, - default_dump_trigger, xcov_convert_base64, - xcov_instrument) +from SCOV.instr import ( + add_dumper_lch_hook, + default_dump_channel, + default_dump_trigger, + maybe_copy_runtime, + maybe_relocate_binaries, + xcov_convert_base64, + xcov_instrument, +) from SUITE.context import thistest -from SUITE.control import language_info -from SUITE.cutils import ext, to_list, list_to_file, match, no_ext -from SUITE.cutils import contents_of, lines_of +from SUITE.control import language_info, runtime_info +from SUITE.cutils import ext, to_list, list_to_file, no_ext, FatalError +from SUITE.cutils import contents_of, lines_of, unhandled_exception_in from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprfor, xrun, xcov, frame -from SUITE.tutils import gprbuild_cargs_with +from SUITE.tutils import gprbuild_cargs_with, run_and_log from SUITE.tutils import exename_for -from SUITE.tutils import (srctrace_pattern_for, srctracename_for, - tracename_for, ckptname_for, run_cov_program) +from SUITE.tutils import ( + srctrace_pattern_for, + srctracename_for, + tracename_for, + ckptname_for, + run_cov_program, +) +from SUITE.cargo_utils import cargo_for from .cnotes import r0, r0c, xBlock0, xBlock1, lx0, lx1, lFullCov, lPartCov +from .cnotes import Xr0, Xr0c from .cnotes import KnoteDict, elNoteKinds, erNoteKinds, rAntiKinds -from .cnotes import xNoteKinds, sNoteKinds, dNoteKinds, cNoteKinds, tNoteKinds +from .cnotes import ( + xNoteKinds, + sNoteKinds, + dNoteKinds, + cNoteKinds, + gNoteKinds, + tNoteKinds, + atcNoteKinds, + aNoteKinds, + fNoteKinds, +) +from .cnotes import XsNoteKinds, XoNoteKinds, XcNoteKinds from .cnotes import strict_p, deviation_p, anti_p, positive_p from .xnexpanders import XnotesExpander @@ -123,7 +147,6 @@ class WdirControl: # for the TestCase implementation to decide. def __init__(self, wdbase, bdbase, subdirhint): - # WDBASE is the base prefix to use for testcase Working directory. # BDBASE is the base prefix to use for testcase Binary directory. # Fallback to WDBASE when not provided. @@ -164,14 +187,14 @@ def __init__(self, wdbase, bdbase, subdirhint): r_eln_for = { CAT.stmt: elNoteKinds, CAT.decision: elNoteKinds, - CAT.mcdc: elNoteKinds + CAT.mcdc: elNoteKinds, } # Relevant line expectations r_lxp_for = { CAT.stmt: r_eln_for[CAT.stmt], CAT.decision: r_eln_for[CAT.decision], - CAT.mcdc: r_eln_for[CAT.mcdc] + CAT.mcdc: r_eln_for[CAT.mcdc], } # The set of Report expectations we need to care about varies across @@ -187,9 +210,21 @@ def __init__(self, wdbase, bdbase, subdirhint): # Relevant emitted report notes r_ern_for = { - CAT.stmt: tNoteKinds + xNoteKinds + sNoteKinds, - CAT.decision: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds, - CAT.mcdc: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds + cNoteKinds, + CAT.stmt: tNoteKinds + xNoteKinds + sNoteKinds + XsNoteKinds, + CAT.decision: tNoteKinds + + xNoteKinds + + sNoteKinds + + dNoteKinds + + XsNoteKinds + + XoNoteKinds, + CAT.mcdc: tNoteKinds + + xNoteKinds + + sNoteKinds + + dNoteKinds + + cNoteKinds + + XsNoteKinds + + XoNoteKinds + + XcNoteKinds, } # Relevant report expectations @@ -200,6 +235,17 @@ def __init__(self, wdbase, bdbase, subdirhint): } +def strictest_cat_for(level: str): + if level.startswith("stmt+mcdc"): + return CAT.mcdc + elif level.startswith("stmt+decision"): + return CAT.decision + elif level.startswith("stmt"): + return CAT.stmt + else: + thistest.stop(FatalError("unknwon coverage level: " + level)) + + class _Xchecker: """Internal eXpectation marks checker class. This is used by SCOV_helper to compare sets of lines where coverage marks are expected with sets of @@ -235,10 +281,9 @@ def __discharges(self, en, xn): # The emitted note needs to designate a sloc range within the # expected sloc range and separation tags, when any is expected, # must match. - return ( - en.segment.within(xn.segment) - and ((not xn.stag and not en.stag) - or (xn.stag and en.stag and en.stag.match(xn.stag))) + return en.segment.within(xn.segment) and ( + (not xn.stag and not en.stag) + or (xn.stag and en.stag and en.stag.match(xn.stag)) ) def try_sat_over(self, ekind, xn): @@ -249,11 +294,10 @@ def try_sat_over(self, ekind, xn): # Note that we only check for section inclusions here, so don't # validate the correctness of exemption justifications at this stage. - # Ensuring that an emitted note is not used to satify multiple + # Ensuring that an emitted note is not used to satisfy multiple # expectations is stricter so the most correct in principle. for en in self.edict[ekind]: - if not en.discharges and self.__discharges(en=en, xn=xn): en.discharges = xn xn.discharger = en @@ -359,8 +403,9 @@ def run(self, discharge_kdict): # notes processing below. for xkind in self.rxp: - self.process_xkind(xkind=xkind, - ekinds=discharge_kdict.get(xkind, [xkind])) + self.process_xkind( + xkind=xkind, ekinds=discharge_kdict.get(xkind, [xkind]) + ) # Then process the relevant emitted notes, complaining about those # that don't discharge any expectation as required, or that discharge @@ -381,47 +426,14 @@ def run(self, discharge_kdict): class SCOV_helper: """Helper class for source coverage activities.""" + def sources_of_interest(self): + """List of sources for which we have expectations to match.""" + return self.xrnotes.keys() + # The differences between the different kinds of traces (binary or source) # are handled by specializing a few operations. - def mode_build(self): - """For a single test (not consolidation), build the program to run - out of the test sources. - """ - raise NotImplementedError - - def mode_execute(self, main): - """Execute the program designated by MAIN, arranging to produce an - execution trace. Return the name of a file containing the execution - output. - """ - raise NotImplementedError - - def mode_scofile_for(self, source): - """The _base_ file name of a file that would contain SCOs for the - provide source file name. This is used as a candidate file name to - be searched in a set of possible object directories for the current - test. - """ - raise NotImplementedError - - def mode_scofiles_switch(self): - """The command line switch to pass to convey the name of a file - containing SCOs, expected to support the '@' response file syntax - as well. This would be passed to gnatcov coverage when units of - interest are not to be conveyed by way of project files. - """ - raise NotImplementedError - - def mode_tracename_for(self, pgm): - """Name of the trace file for the given program name. - - Due to specificities of the source trace files in native contexts, this - method should be called only once the trace file has been created.""" - raise NotImplementedError - def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): - # The TESTCASE object that delegates the hard work to us :-) self.testcase = testcase @@ -452,14 +464,14 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): # Compute the gnatcov coverage specific extra options that we'll have # to pass. We need these early for Xnote expansions. - self.covoptions = ['--level=' + self.xcovlevel] + self.covoptions = ["--level=" + self.xcovlevel] if self.covctl: self.covoptions += to_list(self.covctl.covoptions) # Compute the list of test launch options strings that we need for # expectation CTL lines. - ctl_opts = ['--trace-mode=%s' % thistest.options.trace_mode] + ctl_opts = ["--trace-mode=%s" % thistest.options.trace_mode] self.extracargs = to_list(self.testcase.extracargs) @@ -476,12 +488,13 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): self.ernotes = {} xnotes = XnotesExpander( - xfile=xfile, xcov_level=xcovlevel, + xfile=xfile, + xcov_level=xcovlevel, ctl_opts=ctl_opts, ctl_cov=self.covoptions, ctl_cargs=gprbuild_cargs_with(thiscargs=self.extracargs), ctl_tags=thistest.options.tags, - ctl_cons=[thistest.options.consolidate] + ctl_cons=[thistest.options.consolidate], ) self.xlnotes = xnotes.xlnotes self.xrnotes = xnotes.xrnotes @@ -497,49 +510,6 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): thistest.fail_if(not self.xlnotes, "empty xlnotes from %s !!" % xfile) thistest.fail_if(not self.xrnotes, "empty xrnotes from %s !!" % xfile) - def sources_of_interest(self): - """List of sources for which we have expectations to match.""" - return self.xrnotes.keys() - - def is_subunit(self, soi): - """Determine whether the input Source Of Interest name denotes - a subunit, assuming source file names obey the standard GNAT naming - convention. - """ - - # There has to be a '-' in the source file name, which could also - # be for a child unit. Check if we also have a line starting with - # "separate" to disambiguate. - - return ( - '-' in os.path.basename(soi) - and any(line.lstrip().lower().startswith('separate') - for line in lines_of(self.abspaths[soi])) - ) - - def units_of_interest(self): - """Set of units for which we have expectations to match, based - on the list of sources for which we have expectations and assuming - standard use of '-' in filenames for child units or subunits - (foo-bar.ads for package Foo.Bar). Subunits are excluded from this - set.. - - ??? If a project has an instrument-c ada unit and an instrument.c - C source file, the representative string will be the same for both. - """ - - uoi = set() - - for soi in self.sources_of_interest(): - extension = ext(soi) - if extension == ".adb" or extension == ".ads": - if not self.is_subunit(soi): - uoi.add(no_ext(os.path.basename(soi)).replace('-', '.')) - else: - uoi.add(os.path.basename(soi)) - - return uoi - def programs(self): """List of base binary file names for the test drivers we are given to exercise. @@ -549,91 +519,23 @@ def programs(self): def xcov_translation_for(self, source): """How a SOURCE reference in expectations translates as the basename of an =xcov annotated source file.""" - return source.replace('/', '-') + return source.replace("/", "-") def report_translation_for(self, source): """How a SOURCE reference in expectations translates in slocs found in =report outputs.""" - return os.sep.join(source.split('/')) + return os.sep.join(source.split("/")) def singletest(self): """Whether SELF instantiates a single test.""" return len(self.drivers) == 1 - def run(self): - """Evaluate source coverage as exercised by self.drivers""" - - self.log() - - # Whatever the kind of test, we get to a Working Directory and - # switch back when done: - self.to_workdir(self.rwdir()) - - # If we are requested to convey units of interest through a project - # file and don't have a coverage control object to obey, build one to - # convey the units of interest: - - if thistest.options.gprmode and not self.covctl: - self.covctl = CovControl(units_in=self.units_of_interest()) - - # Assess whether we should be using a project file to convey units of - # interest, either requested from the command line or for specific - # test purposes: - - self.gprmode = ( - thistest.options.gprmode - or (self.covctl - and self.covctl.requires_gpr())) - - # Compute our GPR now, which we will need for build of single tests - # and/or analysis later on if in gprmode. Turn inlining off for the - # driver unit, so we exercise the functional code as separately - # compiled, not as an inlined version of it in a non-representative - # driver context. - - # Most of the tests with coverage control operate within - # an extra subdir level - this_depth = thistest.depth + 1 if self.covctl else thistest.depth - - self.gpr_obj_dir = 'obj' - self.gpr = gprfor( - mains=self.drivers, - prjid="gen", - objdir=self.gpr_obj_dir, - srcdirs=["../"*n + "src" for n in range(1, this_depth)], - exedir=self.abdir(attribute=True), - main_cargs="-fno-inline", - deps=self.covctl.deps if self.covctl else [], - extra=self.covctl.gpr() if self.covctl else "") - - # For single tests (no consolidation), we first need to build, then - # to execute to get an execution trace. All these we already have for - # consolidation tests, and there's actually no need to build if we - # were provided a bin directory to reuse: - - if self.singletest() and not self.wdctl.reuse_bin: - self.mode_build() - - # Do gnatcov run now unless we're consolidating. We'll just reuse - # traces from previous executions in the latter case. - - if self.singletest(): - self.run_test(main=no_ext(self.drivers[0])) - - # At this point, we have everything we need for the analysis. Either - # from the just done build+run in the single test case, or from - # previous such sequences in the consolidation case. Run gnatcov - # coverage to get actual coverage reports and check against our - # Xpectation specs. - - self.gen_xcov_reports() - self.check_expectations() - - self.to_homedir() - thistest.flush() - - # Let callers retrieve execution data at will - return self + def run(): + """Main driver procedure, which is responsible for generating the + environment, building the test and checking the coverage result against + the expected SCOs. + """ + raise NotImplementedError # ------------------------- # -- working directories -- @@ -702,15 +604,16 @@ def abdir_for(self, main, attribute=False): return self.adir_for(self.rbdir_for(main, attribute)) def main(self): - # For a single test, discriminate with driver basename. For a # consolidation test, discriminate with the expectation file basename. # We need the latter to allow multiple consolidation scenarii for a # testcase. - return (no_ext(self.drivers[0]) - if self.singletest() - else os.path.basename(no_ext(self.xfile))) + return ( + no_ext(self.drivers[0]) + if self.singletest() + else os.path.basename(no_ext(self.xfile)) + ) def rwdir(self): """Relative path to Working Directory for current instance.""" @@ -730,23 +633,26 @@ def abdir(self, attribute=False): def run_test(self, main): """Execute the MAIN program to produce an execution trace, and - trigger a failure if it raises an unhandled exception.""" + always trigger a failure if it raises an unhandled exception.""" out_file = self.mode_execute(main=main) - thistest.fail_if( - match( - r"(!!! EXCEPTION RAISED !!!" - r"|raised [A-Z_]+ : [-._a-zA-Z]+:[0-9]+ \w+)", - out_file - ), - "exception raised while running '%s'." % main - ) + # The exception check is performed by the lower execution + # layers if we don't expect a failure from this test (out of + # our register_failure requests). - def gen_one_xcov_report(self, inputs, format, options=""): - """Helper for gen_xcov_reports, to produce one specific report for a - particulat FORMAT, from provided INPUTS. The command output is saved - in a file named FORMAT.out.""" + if self.testcase.expect_failures: + thistest.fail_if( + unhandled_exception_in(contents_of(out_file)), + "exception raised while running '%s'." % main, + ) + + def gen_one_xcov_report(self, trace, report_format, options=""): + """ + Helper for gen_xcov_reports, to produce one specific report for a + particular REPORT_FORMAT, from provided TRACE. The command output is + saved in a file named REPORT_FORMAT.out. + """ # Compute the set of arguments we are to pass to gnatcov coverage. @@ -757,37 +663,56 @@ def gen_one_xcov_report(self, inputs, format, options=""): # options which might be absent from the tool qualified interface # descriptions. - covargs = (['--annotate=' + format, inputs] - + self.covoptions + to_list(options)) + covargs = ( + ["--annotate=" + report_format, trace] + + self.covoptions + + to_list(options) + ) if self.gprmode: - covargs.append('--output-dir=.') + covargs.append("--output-dir=.") # Run, latching standard output in a file so we can check contents on # return. - ofile = format + ".out" - xcov(args=['coverage'] + covargs, out=ofile) + ofile = report_format + ".out" + xcov( + args=["coverage"] + covargs, + tolerate_messages=self.testcase.tolerate_cov_messages, + out=ofile, + ) - # Standard output might typically contain labeling warnings issued - # by the static analysis phase, or error messages issued when a trace - # indicates that some unlabeled edge was taken. None of this should - # happen so we simply fail as soon as the output file is not empty. - # Note that we do this in qualification mode as well, even though what - # we're looking at is not stricly part of the qualified interface. + # Only check the output when running with binary traces, as this is + # done in xcov for source traces. + if thistest.options.trace_mode == "bin": + # Standard output might typically contain labeling warnings issued + # by the static analysis phase, or error messages issued when a + # trace indicates that some unlabeled edge was taken. None of this + # should happen so we simply fail as soon as the output file is not + # empty. Note that we do this in qualification mode as well, even + # though what we're looking at is not stricly part of the qualified + # interface. + + # Warnings about -S being deprecated are expected: just ignore them + output_lines = lines_of(ofile) + for i, line in reversed(list(enumerate(output_lines))): + if line == ( + "warning: -S is deprecated. " + "This option will be removed in release 26." + ): + output_lines.pop(i) + output = "\n".join(output_lines) - thistest.fail_if( - os.path.getsize(ofile) > 0, - "xcov standard output not empty (%s):\n--\n%s" % ( - ofile, contents_of(ofile) + thistest.fail_if( + output, + f"xcov standard output not empty ({ofile}:\n--\n{output}", ) - ) def force_xcov_report(self, source): - filename = self.xcov_translation_for(source) + '.xcov' + filename = self.xcov_translation_for(source) + ".xcov" if not os.path.exists(filename): - with open(filename, 'w') as report: + with open(filename, "w") as report: report.write("dummy xcov report") def gen_xcov_reports(self): @@ -802,47 +727,67 @@ def gen_xcov_reports(self): # produce a checkpoint for possible future consolidation if the # current execution mode calls for it: - checkpoints = thistest.options.consolidate == 'checkpoints' + checkpoints = thistest.options.consolidate == "checkpoints" single_driver = no_ext(self.drivers[0]) if self.singletest() else None - use_checkpoint_inputs = checkpoints and not single_driver - # We request traces as input with "@inputs.list", where the file # contains the list of traces to use, derived from the set of drivers. # We request checkpoints as inputs with "--checkpoint=@inputs.list", # where the file contains the list of checkpoints to use, derived # from the set of drivers as well: - input_opt, input_fn = ( - ("--checkpoint=", ckptname_for) - if use_checkpoint_inputs - else ("", self.mode_tracename_for) + trace_inputs = "@%s" % ( + list_to_file( + [ + self.mode_tracename_for( + os.path.join(self.awdir_for(pgm), pgm) + ) + for pgm in self.programs() + ], + "inputs.list", + ), ) - - inputs = "%s@%s" % ( - input_opt, - list_to_file([input_fn(os.path.join(self.awdir_for(pgm), pgm)) - for pgm in self.programs()], - "inputs.list") + ckpt_inputs = "--checkpoint=@%s" % ( + list_to_file( + [ + ckptname_for(os.path.join(self.awdir_for(pgm), pgm)) + for pgm in self.programs() + ], + "ckpts.list", + ), ) # Determine what command line options we'll pass to designate units of # interest and maybe produce a coverage checkpoint. We don't need and # don't want to pass SCO options when using checkpoints as inputs. - sco_options = ([] if use_checkpoint_inputs - else self.coverage_sco_options()) + sco_options = [] if checkpoints else self.coverage_sco_options() - save_checkpoint_options = ( - ["--save-checkpoint=%s" % ckptname_for(single_driver)] - if single_driver and checkpoints else []) + # Produce the checkpoint if required + if checkpoints and single_driver: + save_checkpoint_options = ( + ["--save-checkpoint=%s" % ckptname_for(single_driver)] + if single_driver and checkpoints + else [] + ) + self.gen_one_xcov_report( + trace_inputs, + report_format="report", + options=self.coverage_sco_options() + + save_checkpoint_options + + ["--cancel-annotate"], + ) + + inputs = ckpt_inputs if checkpoints else trace_inputs # Now produce the --annotate=report format: self.gen_one_xcov_report( - inputs, format="report", - options=sco_options + save_checkpoint_options + ['-o', 'test.rep']) + inputs, + report_format="report", + options=sco_options + ["-o", "test.rep"], + ) # Then an alternate .xcov output format, unless we are performing a # qualification run, for which that format isn't appropriate. No need @@ -853,7 +798,9 @@ def gen_xcov_reports(self): if thistest.options.qualif_level: return - self.gen_one_xcov_report(inputs, format="xcov", options=sco_options) + self.gen_one_xcov_report( + inputs, report_format="xcov", options=sco_options + ) def check_unexpected_reports(self): """Check that we don't have unexpected reports or notes.""" @@ -861,13 +808,13 @@ def check_unexpected_reports(self): for s in self.ernotes: thistest.fail_if( self.covctl.unexpected(s), - "report note found for %s, not in expected list" % s + "report note found for %s, not in expected list" % s, ) for s in ls("*.xcov"): thistest.fail_if( self.covctl.unexpected(s.rstrip(".xcov")), - "%s report found, for source not in expected list" % s + "%s report found, for source not in expected list" % s, ) def check_expectations(self): @@ -905,7 +852,7 @@ def check_expectations(self): # When we're running for a level stricter than the test category # (e.g. running a stmt test with --level=stmt+decision), we # - # * Just ignore some emitted notes, simply irrelevant for the catgory + # * Just ignore some emitted notes, simply irrelevant for the category # (e.g. dT-, which doesn't change the statement coverage status of # the outer statement). This is conveyed by the rp_?notes_for sets. # @@ -918,40 +865,48 @@ def check_expectations(self): # when that happens. # Symbolic strength of each category and context level, to let us - # determine when we're running some test of a given catgeory with a + # determine when we're running some test of a given category with a # stricter --level - strength = { - # Categories - CAT.stmt: 1, - CAT.decision: 2, - CAT.mcdc: 3, - - # Context levels - "stmt": 1, - "stmt+decision": 2, - "stmt+mcdc": 3, - "stmt+uc_mcdc": 3, - } + def level_strength(lvl): + """ + The strengh of a level is determined by its base level: + 3 for mcdc + 2 for decision + 1 for stmt + """ + if lvl == CAT.mcdc or ( + isinstance(lvl, str) + and ( + lvl.startswith("stmt+mcdc") + or lvl.startswith("stmt+uc_mcdc") + ) + ): + return 3 + elif lvl == CAT.decision or ( + isinstance(lvl, str) and lvl.startswith("stmt+decision") + ): + return 2 + elif lvl == CAT.stmt or ( + isinstance(lvl, str) and lvl.startswith("stmt") + ): + return 1 + else: + thistest.stop(FatalError("unknwon coverage level: " + lvl)) - stricter_level = ( - self.testcase.category - and strength[self.xcovlevel] > strength[self.testcase.category] - ) + stricter_level = self.testcase.category and level_strength( + self.xcovlevel + ) > level_strength(self.testcase.category) # For tests without a category, we will pick the relevant note # kinds from the strictest category possibly corresponding to the # xcov-level. - strictest_cat_for = { - "stmt": CAT.stmt, - "stmt+decision": CAT.decision, - "stmt+mcdc": CAT.mcdc - } - - relevance_cat = (self.testcase.category - if self.testcase.category - else strictest_cat_for[self.xcovlevel]) + relevance_cat = ( + self.testcase.category + if self.testcase.category + else strictest_cat_for(self.xcovlevel) + ) # Setup our report and line discharging configurations (kinds of # emitted notes that are allowed to discharge other kinds of expected @@ -959,30 +914,44 @@ def check_expectations(self): # =report outputs, stricter_level micro relaxations first: - r_discharge_kdict = { - # let an emitted xBlock1 discharge an xBlock0 expectation, as an - # extra exempted violations are most likely irrelevant for the - # category - xBlock0: [xBlock0, xBlock1]} if stricter_level else {} + r_discharge_kdict = ( + { + # Let an emitted xBlock1 discharge an xBlock0 expectation, as + # an extra exempted violations are most likely irrelevant for + # the category. + xBlock0: [xBlock0, xBlock1] + } + if stricter_level + else {} + ) # Then augment with what is allowed to hit "0" or "0c" expectation # statements: - r_discharge_kdict.update({r0: r_ern_for[relevance_cat], - r0c: r_ern_for[relevance_cat]}) + r_discharge_kdict.update( + { + r0: r_ern_for[relevance_cat], + r0c: r_ern_for[relevance_cat], + Xr0: r_ern_for[relevance_cat], + Xr0c: r_ern_for[relevance_cat], + } + ) # =xcov outputs, stricter_level micro relaxations only: - l_discharge_kdict = { - # an emitted l! discharge an expected l+, when the l! is most - # likely caused by irrelevant violations for the category - lFullCov: [lFullCov, lPartCov], - - # an emitted lx1 discharge an lx0 expectation, when the extra - # exempted violations are most likely caused by the level extra - # strictness, hence irrelevant for the category - lx0: [lx0, lx1] - } if stricter_level else {} + l_discharge_kdict = ( + { + # an emitted l! discharge an expected l+, when the l! is most + # likely caused by irrelevant violations for the category + lFullCov: [lFullCov, lPartCov], + # an emitted lx1 discharge an lx0 expectation, when the extra + # exempted violations are most likely caused by the level extra + # strictness, hence irrelevant for the category + lx0: [lx0, lx1], + } + if stricter_level + else {} + ) # Now process source by source, skipping those for which no report # is expected when the list happens to be specified. @@ -995,18 +964,20 @@ def check_expectations(self): for source in self.sources_of_interest(): if not self.covctl or self.covctl.expected(source): self.check_expectations_over( - source=source, relevance_cat=relevance_cat, + source=source, + relevance_cat=relevance_cat, r_discharge_kdict=r_discharge_kdict, - l_discharge_kdict=l_discharge_kdict + l_discharge_kdict=l_discharge_kdict, ) - def check_expectations_over(self, source, relevance_cat, - r_discharge_kdict, l_discharge_kdict): + def check_expectations_over( + self, source, relevance_cat, r_discharge_kdict, l_discharge_kdict + ): """Process expectations for a particular SOURCE, comparing expected coverage marks against what is found in the xcov reports for this source.""" - frame("Processing UX for %s" % source, post=0, char='~').display() + frame("Processing UX for %s" % source, post=0, char="~").display() # Source names in expectations might still contain path indications # when they reach here, to indicate that the path components are @@ -1015,13 +986,36 @@ def check_expectations_over(self, source, relevance_cat, # Report notes checks + # Augment the set of recognized deviations based on the additional + # level(s) that are enabled. + # + # TODO: Also augment the expected notes for assertion coverage, the + # testsuite currently does not work for those levels? + + tc_r_rxp_for = r_rxp_for[relevance_cat] + tc_r_ern_for = r_ern_for[relevance_cat] + + if self.testcase.assert_lvl == "atc": + tc_r_rxp_for += atcNoteKinds + tc_r_ern_for += atcNoteKinds + elif self.testcase.assert_lvl == "atcc": + tc_r_rxp_for += aNoteKinds + tc_r_ern_for += aNoteKinds + if self.testcase.fun_call_lvl: + tc_r_rxp_for += fNoteKinds + tc_r_ern_for += fNoteKinds + + if self.testcase.gexpr_lvl: + tc_r_rxp_for += gNoteKinds + tc_r_ern_for += gNoteKinds + strans = self.report_translation_for(source) _Xchecker( - report='test.rep', + report="test.rep", xdict=self.xrnotes.get(source), - rxp=r_rxp_for[relevance_cat], + rxp=tc_r_rxp_for, edict=self.ernotes.get(strans, KnoteDict(erNoteKinds)), - ren=r_ern_for[relevance_cat] + ren=tc_r_ern_for, ).run(r_discharge_kdict) # Line notes checks, meaningless if we're in qualification mode @@ -1031,24 +1025,28 @@ def check_expectations_over(self, source, relevance_cat, strans = self.xcov_translation_for(source) _Xchecker( - report=strans+'.xcov', + report=strans + ".xcov", xdict=self.xlnotes.get(source), rxp=r_lxp_for[relevance_cat], edict=self.elnotes.get(strans, KnoteDict(elNoteKinds)), - ren=r_eln_for[relevance_cat] + ren=r_eln_for[relevance_cat], ).run(l_discharge_kdict) def log(self): frame( - "%s/ %s, %s\n%s coverage with %s" % ( + "%s/ %s, %s\n%s coverage with %s" + % ( os.path.relpath(os.getcwd(), thistest.homedir), [no_ext(main) for main in self.drivers], self.xfile, - self.testcase.category.name - if self.testcase.category else "generic", - ' '.join(self.covoptions) + ( + self.testcase.category.name + if self.testcase.category + else "generic" + ), + " ".join(self.covoptions), ), - char='*' + char="*", ).display() def to_workdir(self, wdir): @@ -1066,6 +1064,208 @@ def to_homedir(self): """Switch to this test's homedir.""" cd(self.homedir) + def wdbase_for(self, covlevel): + """ + Compute a short base prefix for the working directory that will + contain the output of coverage analysis for level covlevel. + + Uses the first letter of the highest level ('s' for "stmt" or 'u' for + "stmt+uc_mcdc") and the full name of the assertion level if assertion + coverage is enabled. If function and call coverage is needed, append + "fc". + """ + levels = covlevel.split("+") + + if len(levels) == 1: + return "s_" + + wdbase = levels[1][0] + + if self.assert_lvl: + wdbase += self.assert_lvl + + if self.fun_call_lvl: + wdbase += "fc" + + return wdbase + "_" + + def xcovlevel_for(self, wdname): + """ + Compute the source coverage level from the working directory prefix + by matching the first letter of the highest coverage level plus the + full name of the assertion level is enabled. + """ + res = "stmt" + wdbase = wdname.split("_")[0] + + for lvl in ["decision", "mcdc", "uc_mcdc"]: + if wdbase[0] == lvl[0]: + res += "+" + lvl + + if len(wdbase) > 1: + res += "+" + wdbase[1:] + + return res + + def coverage_sco_options(self) -> list[str]: + """The list of options to pass to gnatcov coverage to convey + SCOs to be discharged for the test at hand.""" + raise NotImplementedError + + +class SCOV_helper_gpr(SCOV_helper): + """Helper class for GPR-based tests.""" + + def mode_build(self): + """For a single test (not consolidation), build the program to run + out of the test sources. + """ + raise NotImplementedError + + def mode_execute(self, main): + """Execute the program designated by MAIN, arranging to produce an + execution trace. Return the name of a file containing the execution + output. + """ + raise NotImplementedError + + def mode_scofile_for(self, source): + """The _base_ file name of a file that would contain SCOs for the + provide source file name. This is used as a candidate file name to + be searched in a set of possible object directories for the current + test. + """ + raise NotImplementedError + + def mode_scofiles_switch(self): + """The command line switch to pass to convey the name of a file + containing SCOs, expected to support the '@' response file syntax + as well. This would be passed to gnatcov coverage when units of + interest are not to be conveyed by way of project files. + """ + raise NotImplementedError + + def mode_tracename_for(self, pgm): + """Name of the trace file for the given program name. + + Due to specificities of the source trace files in native contexts, this + method should be called only once the trace file has been created.""" + raise NotImplementedError + + def run(self): + """Evaluate source coverage as exercised by self.drivers""" + + self.log() + + # Whatever the kind of test, we get to a Working Directory and + # switch back when done: + self.to_workdir(self.rwdir()) + + # If we are requested to convey units of interest through a project + # file and don't have a coverage control object to obey, build one to + # convey the units of interest: + + if thistest.options.gprmode and not self.covctl: + self.covctl = CovControl(units_in=self.units_of_interest()) + + # Assess whether we should be using a project file to convey units of + # interest, either requested from the command line or for specific + # test purposes: + + self.gprmode = thistest.options.gprmode or ( + self.covctl and self.covctl.requires_gpr() + ) + + # Compute our GPR now, which we will need for build of single tests + # and/or analysis later on if in gprmode. Turn inlining off for the + # driver unit, so we exercise the functional code as separately + # compiled, not as an inlined version of it in a non-representative + # driver context. + + # Most of the tests with coverage control operate within + # an extra subdir level + this_depth = thistest.depth + 1 if self.covctl else thistest.depth + + self.gpr_obj_dir = "obj" + self.gpr_exe_dir = self.abdir(attribute=True) + self.gpr = gprfor( + mains=self.drivers, + prjid="gen", + objdir=self.gpr_obj_dir, + srcdirs=["../" * n + "src" for n in range(1, this_depth)], + exedir=self.gpr_exe_dir, + main_cargs="-fno-inline", + deps=self.covctl.deps if self.covctl else [], + extra=self.covctl.gpr() if self.covctl else "", + ) + + # For single tests (no consolidation), we first need to build, then + # to execute to get an execution trace. All these we already have for + # consolidation tests, and there's actually no need to build if we + # were provided a bin directory to reuse: + + if self.singletest() and not self.wdctl.reuse_bin: + self.mode_build() + + # Do gnatcov run now unless we're consolidating. We'll just reuse + # traces from previous executions in the latter case. + + if self.singletest(): + self.run_test(main=no_ext(self.drivers[0])) + + # At this point, we have everything we need for the analysis. Either + # from the just done build+run in the single test case, or from + # previous such sequences in the consolidation case. Run gnatcov + # coverage to get actual coverage reports and check against our + # Xpectation specs. + + self.gen_xcov_reports() + self.check_expectations() + + self.to_homedir() + thistest.flush() + + # Let callers retrieve execution data at will + return self + + def is_subunit(self, soi): + """Determine whether the input Source Of Interest name denotes + a subunit, assuming source file names obey the standard GNAT naming + convention. + """ + + # There has to be a '-' in the source file name, which could also + # be for a child unit. Check if we also have a line starting with + # "separate" to disambiguate. + + return "-" in os.path.basename(soi) and any( + line.lstrip().lower().startswith("separate") + for line in lines_of(self.abspaths[soi]) + ) + + def units_of_interest(self): + """Set of units for which we have expectations to match, based + on the list of sources for which we have expectations and assuming + standard use of '-' in filenames for child units or subunits + (foo-bar.ads for package Foo.Bar). Subunits are excluded from this + set.. + + If a project has an instrument-c ada unit and an instrument.c + C source file, the representative string will be the same for both. + """ + + uoi = set() + + for soi in self.sources_of_interest(): + extension = ext(soi) + if extension == ".adb" or extension == ".ads": + if not self.is_subunit(soi): + uoi.add(no_ext(os.path.basename(soi)).replace("-", ".")) + else: + uoi.add(os.path.basename(soi)) + + return uoi + # ----------------------- # - common_build_gargs -- # ----------------------- @@ -1110,9 +1310,13 @@ def coverage_sco_options(self): # Fallback to --scos/--sid with a list of files we compute here: else: - return ["%s=@%s" % ( - self.mode_scofiles_switch(), - list_to_file(self._scofiles_list(), "scos.list"))] + return [ + "%s=@%s" + % ( + self.mode_scofiles_switch(), + list_to_file(self._scofiles_list(), "scos.list"), + ) + ] def _locate_scofile(self, source): """Return the fullpath of the ali file corresponding to the given @@ -1130,7 +1334,7 @@ def _locate_scofile(self, source): # all identical, and they should be for typical situations where the # same sources were exercised by multiple drivers: - lpath = os.path.join('obj', self.mode_scofile_for(source)) + lpath = os.path.join("obj", self.mode_scofile_for(source)) for main in self.drivers: tloc = os.path.join(self.abdir_for(no_ext(main)), lpath) if os.path.exists(tloc): @@ -1153,13 +1357,16 @@ def _scofiles_list(self): # package. We make our result a set to prevent duplicates and xcov # warnings later on. - return {scof - for scof in (self._locate_scofile(soi) - for soi in self.sources_of_interest()) - if scof} + return { + scof + for scof in ( + self._locate_scofile(soi) for soi in self.sources_of_interest() + ) + if scof + } -class SCOV_helper_bin_traces(SCOV_helper): +class SCOV_helper_bin_traces(SCOV_helper_gpr): """SCOV_helper specialization for the binary execution trace based mode.""" # Outline of the binary trace based scheme: @@ -1186,12 +1393,13 @@ class SCOV_helper_bin_traces(SCOV_helper): def mode_build(self): gprbuild( - self.gpr, extracargs=self.extracargs, - gargs=self.common_build_gargs()) + self.gpr, + extracargs=self.extracargs, + gargs=self.common_build_gargs(), + ) def mode_execute(self, main): - - out_file = 'xrun_{}.out'.format(main) + out_file = "xrun_{}.out".format(main) # Feed xcov run with full path (absolute dir) of the program so we # can directly get to the binary from the trace when reading it from @@ -1204,9 +1412,12 @@ def mode_execute(self, main): # failures (such as harness tests), assuming that they will perform # further checks that are bound to fail if the execution doesn't # proceed as expected somehow (e.g. not producing a trace). - xrun([main_path, "--level=%s" % self.xcovlevel] + - self.coverage_sco_options(), - out=out_file, register_failure=not self.testcase.expect_failures) + xrun( + [main_path, "--level=%s" % self.xcovlevel] + + self.coverage_sco_options(), + out=out_file, + register_failure=not self.testcase.expect_failures, + ) return out_file @@ -1220,7 +1431,7 @@ def mode_tracename_for(self, pgm): return tracename_for(pgm) -class SCOV_helper_src_traces(SCOV_helper): +class SCOV_helper_src_traces(SCOV_helper_gpr): """SCOV_helper specialization for the source instrumentation mode.""" # Outline of the source instrumentation based scheme: @@ -1258,8 +1469,21 @@ class SCOV_helper_src_traces(SCOV_helper): # in SID files for source traces and in executables (as debug info) for # binary traces. - def mode_build(self): + def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): + super().__init__( + testcase, + drivers, + xfile, + xcovlevel, + covctl, + wdctl, + ) + + # Check wether we need to set the testsuite in manual dump trigger + # mode from the instrumentation options + self.use_manual_dump = self.dump_trigger == "manual" + def mode_build(self): # We first need to instrument, with proper selection of the units of # interest. Expect we are to provide this through a project file as # we have no LI file at hand: @@ -1282,72 +1506,97 @@ def mode_build(self): units=self.covctl.gprsw.units, no_subprojects=self.covctl.gprsw.no_subprojects, xvars=self.covctl.gprsw.xvars, - subdirs=subdirs) + subdirs=subdirs, + ) else: subdirs = None instrument_gprsw = GPRswitches(root_project=self.gpr) - out = 'xinstr.out' + # The AAMP target does not support library project and requires + # rebuilding the instrumentation runtime: copy it in the test + # directory. + maybe_copy_runtime(os.getcwd()) + + # Instrument now, requesting the propagation of instrumentation + # issues on the test status. Note that we expect this to include + # a check on instrumentation warnings. + out = "xinstr.out" + xcov_instrument( covlevel=self.xcovlevel, - extra_args=to_list(self.covctl.covoptions) if self.covctl else [], + extra_args=( + to_list(self.covctl.instroptions) if self.covctl else [] + ), dump_channel=self.dump_channel, + dump_trigger=self.dump_trigger, gprsw=instrument_gprsw, gpr_obj_dir=self.gpr_obj_dir, - out=out) + out=out, + register_failure=True, + tolerate_messages=self.testcase.tolerate_messages, + ) - # When exception propagation is not available, the "main-end" dump - # trigger will not work when the test driver ends with an unhandled - # exception. To workaround that, force the dump in the last chance - # handler. - if default_dump_trigger(self.drivers) == 'main-end': + # When exception propagation is not available, a test ending with an + # unhandled exception goes straight to the last_chance_handler from + # the point of the raise, bypassing the coverage buffers dump if the + # selected dump-trigger is "main-end". For such situations, provide by + # a last chance handler entry hook to dump the buffers at that point + # instead. + + if ( + self.dump_trigger == "main-end" + and not runtime_info().has_exception_propagation + ): # The only tests with multiple drivers are consolidation ones, # which compute consolidated coverage reports from data obtained # in previously executed tests (trace files or checkpoints). These # tests are not built, so we can assume here that there is only one # driver to build. assert len(self.drivers) == 1 - if (language_info(self.drivers[0]).name == "Ada"): - add_last_chance_handler( - instrument_gprsw.root_project, - self.gpr_obj_dir, - subdirs, - no_ext(self.drivers[0]), - silent=not self.testcase.expect_failures) - - # Standard output might contain warnings indicating instrumentation - # issues. This should not happen, so simply fail as soon as the output - # file is not empty. - thistest.fail_if( - os.path.getsize(out) > 0, - 'xcov instrument standard output not empty ({}):' - '\n--' - '\n{}'.format(out, contents_of(out))) + if language_info(self.drivers[0]).name == "Ada": + add_dumper_lch_hook( + project=instrument_gprsw.root_project, + obj_dir=self.gpr_obj_dir, + subdirs=subdirs, + main_unit=no_ext(self.drivers[0]), + ) # Now we can build, instructing gprbuild to fetch the instrumented # sources in their dedicated subdir: gprbuild( - self.gpr, extracargs=self.extracargs, - gargs=self.common_build_gargs() + ['--src-subdirs=gnatcov-instr']) + self.gpr, + extracargs=self.extracargs, + gargs=self.common_build_gargs() + ["--src-subdirs=gnatcov-instr"], + ) + maybe_relocate_binaries( + self.gpr_obj_dir, self.gpr_exe_dir, [exename_for(self.main())] + ) def mode_execute(self, main): register_failure = not self.testcase.expect_failures # Run the program itself - out_file = 'cmdrun_{}.out'.format(main) + out_file = "cmdrun_{}.out".format(main) main_path = os.path.join(self.abdir_for(main), exename_for(main)) - run_cov_program(main_path, out=out_file, - register_failure=register_failure) + run_cov_program( + main_path, + out=out_file, + register_failure=register_failure, + expect_non_zero_code=self.testcase.expect_non_zero_code, + ) # If the dump channel just writes text on stdout, extract traces from # it. - if self.dump_channel == 'base64-stdout': + if self.dump_channel == "base64-stdout": # The mode_tracename_for method works only after the trace file has # been created: create a trace file that srctracename_for (called # in mode_tracename_for) will pick up. - trace_file = srctrace_pattern_for(main).replace("*", "unique") - xcov_convert_base64(out_file, trace_file, - register_failure=register_failure) + trace_file = srctrace_pattern_for( + main, manual=self.use_manual_dump, manual_prj_name="gen" + ).replace("*", "unique") + xcov_convert_base64( + out_file, trace_file, register_failure=register_failure + ) return out_file @@ -1358,9 +1607,123 @@ def mode_scofiles_switch(self): return "--sid" def mode_tracename_for(self, pgm): - return srctracename_for(pgm) + return srctracename_for( + pgm, manual=self.use_manual_dump, manual_prj_name="gen" + ) @property def dump_channel(self): """Return the dump channel to use when instrumenting programs.""" return default_dump_channel() + + @property + def dump_trigger(self): + """Return the dump trigger to use when instrumenting programs.""" + if self.covctl and self.covctl.dump_trigger: + return self.covctl.dump_trigger + else: + return default_dump_trigger(self.drivers) + + +class SCOV_helper_rust(SCOV_helper): + """Helper class for Rust-based tests.""" + + PROFRAW_FILE = "out.profraw" + + def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): + assert len(drivers) == 1, "Multi-driver test is not supported in Rust" + + super().__init__( + testcase, + drivers, + xfile, + xcovlevel, + covctl, + wdctl, + ) + + self.gprmode = False + + def coverage_sco_options(self) -> list[str]: + return ["--exec", self.get_executable()] + + def run(self): + self.log() + + # Whatever the kind of test, we get to a Working Directory and + # switch back when done: + self.to_workdir(self.rwdir()) + + # Build the cargo file + cargo_for( + prjid="cargo-gen", + main=self.drivers[0], + src_dir=os.path.join("..", "src"), + cargo_dir=self.awdir(), + ) + + # Build the project cargo + p = run_and_log( + ["cargo", "build", "-v"], + env=self.cargo_environment(), + ignore_environ=False, + ) + if p.status != 0: + thistest.stop( + FatalError( + "cargo build failed", + outstr=f"stdout:\n{p.out}\n\nstderr:\n{p.err}", + ) + ) + + # Run the program + p = run_and_log( + [self.get_executable()], + env={"LLVM_PROFILE_FILE": self.PROFRAW_FILE}, + ) + + # At this point, we have everything we need for the analysis. Run + # gnatcov coverage to get actual coverage reports and check against our + # Xpectation specs. + + self.gen_xcov_reports() + self.check_expectations() + + self.to_homedir() + thistest.flush() + + # Let callers retrieve execution data at will + return self + + def _covlevel_to_rust_args(self) -> str: + cov_category = ( + self.testcase.category + if self.testcase.category + else strictest_cat_for(self.xcovlevel) + ) + + if cov_category == CAT.mcdc: + return ["-Cinstrument-coverage", "-Ccoverage-options=mcdc"] + elif cov_category == CAT.decision: + # decision coverage uses Rust's MCDC instrumentation + return ["-Cinstrument-coverage", "-Ccoverage-options=mcdc"] + elif cov_category == CAT.stmt: + return ["-Cinstrument-coverage"] + else: + thistest.stop( + FatalError(f"Unknown coverage level '{cov_category}'") + ) + + def cargo_environment(self) -> dict[str, str]: + return {"RUSTFLAGS": " ".join(self._covlevel_to_rust_args())} + + def get_executable(self): + return os.path.join( + self.abdir(), + "target", + "debug", + exename_for(no_ext(self.drivers[0])), + ) + + def mode_tracename_for(self, _pgm): + return self.PROFRAW_FILE diff --git a/testsuite/SCOV/internals/lnexpanders.py b/testsuite/SCOV/internals/lnexpanders.py index fa9ff44ac..279fac196 100644 --- a/testsuite/SCOV/internals/lnexpanders.py +++ b/testsuite/SCOV/internals/lnexpanders.py @@ -10,34 +10,56 @@ from e3.fs import ls -from .cnotes import (KnoteDict, Enote, elNoteKinds, lNoCode, lFullCov, - lPartCov, lNoCov, lNotCoverable, lUndetCov, lx0, lx1, - lx2) +from .cnotes import ( + KnoteDict, + Enote, + elNoteKinds, + lNoCode, + lFullCov, + lPartCov, + lNoCov, + lNotCoverable, + lUndetCov, + lDisCov, + lx0, + lx1, + lx2, +) from .segments import Line from .tfiles import Tfile class LnotesExpander: - - NK_for = {'.': lNoCode, '0': lNotCoverable, '?': lUndetCov, - '+': lFullCov, '-': lNoCov, '!': lPartCov, - '#': lx0, '*': lx1, '@': lx2} + NK_for = { + ".": lNoCode, + "0": lNotCoverable, + "?": lUndetCov, + "D": lDisCov, + "+": lFullCov, + "-": lNoCov, + "!": lPartCov, + "#": lx0, + "*": lx1, + "@": lx2, + } def process_tline(self, tline): - m = re.match(r'\s*([0-9]+) (.):', tline.text) + m = re.match(r"\s*([0-9]+) (.):", tline.text) if m: self.elnotes[self.source].register( - Enote(kind=self.NK_for[m.group(2)], - segment=Line(int(m.group(1))), - source=self.source)) + Enote( + kind=self.NK_for[m.group(2)], + segment=Line(int(m.group(1))), + source=self.source, + ) + ) def listing_to_enotes(self, dotxcov): - self.source = dotxcov.rsplit('.', 1)[0] + self.source = dotxcov.rsplit(".", 1)[0] self.elnotes[self.source] = KnoteDict(elNoteKinds) Tfile(filename=dotxcov, process=self.process_tline) def __init__(self, dotxcov_pattern): - # xcov --annotate=xcov produces a set of .xcov annotated unit sources, # each featuring a synthetic note per line. diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 93b0cff0a..27e0f7ec7 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -9,10 +9,49 @@ from SUITE.context import thistest from .cnotes import ( - xBlock0, xBlock1, sNoCov, sPartCov, sNotCoverable, dfAlways, dtAlways, - dfNoCov, dtNoCov, dNoCov, dPartCov, efNoCov, etNoCov, eNoCov, ePartCov, - cPartCov, Enote, KnoteDict, erNoteKinds, sUndetCov, - dUndetCov, eUndetCov, xBlock2 + xBlock0, + xBlock1, + sNoCov, + sPartCov, + sNotCoverable, + dfAlways, + dtAlways, + dNotCoverable, + dfNoCov, + dtNoCov, + dNoCov, + dPartCov, + efNoCov, + etNoCov, + eNoCov, + ePartCov, + cPartCov, + aNoCov, + atNoCov, + acPartCov, + fNoCov, + cNoCov, + fUndetCov, + cUndetCov, + gNoCov, + gUndetCov, + Enote, + KnoteDict, + erNoteKinds, + sUndetCov, + dUndetCov, + eUndetCov, + xBlock2, + XsNoCov, + XsPartCov, + XsNotCoverable, + XsUndetCov, + XotNoCov, + XofNoCov, + XoPartCov, + XoNoCov, + XcPartCov, + dBlock, ) from .segments import Sloc, Sloc_from_match from .stags import Stag_from @@ -53,13 +92,14 @@ # 2 DECISION violations. <- mapped to an internal "contents # <- block" representation. + class Rdiagline: """ Abstract diagnostic line, a-la "p.adb:8:4 statement not executed". This is a general Sloc followed by some diagnostic text. """ - def __init__(self, sloc, diag): + def __init__(self, sloc, diag): # SLOC object and DIAGnostic text self.sloc = sloc @@ -78,11 +118,11 @@ def __init__(self, sloc, diag): def Rdiagline_from(text): - p = re.match(Rdiagline.re, text) - return Rdiagline(sloc=Sloc_from_match(p), - diag=p.group("diag")) if p else None + return ( + Rdiagline(sloc=Sloc_from_match(p), diag=p.group("diag")) if p else None + ) class Rblock: @@ -92,7 +132,6 @@ class Rblock: """ def __init__(self, name, re_start, re_end): - # NAME holds the text with which this block will be referred to in # error messages. RE_START/RE_END are regexps which tells whether a # line of text matches the expected header line for this block: @@ -140,10 +179,11 @@ def check(self): thistest.fail_if( n_starts != n_ends, "(%s report section): %d starts != %d ends" - % (self.name, n_starts, n_ends)) + % (self.name, n_starts, n_ends), + ) def value(self, count): - return (0 if count == "No" else int(count)) + return 0 if count == "No" else int(count) # --------------------------- @@ -154,12 +194,12 @@ def value(self, count): # numbering at the start of the header title, possibly preceded by decorative # characters. + def re_block_number(pre, ndigits): return pre + r"[0-9]\." * ndigits + " " class Rchapter(Rblock): - # Chapter titles are characterized by a single digit number preceded by # two decorative characters, for example: # @@ -167,22 +207,26 @@ class Rchapter(Rblock): def __init__(self, re_start, re_end): Rblock.__init__( - self, name=re_start, + self, + name=re_start, re_start=re_block_number(pre=".. ", ndigits=1) + re_start, - re_end=re_end) + re_end=re_end, + ) class Rsection(Rblock): - # Section titles are characterized by a single digit number preceded by # two decorative characters, for example: # # 2.1. STATEMENT COVERAGE VIOLATIONS def __init__(self, re_start, re_end): - Rblock.__init__(self, name=re_start, - re_start=re_block_number(pre="", ndigits=2) + re_start, - re_end=re_end) + Rblock.__init__( + self, + name=re_start, + re_start=re_block_number(pre="", ndigits=2) + re_start, + re_end=re_end, + ) # -------------------------------- @@ -193,10 +237,9 @@ def __init__(self, re_start, re_end): # messages), which all contain a list of emitted notes + a counter of the # number of such notes at the end. Some are sections, some are chapters. -class Nblock(Rblock): +class Nblock(Rblock): def __init__(self, re_notes): - self.re_notes = re_notes # Remember the set of notes that we found in this block, so @@ -205,10 +248,7 @@ def __init__(self, re_notes): self.enotes = [] - # def nkind_for(self, rline) - def try_parse_enote(self, rline): - dline = Rdiagline_from(rline) # If no match at all, punt. @@ -220,11 +260,14 @@ def try_parse_enote(self, rline): # to sort out the note kind and separation tag from the diagnostic # text - enote = Enote(segment=dline.sloc.section, - source=dline.sloc.filename, - kind=None, stag=None) + enote = Enote( + segment=dline.sloc.section, + source=dline.sloc.filename, + kind=None, + stag=None, + ) - # Fetch and remove a possible separation tag from the diganostic + # Fetch and remove a possible separation tag from the diagnostic # text. Removal is useful to facilitate matching of other parts, hence # attempted first. @@ -233,17 +276,28 @@ def __stag_replacement_for(m): enote.stag = Stag_from(m.group(1), True) return "" - this_diag = re.sub(pattern=r" \(from (.*)\)", - repl=__stag_replacement_for, - string=dline.diag) + this_diag = re.sub( + pattern=r" \(from (.*)\)", + repl=__stag_replacement_for, + string=dline.diag, + ) # Then determine the note kind from the remaining contents enote.kind = self.nkind_for(this_diag) + return self.check_enote(this_diag, enote) + + def report_unexpected_enote(self, rline): + thistest.failed( + "(%s report section) '%s' does not" + " correspond to any expected violation note" + % (self.name, rline.rstrip("\n")) + ) + + def check_enote(self, rline, enote): if enote.kind is None: - thistest.failed("(%s =report section) '%s' ?" - % (self.name, rline.rstrip('\n'))) + self.report_unexpected_enote(rline) return None else: return enote @@ -254,18 +308,18 @@ def try_parse(self, rline): self.enotes.append(enote) return enote - def __validate_ecount(self, count): + def validate_ecount(self, count): self.ecount = len(self.enotes) thistest.fail_if( count != self.ecount, "(%s report section) recognized %d notes != summary (%d)\n" - % (self.name, self.ecount, count) + % (self.name, self.ecount, count), ) def ends_on(self, rline): p = Rblock.ends_on(self, rline) if p: - self.__validate_ecount(count=self.value(p.group(1))) + self.validate_ecount(count=self.value(p.group(1))) return p def re_summary(self): @@ -284,31 +338,33 @@ def nkind_for(self, rline): class Nsection(Nblock, Rsection): - def __init__(self, re_start, re_end, re_notes): Rsection.__init__(self, re_start=re_start, re_end=re_end) Nblock.__init__(self, re_notes=re_notes) class Nchapter(Nblock, Rchapter): - def __init__(self, re_start, re_end, re_notes): Rchapter.__init__(self, re_start=re_start, re_end=re_end) Nblock.__init__(self, re_notes=re_notes) -# VIOsection, OERsection, XREchapter, NCIchapter, SMRchapter +# VIOsection, OERsection, XREchapter, NCIchapter, SMRchapter, DCRChapter # # Leaf specializations, a set of which will be instantiated for report # processing. + class VIOsection(Nsection): """Coverage Violations section.""" def __init__(self, re_start, re_notes): - Nsection.__init__(self, re_start=re_start, - re_end=r"(No|\d+) violation[s]*\.$", - re_notes=re_notes) + Nsection.__init__( + self, + re_start=re_start, + re_end=r"(No|\d+) violation[s]*\.$", + re_notes=re_notes, + ) def re_summary(self): return r"(No|\d+).* %s violation[s]*\.$" % self.name.split()[0] @@ -316,13 +372,16 @@ def re_summary(self): class OERsection(Nsection): """Other errors section.""" + def __init__(self, re_start): - Nsection.__init__(self, re_start=re_start, - re_end=r"(No|\d+) message[s]*\.$", - re_notes=None) + Nsection.__init__( + self, + re_start=re_start, + re_end=r"(No|\d+) message[s]*\.$", + re_notes=None, + ) def nkind_for(self, rline): - # Messages in this section are always unexpected and should trigger # test failure. Just tell we don't know how to bind them on any sort # of expected note kind, and let the generic engine do the rest. @@ -332,54 +391,163 @@ def nkind_for(self, rline): class XREchapter(Nchapter): """Exemptions Regions chapter.""" - def __init__(self, re_start, re_notes): - Nchapter.__init__(self, re_start=re_start, - re_end=r"(No|\d+) exempted region[s]*\.$", - re_notes=re_notes) + + def __init__(self, re_start, re_notes, exempted_notes): + # The list of notes acceptable for an exempted violation + self.exempted_notes = exempted_notes + + # The number of exempted violations found + self.ecount_exempted = 0 + + re_end = ( + r"(No|\d+) exempted region[s]*, " + r"(No|\d+) exempted violation[s]*\.$" + ) + + Nchapter.__init__( + self, re_start=re_start, re_end=re_end, re_notes=re_notes + ) + + def __check_summary_count(self, sec, sum_count, sec_count): + thistest.fail_if( + sum_count != sec_count, + "summary count %d != section count %d for %s" + % (sum_count, sec_count, sec.name), + ) + thistest.fail_if( + len(sec.start_hits) != 1, + "summary found for section starts != 1 (%s)" % sec.name, + ) + + def check_exempted_summary(self, sec, p): + # The emitted notes of exempted violations are logged in self.enotes + # to be checked for discharging expected notes later on. However + # we still need to check the number of notes belonging to the exempted + # region itself and the number of notes for exempted violations + # separately. + ecount = len(self.enotes) - self.ecount_exempted + + self.__check_summary_count(sec, self.value(p.group(1)), ecount) + + self.__check_summary_count( + sec, self.value(p.group(2)), self.ecount_exempted + ) + + def __validate(self, actual_count, count, element_counted): + thistest.fail_if( + actual_count != count, + "(%s report section) recognized %d notes != summary (%d)" + "for (%s)\n" % (self.name, actual_count, count, element_counted), + ) + + def ends_on(self, rline): + p = Rblock.ends_on(self, rline) + if p: + # Validate the number of exempted regions + self.__validate( + len(self.enotes) - self.ecount_exempted, + self.value(p.group(1)), + "exempted regions", + ) + + # Validate the total number of exempted violations + self.__validate( + self.ecount_exempted, + self.value(p.group(2)), + "exempted violations", + ) + + return p + + def check_enote(self, rline, enote): + if enote.kind is None: + self.report_unexpected_enote(rline) + return None + + # Check if the note is that of an exempted violation in the region. If + # so, increment the exempted violations counter. + if enote.kind in self.exempted_notes.values(): + self.ecount_exempted += 1 + + return enote + + +class DCRchapter(Nsection): + """Disabled Coverage Regions section.""" + + def __init__(self, re_start): + Nchapter.__init__( + self, + re_start=re_start, + re_end=r"(\d+) region[s]* with disabled coverage\.$", + re_notes={".*": dBlock}, + ) + + def re_summary(self): + return r"(\d+) region[s]* with disabled coverage\.$" class NCIchapter(Nchapter): """Non-coverable Items chapter.""" + def __init__(self, re_start, re_notes): - Nchapter.__init__(self, re_start=re_start, - re_end=r"(No|\d+) exclusion[s]*\.$", - re_notes=re_notes) + Nchapter.__init__( + self, + re_start=re_start, + re_end=r"(No|\d+) exclusion[s]*\.$", + re_notes=re_notes, + ) def re_summary(self): return r"(No|\d+) coverage exclusion[s]*\.$" -class UCIchapter (Nchapter): +class UCIchapter(Nchapter): """Undetermined Coverage Items chapter.""" + def __init__(self, re_start, re_notes): - Nchapter.__init__(self, re_start=re_start, - re_end=r"(\d+) undetermined coverage item[s]*\.$", - re_notes=re_notes) + Nchapter.__init__( + self, + re_start=re_start, + re_end=r"(\d+) undetermined coverage item[s]*\.$", + re_notes=re_notes, + ) def re_summary(self): - return r"(\d+) undetermined coverage items[s]*\.$" + return r"(\d+) undetermined coverage item[s]*\.$" class SMRchapter(Rchapter): """Analysis Summary chapter.""" + def __init__(self, re_start, skeys): - Rchapter.__init__(self, re_start=re_start, - re_end=".. END OF REPORT ..$") + Rchapter.__init__( + self, re_start=re_start, re_end=".. END OF REPORT ..$" + ) self.skeys = skeys - self.checked = {sec: False for sec in skeys} + self.checked = dict.fromkeys(skeys, False) def try_match(self, sec, rline): p = re.match(self.skeys[sec], rline) if p: - sum_count = self.value(p.group(1)) - sec_count = sec.ecount - thistest.fail_if( - sum_count != sec_count, - "summary count %d != section count %d for %s" % ( - sum_count, sec_count, sec.name)) - thistest.fail_if( - len(sec.start_hits) != 1, - "summary found for section starts != 1 (%s)" % sec.name) + # If the check is done on the exempted regions chapter then the + # summary verification has to be done on the number of regions and + # the number of violations + + if sec.name == "EXEMPTED REGIONS": + sec.check_exempted_summary(sec, p) + else: + sum_count = self.value(p.group(1)) + sec_count = sec.ecount + thistest.fail_if( + sum_count != sec_count, + "summary count %d != section count %d for %s" + % (sum_count, sec_count, sec.name), + ) + thistest.fail_if( + len(sec.start_hits) != 1, + "summary found for section starts != 1 (%s)" % sec.name, + ) self.checked[sec] = True def try_parse(self, rline): @@ -394,7 +562,8 @@ def check(self): for sec in self.skeys: thistest.fail_if( len(sec.start_hits) > 0 and not self.checked[sec], - "summary count check missing for section %s" % sec.name) + "summary count check missing for section %s" % sec.name, + ) # At this point, we have the class hierarchy involved in modeling the @@ -417,12 +586,14 @@ def check(self): # We now add grab bags specializations aimed at catching # unexpected blocks: + class Ublock(Rblock): def check(self): thistest.fail_if( len(self.start_hits) > 0, "Unexpected headers caught by %s:\n%s" - % (self.__class__.__name__, ''.join(self.start_hits))) + % (self.__class__.__name__, "".join(self.start_hits)), + ) class Uchapter(Ublock, Rchapter): @@ -440,6 +611,7 @@ def __init__(self): # Just claim immediate end. Everything will be ignored until # the next section or block starter. + class Tchapter(Rchapter): def __init__(self, re_start): Rchapter.__init__(self, re_start=re_start, re_end=".") @@ -448,9 +620,9 @@ def __init__(self, re_start): # Now ready to materialize and wrapup the whole set of blocks needed to # process a report: + class RblockSet: def __init__(self): - # We need a list of all the blocks to drive the report parsing # process, and a list of all the note blocks to setup the analysis # summary checker: @@ -462,67 +634,142 @@ def __init__(self): stmt_notes = { "statement not executed": sNoCov, - "multiple statements on line": sPartCov} + "multiple statements on line": sPartCov, + } self.noteblocks.append( - VIOsection(re_start="STMT COVERAGE", re_notes=stmt_notes)) + VIOsection(re_start="STMT COVERAGE", re_notes=stmt_notes) + ) dc_notes = { "decision outcome FALSE never": dfNoCov, "decision outcome TRUE never": dtNoCov, "decision never evaluated": dNoCov, - "decision not exercised in both directions": dPartCov} + "decision not exercised in both directions": dPartCov, + } self.noteblocks.append( - VIOsection(re_start="DECISION COVERAGE", re_notes=dc_notes)) + VIOsection(re_start="DECISION COVERAGE", re_notes=dc_notes) + ) mcdc_notes = { "decision outcome FALSE never": efNoCov, "decision outcome TRUE never": etNoCov, "decision never evaluated": eNoCov, "decision not exercised in both directions": ePartCov, - "condition has no independent influence pair": cPartCov} + "condition has no independent influence pair": cPartCov, + } + self.noteblocks.append( + VIOsection(re_start="UC_MCDC COVERAGE", re_notes=mcdc_notes) + ) + self.noteblocks.append( + VIOsection(re_start="MCDC COVERAGE", re_notes=mcdc_notes) + ) + + # Assertion coverage + + atc_notes = { + "contract expression outcome TRUE never": atNoCov, + "contract expression never evaluated": aNoCov, + } self.noteblocks.append( - VIOsection(re_start="UC_MCDC COVERAGE", re_notes=mcdc_notes)) + VIOsection(re_start="ATC COVERAGE", re_notes=atc_notes) + ) + + atcc_notes = { + "condition was never evaluated during an evaluation of the " + "decision to True": acPartCov + } self.noteblocks.append( - VIOsection(re_start="MCDC COVERAGE", re_notes=mcdc_notes)) + VIOsection(re_start="ATCC COVERAGE", re_notes=atcc_notes) + ) + + fun_call_notes = { + "function not executed": fNoCov, + "call not executed": cNoCov, + } + self.noteblocks.append( + VIOsection(re_start="FUN_CALL COVERAGE", re_notes=fun_call_notes) + ) + + gexpr_notes = { + "guarded_expr not executed": gNoCov, + } + self.noteblocks.append( + VIOsection(re_start="GEXPR COVERAGE", re_notes=gexpr_notes) + ) # Non coverable items nc_notes = { "statement has no object code": sNotCoverable, "decision is always TRUE": dtAlways, - "decision is always FALSE": dfAlways} + "decision is always FALSE": dfAlways, + "decision has no object code": dNotCoverable, + } self.noteblocks.append( - NCIchapter(re_start="NON COVERABLE ITEMS", re_notes=nc_notes)) + NCIchapter(re_start="NON COVERABLE ITEMS", re_notes=nc_notes) + ) # Undetermined coverage items ni_notes = { "statement was not instrumented": sUndetCov, "decision was not instrumented" - " for decision coverage" : dUndetCov, - "decision was not instrumented" - " for MC/DC coverage" : eUndetCov + " for decision coverage": dUndetCov, + "decision was not instrumented for MCDC": eUndetCov, + "decision was not instrumented for UC_MCDC": eUndetCov, + "function was not instrumented": fUndetCov, + "call was not instrumented": cUndetCov, + "guarded_expr was not instrumented": gUndetCov, } self.noteblocks.append( - UCIchapter(re_start="UNDETERMINED COVERAGE ITEMS", re_notes=ni_notes)) + UCIchapter( + re_start="UNDETERMINED COVERAGE ITEMS", re_notes=ni_notes + ) + ) - # Exemptions regions + # Exempted regions xr_notes = { "0 exempted violation": xBlock0, r"[1-9]\d* exempted violation": xBlock1, - r"\d+ exempted violations?; [1-9]\d+ exempted undetermined" - r"coverage items?": xBlock2 + r"\d+ exempted violations?; [1-9]\d+ exempted undetermined " + r"coverage items?": xBlock2, + } + + # Exempted violations + + Xr_notes = { + "statement not executed": XsNoCov, + "multiple statements on line": XsPartCov, + "statement has no object code": XsNotCoverable, + "statement was not instrumented": XsUndetCov, + "decision outcome FALSE never": XofNoCov, + "decision outcome TRUE never": XotNoCov, + "decision outcome never evaluated": XoNoCov, + "decision not exercised in both directions": XoPartCov, + "condition has no independent influence pair": XcPartCov, } + self.noteblocks.append( - XREchapter(re_start="EXEMPTED REGIONS", re_notes=xr_notes)) + XREchapter( + re_start="EXEMPTED REGIONS", + re_notes=xr_notes | Xr_notes, + exempted_notes=Xr_notes, + ) + ) # Other note blocks self.noteblocks.append(OERsection(re_start="OTHER ERRORS")) + self.noteblocks.append( + DCRchapter( + re_start="COVERAGE DISABLED REGIONS", + ) + ) + # We're done with the note blocks at this point self.allblocks.extend(self.noteblocks) @@ -530,15 +777,18 @@ def __init__(self): # Analysis Summary chapter self.allblocks.append( - SMRchapter(re_start="ANALYSIS SUMMARY", - skeys={s: s.re_summary() for s in self.noteblocks})) + SMRchapter( + re_start="ANALYSIS SUMMARY", + skeys={s: s.re_summary() for s in self.noteblocks}, + ) + ) # Transparent chapters + self.allblocks.append(Tchapter(re_start="ASSESSMENT CONTEXT")) self.allblocks.append( - Tchapter(re_start="ASSESSMENT CONTEXT")) - self.allblocks.append( - Tchapter(re_start="(NON-EXEMPTED )?COVERAGE VIOLATIONS")) + Tchapter(re_start="(NON-EXEMPTED )?COVERAGE VIOLATIONS") + ) # Unexpected chapter/section catchers @@ -560,7 +810,6 @@ class RnotesExpander: """Produce list of Enote instances found in a "report" output.""" def to_enotes(self, report): - # We need to ignore everything not in the report sections # of interest, so until we know we're in ... @@ -579,7 +828,6 @@ def register(self, enote): self.ernotes[source].register(enote) def process_tline(self, tline): - rline = tline.text # Check if we are getting in a section of interest. If so, register @@ -612,7 +860,6 @@ def process_tline(self, tline): return enote def __init__(self, report): - # xcov --annotate=report produces a single report featuring a list of # indications for slocs in all the units. diff --git a/testsuite/SCOV/internals/segments.py b/testsuite/SCOV/internals/segments.py index 3ce5a4c06..2b6197c33 100644 --- a/testsuite/SCOV/internals/segments.py +++ b/testsuite/SCOV/internals/segments.py @@ -31,18 +31,18 @@ def __init__(self, line, col): self.c = col def pastoreq(self, other): - return (self.lineno > other.lineno - or (self.lineno == other.lineno - and (self.c >= other.c or other.c == 0))) + return self.lineno > other.lineno or ( + self.lineno == other.lineno and (self.c >= other.c or other.c == 0) + ) def beforeq(self, other): - return (self.lineno < other.lineno - or (self.lineno == other.lineno - and (self.c <= other.c or other.c == 0))) + return self.lineno < other.lineno or ( + self.lineno == other.lineno and (self.c <= other.c or other.c == 0) + ) def Spoint_from(text): - items = text.split(':', 1) + items = text.split(":", 1) return Spoint(line=int(items[0]), col=int(items[1])) @@ -52,12 +52,14 @@ def Spoint_from(text): # gnatcov outputs. The _str_ images do not need to match the format expected # by their _from sibling in the same class. + class Section: """ A Section is the association of two slocs to materialize the start and the end of a source section, and which knows to determine if it is included within another section. """ + # ... # l0 -> 3: if a and then b then # ^ @@ -75,27 +77,35 @@ def __init__(self, l0, c0, l1, c1): self.sp1 = Spoint(line=l1, col=c1) def within(self, other): - return (self.sp0.pastoreq(other.sp0) - and self.sp1.beforeq(other.sp1)) + return self.sp0.pastoreq(other.sp0) and self.sp1.beforeq(other.sp1) def __str__(self): return "section %d:%d-%d:%d" % ( - self.sp0.lineno, self.sp0.c, self.sp1.lineno, self.sp1.c) + self.sp0.lineno, + self.sp0.c, + self.sp1.lineno, + self.sp1.c, + ) def Section_from(text): - topitems = text.split('-', 1) - subitems0 = topitems[0].split(':', 1) - subitems1 = topitems[1].split(':', 1) - return Section(l0=int(subitems0[0]), c0=int(subitems0[1]), - l1=int(subitems1[0]), c1=int(subitems1[1])) - - -class Segment (Section): + topitems = text.split("-", 1) + subitems0 = topitems[0].split(":", 1) + subitems1 = topitems[1].split(":", 1) + return Section( + l0=int(subitems0[0]), + c0=int(subitems0[1]), + l1=int(subitems1[0]), + c1=int(subitems1[1]), + ) + + +class Segment(Section): """ A Segment is a Section for which the start and end are known to be on the same line. """ + def __init__(self, lno, clo, chi): Section.__init__(self, l0=lno, c0=clo, l1=lno, c1=chi) @@ -104,15 +114,16 @@ def __str__(self): def Segment_from(text): - topitems = text.split(':', 1) - subitems = topitems[1].split('-', 1) - return Segment(lno=int(topitems[0]), - clo=int(subitems[0]), - chi=int(subitems[1])) + topitems = text.split(":", 1) + subitems = topitems[1].split("-", 1) + return Segment( + lno=int(topitems[0]), clo=int(subitems[0]), chi=int(subitems[1]) + ) class Line(Segment): """A Line is a Segment spanning from first to last column.""" + def __init__(self, lno): Segment.__init__(self, lno=lno, clo=0, chi=0) @@ -121,7 +132,7 @@ def __str__(self): def Line_from(text): - items = text.split(':', 1) + items = text.split(":", 1) return Line(lno=int(items[0])) @@ -129,6 +140,7 @@ class Point(Segment): """ A Point is a Segment for which the start and end columns are identical. """ + def __init__(self, lno, col): Segment.__init__(self, lno=lno, clo=col, chi=col) @@ -137,7 +149,7 @@ def __str__(self): def Point_from(text): - items = text.split(':', 1) + items = text.split(":", 1) return Point(lno=int(items[0]), col=int(items[1])) @@ -188,15 +200,16 @@ def __init__(self, filename, section): # Note that the registered LANGINFO extensions embed the '.' character, - re = '(?P[^ ]*)(?P%s):(?P[^ ]*)' % '|'.join( - ext - for li in LANGINFO.values() - for ext in li.src_ext) + re = "(?P[^ ]*)(?P%s):(?P[^ ]*)" % "|".join( + ext for li in LANGINFO.values() for ext in li.src_ext + ) def Sloc_from_match(m): - return Sloc(filename=''.join([m.group("sbase"), m.group("ext")]), - section=Section_within(m.group("sec"))) + return Sloc( + filename="".join([m.group("sbase"), m.group("ext")]), + section=Section_within(m.group("sec")), + ) def Sloc_from(text): diff --git a/testsuite/SCOV/internals/stags.py b/testsuite/SCOV/internals/stags.py index 50e331c44..b3efb90e0 100644 --- a/testsuite/SCOV/internals/stags.py +++ b/testsuite/SCOV/internals/stags.py @@ -25,13 +25,16 @@ class Stag: """Abstract separation tag.""" + def __init__(self, text): self.text = text def match(self, other): - return (False - if self.__class__ != other.__class__ - else self.match_akin(other)) + return ( + False + if self.__class__ != other.__class__ + else self.match_akin(other) + ) def Stag_from(text, from_report): @@ -49,6 +52,7 @@ def Stag_from(text, from_report): class Rtag(Stag): """Routine separation tag. Text is routine name.""" + def __init__(self, text): Stag.__init__(self, text) @@ -65,11 +69,11 @@ class Itag(Stag): def __init__(self, text): Stag.__init__(self, text) - self.components = [Sloc_from(part) - for part in text.rstrip(']').split('[')] + self.components = [ + Sloc_from(part) for part in text.rstrip("]").split("[") + ] def __all_components_match(self, other): - # Check whether any component pair is found not to match: for c1, c2 in zip(self.components, other.components): @@ -82,5 +86,6 @@ def __all_components_match(self, other): return True def match_akin(self, other): - return (len(self.components) == len(other.components) - and self.__all_components_match(other)) + return len(self.components) == len( + other.components + ) and self.__all_components_match(other) diff --git a/testsuite/SCOV/internals/tfiles.py b/testsuite/SCOV/internals/tfiles.py index 96c1086dc..744426383 100644 --- a/testsuite/SCOV/internals/tfiles.py +++ b/testsuite/SCOV/internals/tfiles.py @@ -11,6 +11,7 @@ class Tline: """Associate a line contents with its position in a text file.""" + def __init__(self, lno, text): self.lno = lno self.text = text diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 4161e007e..53b42bdf3 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -14,9 +14,23 @@ from SUITE.control import language_info from SUITE.cutils import FatalError, lines_of from .cnotes import ( - Block, KnoteDict, dNoCov, dPartCov, dfNoCov, dtNoCov, eNoCov, ePartCov, - efNoCov, etNoCov, lPartCov, oNoCov, oPartCov, ofNoCov, otNoCov, sNoCov, - xlNoteKinds, xrNoteKinds + KnoteDict, + dNoCov, + dPartCov, + dfNoCov, + dtNoCov, + eNoCov, + ePartCov, + efNoCov, + etNoCov, + lPartCov, + oNoCov, + oPartCov, + ofNoCov, + otNoCov, + sNoCov, + xlNoteKinds, + xrNoteKinds, ) from .tfiles import Tfile from .xnotep import XnoteP @@ -53,12 +67,13 @@ # lx_lnote_list := lx_lnote_choice ["," lx_lnote_list] # lx_lnote_choice := [cov_level_test] [weak_mark] lx_lnote -# lx_lnote := +# lx_lnote := # lx_rnote_list := lx_rnote_choice [rnote_sep lx_rnote_list] # lx_rnote_choice := [cov_level_test] [weak_mark] lx_rnote -# lx_rnote_kind = -# lx_rnote := lx_rnote_kind[:"TEXT"][@(STAG)] +# lx_rnote_kind := +# lx_ernote_kind := +# lx_rnote := [:"TEXT"][@(STAG)] # rnote_sep is selected to be '#' if any # is found on the line, # or ',' if any , is found on the line, @@ -342,7 +357,7 @@ def __resolve(self, xpath): the current point. """ - for pdir in ("../"*n + "src/" for n in range(0, thistest.depth)): + for pdir in ("../" * n + "src/" for n in range(0, thistest.depth)): if os.path.exists(pdir + xpath): return pdir + xpath @@ -357,7 +372,7 @@ def __init__(self, xsource): self.xsource = xsource # XPATH: The relative path expressed in the expectation: - self.xpath = xsource[1:] if xsource.startswith('+') else xsource + self.xpath = xsource[1:] if xsource.startswith("+") else xsource # SPATH: The resolved path to an actual source file reachable for # the testcase at hand: @@ -371,7 +386,6 @@ class LineCX: """ def __init__(self, lre, lnp, rnps, override): - self.lre = lre self.lnp = lnp self.rnps = rnps @@ -385,9 +399,11 @@ def instanciate_lnotes_over(self, tline, block, srules): return [self.lnp.instanciate_over(tline, block, srules)] def instanciate_rnotes_over(self, tline, block, srules): - return [rnp.instanciate_over(tline, block, srules) - for rnp in self.rnps - if rnp.kind] + return [ + rnp.instanciate_over(tline, block, srules) + for rnp in self.rnps + if rnp.kind + ] class UnitCX: @@ -407,29 +423,6 @@ def instanciate_notes_for(self, lx, tline, block, srules): if rn: self.xrdict.register(rn) - # Fuzz block processing - # - # We identify block with the help of explicit comments, not with lone - # language constructs such as begin/end in Ada. Finding the proper couples - # of the latter is not easy and error prone. - - def blopen_p(self, tline): - return re.match(r"^\s*begin\s*-- #", tline.text) - - def blclose_p(self, tline): - return re.match(r"^\s*end;\s*-- #", tline.text) - - def check_block_on(self, tline): - - if self.blopen_p(tline): - self.current_block = Block(parent=self.current_block) - - if self.blclose_p(tline): - thistest.stop_if( - not self.current_block, - FatalError("end of nonexistant block at\n=> " + tline.text)) - self.current_block = self.current_block.parent - # Kind subsitution rules processing # # For shared drivers that exercise boolean expressions in different @@ -448,56 +441,51 @@ def check_block_on(self, tline): # anchors, with the following possible values for each : subst_tuples_for = { - # o/d: Outcome expectations for line are to produce "decision" # expectations, for instance on # # if A and then B then -- # eval :o/d: - - "o/d": {otNoCov: dtNoCov, - ofNoCov: dfNoCov, - oPartCov: dPartCov, - oNoCov: dNoCov}, - + "o/d": { + otNoCov: dtNoCov, + ofNoCov: dfNoCov, + oPartCov: dPartCov, + oNoCov: dNoCov, + }, # o/e: Outcome expectations for line are to produce "expression" # expectations, for instance on # # return Value (A and then B); -- # eval :o/e: - - "o/e": {otNoCov: etNoCov, - ofNoCov: efNoCov, - oPartCov: ePartCov, - oNoCov: eNoCov}, - + "o/e": { + otNoCov: etNoCov, + ofNoCov: efNoCov, + oPartCov: ePartCov, + oNoCov: eNoCov, + }, # o/0: outcome expectations for line are to be ignored, for # contexts where the evaluated expression is not actually a # decision, for instance on # # pragma Precondition (not X); -- # eval :o/0: - - "o/0": {otNoCov: None, - ofNoCov: None, - oPartCov: None, - oNoCov: None, - lPartCov: None}, - + "o/0": { + otNoCov: None, + ofNoCov: None, + oPartCov: None, + oNoCov: None, + lPartCov: None, + }, # s/e: Statement uncovered expectations for line are to be # matched as expression never evaluated, for contexts where # the evaluated expression is not enclosed in a statement, # for instance on # # pragma Precondition (A and then B); -- # eval :s/e: - "s/e": {sNoCov: eNoCov}, - # eval on the line are in expression or decision context - "e": {}, - "d": {} - } + "d": {}, + } def check_srules_on(self, tline): - # Check for kind substitution rules on this line. Reset # at every line for now. @@ -507,7 +495,7 @@ def check_srules_on(self, tline): self.current_srules = None else: self.current_srules = {} - for sim in m.group(1).split(','): + for sim in m.group(1).split(","): self.current_srules.update(self.subst_tuples_for[sim]) # Toplevel processing @@ -516,12 +504,11 @@ def process_tline(self, tline): self.check_srules_on(tline) for lx in self.LXset: if re.search(lx.lre, tline.text): - self.instanciate_notes_for(lx, tline, self.current_block, - self.current_srules) - self.check_block_on(tline) + self.instanciate_notes_for( + lx, tline, self.current_block, self.current_srules + ) def __init__(self, sref, LXset): - self.LXset = LXset # dictionaries of expected line and report notes for our unit @@ -536,14 +523,13 @@ def __init__(self, sref, LXset): self.sref = sref - thistest.stop_if(self.current_block, - FatalError("fuzz block still open at EOF")) + thistest.stop_if( + self.current_block, FatalError("fuzz block still open at EOF") + ) class UXgroup: - def __init__(self, candlists): - # SRLIST: good list of source ref objects from the set of candidate # lists received in CANDLISTS for this group, as specified in the # expectation spec. This is a list of lists like @@ -604,8 +590,10 @@ def __select_srlist_from(self, candlists): thistest.stop_if( len(goodlists) != 1, - FatalError("goodlists = %d, != 1 for %s" - % (len(goodlists), candlists))) + FatalError( + "goodlists = %d, != 1 for %s" % (len(goodlists), candlists) + ), + ) return goodlists[0] @@ -640,8 +628,9 @@ def close(self): # Now instanciate a unit coverage expectations object for each # source ref in our list: - self.uxset = [UnitCX(sref=sref, LXset=self.lxset) - for sref in self.srlist] + self.uxset = [ + UnitCX(sref=sref, LXset=self.lxset) for sref in self.srlist + ] return self.uxset @@ -688,9 +677,16 @@ class XnotesExpander: # | # > g.close () for all parsed groups - def __init__(self, xfile, xcov_level, ctl_opts, ctl_cov, ctl_cargs, - ctl_tags, ctl_cons): - + def __init__( + self, + xfile, + xcov_level, + ctl_opts, + ctl_cov, + ctl_cargs, + ctl_tags, + ctl_cons, + ): # XFILE is the name of the file from which coverage expectations # are to be extracted. @@ -711,11 +707,13 @@ def __init__(self, xfile, xcov_level, ctl_opts, ctl_cov, ctl_cargs, # CTL_TAGS - set of discriminants for the current run, and # CTL_CONS - kinds of consolidation artifacts we are requested to use - self.ctls = {"%opts": ' '.join(ctl_opts), - "%cargs": ' '.join(ctl_cargs), - "%cov": ' '.join(ctl_cov), - "%tags": ' '.join(ctl_tags), - "%cons": ' '.join(ctl_cons)} + self.ctls = { + "%opts": " ".join(ctl_opts), + "%cargs": " ".join(ctl_cargs), + "%cov": " ".join(ctl_cov), + "%tags": " ".join(ctl_tags), + "%cons": " ".join(ctl_cons), + } # And these are the dictionaries we expose. This includes the expected # line notes, the expected report notes, and the absolute paths to the @@ -729,13 +727,14 @@ def __init__(self, xfile, xcov_level, ctl_opts, ctl_cov, ctl_cargs, self.__expose(ux) def __expose(self, ux): - # A '+' prefix on the source reference means we expect # sources to be referenced with relative dir indications: - source = (ux.sref.xpath - if ux.sref.xsource.startswith('+') - else os.path.basename(ux.sref.xpath)) + source = ( + ux.sref.xpath + if ux.sref.xsource.startswith("+") + else os.path.basename(ux.sref.xpath) + ) self.abspaths[source] = os.path.abspath(ux.sref.spath) self.xrnotes[source] = ux.xrdict @@ -762,13 +761,13 @@ def __get_scovdata(self, scov_file): # more flexibility. Also take care of the trailing new-line # character that we get from lines_of. line.strip() - if line.startswith(lang_info.comment + '#'): + if line.startswith(lang_info.comment + "#"): in_scovdata = True if in_scovdata and line.startswith(lang_info.comment): # Also take this opportunity to strip the leading comment # string as well as any space immediately following it. # This will simplify the parsing a little bit. - contents.append(line[len(lang_info.comment):].lstrip()) + contents.append(line[len(lang_info.comment) :].lstrip()) return contents def __parse_scovdata(self, scovdata): @@ -834,11 +833,9 @@ def __parse_groups_from(self, scovdata): lastlx = None for line in scovdata: - ctl_update, ctl_value = self.__try_ctl_update_from(line) if ctl_update: - # A CTL line was found, update our processing state # accordingly: @@ -847,15 +844,13 @@ def __parse_groups_from(self, scovdata): else: grabbing = ctl_value - elif grabbing and line.startswith('+#'): - + elif grabbing and line.startswith("+#"): # A continuation line, to add rnotes that didn't fit # on the previous ones. lastlx.rnps.extend(self.__parse_expected_rnotes(line[3:])) - elif line.startswith('#'): - + elif line.startswith("#"): # A new group starts. Close the current one first and start # grabbing again unconditionally: @@ -865,8 +860,7 @@ def __parse_groups_from(self, scovdata): current_uxg = UXgroup(candlists=self.__parse_sources(line)) grabbing = True - elif grabbing and line.startswith(('/', '=')): - + elif grabbing and line.startswith(("/", "=")): # This must be an LX line. Check lre overriding and add to the # set attached to the current group consistency. @@ -876,13 +870,14 @@ def __parse_groups_from(self, scovdata): lx.lre in current_uxg.lxset and not lx.override, FatalError( "LRE dup without overriding note (%s, %s)" - % (lx.lre, self.xfile))) + % (lx.lre, self.xfile) + ), + ) current_uxg.lxset[lx.lre] = lx lastlx = lx else: - # Not grabbing or regular comment. Just ignore. pass @@ -912,9 +907,11 @@ def __end_parse_on(self, uxg): # # What default notes we expect for what designator text - builtin_lxs = {"__l-s-": "l- ## s-", - "__l!d!": "l! ## d!", - "__l!dT-": "l! ## dT-"} + builtin_lxs = { + "__l-s-": "l- ## s-", + "__l!d!": "l! ## d!", + "__l!dT-": "l! ## dT-", + } def __builtin_lcxs_for(self, uxg): """Add builtin default LineCX for UXG.""" @@ -927,8 +924,10 @@ def __builtin_lcxs_for(self, uxg): # Now compute the list of LCX objects for each of those defaults - return [self.__parse_lcx("/%s/ %s" % (lre, self.builtin_lxs[lre])) - for lre in nothere] + return [ + self.__parse_lcx("/%s/ %s" % (lre, self.builtin_lxs[lre])) + for lre in nothere + ] # CTL parsing for control of conditional sections @@ -948,7 +947,7 @@ def __try_ctl_update_from(self, line): # CTL lines are like "%cov: -S routines %cargs: !-gnatn" # They are the only lines that may start with '%'. - if not line.startswith('%'): + if not line.startswith("%"): return (False, None) # To keep grabbing LX lines, all the CTL parts must evaluate True. @@ -1011,17 +1010,15 @@ def __eval_ctl_update_from(self, part): # of options that we were given for the key: this_val = True - for oseq in opts.split(','): - + for oseq in opts.split(","): oseq = oseq.strip() - if oseq.startswith('!'): + if oseq.startswith("!"): invert = True oseq = oseq[1:] else: invert = False - optin = re.search(pattern=oseq, - string=self.ctls[key]) is not None + optin = re.search(pattern=oseq, string=self.ctls[key]) is not None this_val &= not optin if invert else optin @@ -1043,7 +1040,7 @@ def __parse_sources(self, image): # to mean "this section applies to (x0.adb and y0.adb) or (x1.c an # y1.c), whichever set we can reach from here. - return [alt.split(' ') for alt in image[1:].strip().split('|')] + return [alt.split(" ") for alt in image[1:].strip().split("|")] # Instance name resolution helpers for __resolve_stags_from() @@ -1066,7 +1063,6 @@ def __parse_sources(self, image): imark = "i:" def __resolve_itags_within(self, xnp, idict): - # xnp.stag contains something like i:NAME1[i:NAME2[i:NAME3]] to # designate instantiations @@ -1083,20 +1079,25 @@ def __sloc_for(m): # stash a dummy column number here, required to form a regular # Sloc still. - slocs = ["%s:%d:0" % (os.path.basename(sp), tl.lno) - for sp in idict - for tl in idict[sp] - if name in tl.text] + slocs = [ + "%s:%d:0" % (os.path.basename(sp), tl.lno) + for sp in idict + for tl in idict[sp] + if name in tl.text + ] thistest.stop_if( len(slocs) != 1, - FatalError("%d slocs found for stag %s" % (len(slocs), name))) + FatalError("%d slocs found for stag %s" % (len(slocs), name)), + ) return slocs[0] - xnp.stag = re.sub(pattern="%s[A-Za-z_0-9]+" % self.imark, - repl=__sloc_for, - string=xnp.stag) + xnp.stag = re.sub( + pattern="%s[A-Za-z_0-9]+" % self.imark, + repl=__sloc_for, + string=xnp.stag, + ) def __resolve_itags_from(self, all_xnps, uxgroups): """ @@ -1105,9 +1106,9 @@ def __resolve_itags_from(self, all_xnps, uxgroups): all the units in UXGROUPS. """ - i_xnps = [xnp - for xnp in all_xnps - if xnp.stag and self.imark in xnp.stag] + i_xnps = [ + xnp for xnp in all_xnps if xnp.stag and self.imark in xnp.stag + ] if len(i_xnps) == 0: return @@ -1117,9 +1118,9 @@ def __resolve_itags_from(self, all_xnps, uxgroups): def __ilines_for(sp): tf = Tfile(filename=sp, process=lambda tl: None) - return [tl - for tl in tf.contents() - if "# %s" % self.imark in tl.text] + return [ + tl for tl in tf.contents() if "# %s" % self.imark in tl.text + ] spaths = [sref.spath for uxg in uxgroups for sref in uxg.srlist] idict = {sp: __ilines_for(sp) for sp in spaths} @@ -1135,10 +1136,9 @@ def __resolve_stags_from(self, uxgroups): separation tag strings into Stag objects. """ - all_xnps = [xnp - for uxg in uxgroups - for lx in uxg.lxset - for xnp in lx.rnps] + all_xnps = [ + xnp for uxg in uxgroups for lx in uxg.lxset for xnp in lx.rnps + ] self.__resolve_itags_from(all_xnps=all_xnps, uxgroups=uxgroups) @@ -1152,7 +1152,8 @@ def __parse_expected_rnotes(self, image): # We will use shlex (which is useful for parsing quoted strings). # It enables us to split the given string, according a given separator, # but still preserves quoted text altogether (i.e. if there is a - # separator in some quoted text, it won't be considered as a separator). + # separator in some quoted text, it won't be considered as a + # separator). # # The separator can be a "#", or a ",", so we will split on them. We # will also remove whitespaces (as when splitting, shlex also skips @@ -1169,13 +1170,13 @@ def __parse_expected_rnotes(self, image): splitter.whitespace_split = True splitter.whitespace += "#," imlist = list(splitter) - return [rnote - for rnote in (self.__parse_one_expected_rnote(im) - for im in imlist) - if rnote] + return [ + rnote + for rnote in (self.__parse_one_expected_rnote(im) for im in imlist) + if rnote + ] def __parse_one_expected_rnote(self, image): - # We have at hand single note spec, possibly conditioned by the # xcov-level. Something like "s-", "d=>dT-", or "mu=>c!:"B". @@ -1193,18 +1194,18 @@ def __parse_one_expected_rnote(self, image): # possible instance specialization parts and return a note pattern # instance - if '@(' in ntext: - ntext, stag = ntext.split('@(') - stag = stag.rstrip(')') + if "@(" in ntext: + ntext, stag = ntext.split("@(") + stag = stag.rstrip(")") else: stag = None - if ':' in ntext: + if ":" in ntext: # We split only once, as we have occurrences of notes as such: # s-:"P :=" (the string as parsed by shlex would be 's-:P :='), # with a colon inside the quoted string. We don't want to split on # that second colon, as it is part of the source code. - ntext, stext = ntext.split(':', 1) + ntext, stext = ntext.split(":", 1) else: stext = None @@ -1226,10 +1227,42 @@ def __decode_note_choice(self, text): or [('stmt', 'l+'), ('stmt+decision', 'l+')] """ - level_from_char = {"s": "stmt", - "d": "stmt+decision", - "m": "stmt+mcdc", - "u": "stmt+uc_mcdc"} + level_from_char = { + "s": ["stmt"], + "d": ["stmt+decision"], + "m": ["stmt+mcdc"], + "u": ["stmt+uc_mcdc"], + } + + def make_new_lvl_combinaison(lvl): + """ + Add the coverage level lvl to other regular coverage level + combinaisons defined in level_from_char. Return the list of + combinaisons. + """ + res = [] + for char in level_from_char: + for comb in level_from_char[char]: + res.append(comb + "+" + lvl) + return res + + assert_level_from_char = { + "a": make_new_lvl_combinaison("atc"), + "c": make_new_lvl_combinaison("atcc"), + } + + level_from_char.update(assert_level_from_char) + + fun_call_level_from_char = { + "f": make_new_lvl_combinaison("fun_call"), + } + + level_from_char.update(fun_call_level_from_char) + + gexpr_level_from_char = {"g": make_new_lvl_combinaison("gexpr")} + + level_from_char.update(gexpr_level_from_char) + result = text.split("=>") if len(result) == 1: @@ -1238,18 +1271,24 @@ def __decode_note_choice(self, text): elif len(result) > 2: # Parse error raise FatalError( - "Note choice %s contains more than one arrow" % text) + "Note choice %s contains more than one arrow" % text + ) else: - note = result[1].lstrip(' ') - lev_list = result[0].rstrip(' ') + note = result[1].lstrip(" ") + lev_list = result[0].rstrip(" ") - return [(level_from_char[lchar], note) for lchar in lev_list] + res = [] + for lchar in lev_list: + for combinaison in level_from_char[lchar]: + res.append((combinaison, note)) + + return res def __select_lnote(self, text): """Decode text to return the line note for the current coverage level.""" - lx_lnote_list = [alt.strip() for alt in text.split(',')] + lx_lnote_list = [alt.strip() for alt in text.split(",")] level_table = dict( ln_tuple @@ -1259,28 +1298,30 @@ def __select_lnote(self, text): if self.xcov_level in level_table: return level_table[self.xcov_level] - elif '' in level_table: - return level_table[''] + elif "" in level_table: + return level_table[""] else: raise FatalError( "Missing line expectation choice for level %s in %s" - % (self.xcov_level, text)) + % (self.xcov_level, text) + ) def __select_rnote(self, text): """Decode TEXT into a report note for the current coverage level.""" # Set of level->note_kind associations in TEXT - level_table = dict(ln_tuple - for ln_tuple in self.__decode_note_choice(text)) + level_table = dict( + ln_tuple for ln_tuple in self.__decode_note_choice(text) + ) # If we have one association for the exact level we're running, # use that. Fallback to a default kind if we have one. if self.xcov_level in level_table: return level_table[self.xcov_level] - elif '' in level_table: - return level_table[''] + elif "" in level_table: + return level_table[""] return None @@ -1294,22 +1335,26 @@ def __parse_lcx(self, image): m = re.match( string=image, - pattern=r"\s*(?P=?/.*?/)\s+(?P.*) ## (?P.*)") + pattern=r"\s*(?P=?/.*?/)\s+(?P.*) ## (?P.*)", + ) if m is None: - raise FatalError("Invalid '%s' line expectation spec." - "\nExpected /LRE/ lnotes ## rnotes" % image) + raise FatalError( + "Invalid '%s' line expectation spec." + "\nExpected /LRE/ lnotes ## rnotes" % image + ) lx_lre = m.group("lre") - lre_override = lx_lre[0] == '=' - if lx_lre[0] != '/': + lre_override = lx_lre[0] == "=" + if lx_lre[0] != "/": lx_lre = lx_lre[1:] - lx_lre = lx_lre.strip('/') + lx_lre = lx_lre.strip("/") - lx_lnote = XnoteP(text=self.__select_lnote(m.group("lnote")), - stext=None) + lx_lnote = XnoteP( + text=self.__select_lnote(m.group("lnote")), stext=None + ) lx_rnotes = self.__parse_expected_rnotes(m.group("rnotes")) @@ -1328,8 +1373,9 @@ def __parse_lcx(self, image): else: thistest.stop_if( len(lx_rnotes) > 1 and "0" in lx_rnotes, - FatalError("Contradictory =report expectation in %s" % image) + FatalError("Contradictory =report expectation in %s" % image), ) - return LineCX(lre=lx_lre, lnp=lx_lnote, rnps=lx_rnotes, - override=lre_override) + return LineCX( + lre=lx_lre, lnp=lx_lnote, rnps=lx_rnotes, override=lre_override + ) diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 11b317a68..3b61165f4 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -12,11 +12,69 @@ import re from .cnotes import ( - Xnote, block_p, cPartCov, dNoCov, dPartCov, dfAlways, dfNoCov, dtAlways, - dtNoCov, ePartCov, eNoCov, efNoCov, etNoCov, lFullCov, lNoCode, lNoCov, - lNotCoverable, lPartCov, lx0, lx1, lx2, oNoCov, oPartCov, ofNoCov, - otNoCov, r0, r0c, sNoCov, sNotCoverable, sPartCov, xBlock0, xBlock1, - xBlock2, xNoteKinds, lUndetCov, sUndetCov, dUndetCov, eUndetCov + Xnote, + block_p, + transparent_p, + cPartCov, + dNoCov, + dNotCoverable, + dPartCov, + dfAlways, + dfNoCov, + dtAlways, + dtNoCov, + ePartCov, + eNoCov, + efNoCov, + etNoCov, + lFullCov, + lNoCode, + lNoCov, + lNotCoverable, + lPartCov, + lx0, + lx1, + lx2, + lx, + oNoCov, + oPartCov, + ofNoCov, + otNoCov, + r0, + r0c, + sNoCov, + sNotCoverable, + sPartCov, + xBlock0, + xBlock1, + xBlock2, + xNoteKinds, + lUndetCov, + sUndetCov, + dUndetCov, + eUndetCov, + lDisCov, + XsNoCov, + XsPartCov, + XsNotCoverable, + XsUndetCov, + XotNoCov, + XofNoCov, + XoPartCov, + XoNoCov, + XcPartCov, + Xr0, + Xr0c, + aNoCov, + atNoCov, + acPartCov, + fNoCov, + cNoCov, + fUndetCov, + cUndetCov, + gNoCov, + gUndetCov, + dBlock, ) from .segments import Line, Section, Segment from .stags import Stag_from @@ -30,7 +88,7 @@ class _XnoteP_block: """ - Block notes are relevant for a general section. Eventhough the block is + Block notes are relevant for a general section. Even though the block is matched line by line, we need to materialize a single note for the whole block. """ @@ -42,7 +100,6 @@ def __init__(self, notep): self.lastni = None def instanciate_over(self, tline, block, kind): - # We create a single instance the first time around, then expand the # section over subsequence matches. if self.lastni: @@ -52,7 +109,8 @@ def instanciate_over(self, tline, block, kind): else: thisni = Xnote(xnp=self.notep, block=block, kind=kind) thisni.register_match( - Section(l0=tline.lno, c0=0, l1=tline.lno, c1=0)) + Section(l0=tline.lno, c0=0, l1=tline.lno, c1=0) + ) if thisni: self.lastni = thisni @@ -68,7 +126,6 @@ def __init__(self, notep): self.notep = notep def instanciate_over(self, tline, block, kind): - thisni = Xnote(xnp=self.notep, block=block, kind=kind) thisni.register_match(Line(tline.lno)) @@ -111,9 +168,9 @@ def __extended_segend_for(self, tline, bm): while segend <= linend and pnest >= 0: c = tline.text[segend] - if c == '(': + if c == "(": pnest += 1 - elif c == ')': + elif c == ")": pnest -= 1 segend += 1 @@ -124,7 +181,6 @@ def __extended_segend_for(self, tline, bm): return segend def instanciate_over(self, tline, block, kind): - thisni = Xnote(xnp=self.notep, block=block, kind=kind) # Register matches for Segments corresponding to all the instances of @@ -135,7 +191,7 @@ def instanciate_over(self, tline, block, kind): # not. base = self.stext - if self.stext.startswith('(') and self.stext.endswith('*)'): + if self.stext.startswith("(") and self.stext.endswith("*)"): base = self.stext[0:-2] extend = True else: @@ -148,47 +204,111 @@ def instanciate_over(self, tline, block, kind): for bm in re.finditer(pattern=base, string=tline.text): thisni.register_match( Segment( - tline.lno, bm.start() + 1, - self.__extended_segend_for(bm=bm, tline=tline) - if extend else bm.end())) + tline.lno, + bm.start() + 1, + ( + self.__extended_segend_for(bm=bm, tline=tline) + if extend + else bm.end() + ), + ) + ) thistest.stop_if( thisni.nmatches == 0, - FatalError("couldn't find subtext '%s' in line '%s'" - % (self.stext, tline.text))) + FatalError( + "couldn't find subtext '%s' in line '%s'" + % (self.stext, tline.text) + ), + ) thistest.stop_if( thisni.nmatches > 1, - FatalError("multiple matches of subtext '%s' in line '%s'" - % (self.stext, tline.text))) + FatalError( + "multiple matches of subtext '%s' in line '%s'" + % (self.stext, tline.text) + ), + ) return thisni class XnoteP: - - NK_for = {'l-': lNoCov, 'l!': lPartCov, 'l+': lFullCov, - 'l.': lNoCode, 'l0': lNotCoverable, 'l?': lUndetCov, - 'l#': lx0, 'l*': lx1, 'l@': lx2, - 's-': sNoCov, 's!': sPartCov, 's0': sNotCoverable, - 's?': sUndetCov, - 'dT*': dtAlways, 'dF*': dfAlways, - 'dT-': dtNoCov, 'dF-': dfNoCov, 'd!': dPartCov, 'd-': dNoCov, - 'd?': dUndetCov, - 'eT-': etNoCov, 'eF-': efNoCov, 'e!': ePartCov, 'e-': eNoCov, - 'e?': eUndetCov, - 'oT-': otNoCov, 'oF-': ofNoCov, 'o!': oPartCov, 'o-': oNoCov, - 'c!': cPartCov, - 'x0': xBlock0, 'x+': xBlock1, 'x?': xBlock2, - '0': r0, '0c': r0c} + NK_for = { + "l-": lNoCov, + "l!": lPartCov, + "l+": lFullCov, + "l.": lNoCode, + "l0": lNotCoverable, + "l?": lUndetCov, + "lD": lDisCov, + "l#": lx0, + "l*": lx1, + "l@": lx2, + "l=": lx, + "s-": sNoCov, + "s!": sPartCov, + "s0": sNotCoverable, + "s?": sUndetCov, + "dT*": dtAlways, + "dF*": dfAlways, + "d0": dNotCoverable, + "dT-": dtNoCov, + "dF-": dfNoCov, + "d!": dPartCov, + "d-": dNoCov, + "d?": dUndetCov, + "eT-": etNoCov, + "eF-": efNoCov, + "e!": ePartCov, + "e-": eNoCov, + "e?": eUndetCov, + "oT-": otNoCov, + "oF-": ofNoCov, + "o!": oPartCov, + "o-": oNoCov, + "c!": cPartCov, + "a-": aNoCov, + "aT-": atNoCov, + "ac!": acPartCov, + "f-": fNoCov, + "c-": cNoCov, + "f?": fUndetCov, + "c?": cUndetCov, + "g-": gNoCov, + "g?": gUndetCov, + "x0": xBlock0, + "x+": xBlock1, + "x?": xBlock2, + "0": r0, + "0c": r0c, + "dB": dBlock, + # Exempted notes + "Xs-": XsNoCov, + "Xs!": XsPartCov, + "Xs0": XsNotCoverable, + "Xs?": XsUndetCov, + "XoT-": XotNoCov, + "XoF-": XofNoCov, + "Xo!": XoPartCov, + "Xo-": XoNoCov, + "Xc!": XcPartCov, + "X0": Xr0, + "X0c": Xr0c, + } + + # The notes prefixed with 'X' correspond to the type of violations we + # expect to encounter within an exempted block. In this context we cannot + # determine if a violation on a decision belongs to decision or MCDC + # coverage. Therefore we use the 'o' notes to express this lack of + # information. def __init__(self, text, stext=None, stag=None): - # WEAK conveys whether it is ok (not triggering test failure) for # expectations produced by this pattern not to be discharged by an # emitted note. - self.weak = text[0] == '~' + self.weak = text[0] == "~" if self.weak: text = text[1:] @@ -216,7 +336,8 @@ def __init__(self, text, stext=None, stag=None): thistest.stop_if( False and self.stext is None and self.kind in xNoteKinds, - FatalError("expected justification text required for %s" % text)) + FatalError("expected justification text required for %s" % text), + ) # STAG is the separation tag that we must find on an emitted note to # discharge expectations produced from this pattern. Initially, at this @@ -229,21 +350,26 @@ def __init__(self, text, stext=None, stag=None): self.factory = ( _XnoteP_block(notep=self) - if block_p(self.kind) else - _XnoteP_line(notep=self) - if not self.stext else - _XnoteP_segment(notep=self, stext=stext)) + if block_p(self.kind) + else ( + _XnoteP_line(notep=self) + if not self.stext + else _XnoteP_segment(notep=self, stext=stext) + ) + ) def instantiate_stag(self): self.stag = Stag_from(self.stag, False) def instanciate_over(self, tline, block, srules): - - kind = (srules[self.kind] - if srules and self.kind in srules - else self.kind) - - return (None - if kind is None - else self.factory.instanciate_over(tline=tline, block=block, - kind=kind)) + kind = ( + srules[self.kind] if srules and self.kind in srules else self.kind + ) + + return ( + None + if kind is None or transparent_p(kind) + else self.factory.instanciate_over( + tline=tline, block=block, kind=kind + ) + ) diff --git a/testsuite/SCOV/map.py b/testsuite/SCOV/map.py index 4e7ca155d..2fe9a792b 100644 --- a/testsuite/SCOV/map.py +++ b/testsuite/SCOV/map.py @@ -9,13 +9,21 @@ from SUITE.control import env from SUITE.cutils import Wdir, match, to_list, list_to_file -from SUITE.tutils import (XCOV, thistest, gprfor, gprbuild, exename_for, do, - maybe_valgrind) +from SUITE.tutils import ( + XCOV, + thistest, + gprfor, + gprbuild, + exename_for, + do, + maybe_valgrind, +) class MapChecker: - def __init__(self, sources, options="", execs=None, alis=None, - ensure_dcscos=True): + def __init__( + self, sources, options="", execs=None, alis=None, ensure_dcscos=True + ): self.sources = to_list(sources) self.options = options self.ensure_dcscos = ensure_dcscos @@ -25,45 +33,56 @@ def __init__(self, sources, options="", execs=None, alis=None, self.execs = to_list(execs) else: self.execs = [ - exename_for(source.split('.')[0]) - for source in self.sources + exename_for(source.split(".")[0]) for source in self.sources ] if alis is not None: self.alis = to_list(alis) else: - self.alis = [os.path.join("obj", "%s.ali" % source.split('.')[0]) - for source in self.sources] + self.alis = [ + os.path.join("obj", "%s.ali" % source.split(".")[0]) + for source in self.sources + ] def run(self): - tmp = Wdir('tmp_') + tmp = Wdir("tmp_") # Compile all the sources. This method will not work if there are # sources that are not in the "." directory, but since executabes are # processed next, there will be an error if not all sources are # compiled. - project = gprfor( - self.sources, srcdirs=[".."], main_cargs=self.options) + project = gprfor(self.sources, srcdirs=[".."], main_cargs=self.options) gprbuild(project, gargs=["-bargs", "-z"]) # If requested, check at least one non statement SCO in alis if self.ensure_dcscos: for ali in self.alis: - thistest.fail_if(not match('^C[^S ]', ali, re.MULTILINE), - "couldn't find non-statement SCO in %s" % ali) + thistest.fail_if( + not match("^C[^S ]", ali, re.MULTILINE), + "couldn't find non-statement SCO in %s" % ali, + ) # Run xcov map-routines and check absence of errors - mapoutput = do(maybe_valgrind([ - XCOV, 'map-routines', '-v', f'--target={env.target.triplet}', - '--scos=@{}'.format(list_to_file(self.alis)), - ] + self.execs)) + mapoutput = do( + maybe_valgrind( + [ + XCOV, + "map-routines", + f"--target={env.target.triplet}", + "--scos=@{}".format(list_to_file(self.alis)), + ] + + self.execs + ) + ) - maperrors = [str(m) for m in - re.findall(r"(\*\*\*|\!\!\!)(.*)", mapoutput)] + maperrors = [ + str(m) for m in re.findall(r"(\*\*\*|\!\!\!)(.*)", mapoutput) + ] - thistest.log('\n'.join(maperrors)) + thistest.log("\n".join(maperrors)) thistest.fail_if( maperrors, - "expect no map-routines error for %s" % ", ".join(self.sources)) + "expect no map-routines error for %s" % ", ".join(self.sources), + ) tmp.to_homedir() diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 4ca1eb2ec..ec8b3e7e2 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -15,29 +15,63 @@ from e3.fs import rm -from SCOV.instr import (default_dump_channel, xcov_convert_base64, - xcov_instrument) +from SCOV.instr import ( + default_dump_channel, + maybe_copy_runtime, + maybe_relocate_binaries, + xcov_convert_base64, + xcov_instrument, +) from SUITE.cutils import contents_of, indent from SUITE.tutils import ( - exepath_to, gprbuild, run_cov_program, srctrace_pattern_for, - srctracename_for, thistest, tracename_for, xcov, xrun + exename_for, + exepath_to, + gprbuild, + run_cov_program, + srctrace_pattern_for, + thistest, + tracename_for, + xcov, + xrun, + GNATCOV_INFO, ) -COV_RE = re.compile(r'^ *(\d+) (.):.*$') - - -def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, - gpr_obj_dir=None, gpr_exe_dir=None, ignored_source_files=[], - separate_coverage=None, extra_args=[], extra_run_args=None, - extra_instr_args=None, extra_gprbuild_args=[], - extra_gprbuild_cargs=[], absolute_paths=False, - dump_trigger="auto", dump_channel="auto", - check_gprbuild_output=False, trace_mode=None, - runtime_project=None, gprsw_for_coverage=None, - scos_for_run=True, register_failure=True, program_env=None, - instrument_warnings_as_errors=True, exec_args=None, - auto_languages=True): +COV_RE = re.compile(r"^ *(\d+) (.):.*$") + + +def build_and_run( + gprsw, + covlevel, + mains, + extra_coverage_args, + quiet=True, + scos=None, + gpr_obj_dir=None, + gpr_exe_dir=None, + ignored_source_files=None, + separate_coverage=None, + extra_args=None, + extra_run_args=None, + extra_instr_args=None, + extra_gprbuild_args=None, + extra_gprbuild_cargs=None, + extra_gprbuild_largs=None, + absolute_paths=False, + dump_trigger="auto", + dump_channel="auto", + check_gprbuild_output=False, + trace_mode=None, + runtime_project=None, + gprsw_for_coverage=None, + scos_for_run=True, + register_failure=True, + program_env=None, + tolerate_instrument_messages=None, + exec_args=None, + manual_prj_name=None, + auto_config_args=True, +): """ Prepare a project to run a coverage analysis on it. @@ -56,6 +90,7 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, "gnatcov coverage" command-line returned. This is just for convenience: one can pass an empty list here and manually append extra arguments to the result. + :param bool quiet: Whether to pass "--quiet" to "gnatcov. :param None|list[str] scos: Optional list of SCOs files (ALI or SID) must be passed to gnatcov. These files must have no extension (for instance: 'obj/foo' instead of 'obj/foo.ali'. If absent, we pass "-P" to "gnatcov @@ -67,20 +102,22 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, :param None|str gpr_exe_dir: Optional name of the directory where gprbuild will create executables to run. If left to None, assume they are produced in the current directory. - :param list[str] ignored_source_files: List of file patterns to pass using - the --ignore-source-files option. + :param list[str] | None ignored_source_files: List of file patterns to pass + using the --ignore-source-files option. :param None|str separate_coverage: If provided, the argument is forwarded to gnatcov using the -S option. - :param list[str] extra_args: List of arguments to pass to any + :param list[str] | None extra_args: List of arguments to pass to any execution of gnatcov (gnatcov run|instrument|coverage). :param list[str] extra_run_args: List of arguments to pass to all executions of "gnatcov run". :param list[str] extra_instr_args: List of arguments to pass to all executions of "gnatcov instrument". - :param list[str] extra_gprbuild_args: List of arguments to pass to + :param list[str] | None extra_gprbuild_args: List of arguments to pass to gprbuild. - :param list[str] extra_gprbuild_cargs: List of arguments to pass to + :param list[str] | None extra_gprbuild_cargs: List of arguments to pass to gprbuild's -cargs section. + :param list[str] | None extra_gprbuild_largs: List of arguments to pass to + gprbuild's -largs section. :param bool absolute_paths: If true, use absolute paths in the result. :param None|str dump_trigger: See xcov_instrument. :param None|str dump_channel: See xcov_instrument. @@ -100,81 +137,103 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, exits with a non-zero status code, stop with a FatalError. :param None|dict[str, str] program_env: If not none, environment variables for the program to run. - :param bool instrument_warnings_as_errors: Whether to make the test fail if - there are warnings in the output of "gnatcov instrument". + :param None|str tolerate_instrument_messages: If not None, a re pattern + of error or warning messages tolerated in the "gnatcov instrument" + output. :param None|list[str] exec_args: List of arguments to pass to the executable. This will only work for native configurations. - :param bool auto_languages: See SUITE.tutils.xcov. + :param None|str manual_prj_name: When the dump trigger is manual, several + traces files (one per project) can be emitted if there are dump buffers + procedure calls in at least two distinct projects. This is the name of + the project for which we want to consider traces. + :param bool auto_config_args: If False, do not pass the --config argument + to gprbuild and gnatcov invocations. :rtype: list[str] :return: Incomplete list of arguments to pass to `xcov` in order to run "gnatcov coverage". The only mandatory argument that is missing is the annotation format. The last N arguments correspond to trace files for - the given N mains. + the given N mains. Upon return, the progam execution log for each main + M is available as M_output.txt. """ + def abspath(path): return os.path.abspath(path) if absolute_paths else path def exepath(main): main = os.path.join( gpr_exe_dir, - (os.path.join(gprsw.subdirs, main) if gprsw.subdirs else main)) + (os.path.join(gprsw.subdirs, main) if gprsw.subdirs else main), + ) return abspath(exepath_to(main)) def gprbuild_wrapper(root_project): - # Honor build relevant switches from gprsw here - gprbuild(root_project, - gargs=gprsw.build_switches + extra_gprbuild_args, - extracargs=extra_gprbuild_cargs, - trace_mode=trace_mode, - runtime_project=runtime_project) + gprbuild( + root_project, + gargs=gprsw.build_switches + (extra_gprbuild_args or []), + extracargs=extra_gprbuild_cargs or [], + largs=extra_gprbuild_largs or [], + trace_mode=trace_mode, + runtime_project=runtime_project, + auto_config_args=auto_config_args, + ) if check_gprbuild_output: - gprbuild_out = contents_of('gprbuild.out') + gprbuild_out = contents_of("gprbuild.out") thistest.fail_if( gprbuild_out, - "gprbuild's output (gprbuild.out) is not empty:\n{}" - .format(indent(gprbuild_out))) + "gprbuild's output (gprbuild.out) is not empty:\n{}".format( + indent(gprbuild_out) + ), + ) # When instrumenting, we expect units of interest to be provided # through GPR switches: - assert not (scos and trace_mode == 'src') + assert not (scos and trace_mode == "src") + + extra_args = extra_args or [] - gpr_exe_dir = gpr_exe_dir or '.' - gpr_obj_dir = gpr_obj_dir or os.path.join(gpr_exe_dir, 'obj') + gpr_exe_dir = gpr_exe_dir or "." + gpr_obj_dir = gpr_obj_dir or os.path.join(gpr_exe_dir, "obj") trace_mode = trace_mode or thistest.options.trace_mode # Use a --level= form for --level to faciliate locating and # replacing the switch at once as a whole if need be. - covlevel_args = [] if covlevel is None else ['--level={}'.format(covlevel)] + covlevel_args = [] if covlevel is None else ["--level={}".format(covlevel)] - xcov_args = ['coverage'] + covlevel_args + xcov_args = ["coverage"] + covlevel_args trace_files = [] # Arguments to pass to "gnatcov coverage" (bin trace mode) or "gnatcov # instrument" (src trace mode), in addition to those conveyed by gprsw. - cov_or_instr_args = ( - extra_args + - ['--ignore-source-files={}'.format(pattern) - for pattern in ignored_source_files]) + ignored_source_files = ignored_source_files or [] + cov_or_instr_args = extra_args + [ + "--ignore-source-files={}".format(pattern) + for pattern in ignored_source_files + ] if separate_coverage: - cov_or_instr_args.extend(['-S', separate_coverage]) + cov_or_instr_args.extend(["-S", separate_coverage]) + if quiet: + cov_or_instr_args.append("--quiet") # Compute arguments to specify units of interest. - if trace_mode == 'bin': - scos_arg = '--scos' - scos_ext = 'ali' + if trace_mode == "bin": + scos_arg = "--scos" + scos_ext = "ali" else: - scos_arg = '--sid' - scos_ext = 'sid' - scos = (['{}={}.{}'.format(scos_arg, abspath(a), scos_ext) - for a in scos] - if scos else - gprsw.cov_switches) - - if trace_mode == 'bin': + scos_arg = "--sid" + scos_ext = "sid" + scos = ( + ["{}={}.{}".format(scos_arg, abspath(a), scos_ext) for a in scos] + if scos + else gprsw.cov_switches + ) + + out_file_ = "{}_output.txt" + + if trace_mode == "bin": # Build and run each main gprbuild_wrapper(gprsw.root_project) run_args = covlevel_args + extra_args @@ -189,36 +248,60 @@ def gprbuild_wrapper(root_project): eargs = ["-eargs"] + exec_args for m in mains: - xrun(run_args + [exepath(m)] + eargs, out='run.log', - env=program_env, register_failure=register_failure) + out_file = out_file_.format(m) + xrun( + run_args + [exepath(m)] + eargs, + out=out_file, + env=program_env, + register_failure=register_failure, + ) trace_files = [abspath(tracename_for(m)) for m in mains] xcov_args.extend(cov_or_instr_args) - elif trace_mode == 'src': + elif trace_mode == "src": + # Deal with --dump-trigger=manual, + is_manual = ( + dump_trigger.split(",")[0] == "manual" if dump_trigger else False + ) + if dump_channel == "auto": dump_channel = default_dump_channel() + # The AAMP target does not support library project and requires + # rebuilding the instrumentation runtime: copy it in the test + # directory. + maybe_copy_runtime(os.getcwd()) + # Instrument the project and build the result extra_instr_args = cov_or_instr_args + list(extra_instr_args or []) - xcov_instrument(gprsw, covlevel, extra_args=extra_instr_args, - gpr_obj_dir=gpr_obj_dir, dump_trigger=dump_trigger, - dump_channel=dump_channel, - runtime_project=runtime_project, - out='instrument.log', - register_failure=register_failure, - warnings_as_errors=instrument_warnings_as_errors, - auto_languages=auto_languages) + xcov_instrument( + gprsw, + covlevel, + quiet=False, + extra_args=extra_instr_args, + gpr_obj_dir=gpr_obj_dir, + dump_trigger=dump_trigger, + dump_channel=dump_channel, + runtime_project=runtime_project, + out="instrument.log", + register_failure=register_failure, + tolerate_messages=tolerate_instrument_messages, + auto_config_args=auto_config_args, + ) gprbuild_wrapper(gprsw.root_project) - # If an explicit dump channel was requested, check that "gnatcov - # instrument" used it. In case it was implicit, get the one that was - # used. + # Retrieve the dump_channel that "gnatcov instrument" actually used, + # when available. It could be unavailable when either + # + # - the version of gnatcov we run doesn't dump the parameters it + # used (older than the introduction of gnatcov setup, typically + # in qualification contexts), # - # The mode in which we do not register failures is tricky: in this case - # we may not have an actual dump channel because instrumentation did - # not complete. In that case we cannot use source traces, but we must - # build and run programs nonetheless. + # - or we are called in a context causing a failure on purpose + # (register_failure False), at a point before gnatcov has dumped + # the parameters. + params_file_dir = gpr_obj_dir if gprsw.subdirs: params_file_dir = os.path.join(params_file_dir, gprsw.subdirs) @@ -226,64 +309,115 @@ def gprbuild_wrapper(root_project): try: f = open(params_file) except FileNotFoundError: - if register_failure: - raise - else: - actual_dump_channel = None + actual_dump_channel = None else: with f: params = json.load(f) actual_dump_channel = params["dump-channel"] - if dump_channel in (None, "auto"): - dump_channel = actual_dump_channel - elif dump_channel and actual_dump_channel: - thistest.fail_if_not_equal( - "actual dump channel", dump_channel, actual_dump_channel - ) + # Fail if we expected to be able to retrieve the dump channel + # actually used, but don't have it: + thistest.fail_if( + register_failure + and GNATCOV_INFO.has_setup + and actual_dump_channel is None, + "Unable to retrieve actual dump_channel from {}".format( + params_file + ), + ) - # Then execute each main and collect trace files - trace_files = [] - for m in mains: - # Remove potential existing source trace files: the name is - # non-deterministic by default, so we want to avoid getting - # multiple traces in the current directory. - rm(srctrace_pattern_for(m)) + # At this point, dump_channel is either None (request not to pass an + # argument at all), or a meaningful value that was passed to gnatcov + # instrument, possibly inferred from an "auto" selection at our level. - out_file = '{}_output.txt'.format(m) - run_cov_program(exepath(m), out=out_file, env=program_env, - register_failure=register_failure, - exec_args=exec_args) + # If an explicit dump channel was provided to gnatcov instrument and + # we have the actual dump channel used, the two should be consistent: + thistest.fail_if( + dump_channel + and actual_dump_channel + and dump_channel != actual_dump_channel, + "requested dump_channel ({}) != actual ({})".format( + dump_channel, actual_dump_channel + ), + ) - # Depending on the dump channel, we also may have to create the - # trace file. If we could not determine the actually used dump - # channel (see above), do not collect the trace file. - if dump_channel is None: - continue + # Now execute each main and collect the trace files we can. Tests + # triggering instrumentation failures on purpose are not guaranteed to + # produce a trace. - elif dump_channel == 'bin-file': - trace_file = srctracename_for(m, - register_failure=register_failure) - if trace_file is None: - continue + # See if we know the dump-channel that was used. Sometimes we don't, + # e.g. from a test failing to instrument or from a test requesting not + # to pass a dump-channel switch (dump_channel None) with a pre-setup + # version of gnatcov that would fallback to a default but not dump the + # parameters it used. - elif dump_channel == 'base64-stdout': - # Create a trace name that is compatible with srctracename_for - trace_file = srctrace_pattern_for(m).replace("*", "unique") + known_channel = dump_channel or actual_dump_channel - xcov_convert_base64(out_file, trace_file, - register_failure=register_failure) + # Remove potential existing source trace files: the name is + # non-deterministic by default, so we want to avoid getting + # multiple traces in the current directory. + for m in mains: + rm(srctrace_pattern_for(m, is_manual, manual_prj_name)) + # Callback to run for each instrumented main + maybe_relocate_binaries(gpr_obj_dir, gpr_exe_dir, [exename_for(m)]) - else: - raise ValueError('Invalid dump channel: {}' - .format(dump_channel)) + patterns = set() + trace_files = [] + for m in mains: + out_file = out_file_.format(m) + run_cov_program( + exepath(m), + out=out_file, + env=program_env, + register_failure=register_failure, + exec_args=exec_args, + ) - trace_files.append(abspath(trace_file)) + # See if we have a trace file at hand or if could create one from + # a base64 trace in the output. Operate best effort here, simply + # gathering what we can. + + # The possible combinations of gnatcov versions and project file + # contents associated with dump_channel None on entry together + # with tests checking for some kinds of failures on purpose make + # it very tricky to determine what we actually expect at this + # particular spot. + # + # Encoding that logic here is not worth the effort/complexity; + # simply assume that if we fail to get a trace when our context + # expects one, there will be some kind of test failure afterwards. + + if known_channel in [None, "bin-file"]: + patterns.add( + srctrace_pattern_for(m, is_manual, manual_prj_name) + ) + + elif ( + known_channel == "base64-stdout" + or "source trace file ==" in contents_of(out_file) + ): + # Pick a trace name that is compatible with srctracename_for + src_pattern = srctrace_pattern_for( + m, is_manual, manual_prj_name + ) + patterns.add(src_pattern) + trace_file = src_pattern.replace("*", "-" + m) + + # Here we're really supposed to have a trace in the output + # so we can be a tad stricter on the conversion outcome. + xcov_convert_base64( + out_file, trace_file, register_failure=register_failure + ) + + # Expand the list of patterns + if patterns: + for pattern in patterns: + trace_files.extend(glob.glob(pattern)) xcov_args.extend(cov_or_instr_args) else: - assert False, 'Unknown trace mode: {}'.format(trace_mode) + raise AssertionError("Unknown trace mode: {}".format(trace_mode)) # If provided, pass "gnatcov coverage"-specific project arguments, which # replace the list of SCOS. @@ -292,22 +426,44 @@ def gprbuild_wrapper(root_project): elif scos: xcov_args.extend(scos) - return xcov_args + extra_coverage_args + trace_files + return xcov_args + extra_coverage_args + list(trace_files) -def build_run_and_coverage(out='coverage.log', err=None, register_failure=True, - **kwargs): +def build_run_and_coverage( + out="coverage.log", + err=None, + register_failure=True, + auto_config_args=True, + tolerate_coverage_messages=None, + **kwargs, +): """ Helper to call build_and_run and then invoke `xcov`. This invokes `xcov` with the command-line that build_and_run returns to perform the "gnatcov coverage" step. - `out`, `err` and `register_failure` are forwarded to `xcov`, other + `out` and `err` are forwarded to `xcov`, `register_failure` and + `auto_config_args` are reported to `xcov` and `build_and_run`, other arguments are forwarded to `build_and_run`. + + If tolerate_coverage_messages is not None, filter out error or warning + messages from the "gnatcov coverage" output matching the regular + expression. """ - xcov_args = build_and_run(register_failure=register_failure, **kwargs) - xcov(xcov_args, out=out, err=err, register_failure=register_failure) + xcov_args = build_and_run( + register_failure=register_failure, + auto_config_args=auto_config_args, + **kwargs, + ) + xcov( + xcov_args, + auto_config_args=auto_config_args, + out=out, + err=err, + register_failure=register_failure, + tolerate_messages=tolerate_coverage_messages, + ) def checked_xcov(args, out_file): @@ -318,9 +474,9 @@ def checked_xcov(args, out_file): out = contents_of(out_file) thistest.fail_if( out, - 'gnatcov output not empty ({}):\n' - ' {}\n' - '{}'.format(out_file, ' '.join(args), out) + "gnatcov output not empty ({}):\n" + " {}\n" + "{}".format(out_file, " ".join(args), out), ) @@ -333,14 +489,18 @@ def fmt_cov(cov_data): """ result = [] for cov_char in sorted(cov_data): - result.append('{}({})'.format( - cov_char, ', '.join(str(lineno) - for lineno in sorted(cov_data[cov_char])) - )) - return ' '.join(result) + result.append( + "{}({})".format( + cov_char, + ", ".join( + str(lineno) for lineno in sorted(cov_data[cov_char]) + ), + ) + ) + return " ".join(result) -def check_xcov_content(filename, expected_cov): +def check_xcov_content(filename, expected_cov, trace_mode=None): """ Dumbed-down version of coverage matching. Check that the XCOV file "filename" matches some expected coverage data. @@ -350,8 +510,13 @@ def check_xcov_content(filename, expected_cov): >>> {'+': {5, 7}, '!': {6}} This is interpreted as: lines 5 and 7 must be fully covered (+), line 6 - must be partially covered (!) and all other lines must be no-code (.), - fully covered (+) or undetermined coverage (?). + must be partially covered (!) and all other lines must be no-code (.) or + fully covered (+). + + The recognized coverage annotation are partially covered (!), + not covered (-), undetermined coverage (?), disabled coverage (D), + exempted with no violations (#) or exempted with at least one + violation (*). """ @@ -359,15 +524,23 @@ def remove_empty_sets(data): """ Remove entries in "data" that contain empty sets of lines. """ - return {annotation: lines - for annotation, lines in data.items() - if lines} + return { + annotation: lines for annotation, lines in data.items() if lines + } # Check that expected coverage data contain only supported line annotations - invalid_line_annotations = set(expected_cov) - {'+', '!', '-', '?'} - assert not invalid_line_annotations, ( - 'Invalid line annotations: {}' - .format(' '.join(sorted(invalid_line_annotations)))) + invalid_line_annotations = set(expected_cov) - { + "+", + "!", + "-", + "?", + "D", + "#", + "*", + } + assert not invalid_line_annotations, "Invalid line annotations: {}".format( + " ".join(sorted(invalid_line_annotations)) + ) got_cov = collections.defaultdict(set) dot_lines = set() @@ -377,7 +550,7 @@ def remove_empty_sets(data): if m: lineno, cov_char = m.groups() lineno = int(lineno) - if cov_char == '.': + if cov_char == ".": dot_lines.add(lineno) else: got_cov[cov_char].add(lineno) @@ -392,73 +565,95 @@ def remove_empty_sets(data): refined_expectations = collections.defaultdict(set) refined_expectations.update(expected_cov) - for line in got_cov.get('+', set()): + for line in got_cov.get("+", set()): if line not in expected_non_dot_lines: - refined_expectations['+'].add(line) + refined_expectations["+"].add(line) got_cov = remove_empty_sets(got_cov) refined_expectations = remove_empty_sets(refined_expectations) thistest.fail_if( got_cov != refined_expectations, - '{}: unexpected coverage report content:\n' - 'Expected: {}\n' - 'Refined to: {}\n' - 'But got: {}\n'.format( - filename, fmt_cov(expected_cov), fmt_cov(refined_expectations), - fmt_cov(got_cov) - ) + "{}: unexpected coverage report content:\n" + "Expected: {}\n" + "Refined to: {}\n" + "But got: {}\n".format( + filename, + fmt_cov(expected_cov), + fmt_cov(refined_expectations), + fmt_cov(got_cov), + ), ) -def check_xcov_reports(xcov_filename_pattern, expected_cov, cwd=None): +def check_xcov_reports(reports_dir, expected_cov, discard_empty=None): """ Check the set of XCOV report files and their content. - Collect files that match "xcov_filename_pattern" (a glob pattern) and check - the set of files matches "expected_cov". Then, check that each report - matches the expected coverage results. + This checks that the set of "*.xcov" files in the directory "reports_dir" + matches files mentionned in "expected_cov" and that each report matches the + expected coverage result. "expected_cov" is a mapping: filename -> coverage data. See "check_xcov_content" for the coverage data format. - If "cwd" is not None, it must be a valid directory name, and both the - filename patterns and the file names in expected_cov must be relative to - it. + "discard_empty" is used to adjust test expectations for binary traces: + + * When True, source file for which there are no coverage expectation are + discarded (binary traces have a technical limitation: gnatcov is unable + to generate coverage reports for SCO-less source files: see + eng/das/cov/gnatcoverage#245). + + * When False, reports of source files with no coverage expectations are + checked. + + * If left to None, "discard_empty" is treated as True when the testsuite + runs in binary traces mode, and treated as False when the testsuite runs + in source traces mode. + + None is the most useful default. Tests that force the use of source traces + regardless of the testsuite trace mode should pass discard_empty=True. + Tests that have source files showing up as completely no code with binary + traces should pass discard_empty=False and adjust "expected_cov" depending + on the testsuite trace mode. """ def fmt_sorted_indented_list(items): - return '\n'.join(' {}'.format(s) for s in sorted(items)) + return "\n".join(" {}".format(s) for s in sorted(items)) # Avoid discrepancies between filenames on Windows and Unix. Although it is # not the canonical representation, Windows supports using slash as # separators, so use it. def canonicalize_file(filename): - return filename.replace('\\', '/') + return filename.replace("\\", "/") + + if discard_empty or ( + discard_empty is None and thistest.options.trace_mode == "bin" + ): + expected_cov = { + filename: expectations + for filename, expectations in expected_cov.items() + if any(lines for lines in expectations.values()) + } + + xcov_files = { + canonicalize_file(filename) + for filename in os.listdir(reports_dir) + if filename.endswith(".xcov") + } + expected_cov = { + canonicalize_file(filename): cov_data + for filename, cov_data in expected_cov.items() + } - home_dir = None - try: - if cwd is not None: - home_dir = os.getcwd() - os.chdir(cwd) - - xcov_files = {canonicalize_file(filename) - for filename in glob.glob(xcov_filename_pattern)} - expected_cov = {canonicalize_file(filename): cov_data - for filename, cov_data in expected_cov.items()} - - thistest.fail_if( - xcov_files != set(expected_cov), - 'Unexpected XCOV files. Expected:\n' - '{}\n' - 'But got instead:\n' - '{}\n'.format(fmt_sorted_indented_list(expected_cov), - fmt_sorted_indented_list(xcov_files)) - ) + thistest.fail_if( + xcov_files != set(expected_cov), + "Unexpected XCOV files. Expected:\n" + f"{fmt_sorted_indented_list(expected_cov)}\n" + "But got instead:\n" + f"{fmt_sorted_indented_list(xcov_files)}\n", + ) - for filename, cov_data in expected_cov.items(): - if filename in xcov_files: - check_xcov_content(filename, cov_data) - finally: - if home_dir is not None: - os.chdir(home_dir) + for filename, cov_data in expected_cov.items(): + if filename in xcov_files: + check_xcov_content(os.path.join(reports_dir, filename), cov_data) diff --git a/testsuite/SCOV/report.py b/testsuite/SCOV/report.py index 4926615e4..42d5e063d 100644 --- a/testsuite/SCOV/report.py +++ b/testsuite/SCOV/report.py @@ -16,6 +16,7 @@ from e3.fs import ls +from SCOV.internals.driver import SCOV_helper from SCOV.internals.cnotes import xNoteKinds from SCOV.internals.tfiles import Tfile from SUITE.tutils import XCOV, thistest, frame @@ -29,7 +30,6 @@ class Piece: """Single pattern of text expected somewhere in a report.""" def __init__(self, pattern, pre, nexpected=1): - # Regexp pattern to match over report lines self.pattern = pattern @@ -103,13 +103,18 @@ def check(self): 0 and thistest.log( "--\nChecking {}:\n" "pattern = '{}', nexpected = {}, nmatches = {}\n" - "pre = {}" - .format(self, self.pattern, self.nexpected, nmatches, self.pre)) + "pre = {}".format( + self, self.pattern, self.nexpected, nmatches, self.pre + ) + ) # Punt if we don't have the number of expected matches if nmatches != self.nexpected: - thistest.failed('On "{}", {} matches != expected {}' - .format(self.pattern, nmatches, self.nexpected)) + thistest.failed( + 'On "{}", {} matches != expected {}'.format( + self.pattern, nmatches, self.nexpected + ) + ) return # If we expected matches, have some, and have an ordering @@ -119,12 +124,14 @@ def check(self): first_self = self.__first_match() if not last_pre: thistest.failed( - 'On "%s", absence of match for predecessor "%s"' % ( - self.pattern, self.pre.pattern)) + 'On "%s", absence of match for predecessor "%s"' + % (self.pattern, self.pre.pattern) + ) elif last_pre.lno > first_self.lno: thistest.failed( - 'first match for "%s" too early wrt predecessor "%s"' % ( - self.pattern, self.pre.pattern)) + 'first match for "%s" too early wrt predecessor "%s"' + % (self.pattern, self.pre.pattern) + ) # All the possible per-criterion sections, ordered as they should be in the @@ -136,16 +143,7 @@ def check(self): "stmt": ["STMT"], "stmt+decision": ["STMT", "DECISION"], "stmt+mcdc": ["STMT", "DECISION", "MCDC"], - "stmt+uc_mcdc": ["STMT", "DECISION", "MCDC"] -} - -# Base prefix of the working subdirectory for each xcovlevel. ??? This is -# relying too much on knowledge about how the testuite driver works ... -xcovlevel_from = { - "sc_": "stmt", - "dc_": "stmt+decision", - "mc_": "stmt+mcdc", - "uc_": "stmt+uc_mcdc" + "stmt+uc_mcdc": ["STMT", "DECISION", "MCDC"], } @@ -162,7 +160,6 @@ def __register(self, rpieces): self.rpElements.extend(rpieces) def __setup_expectations(self, ntraces, xcovlevel, xregions): - self.rpElements = [] # Track the last Piece with nexpected > 0 @@ -195,30 +192,50 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): # # : gnatcov coverage - covLevel = Piece(pattern=r"Coverage level: stmt(\+(decision|mcdc))?", - pre=cmdLine2) + covLevel = Piece( + pattern=r"Coverage level: stmt(\+(decision|mcdc))?", pre=cmdLine2 + ) trHeader = Piece(pattern="Trace files:", pre=covLevel) - trFile = Piece(pattern=(r'\.trace' - if thistest.options.trace_mode == 'bin' else - r'\.srctrace'), - pre=trHeader, - nexpected=ntraces) + trFile = Piece( + pattern=( + r"\.trace" + if thistest.options.trace_mode == "bin" + else r"\.srctrace" + ), + pre=trHeader, + nexpected=ntraces, + ) trPgm = Piece(pattern="program *:", pre=None, nexpected=ntraces) trDate = Piece(pattern="date *:", pre=None, nexpected=ntraces) trTag = Piece(pattern="tag *:", pre=None, nexpected=ntraces) self.__register( - rpieces=[ctxHeader, runStamp, verNumber, - cmdLine1, cmdLine2, - covLevel, trHeader, trFile, trPgm, trDate, trTag]) + rpieces=[ + ctxHeader, + runStamp, + verNumber, + cmdLine1, + cmdLine2, + covLevel, + trHeader, + trFile, + trPgm, + trDate, + trTag, + ] + ) # NON-EXEMPTED VIOLATIONS - vioHeader = Piece(pattern=(r"\d+. %sCOVERAGE VIOLATIONS" - % ("NON-EXEMPTED " if xregions else "")), - pre=trTag) + vioHeader = Piece( + pattern=( + r"\d+. %sCOVERAGE VIOLATIONS" + % ("NON-EXEMPTED " if xregions else "") + ), + pre=trTag, + ) self.__register(rpieces=[vioHeader]) @@ -232,18 +249,20 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): # depends on the xcov --level argument nexpected = 1 if crit in crit_for[xcovlevel] else 0 - vsHeader = Piece(pattern="%s COVERAGE" % crit, - nexpected=nexpected, - pre=pre if nexpected else None) + vsHeader = Piece( + pattern="%s COVERAGE" % crit, + nexpected=nexpected, + pre=pre if nexpected else None, + ) self.__register(rpieces=[vsHeader]) # If we do expect a section, add a pattern for the violation # counter and update the current pre chain reference. Unexpected # sections should be left out of that chain. if nexpected > 0: - vsCount = Piece(pattern="([0-9]+|No) violation", - nexpected=-1, - pre=vsHeader) + vsCount = Piece( + pattern="([0-9]+|No) violation", nexpected=-1, pre=vsHeader + ) self.__register(rpieces=[vsCount]) pre = vsCount @@ -251,9 +270,12 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): if xregions: xmrHeader = Piece(pattern="EXEMPTED REGIONS", pre=pre) - xmrCount = Piece(pattern="([0-9]+|No) exempted region", - nexpected=-1, - pre=xmrHeader) + xmrCount = Piece( + pattern="([0-9]+|No) exempted region[s]*, " + "([0-9]+|No) exempted violation[s]*", + nexpected=-1, + pre=xmrHeader, + ) self.__register(rpieces=[xmrHeader, xmrCount]) pre = xmrCount @@ -266,17 +288,19 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): for crit in crit_for[xcovlevel]: sumLine = Piece( - pattern=("([0-9]+|No) %s%s violation" % - ("non-exempted " if xregions else "", crit)), - pre=pre) + pattern=( + "([0-9]+|No) %s%s violation" + % ("non-exempted " if xregions else "", crit) + ), + pre=pre, + ) self.__register(rpieces=[sumLine]) pre = sumLine if xregions: sumLine = Piece( - pattern="([0-9]+|No) exempted region", - nexpected=-1, - pre=pre) + pattern="([0-9]+|No) exempted region", nexpected=-1, pre=pre + ) self.__register(rpieces=[sumLine]) pre = sumLine @@ -286,9 +310,13 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): self.__register(rpieces=[rpEnd]) def __process_one_test(self, qde): - frame(text=("report check for xfile = %s\n" % qde.xfile - + "drivers = %s" % str(qde.drivers)), - char='~').display() + frame( + text=( + "report check for xfile = %s\n" % qde.xfile + + "drivers = %s" % str(qde.drivers) + ), + char="~", + ).display() # Count the number of expected exemption regions xregions = 0 @@ -300,13 +328,17 @@ def __process_one_test(self, qde): # applicable xcov-level self.__setup_expectations( ntraces=len(qde.drivers), - xcovlevel=xcovlevel_from[os.path.basename(qde.wdir)[0:3]], - xregions=xregions) + xcovlevel=SCOV_helper.xcovlevel_for( + self.tc, os.path.basename(qde.wdir) + ), + xregions=xregions, + ) reports = ls(os.path.join(qde.wdir, "test.rep")) - thistest.fail_if(len(reports) != 1, - "expected 1 report, found %d" % len(reports)) + thistest.fail_if( + len(reports) != 1, "expected 1 report, found %d" % len(reports) + ) self.report = Tfile(reports[0], self.__process_line) for rpe in self.rpElements: diff --git a/testsuite/SCOV/sarif.py b/testsuite/SCOV/sarif.py new file mode 100644 index 000000000..ec197484f --- /dev/null +++ b/testsuite/SCOV/sarif.py @@ -0,0 +1,47 @@ +""" +Helpers to check SARIF reports. +""" + +import json +import os.path + +from SUITE.context import thistest + + +def check_sarif_report(baseline_filename: str, actual_filename: str) -> None: + """ + Check that some actual SARIF report matches the corresponding baseline. + """ + + def refine(v): + match v: + case dict(): + if "uri" in v: + v["uri"] = os.path.basename(v["uri"]) + for item in v.values(): + refine(item) + + case list(): + for item in v: + refine(item) + + # Rewrite the actual report so that computing a diff is possible (e.g. + # basenames instead of URIs) and is human friendly (indentation). + modified_actual = f"modified-{os.path.basename(actual_filename)}" + with open(actual_filename) as f: + doc = json.load(f) + refine(doc) + for run in doc["runs"]: + driver = run["tool"]["driver"] + if driver["name"] == "gnatcov": + driver["version"] = "" + with open(modified_actual, "w") as f: + json.dump(doc, f, indent=2) + f.write("\n") + + thistest.fail_if_diff( + baseline_filename, + modified_actual, + failure_message=f"unexpected content for {actual_filename}", + ignore_white_chars=False, + ) diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index ec3a7ea04..bac14825f 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -27,17 +27,19 @@ from e3.fs import ls -from SCOV.internals.driver import (SCOV_helper_bin_traces, - SCOV_helper_src_traces) +from SCOV.internals.driver import ( + SCOV_helper_bin_traces, + SCOV_helper_src_traces, + SCOV_helper_rust, +) from SCOV.internals.driver import WdirControl from SCOV.tctl import CAT from SUITE.context import thistest -from SUITE.cutils import to_list, contents_of, FatalError +from SUITE.cutils import to_list, contents_of, FatalError, ext from SUITE.qdata import Qdata, QDentry class TestCase: - # Helpers for __init__ def __expand_drivers(self, patterns): @@ -57,10 +59,11 @@ def __with_extensions(self, pattern): return a string listing PATTERN with all the possible language extensions we expect for drivers.""" - # We expect .adb for Ada bodies, .c for C sources and .cpp - # for C++ sources. - return ' '.join( - "%s%s" % (pattern, ext) for ext in [".adb", ".c", ".cpp"]) + # We expect .adb for Ada bodies, .c for C sources, .cpp + # for C++ sources and .rs for Rust sources. + return " ".join( + "%s%s" % (pattern, ext) for ext in [".adb", ".c", ".cpp", ".rs"] + ) def __expand_shared_controllers(self, drivers, cspecs): """Search and expand possible shared drivers and/or consolidation @@ -75,11 +78,14 @@ def __expand_shared_controllers(self, drivers, cspecs): # possible lists of drivers (each maybe empty). Beware not to include # child or sub units, as these dont mirror as such in the set of test # drivers. - sxx = set(srcmatch.group(1) - for srcmatch in (re.match(r"([a-z_]*).*\.(adb|c)", - os.path.basename(src)) - for src in ls("src/*")) - if srcmatch) + sxx = { + srcmatch.group(1) + for srcmatch in ( + re.match(r"([a-z_]*).*\.(adb|c)", os.path.basename(src)) + for src in ls("src/*") + ) + if srcmatch + } # If there is no candidate body in src/, arrange to run all the # drivers. This is useful for test groups on GPR variations for @@ -93,10 +99,11 @@ def __expand_shared_controllers(self, drivers, cspecs): if drivers: self.__expand_drivers( self.__with_extensions( - "%ssrc/test_%s*" % (prefix, body))) + "%ssrc/test_%s*" % (prefix, body) + ) + ) if cspecs: - self.__expand_cspecs( - "%ssrc/cons_%s*.txt" % (prefix, body)) + self.__expand_cspecs("%ssrc/cons_%s*.txt" % (prefix, body)) def __category_from_dir(self): """Compute test category from directory location.""" @@ -106,8 +113,9 @@ def __category_from_dir(self): if re.search(r"/%s" % cat.name, test_dir): return cat - raise FatalError("Unable to infer test category from subdir '%s'" - % test_dir) + raise FatalError( + "Unable to infer test category from subdir '%s'" % test_dir + ) def __drivers_from(self, cspec): """ @@ -123,10 +131,32 @@ def __drivers_from(self, cspec): # match this expression return [drv for drv in self.all_drivers if re.search(drv_expr, drv)] - def __init__(self, extradrivers="", extracargs="", category=CAT.auto): + def __init__( + self, + extradrivers="", + extracargs="", + category=CAT.auto, + tolerate_messages=None, + tolerate_cov_messages=None, + expect_non_zero_code=False, + assert_lvl=None, + fun_call_lvl=False, + gexpr_lvl=False, + ): # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) self.expect_failures = False + # Specifically expect the test binary (eventually run in a + # cross environment) to return a non-zero exit code. + self.expect_non_zero_code = expect_non_zero_code + + # Pass tolerate_messages to gnatcov instrument invocations (see the doc + # for xcov_instrument). + self.tolerate_messages = tolerate_messages + + # Pass tolerate_cov_messages to gnatcov coverage invocations (only when + # using source traces). + self.tolerate_cov_messages = tolerate_cov_messages # Step 1: Compute the list of drivers and consolidation specs # to exercise @@ -138,13 +168,16 @@ def __init__(self, extradrivers="", extracargs="", category=CAT.auto): # exercise at all self.all_drivers = [] self.__expand_drivers( - self.__with_extensions("src/test_*") + " " + extradrivers) + self.__with_extensions("src/test_*") + " " + extradrivers + ) if not self.all_drivers: self.__expand_shared_controllers(drivers=True, cspecs=False) - thistest.stop_if(not self.all_drivers, - FatalError("Request to exercise empty test_set")) + thistest.stop_if( + not self.all_drivers, + FatalError("Request to exercise empty test_set"), + ) # Seek consolidation specs, then. Similar scheme, local check first, # then seek shared entities @@ -162,9 +195,13 @@ def __init__(self, extradrivers="", extracargs="", category=CAT.auto): # If automatic detection from subdir was requested, do that. # Otherwise, use the provided argument, which might be None or a # criterion related value. - self.category = (self.__category_from_dir() - if category == CAT.auto else - category) + self.category = ( + self.__category_from_dir() if category == CAT.auto else category + ) + + self.assert_lvl = assert_lvl + self.fun_call_lvl = fun_call_lvl + self.gexpr_lvl = gexpr_lvl # - extra compilation arguments, added to what --cargs was provided to # the testsuite command line: @@ -186,19 +223,32 @@ def __xcovlevels(self): if thistest.options.xcov_level: return [thistest.options.xcov_level] + assert not thistest.options.qualif_level + default_xcovlevels_for = { # Tests without categories should be ready for anything. # Exercise with the strictest possible mode: None: ["stmt+mcdc"], - CAT.stmt: ["stmt"], CAT.decision: ["stmt+decision"], - CAT.mcdc: ["stmt+mcdc", "stmt+uc_mcdc"]} + CAT.mcdc: ["stmt+mcdc", "stmt+uc_mcdc"], + } + + # Add a "+" before the name of the assertion coverage level in order + # to append it at the end of the the other specified coverage levels + # passed to gnatcov. + alvl = ("+" + self.assert_lvl) if self.assert_lvl else "" + + # Append "+fun_call" to activate function and call coverage if needed + fclvl = "+fun_call" if self.fun_call_lvl else "" - defaults = default_xcovlevels_for[self.category] - return ([defaults[0]] - if thistest.options.qualif_level else - defaults) + # Append "+gexpr" to activate guarded expression coverage if needed + glvl = "+gexpr" if self.gexpr_lvl else "" + + return [ + d + alvl + fclvl + glvl + for d in default_xcovlevels_for[self.category] + ] def __register_qde_for(self, drvo): """ @@ -206,16 +256,13 @@ def __register_qde_for(self, drvo): executed. """ self.qdata.register( - QDentry(xfile=drvo.xfile, - drivers=drvo.drivers, xrnotes=drvo.xrnotes, - wdir=os.path.normpath(drvo.awdir()))) - - # Base prefix for Working directories, per --level. Shared across - # runs for multiples levels. - _wdbase_for = {"stmt": "st_", - "stmt+decision": "dc_", - "stmt+mcdc": "mc_", - "stmt+uc_mcdc": "uc_"} + QDentry( + xfile=drvo.xfile, + drivers=drvo.drivers, + xrnotes=drvo.xrnotes, + wdir=os.path.normpath(drvo.awdir()), + ) + ) def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): """ @@ -224,23 +271,40 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): requesting SUBDIRHINT to be part of temp dir names. """ - this_scov_helper = ( - SCOV_helper_bin_traces if thistest.options.trace_mode == 'bin' - else SCOV_helper_src_traces if thistest.options.trace_mode == 'src' - else None) + rust_test = any(ext(drv) == ".rs" for drv in self.all_drivers) + thistest.stop_if( + rust_test + and not all(ext(drv) == ".rs" for drv in self.all_drivers), + "Rust drivers with other drivers is not yet supported", + ) + + this_scov_helper = None + if rust_test: + this_scov_helper = SCOV_helper_rust + elif thistest.options.trace_mode == "bin": + this_scov_helper = SCOV_helper_bin_traces + elif thistest.options.trace_mode == "src": + this_scov_helper = SCOV_helper_src_traces # Compute the Working directory base for this level, then run the test # for each indivdual driver. - this_wdbase = self._wdbase_for[covlevel] + this_wdbase = this_scov_helper.wdbase_for(self, covlevel) - wdctl = WdirControl(wdbase=this_wdbase, bdbase=self._available_bdbase, - subdirhint=subdirhint) + wdctl = WdirControl( + wdbase=this_wdbase, + bdbase=self._available_bdbase, + subdirhint=subdirhint, + ) for driver in self.all_drivers: - drvo = this_scov_helper(self, drivers=[driver], - xfile=driver, - xcovlevel=covlevel, covctl=covcontrol, - wdctl=wdctl) + drvo = this_scov_helper( + self, + drivers=[driver], + xfile=driver, + xcovlevel=covlevel, + covctl=covcontrol, + wdctl=wdctl, + ) self.__register_qde_for(drvo) drvo.run() @@ -249,14 +313,21 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): self._available_bdbase = this_wdbase # Next, run applicable consolidation tests - wdctl = WdirControl(wdbase=this_wdbase, bdbase=self._available_bdbase, - subdirhint=subdirhint) + wdctl = WdirControl( + wdbase=this_wdbase, + bdbase=self._available_bdbase, + subdirhint=subdirhint, + ) for cspec in self.all_cspecs: - drvo = this_scov_helper(self, drivers=self.__drivers_from(cspec), - xfile=cspec, - xcovlevel=covlevel, covctl=covcontrol, - wdctl=wdctl) + drvo = this_scov_helper( + self, + drivers=self.__drivers_from(cspec), + xfile=cspec, + xcovlevel=covlevel, + covctl=covcontrol, + wdctl=wdctl, + ) self.__register_qde_for(drvo) drvo.run() @@ -278,9 +349,11 @@ def run(self, covcontrol=None, subdirhint=""): # the binaries together with the other artifacts is convenient. self._available_bdbase = None for covlevel in self.__xcovlevels(): - self.__run_one_covlevel(covlevel=covlevel, - covcontrol=covcontrol, - subdirhint=subdirhint) + self.__run_one_covlevel( + covlevel=covlevel, + covcontrol=covcontrol, + subdirhint=subdirhint, + ) finally: # If we are running for qualification purposes, dump data needed # for qualification test-results production purposes. try/finally diff --git a/testsuite/SCOV/tctl.py b/testsuite/SCOV/tctl.py index 59db8d785..4b463e888 100644 --- a/testsuite/SCOV/tctl.py +++ b/testsuite/SCOV/tctl.py @@ -25,11 +25,27 @@ class CovControl: (gprsw). * Influence the non-GPR related command line options to gnatcov coverage - (covoptions). + (covoptions), and gnatcov instrument (instroptions). + If instroption is equal to "same" (the default), then it is set to the + value of covoption, to avoid the need to duplicate options. + + * Influence some instrumentation specific aspects of the test, like forcing + a specific dump trigger (dump_trigger) """ - def __init__(self, deps=(), units_in=None, ulist_in=None, units_out=None, - ulist_out=None, xreports=None, gprsw=None, covoptions=''): + def __init__( + self, + deps=(), + units_in=None, + ulist_in=None, + units_out=None, + ulist_out=None, + xreports=None, + gprsw=None, + covoptions="", + instroptions="same", + dump_trigger=None, + ): # To control "with" dependencies (set of projects that will be withed # by the one we will be generating for the testcase): self.deps = list(deps) @@ -41,6 +57,12 @@ def __init__(self, deps=(), units_in=None, ulist_in=None, units_out=None, # Extra options to gnatcov coverage only, typically for "-S" variants. self.covoptions = covoptions + # Extra options to gnatcov instrument only, potentially to be copied + # from covoptions + self.instroptions = ( + covoptions if instroptions == "same" else instroptions + ) + # To control Units related attributes in the GPR Coverage package. # # None is taken to mean "no attribute at all", which differs from @@ -63,9 +85,13 @@ def __init__(self, deps=(), units_in=None, ulist_in=None, units_out=None, # unexpected. self.xreports = xreports + # Dump trigger to be used in source trace mode. If left to None, the + # testsuite will determine automatically the best candidate based on + # the target and runtime. + self.dump_trigger = dump_trigger + def unexpected(self, source): - return (self.xreports is not None and - source not in self.xreports) + return self.xreports is not None and source not in self.xreports def expected(self, source): return not self.unexpected(source) @@ -75,22 +101,26 @@ def requires_gpr(self): Whether honoring this control object implictly requires the use of a project file. """ - return (self.deps - or self.gprsw - or self.units_in is not None - or self.units_out is not None - or self.ulist_in is not None - or self.ulist_out is not None) + return ( + self.deps + or self.gprsw + or self.units_in is not None + or self.units_out is not None + or self.ulist_in is not None + or self.ulist_out is not None + ) def gpr(self): """ The GPR Coverage package corresponding to our lists of attribute contents, as a multiline string. """ - return gprcov_for(units_in=self.units_in, - units_out=self.units_out, - ulist_in=self.ulist_in, - ulist_out=self.ulist_out) + return gprcov_for( + units_in=self.units_in, + units_out=self.units_out, + ulist_in=self.ulist_in, + ulist_out=self.ulist_out, + ) class _Category: @@ -99,6 +129,7 @@ class _Category: A specific category tells the testsuite engine which coverage notes are relevant for a testcase execution. """ + def __init__(self, name): self.name = name @@ -111,12 +142,12 @@ class CAT: """ # Set of criteria related categories - stmt = _Category(name='stmt') - decision = _Category(name='decision') - mcdc = _Category(name='mcdc') + stmt = _Category(name="stmt") + decision = _Category(name="decision") + mcdc = _Category(name="mcdc") critcats = (stmt, decision, mcdc) # Special value asking to determine the category from the Testcase # location (relative pathname from the testsuite root) - auto = _Category(name='auto') + auto = _Category(name="auto") diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index d55f8b618..459526d26 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -3,7 +3,8 @@ # GNATcoverage documentation build configuration file, created by # sphinx-quickstart on Fri Apr 22 12:56:32 2011. # -# This file is execfile()d with the current directory set to its containing dir. +# This file is execfile()d with the current directory set to its +# containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. @@ -11,213 +12,219 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +from scripts.common_conf import ( + project_name, + str_doc_id, + version, +) doc_standard_name = "Tool Operational Verification and Validation Results" rst_prolog = ".. |str_doc| replace:: *%s*" % doc_standard_name -common_file = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__)))), - "gnatcoverage-git-clone", - "qualification", "qm", "common_conf.py") - -if os.path.isfile(common_file): - exec(open(common_file).read()) -else: - print("Couldn't find common configuration file") - print(common_file) - print("from: %s" % __file__) # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) -# -- General configuration ----------------------------------------------------- +# -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'content' +master_doc = "content" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = None # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] -# -- Options for HTML output --------------------------------------------------- +# -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = "classic" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +html_theme_options = {"body_max_width": None} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = "%s Verification and Validation Results" % project_name # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'GNATcoveragedoc' +htmlhelp_basename = "GNATcoveragedoc" -# -- Options for LaTeX output -------------------------------------------------- +# -- Options for LaTeX output ------------------------------------------------ # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). +# (source start file, target name, title, author, +# documentclass [howto/manual]). latex_documents = [ - ('content', 'STR.tex', u'GNATcoverage DO-178C/ED-12C Qualification Material: %s' % doc_standard_name, - u'AdaCore', 'manual'), + ( + "content", + "STR.tex", + "GNATcoverage DO-178C/ED-12C Qualification Material: %s" + % doc_standard_name, + "AdaCore", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Additional stuff for the LaTeX preamble, in the QM fashion doc_id = str_doc_id + def project_settings(): full_document_name = project_name if doc_id is not None and len(doc_id) > 0: - full_document_name = '%s - %s' % (project_name, doc_id) - - return '\n'.join([ - r'\newcommand*{\QMFullDocumentName}[0]{' + full_document_name + r'}', - r'\newcommand*{\QMProjectName}[0]{' + project_name + r'}', - r'\newcommand*{\QMDocID}[0]{' + doc_id + r'}', - r'\newcommand*{\QMVersion}[0]{' + version + r'}']) - -latex_preamble = project_settings() + r""" + full_document_name = "%s - %s" % (project_name, doc_id) + + return "\n".join( + [ + r"\newcommand*{\QMFullDocumentName}[0]{" + + full_document_name + + r"}", + r"\newcommand*{\QMProjectName}[0]{" + project_name + r"}", + r"\newcommand*{\QMDocID}[0]{" + doc_id + r"}", + r"\newcommand*{\QMVersion}[0]{" + version + r"}", + ] + ) + + +latex_preamble = ( + project_settings() + + r""" \RequirePackage{lastpage} \addtocontents{toc}{\protect\thispagestyle{mytoc}} @@ -307,20 +314,23 @@ def project_settings(): } \makeatother """ +) +latex_elements = {"preamble": latex_preamble} # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True -# -- Options for manual page output -------------------------------------------- +# -- Options for manual page output ------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('content', 'gnatcoverage', u'GNATcoverage Documentation', - [u'AdaCore'], 1) + ("content", "gnatcoverage", "GNATcoverage Documentation", ["AdaCore"], 1) ] + +# flake8: noqa diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index f8d11e269..fea689796 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -21,11 +21,14 @@ # --testsuite-dir, though the two should be consistent wrt the python script # sources (e.g. the CTXdata structure must match) -LOCAL_TESTSUITE_DIR = \ - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +LOCAL_TESTSUITE_DIR = os.path.dirname( + os.path.dirname(os.path.abspath(__file__)) +) sys.path.append(LOCAL_TESTSUITE_DIR) -from SUITE.qdata import qdaf_in, stdf_in +TEST_LOG = "test.py.log" + +from SUITE.qdata import qdafs_from, stdf_in from SUITE.qdata import STATUSDATA_FILE, QLANGUAGES, QROOTDIR from SUITE.qdata import CTXDATA_FILE, Qdata from SUITE.control import BUILDER @@ -33,10 +36,25 @@ from SUITE import dutils from SCOV.internals.cnotes import ( - r0, r0c, xBlock0, sNoCov, sPartCov, - dtNoCov, dfNoCov, dPartCov, dNoCov, etNoCov, efNoCov, ePartCov, - eNoCov, cPartCov, xBlock1) -from SUITE.cutils import FatalError + r0, + r0c, + xBlock0, + sNoCov, + sPartCov, + dtNoCov, + dfNoCov, + dPartCov, + dNoCov, + etNoCov, + efNoCov, + ePartCov, + eNoCov, + cPartCov, + XsNoCov, + Xr0c, + xBlock1, +) +from SUITE.cutils import FatalError, lines_of from REST import rest # ============================= @@ -60,6 +78,7 @@ def exit_if(p, msg): print(msg) sys.exit(1) + # ================================================ # == QDregistry - Qualification Data repository == # ================================================ @@ -81,7 +100,6 @@ def exit_if(p, msg): class QualificationDataRepository(object): - def __init__(self, testsuite_dir): """Initialize a Qualification Data repository. @@ -93,6 +111,7 @@ def __init__(self, testsuite_dir): self.qdl = [] self.load_all(root=testsuite_dir) + self.root = testsuite_dir def load_all(self, root): """Load all data generated by a testsuite run. @@ -117,30 +136,30 @@ def load_test(self, dirname): print("loading from %s" % dirname) # Some tests in the Common chapter have status data and multiple - # individual test data files in subdirectories. Their purpose is to - # verify the proper behavior of a general functionality such as the - # ability to use project files, not to verify that the tool assesses - # such or such criteria properly. Even if they use an internal - # facility that does this as well, the individual datapoints - # are irrelevant and shouldn't be loaded. The general test result - # remains of interest of course. + # individual test data files in subdirectories. To properly load + # these multiple test data files, load them one at a time and merge + # the entries in the Qdata object of the whole testcase. # Fetch the status data first, then complete it with test data - # at the same place if any. + # located in the directory tree rooted at dirname, if any. std = dutils.pload_from(stdf_in(dirname)) - tcdf = qdaf_in(dirname) + tcdfs = qdafs_from(dirname) + + qda = Qdata(tcid=dirname) - qda = ( - dutils.pload_from(tcdf) if os.path.exists(tcdf) - else Qdata(tcid=dirname)) + for tcdf in tcdfs: + sub_qda = dutils.pload_from(tcdf) + for entry in sub_qda.entries: + qda.register(entry) qda.status = std.status qda.comment = std.comment self.qdl.append(qda) + # ======================================= # == Qualification report and helpers == # ======================================= @@ -154,7 +173,6 @@ def load_test(self, dirname): class Column(object): def __init__(self, htext, legend="", hidden=False): - # HTEXT is the column header text, # LEGEND is a brief description of the column contents, # HIDDEN tells if the column should not be displayed @@ -165,113 +183,104 @@ def __init__(self, htext, legend="", hidden=False): class colid(object): - # Testcase description and status, for testcase table - tc = Column( - htext="testcase", legend="Testcase Identifier") + tc = Column(htext="testcase", legend="Testcase Identifier") - sta = Column( - htext="status", - legend="Execution status" - ) + sta = Column(htext="status", legend="Execution status") - cat = Column( - htext="Test category", legend="Test category") + cat = Column(htext="Test category", legend="Test category") # Expectation counters, for testcase table and counters summary nov = Column( htext="nov", - legend="Number of expected absence of violations in testcase") + legend="Number of expected absence of violations in testcase", + ) scv = Column( htext="scv", - legend="Number of expected STATEMENT Coverage violations in testcase") + legend="Number of expected STATEMENT Coverage violations in testcase", + ) dcv = Column( htext="dcv", - legend="Number of expected DECISION Coverage violations in testcase") + legend="Number of expected DECISION Coverage violations in testcase", + ) mcv = Column( htext="mcv", - legend="Number of expected MCDC Coverage violations in testcase") + legend="Number of expected MCDC Coverage violations in testcase", + ) xbv = Column( htext="xbv", legend="Number of expected EXEMPTION " - "blocks with violations in testcase") + "blocks with violations in testcase", + ) - igv = Column( - htext="igv", legend="counters to be ignored", hidden=True) + igv = Column(htext="igv", legend="counters to be ignored", hidden=True) # Status counters and overall status, for status summary failed = Column( htext="failed", - legend="Number of tests with status *failed* in category") + legend="Number of tests with status *failed* in category", + ) passed = Column( htext="passed", - legend="Number of tests with status *passed* in category") + legend="Number of tests with status *passed* in category", + ) xfail = Column( - htext="xfail", - legend="Number of tests with status *xfail* in category") + htext="xfail", legend="Number of tests with status *xfail* in category" + ) ovsta = Column( htext="testsuite status", legend="Testsuite overall status, *passed* if all tests were " - "*passed* or *xfail*") + "*passed* or *xfail*", + ) # Other status counters - uok = Column( - htext="uok", legend="Test ran OK despite expected to fail") + uok = Column(htext="uok", legend="Test ran OK despite expected to fail") # Columns for legend sub-tables - colname = Column( - htext="column", legend=None) + colname = Column(htext="column", legend=None) + + legend = Column(htext="legend", legend=None) - legend = Column( - htext="legend", legend=None) # ------------------------------------ # -- Mappings to column identifiers -- # ------------------------------------ column_for = { - # When counting notes, map note kinds to table columns - r0: colid.nov, r0c: colid.igv, xBlock0: colid.nov, - sNoCov: colid.scv, sPartCov: colid.scv, - dtNoCov: colid.dcv, dfNoCov: colid.dcv, dPartCov: colid.dcv, dNoCov: colid.dcv, - etNoCov: colid.mcv, efNoCov: colid.mcv, ePartCov: colid.mcv, eNoCov: colid.mcv, cPartCov: colid.mcv, - xBlock1: colid.xbv, - # When checking status, map text passed by toplevel driver # to column. - - 'PASS': colid.passed, - 'XPASS': colid.passed, - 'FAIL': colid.failed, - 'XFAIL': colid.xfail, + "PASS": colid.passed, + "XPASS": colid.passed, + "FAIL": colid.failed, + "XFAIL": colid.xfail, } # ------------------------------- @@ -280,9 +289,9 @@ class colid(object): # Violation counters we care about for each possible do-level viocnt_columns_for = { - 'doA': (colid.nov, colid.igv, colid.scv, colid.dcv, colid.mcv, colid.xbv), - 'doB': (colid.nov, colid.igv, colid.scv, colid.dcv, colid.xbv), - 'doC': (colid.nov, colid.igv, colid.scv, colid.xbv) + "doA": (colid.nov, colid.igv, colid.scv, colid.dcv, colid.mcv, colid.xbv), + "doB": (colid.nov, colid.igv, colid.scv, colid.dcv, colid.xbv), + "doC": (colid.nov, colid.igv, colid.scv, colid.xbv), } # Status counters @@ -301,7 +310,6 @@ class colid(object): class CountersCell(object): - def __init__(self): self.expected = 0 self.satisfied = 0 @@ -316,18 +324,19 @@ def augment_by(self, other): self.expected += other.expected self.satisfied += other.satisfied + # Cell to hold a simple integer value # ----------------------------------- class IntCell(object): - def __init__(self, initval=0): self.value = initval def img(self, details=False): return "%d" % self.value + # Cell to hold a simple text # -------------------------- @@ -339,17 +348,18 @@ def __init__(self, text): def img(self, details=False): return "%s" % self.text + # Cell to hold a TC id in a context where the language # and test category are explicit by some other means # ----------------------------------------------------- class TcidCell(object): - def __init__(self, text): + def __init__(self, text, root): self.text = text + self.root = root def img(self, details=False): - # Arrange to strip: # # * The common leading part that can be inferred from the tc @@ -367,25 +377,28 @@ def img(self, details=False): # Applied in sequence and the order matters. re_strip = collections.OrderedDict( - ((QROOTDIR + "/", ""), - ("(Ada|C)/(stmt|decision|mcdc)/", ""), - ("Common/Report/", ""), - ("^[0-9]+_", ""), - ("/[0-9]+_", "/")) + ( + (re.escape(self.root), ""), + (QROOTDIR + "/", ""), + ("(Ada|C)/(stmt|decision|mcdc)/", ""), + ("Common/Report/", ""), + ("^[0-9]+_", ""), + ("/[0-9]+_", "/"), ) + ) img = self.text for r in re_strip: img = re.sub(pattern=r, repl=re_strip[r], string=img) return img + # Cell to hold a qualification status # ----------------------------------- class QstatusCell(object): def __init__(self, text): - # TEXT is the precise test execution status provided by the toplevel # driver (with uok, xfail, ...). Switch to the qualification status by # mapping to the status counter column. @@ -395,6 +408,7 @@ def __init__(self, text): def img(self, details=False): return "%s" % self.colid.htext + # ============= # == RSTfile == # ============= @@ -405,8 +419,8 @@ def __init__(self, filename): self.fd = None self.open(filename) - def open(self, filename): - self.fd = open("source/" + filename, 'w') + def open(self, filename): # noqa: A003 + self.fd = open("source/" + filename, "w") def write(self, text, pre=0, post=1): self.fd.write(rest.isolate(text=text, pre=pre, post=post)) @@ -414,15 +428,14 @@ def write(self, text, pre=0, post=1): def close(self): self.fd.close() + # ============== # == RSTtable == # ============== class RSTtable(object): - def __init__(self, title, text, columns, contents): - # COLUMNS is the list of columns for this table, CONTENTS is a # list of {col -> text} dictionaries, one per table line. Compared # to CONTENTS.keys(), COLUMNS is useful to enforce a column order. @@ -441,7 +454,6 @@ def __init__(self, title, text, columns, contents): self.text = text def __dump_description(self): - # Dump the table title, descriptive text and legend if self.title: @@ -456,12 +468,14 @@ def __dump_description(self): # as a (description-less) table itself ... ASCIItable( - title=None, text=None, + title=None, + text=None, columns=(colid.colname, colid.legend), contents=[ - {colid.colname: rest.emph(col.htext), - colid.legend: col.legend} for col in self.columns] - ).dump_to(self.rstf) + {colid.colname: rest.emph(col.htext), colid.legend: col.legend} + for col in self.columns + ], + ).dump_to(self.rstf) def __dump_contents(self): [self.dump_centry(ce) for ce in self.contents] @@ -484,7 +498,6 @@ def dump_footer(self): # ------------- def dump_to(self, rstf): - self.rstf = rstf self.__dump_description() @@ -505,33 +518,37 @@ def dump_to(self, rstf): class CSVtable(RSTtable): - - def __init__(self, title, text, columns, contents, - delim='&', controls=()): - + def __init__(self, title, text, columns, contents, delim="&", controls=()): self.controls = controls self.delim = delim RSTtable.__init__( - self, title=title, text=text, - columns=columns, contents=contents) + self, title=title, text=text, columns=columns, contents=contents + ) def dump_header(self): - text = '\n' + '\n'.join( - ['.. csv-table::', - ' :delim: ' + self.delim, - ' :header: %s' % " , ".join( - ['"%s"' % col.htext for col in self.columns]) - ] + [' ' + ctl for ctl in self.controls] - ) + "\n" + text = ( + "\n" + + "\n".join( + [ + ".. csv-table::", + " :delim: " + self.delim, + " :header: %s" + % " , ".join(['"%s"' % col.htext for col in self.columns]), + ] + + [" " + ctl for ctl in self.controls] + ) + + "\n" + ) self.rstf.write(text) def dump_centry(self, ce): entryl = (" %s " % self.delim).join( - [" %s" % ce[col] for col in self.columns]) + [" %s" % ce[col] for col in self.columns] + ) self.rstf.write(entryl) def dump_footer(self): - self.rstf.write('\n') + self.rstf.write("\n") # ================ @@ -549,43 +566,42 @@ def dump_footer(self): class ASCIItable(RSTtable): - def __init__(self, title, text, columns, contents): RSTtable.__init__( - self, title=title, text=text, - columns=columns, contents=contents) + self, title=title, text=text, columns=columns, contents=contents + ) self.__compute_widths() def __compute_widths(self): - # Compute the current width of every column, as the max of # all the texts (on every contents + header line) # This is useful to align the text of every column, for both # content rows and the ReST table separation lines. - self.width = dict( - [(col, 0) for col in self.columns]) + self.width = dict.fromkeys(self.columns, 0) # Maximize column width over contents entries - [self.width.__setitem__( - col, max(self.width[col], len(centry[col]))) - for centry in self.contents for col in self.columns] + [ + self.width.__setitem__(col, max(self.width[col], len(centry[col]))) + for centry in self.contents + for col in self.columns + ] # Maximize column width with length of column header - [self.width.__setitem__( - col, max(self.width[col], len(col.htext))) - for col in self.columns] + [ + self.width.__setitem__(col, max(self.width[col], len(col.htext))) + for col in self.columns + ] def dump_header(self): - sepl = " ".join( - ["=" * self.width[col] for col in self.columns]) + sepl = " ".join(["=" * self.width[col] for col in self.columns]) headl = " ".join( - ["%-*s" % (self.width[col], col.htext) - for col in self.columns]) + ["%-*s" % (self.width[col], col.htext) for col in self.columns] + ) self.rstf.write(sepl) self.rstf.write(headl) @@ -593,12 +609,12 @@ def dump_header(self): def dump_centry(self, ce): entryl = " ".join( - ["%-*s" % (self.width[col], ce[col]) for col in self.columns]) + ["%-*s" % (self.width[col], ce[col]) for col in self.columns] + ) self.rstf.write(entryl) def dump_footer(self): - sepl = " ".join( - ["=" * self.width[col] for col in self.columns]) + sepl = " ".join(["=" * self.width[col] for col in self.columns]) self.rstf.write(sepl, post=2) @@ -633,27 +649,29 @@ def dump_footer(self): class LISTtable(RSTtable): - def __init__(self, title, text, columns, contents): RSTtable.__init__( - self, title=title, text=text, - columns=columns, contents=contents) + self, title=title, text=text, columns=columns, contents=contents + ) def dump_header(self): - self.rstf.write('.. list-table::') - self.rstf.write(' :header-rows: 1', post=2) + self.rstf.write(".. list-table::") + self.rstf.write(" :header-rows: 1", post=2) - self.rstf.write(' * ' + "\n ".join( - ["- %s" % col.htext for col in self.columns] - )) + self.rstf.write( + " * " + + "\n ".join(["- %s" % col.htext for col in self.columns]) + ) def dump_centry(self, ce): - self.rstf.write(' * ' + "\n ".join( - ["- %s" % ce[col] for col in self.columns] - )) + self.rstf.write( + " * " + + "\n ".join(["- %s" % ce[col] for col in self.columns]) + ) def dump_footer(self): - self.rstf.write('\n', post=2) + self.rstf.write("\n", post=2) + # ============== # == QDreport == @@ -688,35 +706,34 @@ def trymatch(self, qda): class QDreport(object): - def __init__(self, options): - self.o = options # Fetch the testsuite execution context self.suitedata = dutils.jload_from( - os.path.join(self.o.testsuite_dir, CTXDATA_FILE)) + os.path.join(self.o.testsuite_dir, CTXDATA_FILE) + ) # Pick the testsuite dolevel if none was provided. Check # consistency otherwise: - suite_dolevel = self.suitedata['options']['dolevel'] + suite_dolevel = self.suitedata["options"]["dolevel"] fail_if( not suite_dolevel, - "Testsuite at %s was not run in qualification mode" % ( - self.o.testsuite_dir) - ) + "Testsuite at %s was not run in qualification mode" + % (self.o.testsuite_dir), + ) if self.o.dolevel is None: self.o.dolevel = suite_dolevel else: fail_if( self.o.dolevel != suite_dolevel, - "explicit dolevel (%s) doesn't match testsuite (%s)" % ( - self.o.dolevel, suite_dolevel) - ) + "explicit dolevel (%s) doesn't match testsuite (%s)" + % (self.o.dolevel, suite_dolevel), + ) # Setup the list of violation counters we care about wrt the # targetted do-level: @@ -735,34 +752,41 @@ def __init__(self, options): # categories from common ones. lang_categories = [ - (Category( - lang=lang, name="%s STATEMENT Coverage" % lang, - matcher="%s/%s/stmt" % (QROOTDIR, lang)), - Category( - lang=lang, name="%s DECISION Coverage" % lang, - matcher="%s/%s/decision" % (QROOTDIR, lang)), - Category( - lang=lang, name="%s MCDC Coverage" % lang, - matcher="%s/%s/mcdc" % (QROOTDIR, lang)) - ) for lang in QLANGUAGES - ] + ( + Category( + lang=lang, + name="%s STATEMENT Coverage" % lang, + matcher="%s/%s/stmt" % (QROOTDIR, lang), + ), + Category( + lang=lang, + name="%s DECISION Coverage" % lang, + matcher="%s/%s/decision" % (QROOTDIR, lang), + ), + Category( + lang=lang, + name="%s MCDC Coverage" % lang, + matcher="%s/%s/mcdc" % (QROOTDIR, lang), + ), + ) + for lang in QLANGUAGES + ] lang_categories = [ - cat for lang_cats in lang_categories for cat in lang_cats] + cat for lang_cats in lang_categories for cat in lang_cats + ] other_categories = [ Category( - name="REPORT Format", - matcher="%s/Common/Report" % QROOTDIR), - + name="REPORT Format", matcher="%s/Common/Report" % QROOTDIR + ), Category( name="Testsuite Selftest", matcher="%s/Appendix/Testsuite" % QROOTDIR, - internal=True), - - Category( - name="Others", matcher=".") - ] + internal=True, + ), + Category(name="Others", matcher="."), + ] self.categories = lang_categories + other_categories @@ -772,8 +796,19 @@ def __init__(self, options): # were run). This is useful e.g. to decide which sets of compilation # options should be displayed in the environment description items. - self.languages = set( - [cat.lang for cat in lang_categories if cat.qdl]) + self.languages = {cat.lang for cat in lang_categories if cat.qdl} + + self.dump_trigger = None + self.dump_channel = None + + # Gather effectively used dump-trigger and dump channel from the logs + # in source trace mode. + + if self.suitedata["options"]["trace_mode"] == "src": + ( + self.dump_trigger, + self.dump_channel, + ) = self.gather_trigger_and_channel() self.gen_envinfo(sepfile="env.rst") @@ -784,19 +819,58 @@ def __init__(self, options): self.gen_tctables(sepfile="tctables.rst") self.gen_tssummary(sepfile="tssummary.rst") - # Rely on a static toplevel index instead of generating one here. - # This is much simpler to tailor and the harcoded knowledge (set of - # sections/documents) is very limited and unlikely to change. + def _check_one_dump_option(self, line, option_name, current_value): + """ + Helper for gather_trigger_and_channel, inspect a line to determine + if it contains a "gnatcov instrument" command line, look for a + "--dump-{option_name}" and check its value against current_value. + In case of inconsistency, or if the option is not found, raises + FatalError + """ + if "gnatcov instrument" in line: + matcher = re.search( + pattern=f"--dump-{option_name}" + r"(?:=| )(\S*) ", string=line + ) + if matcher is None: + raise FatalError( + comment=f"Found no dump {option_name} in gnatcov" + f"instrument command line: {line}" + ) + if current_value and matcher.group(1) != current_value: + raise FatalError( + comment=f"Inconsistent dump {option_name} found:" + f" got {matcher.group(1)}" + f" but expected {current_value}" + ) + return matcher.group(1) + else: + return current_value - # self.gen_index(sepfiles=["env.rst", "tctables.rst", "tssummary.rst"]) + def gather_trigger_and_channel(self): + """ + Inspect all test.py.log files to determine which dump trigger and + dump channel switches were passed to gnatcov. Raises a FatalError if + one of the "gnatcov instrument" invocation is missing one of the two + arguments, or if we detect inconsistent values across tests. + """ + current_dt = None + current_dc = None + for p in find(self.o.testsuite_dir, TEST_LOG): + for line in lines_of(p): + current_dt = self._check_one_dump_option( + line, "trigger", current_dt + ) + current_dc = self._check_one_dump_option( + line, "channel", current_dc + ) + return (current_dt, current_dc) def categorize(self, qda): for cat in self.categories: if cat.trymatch(qda): return - raise FatalError( - comment="unable to categorize testcase %s" % qda.tcid) + raise FatalError(comment="unable to categorize testcase %s" % qda.tcid) # -------------------- # -- compute_tcdata -- @@ -823,26 +897,28 @@ def count(self, note, cell): cell.satisfied += 1 def tcdata_for(self, qd): - # Process one qualification data item, producing a report data line # for one testcase this_tcdata = dict( - [(colid.tc, TcidCell(qd.tcid))] + - [(key, CountersCell()) for key in self.viocnt_columns] + - [(colid.sta, QstatusCell(qd.status))] - ) - - [self.count(note=note, cell=this_tcdata[column_for[note.kind]]) - for qde in qd.entries for src in qde.xrnotes - for notelist in qde.xrnotes[src].values() - for note in notelist] + [(colid.tc, TcidCell(qd.tcid, self.o.testsuite_dir))] + + [(key, CountersCell()) for key in self.viocnt_columns] + + [(colid.sta, QstatusCell(qd.status))] + ) + + [ + self.count(note=note, cell=this_tcdata[column_for[note.kind]]) + for qde in qd.entries + for src in qde.xrnotes + for notelist in qde.xrnotes[src].values() + for note in notelist + if note.kind not in range(XsNoCov, Xr0c + 1) + ] return this_tcdata def compute_tcdata(self): - self.tcdata = dict( - [(qd, self.tcdata_for(qd)) for qd in self.qdl]) + self.tcdata = {qd: self.tcdata_for(qd) for qd in self.qdl} # ------------------ # -- gen_tctables -- @@ -858,18 +934,17 @@ def compute_tcdata(self): # =========== ======== ======== ... ======= def tcdict_for(self, qd): - # Arrange to provide details on the expected versus satisfied # violation counts only when the test has failed somehow: details = column_for[qd.status] != colid.passed - return dict( - [(col, "%s" % self.tcdata[qd][col].img(details)) - for col in self.tcdata[qd]]) + return { + col: "%s" % self.tcdata[qd][col].img(details) + for col in self.tcdata[qd] + } def gen_tctables(self, sepfile=None): - if sepfile: self.rstf = RSTfile(sepfile) @@ -918,18 +993,21 @@ def gen_tctables(self, sepfile=None): "\n\n" "A general summary of all the results is provided in the " ":ref:`tssummary` section of this report.\n" - ), + ), columns=self.tccolumns(), contents=None, - ).dump_to(self.rstf) + ).dump_to(self.rstf) - [LISTtable( + [ + LISTtable( title=("%s tests [ %s/... ]" % (cat.name, cat.qmprefix)), text=None, columns=self.tccolumns(), - contents=[self.tcdict_for(qd) for qd in cat.qdl] - ).dump_to(self.rstf) - for cat in self.categories if cat.qdl and not cat.internal] + contents=[self.tcdict_for(qd) for qd in cat.qdl], + ).dump_to(self.rstf) + for cat in self.categories + if cat.qdl and not cat.internal + ] if sepfile: self.rstf.close() @@ -951,29 +1029,31 @@ def gen_tctables(self, sepfile=None): def sumcolumns(self): return ( - (colid.cat,) # category - + stacnt_columns # #passed, #failed, #xfail - + self.viocnt_columns # nov, scv, ... - + (colid.ovsta,)) # testsuite status + (colid.cat,) # category + + stacnt_columns # #passed, #failed, #xfail + + self.viocnt_columns # nov, scv, ... + + (colid.ovsta,) + ) # testsuite status def init_data_for(self, catid): - # Initial data for the line corresponding to category CATID. The # overall status column is set separately, once the final counter # values are known return dict( - [(colid.cat, TextCell(catid))] + - [(col, IntCell()) for col in stacnt_columns] + - [(col, CountersCell()) for col in self.viocnt_columns]) + [(colid.cat, TextCell(catid))] + + [(col, IntCell()) for col in stacnt_columns] + + [(col, CountersCell()) for col in self.viocnt_columns] + ) def do_sum(self, qd, catsum): - [catsum[key].augment_by(self.tcdata[qd][key]) - for key in self.viocnt_columns] + [ + catsum[key].augment_by(self.tcdata[qd][key]) + for key in self.viocnt_columns + ] catsum[column_for[qd.status]].value += 1 def sumdata_for(self, cat, totsum): - # Compute the summary data for category CAT, and accumulate # into the TOTSUM total summary along the way @@ -990,16 +1070,19 @@ def sumdata_for(self, cat, totsum): # TOTSUM summary and return thissum.__setitem__( - colid.ovsta, TextCell( - "%s" % "passed" if thissum[colid.failed].value == 0 - else "failed")) + colid.ovsta, + TextCell( + "%s" % "passed" + if thissum[colid.failed].value == 0 + else "failed" + ), + ) [self.do_sum(qd=qd, catsum=totsum) for qd in cat.qdl] return thissum def sumdata(self): - # Compute the base data for the summary table. This is a list of # {colid -> Cell} dictionaries, with one list entry for each test # category + a total. Something like @@ -1015,28 +1098,36 @@ def sumdata(self): totsum = self.init_data_for("Total") catsums = [ - csum for csum in [self.sumdata_for(cat, totsum) - for cat in self.categories if cat.qdl] - if csum] + csum + for csum in [ + self.sumdata_for(cat, totsum) + for cat in self.categories + if cat.qdl + ] + if csum + ] totsum.__setitem__( - colid.ovsta, TextCell( - "%s" % "PASSED" if totsum[colid.failed].value == 0 - else "FAILED")) + colid.ovsta, + TextCell( + "%s" % "PASSED" + if totsum[colid.failed].value == 0 + else "FAILED" + ), + ) return catsums + [totsum] def sumcontents(self): - # Compute the list of { colid -> text } dictionaries for the summary # table, with a list entry for each test category (+ total) - return [dict([(col, "%s" % catsum[col].img()) - for col in self.sumcolumns()]) - for catsum in self.sumdata()] + return [ + {col: "%s" % catsum[col].img() for col in self.sumcolumns()} + for catsum in self.sumdata() + ] def gen_tssummary(self, sepfile): - if sepfile: self.rstf = RSTfile(sepfile) @@ -1051,8 +1142,8 @@ def gen_tssummary(self, sepfile): "refer to the :ref:`tctable` section of this report for an " "explanation of the legend. ", columns=self.sumcolumns(), - contents=self.sumcontents() - ).dump_to(self.rstf) + contents=self.sumcontents(), + ).dump_to(self.rstf) if sepfile: self.rstf.close() @@ -1062,26 +1153,60 @@ def gen_tssummary(self, sepfile): # ----------------------------- def gen_suite_options(self): - def literal(text): - return ":literal:`" + text.strip() + "`" + text = text.strip() + return ":literal:`" + text + "`" if text else "" + + def simplify(sw): + """Given a piece of the testuite.py command line used to execute + the qualification test run, return what should be inserted for + it in the list displayed in the STR document, if anything.""" + + # Simplify /path/to/whatever/testsuite.py: + if "testsuite.py" in sw: + return "testsuite.py" + + # Some switches are entirely meaningless wrt qualification + # and can be omitted from the STR: + if any( + sw.startswith(candidate) + for candidate in [ + "--log-file=", + "--old-output-dir=", + "--output-dir=", + "--failure-exit-code=", + "--gaia-output", + "--dump-environ", + "--generate-text-report", + ] + ): + return None + + return sw def str_relevant_switches_from(switches_string): """The list of individual pieces in `switches_string` - which are of relevance to this STR document. These are - all the switches except --log-file and --old-res + their - argument, of interest to gaia only.""" + which are of relevance to this STR document.""" result = [] skip = False for sw in switches_string.split(): + # If we are to skip this arg for a switch to drop + # encountered just before on the command line, do so: if skip: skip = False continue - elif sw in ('--log-file', '--old-res'): + + # If this is a switch to drop with an arg to follow, + # skip this switch and request skipping the arg: + if sw in ["-t"]: skip = True continue - else: + + # Now see if this switch can be simplified, possibly + # even entirely removed: + sw = simplify(sw) + if sw: result.append(sw) return result @@ -1091,8 +1216,12 @@ def switches_with_eq_from(switches_string): of the form = in SWITCHES_STRING.""" return dict( - [sw.split('=') for - sw in switches_string.split() if '=' in sw]) + [ + sw.split("=", 1) + for sw in switches_string.split() + if "=" in sw + ] + ) itemno = Column(htext="Item #", legend=None) @@ -1111,42 +1240,52 @@ def switches_with_eq_from(switches_string): # - BUILDER.SCOV_CARGS (e.g. -fdump-scos), # - --cargs family - suite_options = self.suitedata['options'] - suite_cmdline = self.suitedata['cmdline'] + suite_options = self.suitedata["options"] + suite_cmdline = self.suitedata["cmdline"] csv_contents = [] # Filter from the command line switches which have no # qualification context value per se and would display badly # within the table. - suite_cmdline = ' '.join( - str_relevant_switches_from(suite_cmdline)) + suite_cmdline = " ".join(str_relevant_switches_from(suite_cmdline)) csv_contents.append( - {itemno: "N/A", - item: "testsuite execution command line", - value: literal(suite_cmdline) - }) + { + itemno: "N/A", + item: "testsuite execution command line", + value: literal(suite_cmdline), + } + ) csv_contents.append( - {itemno: "s1", - item: "compiler switches - language independent", - value: literal(' '.join( - BUILDER.SCOV_CARGS( - collections.namedtuple( - 'SuiteOptions', suite_options.keys()) - (*suite_options.values())) + - [suite_options['cargs']])) - }) + { + itemno: "s1", + item: "compiler switches - language independent", + value: literal( + " ".join( + BUILDER.SCOV_CARGS( + collections.namedtuple( + "SuiteOptions", suite_options.keys() + )(*suite_options.values()) + ) + + [suite_options["cargs"]] + ) + ), + } + ) for lang in self.languages: lang_cargs = suite_options["cargs_%s" % lang] if lang_cargs: csv_contents.append( - {itemno: "s1", - item: "compiler switches - %s specific" % lang, - value: literal(lang_cargs)}) + { + itemno: "s1", + item: "compiler switches - %s specific" % lang, + value: literal(lang_cargs), + } + ) # If we have a -gnatec=bla.adc in the languages cargs, # arrange to dump the contents of bla.adc within a separate @@ -1160,37 +1299,65 @@ def switches_with_eq_from(switches_string): # command line is relative to the testsuite/ subdirectory. # We're call within the STR subdir so ... - with open("../%s" % adc, 'r') as f: + with open("../%s" % adc, "r") as f: adc_contents = f.read().strip() csv_contents.append( - {itemno: "s1", - item: "contents of %s, designated by -gnatec" % adc, - value: (literal(adc_contents) if adc_contents - else rest.emph("empty"))}) + { + itemno: "s1", + item: "contents of %s, designated by -gnatec" % adc, + value: ( + literal(adc_contents) + if adc_contents + else rest.emph("empty") + ), + } + ) # If we have a --RTS=bla on the command line, display it as the # qualification "runtime profile". opts_with_eq = switches_with_eq_from(suite_cmdline) - rts = opts_with_eq.get('--RTS', None) + rts = opts_with_eq.get("--RTS", None) csv_contents.append( - {itemno: "s2", - item: "runtime profile", - value: literal( - ("--RTS=%s" % rts)) if rts - else rest.emph("no --RTS switch")}) + { + itemno: "s2", + item: "runtime profile", + value: ( + literal(("--RTS=%s" % rts)) + if rts + else rest.emph("no --RTS switch") + ), + } + ) + + if self.dump_trigger: + csv_contents.append( + { + itemno: "s3", + item: "GNATcov dump trigger option value", + value: literal(f"--dump-trigger={self.dump_trigger}"), + } + ) + if self.dump_channel: + csv_contents.append( + { + itemno: "s4", + item: "GNATcov dump channel option value", + value: literal(f"--dump-channel={self.dump_channel}"), + } + ) CSVtable( - title=None, text=None, + title="Testsuite execution options", + text=None, columns=(itemno, item, value), controls=[":widths: 7, 30, 60"], - contents=csv_contents - ).dump_to(self.rstf) + contents=csv_contents, + ).dump_to(self.rstf) def gen_suite_environ(self): - # We construct a table like # # Environment item | | @@ -1207,63 +1374,72 @@ def gen_suite_environ(self): v2 = Column(htext="", legend=None) - suite_gnatpro = self.suitedata['gnatpro'] - suite_gnatcov = self.suitedata['gnatcov'] - suite_gnatemu = self.suitedata['gnatemu'] - suite_other = self.suitedata['other'] + suite_gnatpro = self.suitedata["gnatpro"] + suite_gnatcov = self.suitedata["gnatcov"] + suite_gnatemu = self.suitedata["gnatemu"] + suite_other = self.suitedata["other"] # Base table entries, always there: table_entries = [ - {itemno: "e1", - item: "testsuite execution timestamp & host system", - v1: self.suitedata['runstamp'], - v2: self.suitedata['host'] - }, - {itemno: "e2", - item: "GNATcov executable & version", - v1: suite_gnatcov['exename'], - v2: suite_gnatcov['version'] - }, - {itemno: "e3", - item: "GNAT Pro executable & version", - v1: suite_gnatpro['exename'], - v2: suite_gnatpro['version'] - }, - ] + { + itemno: "e1", + item: "testsuite execution timestamp & host system", + v1: self.suitedata["runstamp"], + v2: self.suitedata["host"], + }, + { + itemno: "e2", + item: "GNATcov executable & version", + v1: suite_gnatcov["exename"], + v2: suite_gnatcov["version"], + }, + { + itemno: "e3", + item: "GNAT Pro executable & version", + v1: suite_gnatpro["exename"], + v2: suite_gnatpro["version"], + }, + ] # Add a gnatemu version, unless known to be irrelevant (native, # or when a --board option is passed). - suite_options = self.suitedata['options'] - if suite_options['target'] and not suite_options['board']: + suite_options = self.suitedata["options"] + if suite_options["target"] and not suite_options["board"]: table_entries.append( - {itemno: "e4", - item: "GNATemu executable & version", - v1: suite_gnatemu['exename'], - v2: suite_gnatemu['version']}) + { + itemno: "e4", + item: "GNATemu executable & version", + v1: suite_gnatemu["exename"], + v2: suite_gnatemu["version"], + } + ) # Add the "other tool" version if we have it if suite_other: table_entries.append( - {itemno: "e5", - item: "Other toolset executable & version", - v1: suite_other['exename'], - v2: suite_other['version']}) + { + itemno: "e5", + item: "Other toolset executable & version", + v1: suite_other["exename"], + v2: suite_other["version"], + } + ) CSVtable( - title=None, text=None, + title="Testsuite execution environment", + text=None, columns=(itemno, item, v1, v2), controls=[":widths: 7, 25, 20, 48"], - delim='|', - contents=table_entries - ).dump_to(self.rstf) + delim="|", + contents=table_entries, + ).dump_to(self.rstf) # ??? qemu-system-ppc ??? def gen_envinfo(self, sepfile=None): - if sepfile: self.rstf = RSTfile(sepfile) @@ -1276,38 +1452,34 @@ def gen_envinfo(self, sepfile=None): if sepfile: self.rstf.close() - # --------------- - # -- gen_index -- - # --------------- - - def gen_index(self, sepfiles): - - self.rstf = RSTfile("index.rst") - self.rstf.write(rest.chapter('GNATcoverage Software Test Results')) - self.rstf.write(rest.toctree(sepfiles, depth=1)) - self.rstf.close() # ====================== # == main entry point == # ====================== -valid_dolevels = ('doA', 'doB', 'doC') +valid_dolevels = ("doA", "doB", "doC") if __name__ == "__main__": - op = optparse.OptionParser(usage="%prog ") op.add_option( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, help="Target DO178 qualification level. " - "Defaults to the one of testsuite-dir.") + "Defaults to the one of testsuite-dir.", + ) default_testsuite_dir = LOCAL_TESTSUITE_DIR op.add_option( - "--testsuite-dir", dest="testsuite_dir", default=default_testsuite_dir, + "--testsuite-dir", + dest="testsuite_dir", + default=default_testsuite_dir, help="Name of a directory where the testsuite was run. " - "Defaults to \"%s\"." % default_testsuite_dir) + 'Defaults to "%s".' % default_testsuite_dir, + ) (options, args) = op.parse_args() diff --git a/testsuite/STR/source/content.rst b/testsuite/STR/source/content.rst index 54b06697c..b03998cd3 100644 --- a/testsuite/STR/source/content.rst +++ b/testsuite/STR/source/content.rst @@ -11,6 +11,5 @@ GNATcoverage DO178C/ED-12C Qualification Material: Tool Operational Verification intro.rst env.rst - tctables.rst tssummary.rst - + tctables.rst diff --git a/testsuite/SUITE/cargo_utils.py b/testsuite/SUITE/cargo_utils.py new file mode 100644 index 000000000..5361f00f3 --- /dev/null +++ b/testsuite/SUITE/cargo_utils.py @@ -0,0 +1,34 @@ +import os + +from SUITE.cutils import no_ext + +CARGO_TEMPLATE = """[package] +name = "{pkg_name}" +edition = "2024" + +[[bin]] +name = "{bin_name}" +path = "{main_path}" +""" + + +def cargo_for(prjid: str, main: str, src_dir: str, cargo_dir: str) -> str: + """ + Generate a Cargo.toml manifest + + - prjid : Name of the Cargo project + - main : Source simple filename which contains the main function + - src_dir : Directory where `main` lives + - cargo_dir : Directory to generate the Cargo.toml + """ + path = os.path.join(cargo_dir, "Cargo.toml") + with open(path, "w") as f: + f.write( + CARGO_TEMPLATE.format( + pkg_name=prjid, + bin_name=no_ext(main), + main_path=os.path.join(src_dir, main).replace("\\", "\\\\"), + ) + ) + + return path diff --git a/testsuite/SUITE/checkpointlib.py b/testsuite/SUITE/checkpointlib.py new file mode 100644 index 000000000..ccb182608 --- /dev/null +++ b/testsuite/SUITE/checkpointlib.py @@ -0,0 +1,1244 @@ +""" +Checkpoint/SID files loading library. +""" + +from __future__ import annotations + +import argparse +import dataclasses +import enum +import struct +from typing import Callable, ClassVar, TypeVar + +from SUITE.stream_decoder import ByteStreamDecoder + + +class DecodingError(Exception): + pass + + +def read_scalar( + fp: ByteStreamDecoder, + label: str, + code: str, + size: int, +) -> int: + with fp.label_context(label): + (value,) = struct.unpack(code, fp.read(size)) + return value + + +def read_u8(fp: ByteStreamDecoder, label: str) -> int: + return read_scalar(fp, label, "B", 1) + + +def read_u16(fp: ByteStreamDecoder, label: str) -> int: + return read_scalar(fp, label, "H", 2) + + +def read_u32(fp: ByteStreamDecoder, label: str) -> int: + return read_scalar(fp, label, "I", 4) + + +def read_i32(fp: ByteStreamDecoder, label: str) -> int: + return read_scalar(fp, label, "i", 4) + + +def read_bool(fp: ByteStreamDecoder, label: str) -> bool: + return bool(read_u8(fp, label)) + + +def read_string(fp: ByteStreamDecoder, label: str) -> bytes: + with fp.label_context(label): + first = read_i32(fp, "first") + last = read_i32(fp, "last") + length = max(0, last - first + 1) + with fp.label_context("bytes"): + return fp.read(length) + + +def read_fingerprint(fp: ByteStreamDecoder, label: str) -> bytes: + with fp.label_context(label): + return fp.read(20) + + +CollectionKey = TypeVar("CollectionKey") +CollectionElement = TypeVar("CollectionElement") + + +def read_vector( + fp: ByteStreamDecoder, + read_element: Callable[[ByteStreamDecoder, str], CollectionElement], + label: str, +) -> list[CollectionElement]: + with fp.label_context(label): + length = read_i32(fp, "length") + return [read_element(fp, "element") for _ in range(length)] + + +def read_set( + fp: ByteStreamDecoder, + read_element: Callable[[ByteStreamDecoder, str], CollectionElement], + label: str, +) -> set[CollectionElement]: + with fp.label_context(label): + length = read_i32(fp, "count") + return {read_element(fp, "element") for _ in range(length)} + + +def read_map( + fp: ByteStreamDecoder, + read_key: Callable[[ByteStreamDecoder, str], CollectionKey], + read_element: Callable[[ByteStreamDecoder, str], CollectionElement], + label: str, +) -> dict[CollectionKey, CollectionElement]: + with fp.label_context(label): + length = read_i32(fp, "count") + result = {} + for _ in range(length): + key = read_key(fp, "key") + element = read_element(fp, "element") + result[key] = element + return result + + +def read_tree( + fp: ByteStreamDecoder, + read_element: Callable[[ByteStreamDecoder, str], CollectionElement], + label: str, +) -> int: + def read_children(): + count = read_i32(fp, "count") + for _ in range(count): + read_subtree() + + def read_subtree(): + read_element(fp, "element") + read_children() + + with fp.label_context(label): + count = read_i32(fp, "count") + if count > 0: + read_children() + + return 0 + + +def read_sco_range(fp: ByteStreamDecoder, label: str) -> tuple[int, int]: + with fp.label_context(label): + first = read_i32(fp, "first") + last = read_i32(fp, "last") + return (first, last) + + +read_aspect_id = read_u8 +read_bdd_node_id = read_i32 +read_bit_id = read_i32 +read_condition_id = read_i32 +read_cu_id = read_i32 +read_pragma_id = read_u16 +read_sco_id = read_i32 +read_sfi = read_i32 + + +@dataclasses.dataclass +class LocalSourceLocation: + line: int + column: int + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> LocalSourceLocation: + with fp.label_context(label): + line = read_i32(fp, "line") + column = read_i32(fp, "column") + return cls(line, column) + + +@dataclasses.dataclass +class LocalSourceLocationRange: + first: LocalSourceLocation + last: LocalSourceLocation + + @classmethod + def read( + cls, fp: ByteStreamDecoder, label: str + ) -> LocalSourceLocationRange: + with fp.label_context(label): + first = LocalSourceLocation.read(fp, "first") + last = LocalSourceLocation.read(fp, "last") + return cls(first, last) + + +@dataclasses.dataclass +class SourceLocation: + source_file: int + l: LocalSourceLocation + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SourceLocation: + with fp.label_context(label): + source_file = read_sfi(fp, "source file") + loc = LocalSourceLocation.read(fp, "l") + return cls(source_file, loc) + + +@dataclasses.dataclass +class SourceLocationRange: + source_file: int + l: LocalSourceLocationRange + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SourceLocationRange: + with fp.label_context(label): + source_file = read_sfi(fp, "source file") + loc = LocalSourceLocationRange.read(fp, "l") + return cls(source_file, loc) + + +def read_expansion_info(fp: ByteStreamDecoder, label: str) -> None: + # TODO: create data structures + read_string(fp, "macro name") + SourceLocation.read(fp, "sloc") + + +@enum.unique +class SCOPPKind(enum.Enum): + in_expansion = 0 + no_expansion = 1 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SCOPPKind: + return SCOPPKind(read_u8(fp, label)) + + +def read_pp_info(fp: ByteStreamDecoder, label: str) -> None: + # TODO: create data structures + with fp.label_context(label): + kind = SCOPPKind.read(fp, "kind") + LocalSourceLocationRange.read(fp, "actual source range") + LocalSourceLocationRange.read(fp, "pp source range") + read_vector(fp, read_expansion_info, "expansion stack") + match kind: + case SCOPPKind.in_expansion: + read_expansion_info(fp, "definition loc") + + +def read_scope_entity(fp: ByteStreamDecoder, label: str) -> None: + # TODO: create data structures + with fp.label_context(label): + SourceLocationRange.read(fp, "source range") + read_string(fp, "name") + LocalSourceLocation.read(fp, "sloc") + + with fp.label_context("identifier"): + read_sfi(fp, "decl SFI") + read_i32(fp, "decl line") + + +@dataclasses.dataclass +class DecisionBitInfo: + d_sco: int + outcome: bool + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> DecisionBitInfo: + with fp.label_context(label): + return cls(read_sco_id(fp, "SCO"), read_bool(fp, "outcome")) + + +@dataclasses.dataclass +class MCDCBitInfo: + d_sco: int + path_index: int + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> MCDCBitInfo: + with fp.label_context(label): + return cls(read_sco_id(fp, "SCO"), read_i32(fp, "path index")) + + +@dataclasses.dataclass +class SIDInfo: + blocks: list[list[int]] + stmt_bit_map: dict[int, int] + dc_bit_map: dict[int, DecisionBitInfo] + mcdc_bit_map: dict[int, MCDCBitInfo] + bit_maps_fingerprint: bytes + annotations_fingerprint: bytes + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SIDInfo: + with fp.label_context(label): + blocks = read_vector( + fp, + lambda fp, label: read_vector(fp, read_sco_id, label), + "blocks", + ) + + with fp.label_context("stmt bit map"): + stmt_first = read_bit_id(fp, "stmt_first") + stmt_last = read_bit_id(fp, "stmt_last") + stmt_bit_map = { + bit: read_sco_id(fp, "SCO") + for bit in range(stmt_first, stmt_last + 1) + } + + with fp.label_context("decision bit map"): + dc_first = read_bit_id(fp, "dc_first") + dc_last = read_bit_id(fp, "dc_last") + dc_bit_map = { + bit: DecisionBitInfo.read(fp, "info") + for bit in range(dc_first, dc_last + 1) + } + + with fp.label_context("MCDC bit map"): + mcdc_first = read_bit_id(fp, "mcdc_first") + mcdc_last = read_bit_id(fp, "mcdc_last") + mcdc_bit_map = { + bit: MCDCBitInfo.read(fp, "info") + for bit in range(mcdc_first, mcdc_last + 1) + } + + bit_maps_fingerprint = read_fingerprint(fp, "bit maps fingerprint") + annotations_fingerprint = read_fingerprint( + fp, "annotations fingerprint" + ) + + return cls( + blocks, + stmt_bit_map, + dc_bit_map, + mcdc_bit_map, + bit_maps_fingerprint, + annotations_fingerprint, + ) + + +@enum.unique +class AnyAnnotationKind(enum.Enum): + unknown = 0 + exempt_region = 1 + exempt_on = 2 + exempt_off = 3 + dump_buffers = 4 + reset_buffers = 5 + cov_on = 6 + cov_off = 7 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> AnyAnnotationKind: + return AnyAnnotationKind(read_u8(fp, label)) + + +def read_ali_annotation(fp: ByteStreamDecoder, label: str) -> None: + # TODO: create data structures + with fp.label_context(label): + kind = AnyAnnotationKind.read(fp, "kind") + del kind + + +@enum.unique +class CheckpointPurpose(enum.Enum): + instrumentation = 0 + consolidation = 1 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> CheckpointPurpose: + return CheckpointPurpose(read_u8(fp, label)) + + +@enum.unique +class BinaryTracesBits(enum.Enum): + undetermined = 0 + bits_32 = 1 + bits_64 = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> BinaryTracesBits: + return BinaryTracesBits(read_u8(fp, label)) + + +@enum.unique +class CoverageLevel(enum.Enum): + insn = 0 + branch = 1 + stmt = 2 + decision = 3 + mcdc = 4 + uc_mcdc = 5 + atc = 6 + atcc = 7 + fun_call = 8 + gexpr = 9 + + +@enum.unique +class AnyAcceptedTraceKind(enum.Enum): + unknown = 0 + binary_trace_file = 1 + source_trace_file = 2 + llvm_trace_file = 3 + all_trace_files = 4 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> AnyAcceptedTraceKind: + return AnyAcceptedTraceKind(read_u8(fp, label)) + + +@dataclasses.dataclass +class CheckpointFile: + version: int + purpose: CheckpointPurpose + bits: BinaryTracesBits + levels: set[CoverageLevel] + trace_kind: AnyAcceptedTraceKind + files_table: FilesTable + cu_vector: dict[int, CUInfo] + bdd_vector: dict[int, BDDNode] + sco_vector: dict[int, SCODescriptor | None] + instrumented_unit_to_cu: dict[CompilationUnitPart, int] + pp_cmds: dict[int, Command] + sci_vector: dict[int, SourceCoverageInfo] + trace_files: list[TraceFileElement] + + checkpoint_magic: ClassVar[bytes] = b"GNATcov checkpoint\x00" + + @staticmethod + def read_bdd_vector(fp: ByteStreamDecoder) -> dict[int, BDDNode]: + with fp.label_context("BDD vector"): + result = {} + count = read_i32(fp, "count") + for i in range(count): + result[i + 1] = BDDNode.read(fp, "element") + return result + + @staticmethod + def read_sco_vector( + fp: ByteStreamDecoder, + ) -> dict[int, SCODescriptor | None]: + with fp.label_context("SCO vector"): + result = {} + count = read_i32(fp, "count") + for i in range(count): + result[i + 1] = SCODescriptor.read(fp, "element") + return result + + @staticmethod + def read_sci_vector( + fp: ByteStreamDecoder, + ) -> dict[int, SourceCoverageInfo]: + with fp.label_context("SCI vector"): + result = {} + count = read_i32(fp, "count") + for i in range(count): + result[i + 1] = SourceCoverageInfo.read(fp, "element") + return result + + @classmethod + def read(cls, fp: ByteStreamDecoder) -> CheckpointFile: + with fp.label_context("header"): + with fp.label_context("magic"): + magic = fp.read(len(cls.checkpoint_magic)) + if magic != cls.checkpoint_magic: + raise DecodingError("invalid magic") + + version = read_u32(fp, "version") + purpose = CheckpointPurpose.read(fp, "purpose") + bits = BinaryTracesBits.read(fp, "bits") + with fp.label_context("levels"): + levels = {lv for lv in CoverageLevel if read_bool(fp, str(lv))} + trace_kind = AnyAcceptedTraceKind.read(fp, "trace kind") + + files_table = FilesTable.read(fp) + cu_vector = { + i + 1: cu + for i, cu in enumerate(read_vector(fp, CUInfo.read, "CU vector")) + } + bdd_vector = cls.read_bdd_vector(fp) + + sco_vector = cls.read_sco_vector(fp) + for sco_id in read_set( + fp, read_sco_id, "uninstrumented SCOs (stmt+dc)" + ): + scod = sco_vector[sco_id] + match scod: + case StatementSCODescriptor(): + scod.stmt_instrumented = False + case DecisionSCODescriptor(): + scod.decision_instrumented = False + case _: + raise AssertionError + + for sco_id in read_set(fp, read_sco_id, "uninstrumented SCOs (MCDC)"): + scod = sco_vector[sco_id] + match scod: + case DecisionSCODescriptor(): + scod.decision_instrumented_for_mcdc = False + case _: + raise AssertionError + + instrumented_unit_to_cu = read_map( + fp, + CompilationUnitPart.read, + read_cu_id, + "instrumented unit to CU", + ) + pp_cmds = read_map(fp, read_sfi, Command.read, "PP commands") + + sci_vector = cls.read_sci_vector(fp) + if purpose == CheckpointPurpose.consolidation: + with fp.label_context("invalidated units"): + invalidated = read_bool(fp, "invalidated") + if not invalidated: + count = read_i32(fp, "count") + for _ in range(count): + CompilationUnit.read(fp, "element") + + with fp.label_context("trace files"): + trace_files = [] + while True: + tf = TraceFileElement.read(fp, "element") + if tf is None: + break + trace_files.append(tf) + + return CheckpointFile( + version, + purpose, + bits, + levels, + trace_kind, + files_table, + cu_vector, + bdd_vector, + sco_vector, + instrumented_unit_to_cu, + pp_cmds, + sci_vector, + trace_files, + ) + + +@enum.unique +class FileKind(enum.Enum): + stub_file = 0 + source_file = 1 + library_file = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> FileKind: + return FileKind(read_u8(fp, label)) + + +@enum.unique +class AnyIgnoreStatus(enum.Enum): + unknown = 0 + always = 1 + sometimes = 2 + never = 3 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> AnyIgnoreStatus: + return AnyIgnoreStatus(read_u8(fp, label)) + + +class FilesTable: + def __init__(self) -> None: + self.entries: dict[int, FilesTableEntry] = {} + + @classmethod + def read(cls, fp: ByteStreamDecoder) -> FilesTable: + with fp.label_context("files table"): + first_sfi = read_i32(fp, "first sfi") + last_sfi = read_i32(fp, "last sfi") + result = cls() + while True: + entry = FilesTableEntry.read(fp) + if entry is None: + break + result.entries[entry.sfi] = entry + assert len(result.entries) == max(last_sfi - first_sfi + 1, 0) + return result + + +@dataclasses.dataclass +class FilesTableEntry: + sfi: int + name: bytes + kind: FileKind + indexed_simple_name: bool + + @classmethod + def read(cls, fp: ByteStreamDecoder) -> FilesTableEntry | None: + with fp.label_context("files table entry"): + sfi = read_i32(fp, "source file index") + if sfi == 0: + return None + name = read_string(fp, "name") + kind = FileKind.read(fp, "kind") + indexed_simple_name = read_bool(fp, "indexed_simple_name") + + # TODO: preserve extra information + match kind: + case FileKind.source_file: + ignore_status = AnyIgnoreStatus.read(fp, "ignore status") + unit_known = read_bool(fp, "unit known") + del ignore_status, unit_known + case FileKind.library_file: + main_source = read_i32(fp, "main source") + del main_source + return cls(sfi, name, kind, indexed_simple_name) + + +@dataclasses.dataclass +class CompilationUnit: + language: LanguageKind + unit_name: bytes + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> CompilationUnit: + with fp.label_context(label): + return CompilationUnit( + LanguageKind.read(fp, "kind"), read_string(fp, "unit name") + ) + + +@enum.unique +class SCOProvider(enum.Enum): + compiler = 0 + instrumenter = 1 + llvm = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SCOProvider: + return SCOProvider(read_u8(fp, label)) + + +@dataclasses.dataclass +class CUInfo: + origin: int + main_source: int + deps: list[int] + has_code: bool + pp_info_map: dict[int, None] + scope_entities: int + ali_annotations: dict[SourceLocation, None] + scos: list[tuple[int, int]] + sids_info: dict[bytes, SIDInfo] + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> CUInfo: + with fp.label_context(label): + provider = SCOProvider.read(fp, "SCO provider") + origin = read_i32(fp, "origin") + main_source = read_i32(fp, "main source") + deps = read_vector(fp, read_sfi, "deps") + has_code = read_bool(fp, "has code") + pp_info_map = read_map( + fp, read_sco_id, read_pp_info, "PP info map" + ) + scope_entities = read_tree(fp, read_scope_entity, "scope entities") + ali_annotations = read_map( + fp, SourceLocation.read, read_ali_annotation, "ALI annotations" + ) + scos = read_vector(fp, read_sco_range, "scos") + sids_info: dict[bytes, SIDInfo] = {} + match provider: + case SCOProvider.compiler: + scos_fingerprint = read_fingerprint(fp, "SCOs fingerprint") + return CompilerCUInfo( + origin, + main_source, + deps, + has_code, + pp_info_map, + scope_entities, + ali_annotations, + scos, + sids_info, + scos_fingerprint, + ) + case SCOProvider.llvm: + scos_fingerprint = read_fingerprint(fp, "SCOs fingerprint") + return LLVMCUInfo( + origin, + main_source, + deps, + has_code, + pp_info_map, + scope_entities, + ali_annotations, + scos, + sids_info, + scos_fingerprint, + ) + case SCOProvider.instrumenter: + sids_info = read_map( + fp, read_fingerprint, SIDInfo.read, "SIDs info" + ) + source_fingerprint = read_fingerprint( + fp, "source fingerprint" + ) + return InstrumenterCUInfo( + origin, + main_source, + deps, + has_code, + pp_info_map, + scope_entities, + ali_annotations, + scos, + sids_info, + source_fingerprint, + ) + + +@dataclasses.dataclass +class BaseCompilerCUInfo(CUInfo): + scos_fingerprint: bytes + + +@dataclasses.dataclass +class CompilerCUInfo(BaseCompilerCUInfo): + pass + + +@dataclasses.dataclass +class LLVMCUInfo(BaseCompilerCUInfo): + pass + + +@dataclasses.dataclass +class InstrumenterCUInfo(CUInfo): + source_fingerprint: bytes + + +@enum.unique +class BDDNodeKind(enum.Enum): + outcome = 0 + condition = 1 + jump = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> BDDNodeKind: + return BDDNodeKind(read_u8(fp, label)) + + +@dataclasses.dataclass +class BDDNode: + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> BDDNode: + with fp.label_context(label): + kind = BDDNodeKind.read(fp, "kind") + match kind: + case BDDNodeKind.outcome: + return OutcomeBDDNode(read_bool(fp, "decision outcome")) + + case BDDNodeKind.condition: + return ConditionBDDNode( + read_bdd_node_id(fp, "parent"), + read_bool(fp, "parent value"), + read_sco_id(fp, "condition SCO"), + ( + read_bdd_node_id(fp, "dest:false"), + read_bdd_node_id(fp, "dest:true"), + ), + read_i32(fp, "path offset"), + ) + + case BDDNodeKind.jump: + return JumpBDDNode(read_bdd_node_id(fp, "dest")) + + +@dataclasses.dataclass +class OutcomeBDDNode(BDDNode): + decision_outcome: bool + + +@dataclasses.dataclass +class ConditionBDDNode(BDDNode): + parent: int + parent_value: bool + c_sco: int + dests: tuple[int, int] + path_offset: int + + +@dataclasses.dataclass +class JumpBDDNode(BDDNode): + dest: int + + +@dataclasses.dataclass +class BDDType: + decision: int + root_condition: int + first_node: int + last_node: int + first_multipath_condition: int + reachable_outcomes: tuple[bool, bool] + path_count: int + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> BDDType: + with fp.label_context(label): + return BDDType( + read_sco_id(fp, "decision"), + read_bdd_node_id(fp, "root condition"), + read_bdd_node_id(fp, "first node"), + read_bdd_node_id(fp, "last node"), + read_bdd_node_id(fp, "first multipath condition"), + ( + read_bool(fp, "reachable outcomes:false"), + read_bool(fp, "reachable outcomes:true"), + ), + read_i32(fp, "path count"), + ) + + +@enum.unique +class SCOKind(enum.Enum): + removed = 0 + statement = 1 + decision = 2 + condition = 3 + operator = 4 + fun = 5 + call = 6 + guarded_expr = 7 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SCOKind: + return SCOKind(read_u8(fp, label)) + + +@enum.unique +class StatementKind(enum.Enum): + no_statement = 0 + + type_declaration = 1 + subtype_declaration = 2 + object_declaration = 3 + renaming_declaration = 4 + generic_instantiation = 5 + other_declaration = 6 + + accept_statement = 7 + case_statement = 8 + exit_statement = 9 + for_loop_statement = 10 + if_statement = 11 + pragma_statement = 12 + disabled_pragma_statement = 13 + extended_return_statement = 14 + select_statement = 15 + while_loop_statement = 16 + degenerate_subprogram_statement = 17 + call_stmt = 18 + call_expr = 19 + other_statement = 20 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> StatementKind: + return StatementKind(read_u8(fp, label)) + + +@enum.unique +class DecisionKind(enum.Enum): + if_statement = 0 + exit_statement = 1 + entry_guard = 2 + pragma_decision = 3 + while_loop = 4 + expression = 5 + aspect = 6 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> DecisionKind: + return DecisionKind(read_u8(fp, label)) + + +@enum.unique +class OperatorKind(enum.Enum): + op_not = 0 + op_and_then = 1 + op_or_else = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> OperatorKind: + return OperatorKind(read_u8(fp, label)) + + +@enum.unique +class Tristate(enum.Enum): + false = 0 + true = 1 + unknown = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> Tristate: + return Tristate(read_u8(fp, label)) + + +@dataclasses.dataclass +class SCODescriptor: + origin: int + sloc_range: SourceLocationRange + parent: int + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SCODescriptor | None: + with fp.label_context(label): + kind = SCOKind.read(fp, "kind") + if kind == SCOKind.removed: + return None + + origin = read_cu_id(fp, "origin") + sloc_range = SourceLocationRange.read(fp, "sloc range") + parent = read_sco_id(fp, "parent") + + match kind: + case SCOKind.statement: + return StatementSCODescriptor( + origin, + sloc_range, + parent, + StatementKind.read(fp, "statement kind"), + read_sco_id(fp, "dominant"), + Tristate.read(fp, "dominant value"), + SourceLocation.read(fp, "dominant sloc"), + SourceLocationRange.read(fp, "handler range"), + read_pragma_id(fp, "pragma name"), + ) + + case SCOKind.condition: + return ConditionSCODescriptor( + origin, + sloc_range, + parent, + Tristate.read(fp, "value"), + # TODO: handle 64-bit + read_set(fp, read_u32, "PC set"), + read_bdd_node_id(fp, "BDD node"), + read_condition_id(fp, "index"), + ) + + case SCOKind.decision: + return DecisionSCODescriptor( + origin, + sloc_range, + parent, + read_sco_id(fp, "expression"), + DecisionKind.read(fp, "decision kind"), + SourceLocation.read(fp, "control location"), + read_condition_id(fp, "last condition index"), + BDDType.read(fp, "decision BDD"), + read_bool(fp, "degraded origins"), + read_aspect_id(fp, "aspect name"), + read_i32(fp, "path count"), + ) + + case SCOKind.operator: + read_u8(fp, "first") + read_u8(fp, "last") + return OperatorSCODescriptor( + origin, + sloc_range, + parent, + ( + read_sco_id(fp, "left operand"), + read_sco_id(fp, "right operand"), + ), + OperatorKind.read(fp, "operator kind"), + ) + + case SCOKind.fun | SCOKind.call: + return FunCallSCODescriptor( + origin, + sloc_range, + parent, + read_bool(fp, "is expression"), + read_bool(fp, "fun call instrumented"), + ) + + case SCOKind.guarded_expr: + return GuardedExprSCODescriptor( + origin, + sloc_range, + parent, + read_bool(fp, "gexpr instrumented"), + ) + + case _: + raise AssertionError + + +@dataclasses.dataclass +class StatementSCODescriptor(SCODescriptor): + s_kind: StatementKind + dominant: int + dominant_value: Tristate + dominant_sloc: SourceLocation + handler_range: SourceLocationRange + pragma_name: int + stmt_instrumented: bool = True + + +@dataclasses.dataclass +class ConditionSCODescriptor(SCODescriptor): + value: Tristate + pc_set: set[int] + bdd_node: int + index: int + + +@dataclasses.dataclass +class DecisionSCODescriptor(SCODescriptor): + expression: int + d_kind: DecisionKind + control_location: SourceLocation + last_cond_index: int + decision_bdd: BDDType + degraded_origins: bool + aspect_name: int + path_count: int + decision_instrumented: bool = True + decision_instrumented_for_mcdc: bool = True + + +@dataclasses.dataclass +class OperatorSCODescriptor(SCODescriptor): + operands: tuple[int, int] + op_kind: OperatorKind + + +@dataclasses.dataclass +class FunCallSCODescriptor(SCODescriptor): + is_expr: bool + fun_call_instrumented: bool + + +@dataclasses.dataclass +class GuardedExprSCODescriptor(SCODescriptor): + gexpr_instrumented: bool + + +@enum.unique +class LanguageKind(enum.Enum): + unit_based = 0 + file_based = 1 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> LanguageKind: + return LanguageKind(read_u32(fp, label)) + + +@enum.unique +class UnitPart(enum.Enum): + body = 0 + spec = 1 + separate = 2 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> UnitPart: + return UnitPart(read_u8(fp, label)) + + +@dataclasses.dataclass(frozen=True) +class CompilationUnitPart: + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> CompilationUnitPart: + with fp.label_context(label): + kind = LanguageKind.read(fp, "kind") + match kind: + case LanguageKind.unit_based: + return UnitBasedCompilationUnitPart( + tuple(read_vector(fp, read_string, "unit")), + UnitPart.read(fp, "part"), + ) + case LanguageKind.file_based: + return FileBasedCompilationUnitPart( + read_string(fp, "filename") + ) + case _: + raise AssertionError + + +@dataclasses.dataclass(frozen=True) +class UnitBasedCompilationUnitPart(CompilationUnitPart): + unit: tuple[bytes, ...] + part: UnitPart + + +@dataclasses.dataclass(frozen=True) +class FileBasedCompilationUnitPart(CompilationUnitPart): + filename: bytes + + +@dataclasses.dataclass +class Command: + command: bytes + arguments: list[bytes] + environment: dict[bytes, bytes] + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> Command: + with fp.label_context(label): + return Command( + read_string(fp, "command"), + read_vector(fp, read_string, "arguments"), + read_map(fp, read_string, read_string, "environment"), + ) + + +@enum.unique +class LineState(enum.Enum): + not_covered = 0 + partially_covered = 1 + covered = 2 + no_code = 3 + not_coverable = 4 + undetermined_coverage = 5 + disabled_coverage = 6 + exempted_with_violation = 7 + exempted_with_undetermined_cov = 8 + exempted_no_violation = 9 + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> LineState: + return LineState(read_u8(fp, label)) + + +@dataclasses.dataclass +class SourceCoverageInfo: + state: dict[CoverageLevel, LineState] + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> SourceCoverageInfo: + with fp.label_context(label): + kind = SCOKind.read(fp, "kind") + states = {lv: LineState.read(fp, str(lv)) for lv in CoverageLevel} + match kind: + case SCOKind.statement: + return StatementSourceCoverageInfo( + states, + read_bool(fp, "basic block has code"), + read_bool(fp, "executed"), + read_bool(fp, "line executed"), + ) + case SCOKind.decision: + return DecisionSourceCoverageInfo( + states, + ( + read_bool(fp, "outcome_taken:false"), + read_bool(fp, "outcome_taken:true"), + ), + ( + read_bool(fp, "known_outcome_taken:false"), + read_bool(fp, "known_outcome_taken:true"), + ), + read_set(fp, Evaluation.read, "evaluations"), + ) + case SCOKind.fun | SCOKind.call: + return FunCallSourceCoverageInfo( + states, read_bool(fp, "fun call executed") + ) + case SCOKind.guarded_expr: + return GuardedExprSourceCoverageInfo( + states, read_bool(fp, "gexpr executed") + ) + case _: + return SourceCoverageInfo(states) + + +@dataclasses.dataclass +class StatementSourceCoverageInfo(SourceCoverageInfo): + basic_block_has_code: bool + executed: bool + line_executed: bool + + +@dataclasses.dataclass +class Evaluation: + decision: int + values: dict[int, Tristate] + outcome: Tristate + next_condition: int + + @classmethod + def read(cls, fp: ByteStreamDecoder, label: str) -> Evaluation: + with fp.label_context(label): + decision = read_sco_id(fp, "decision") + + with fp.label_context("values"): + values = {} + count = read_i32(fp, "count") + for i in range(count): + values[i + 1] = Tristate.read(fp, "element") + + outcome = Tristate.read(fp, "outcome") + next_condition = read_condition_id(fp, "next condition") + + return Evaluation(decision, values, outcome, next_condition) + + +@dataclasses.dataclass +class DecisionSourceCoverageInfo(SourceCoverageInfo): + outcome_taken: tuple[bool, bool] + known_outcome_taken: tuple[bool, bool] + evaluations: set + + +@dataclasses.dataclass +class FunCallSourceCoverageInfo(SourceCoverageInfo): + fun_call_executed: bool + + +@dataclasses.dataclass +class GuardedExprSourceCoverageInfo(SourceCoverageInfo): + gexpr_executed: bool + + +@dataclasses.dataclass +class TraceFileElement: + filename: bytes + kind: AnyAcceptedTraceKind + context: bytes + program_name: bytes + time: bytes + user_data: bytes + + @classmethod + def read( + cls, + fp: ByteStreamDecoder, + label: str, + ) -> TraceFileElement | None: + with fp.label_context(label): + name = read_string(fp, "name") + if not name: + return None + + return TraceFileElement( + name, + AnyAcceptedTraceKind.read(fp, "kind"), + read_string(fp, "context"), + read_string(fp, "program name"), + read_string(fp, "time"), + read_string(fp, "user data"), + ) + + +parser = argparse.ArgumentParser("Decode a checkpoint file") +parser.add_argument( + "--debug", "-d", action="store_true", help="Enable debug traces" +) +parser.add_argument("checkpoint-file", help="Checkpoint file to decode") + + +if __name__ == "__main__": + args = parser.parse_args() + with open(getattr(args, "checkpoint-file"), "rb") as f: + ckpt = CheckpointFile.read(ByteStreamDecoder(f, args.debug, 4)) diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index f13fa2161..978187d78 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -18,19 +18,28 @@ from e3.main import Main from e3.os.fs import cd from e3.os.process import Run -from e3.testsuite.driver.diff import (CanonicalizeLineEndings, LineByLine, - OutputRefiner, RefiningChain) +from e3.testsuite.driver.diff import ( + CanonicalizeLineEndings, + LineByLine, + OutputRefiner, + RefiningChain, +) from SUITE import control -from SUITE.control import GPRCLEAN, BUILDER, env -from SUITE.cutils import (exit_if, indent, indent_after_first_line, lines_of, - ndirs_in) +from SUITE.control import GPRCLEAN, env +from SUITE.cutils import ( + exit_if, + indent, + indent_after_first_line, + lines_of, + ndirs_in, +) # This module is loaded as part of a Run operation for a test.py # file found and launched by the toplevel driver -logger = logging.getLogger('SUITE.context') +logger = logging.getLogger("SUITE.context") # This is where the toplevel invocation was issued for the individual test # at hand, which we expect to be where the toplevel testsuite.py is located. @@ -58,6 +67,7 @@ class _ReportOutput(object): the contents of the output attribute should be printed on standard output at the next flush. """ + def __init__(self, report_file): """Constructor. @@ -90,7 +100,7 @@ def log(self, text, end_of_line=True): which adds this '\n' by default too. """ if end_of_line: - text += '\n' + text += "\n" self.output += text self.report_fd.write(text) @@ -100,18 +110,17 @@ def flush(self): if print_diff is True). Reset print_diff to False as well. """ if self.print_diff: - sys.stdout.write(self.output + ' ') + sys.stdout.write(self.output + " ") self.output = "" self.print_diff = False self.report_fd.flush() def close(self): - """Close the file descriptor for our report file. - """ + """Close the file descriptor for our report file.""" self.report_fd.close() -class Test (object): +class Test(object): """Test class: Offer test command line and status management facilities. @@ -150,14 +159,14 @@ def __init__(self): # just fine (join("/foo", "/foo/bar") yields "/foo/bar"). testsuite_py_dir = ROOT_DIR - test_py_dir = os.path.dirname(sys.modules['__main__'].__file__) + test_py_dir = os.path.dirname(sys.modules["__main__"].__file__) self.homedir = os.path.join(testsuite_py_dir, test_py_dir) self.reldir = os.path.relpath(self.homedir, start=testsuite_py_dir) # Perform a simple canonicalization of the relative dir to simplify # related computations/assumptions in other parts of the testsuite. - self.reldir = self.reldir.replace('\\', '/') + self.reldir = self.reldir.replace("\\", "/") # Compute the depth of this test wrt testsuite root. self.depth = ndirs_in(os.path.relpath(self.homedir, ROOT_DIR)) @@ -169,31 +178,6 @@ def __init__(self): self.report = _ReportOutput(self.options.report_file) self.current_test_index = 0 - self.gprconfoptions = [ - # verbose mode for verifiability in qualif mode. - # quiet mode for performance (less io) otherwise. - '-v' if self.options.qualif_level else '-q', - - # gprconfig base, selecting runtime - '--config=%s' % os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)] - self.gprvaroptions = ['-XTARGET=%s' % env.target.triplet] - - if self.options.board: - self.gprvaroptions.append('-XBOARD=%s' % self.options.board) - - # Workaround a desynchronization between default build configuration - # for TMS570 and GNATemulator's settings: see O519-032. We may get rid - # of this kludge one day adapting GNATemulator. - if self.options.RTS and self.options.RTS.endswith('-tms570'): - self.gprvaroptions.append('-XLOADER=LORAM') - - # For trace32 runs where the test is executed on a real board, we - # choose to have both the code and data in RAM. The default is to run - # from flash which would take more time for the probe to program. It - # would also wear out the flash memory. - if self.options.gnatcov_run and 'trace32' in self.options.gnatcov_run: - self.gprvaroptions.append('-XLOADER=RAM') - # Whether this test will be using project files to locate SCOs when # running gnatcov. This is decided on a per gnatcov invocation basis. # self.options.gnatcov states whether we're queried to do this for @@ -208,32 +192,31 @@ def __init__(self): # coverage is deprecated, as it would make all tests fail. Testcases # that check the presence of this warning can just remove this # environment variable. - os.environ['GNATCOV_NO_NATIVE_WARNING'] = '1' + os.environ["GNATCOV_NO_NATIVE_WARNING"] = "1" - def cleanup(self, project): + def cleanup(self, project, options): """Cleanup possible remnants of previous builds.""" - Run([GPRCLEAN, "-P%s" % project] + - self.gprconfoptions + self.gprvaroptions) - rm('*.xcov') - rm('*.bin') + Run([GPRCLEAN, "-P%s" % project] + options) + rm("*.xcov") + rm("*.bin") # Test status management def log(self, text, new_line=True): - """Calls self.report.log. """ + """Calls self.report.log.""" self.report.log(text, new_line) def flush(self): - """Calls self.report.flush. """ + """Calls self.report.flush.""" self.report.flush() def comment(self, text): """Output a TEXT comment.""" - self.log(' - %s.' % indent_after_first_line(text, ' ')) + self.log(" - %s." % indent_after_first_line(text, " ")) def failed(self, comment="assertion failed"): """Register a check failure.""" - self.log(' * %s' % indent_after_first_line(comment, ' ')) + self.log(" * %s" % indent_after_first_line(comment, " ")) self.report.enable_diffs() self.n_failed += 1 @@ -246,21 +229,49 @@ def fail_if_not_equal(self, what, expected, actual): """Register a check failure when EXPECTED and ACTUAL are not equal.""" self.fail_if( expected != actual, - 'Unexpected {}. Expected:' - '\n{}' - '\nBut got:' - '\n{}'.format(what, indent(str(expected)), indent(str(actual)))) + "Unexpected {}. Expected:" + "\n{}" + "\nBut got:" + "\n{}".format(what, indent(str(expected)), indent(str(actual))), + ) - def fail_if_no_match(self, what, regexp, actual): - """Register a check failure when ACTUAL does not match regexp.""" + def _fail_if_regex(self, what, regexp, actual, match_is_fail=False): if isinstance(regexp, str): regexp = re.compile(regexp) + # Canonicalize to Unix-style line endings to have cross-platform checks + actual = actual.replace("\r\n", "\n") + matching = bool(regexp.match(actual)) self.fail_if( - not regexp.match(actual), - 'Unexpected {}. Expected:' - '\n{}' - '\nBut got:' - '\n{}'.format(what, indent(regexp.pattern), indent(str(actual)))) + matching == match_is_fail, + "Error {}." + "\n{}:" + "\n{}" + "\nBut got:" + "\n{}".format( + what, + "Unexpected" if match_is_fail else "Expected", + indent(regexp.pattern), + indent(str(actual)), + ), + ) + + def fail_if_no_match(self, what, regexp, actual): + """Register a check failure when ACTUAL does not match regexp.""" + self._fail_if_regex( + what, + regexp, + actual, + match_is_fail=False, + ) + + def fail_if_match(self, what, regexp, actual): + """Register a check failure when ACTUAL does match regexp.""" + self._fail_if_regex( + what, + regexp, + actual, + match_is_fail=True, + ) def stop(self, exc): self.failed("Processing failed") @@ -286,14 +297,13 @@ class XcovPathRemover(OutputRefiner): """Remove path lines in outputs.""" def refine(self, output): - if os.path.exists(output.strip('\n:')): + if os.path.exists(output.strip("\n:")): return "" return output return [ # Refiners for the xcov report LineByLine(XcovPathRemover()), - # Ignore platform specificities CanonicalizeLineEndings(), ] @@ -304,6 +314,7 @@ def fail_if_diff_internal( actual, failure_message="unexpected output", output_refiners=None, + ignore_white_chars=True, ): """Compute the diff between expected and actual outputs. @@ -319,6 +330,7 @@ def fail_if_diff_internal( and the actual output. Refer to the doc in ``e3.testsuite.driver.diff``. If None, use ``self.report_output_refiners()``. + :param ignore_white_chars: See ``e3.diff``. """ if output_refiners is None: @@ -338,7 +350,11 @@ def fail_if_diff_internal( # Compute the diff. If it is empty, return no failure. Otherwise, # include the diff in the test log and return the given failure # message. - d = diff(expected_lines, actual_lines) + d = diff( + expected_lines, + actual_lines, + ignore_white_chars=ignore_white_chars, + ) if not d: return [] @@ -353,9 +369,7 @@ def fail_if_diff_internal( # Send the appropriate logging. self.failed( - "Diff failure: {}\n".format(message) - + "\n{}".format(d) - + "\n" + "Diff failure: {}\n".format(message) + "\n{}".format(d) + "\n" ) def fail_if_diff( @@ -364,12 +378,20 @@ def fail_if_diff( actual_file, failure_message="unexpected output", output_refiners=None, + ignore_white_chars=True, ): - """Wrapper around fail_if_diff_internal, taking an actual_file parameter - instead of an actual string.""" + """ + Wrapper around fail_if_diff_internal, taking an actual_file parameter + instead of an actual string. + """ with open(actual_file, "r") as f: - self.fail_if_diff_internal(baseline_file, f.read(), - failure_message, output_refiners) + self.fail_if_diff_internal( + baseline_file, + f.read(), + failure_message, + output_refiners, + ignore_white_chars, + ) def result(self): """Output the final result which the testsuite driver looks for. @@ -379,20 +401,23 @@ def result(self): from SUITE.tutils import run_processes if self.n_failed == 0: - self.log('==== PASSED ============================.') + self.log("==== PASSED ============================.") else: - self.log('**** FAILED ****************************.') + self.log("**** FAILED ****************************.") # Log the total execution time as well as the list of processes that # were run, with their duration. This is useful to investigate where # time is spent exactly when testcases take too long to run. duration = time.time() - self.start_time - logger.debug('Total ellapsed time: {:.3f}s'.format(duration)) + logger.debug("Total ellapsed time: {:.3f}s".format(duration)) if run_processes: - logger.debug('Processes run:') + logger.debug("Processes run:") for p in run_processes: - logger.debug(' [{:6.3f}s] {}'.format( - p.duration, ' '.join(p.original_cmd))) + logger.debug( + " [{:6.3f}s] {}".format( + p.duration, " ".join(p.original_cmd) + ) + ) # Flush the output, in case we forgot to do so earlier. This has no # effect if the flush was already performed. @@ -410,20 +435,33 @@ def __cmdline_options(self): """Return an options object to represent the command line options""" main = Main(platform_args=True) parser = main.argument_parser - parser.add_argument('--timeout', type=int, default=None) - parser.add_argument('--report-file', metavar='FILE', - help='The filename where to store the test report' - ' [required]') - parser.add_argument('--qualif-level', metavar='QUALIF_LEVEL', - help='The target qualification level when we are' - ' running in qualification mode.') + parser.add_argument("--timeout", type=int, default=None) + parser.add_argument( + "--report-file", + metavar="FILE", + help="The filename where to store the test report" " [required]", + ) + parser.add_argument( + "--qualif-level", + metavar="QUALIF_LEVEL", + help="The target qualification level when we are" + " running in qualification mode.", + ) - parser.add_argument('--xcov-level', - help='Force the --level argument passed to xcov' - 'instead of deducing it from the test' - ' category when that normally happens.') + parser.add_argument( + "--xcov-level", + help="Force the --level argument passed to xcov" + "instead of deducing it from the test" + " category when that normally happens.", + ) + + parser.add_argument("--tags", default="") - parser.add_argument('--tags', default="") + parser.add_argument( + "--ada-version", + help="Ada version that is passed to gnatcov instrument", + default="", + ) control.add_shared_options_to(parser, toplevel=False) @@ -433,12 +471,13 @@ def __cmdline_options(self): # self-contradictory, but it's easy to do it that way. exit_if( main.args.report_file is None, - "The report file must be specified with --report-file") + "The report file must be specified with --report-file", + ) # Get our tags set as a list. Fetch contents from file if needed # first: - if main.args.tags and main.args.tags.startswith('@'): - main.args.tags = ' '.join(lines_of(main.args.tags[1:])) + if main.args.tags and main.args.tags.startswith("@"): + main.args.tags = " ".join(lines_of(main.args.tags[1:])) if main.args.tags: main.args.tags = main.args.tags.split() @@ -457,10 +496,16 @@ def suite_covpgm_for(self, cmd): Alternate program to launch in lieu of "gnatcov CMD", if any specified with the --gnatcov-CMD= command line option. None otherwise. """ - return getattr(thistest.options, 'gnatcov_%s' % cmd, None) + return getattr(thistest.options, "gnatcov_%s" % cmd, None) + + def suite_gprpgm_for(self, pgm): + """ + Alternate program to launch in lieu of "gpr", + """ + return getattr(thistest.options, pgm, None) def support_dir(self): - return os.path.join(ROOT_DIR, 'support') + return os.path.join(ROOT_DIR, "support") def bits(self): """ @@ -476,5 +521,5 @@ def bits(self): # Allow import of a common "test_support" module from test.py when # there is a test_support.py available uptree. __parent_dir = os.path.dirname(os.getcwd()) -if (os.path.exists(os.path.join(__parent_dir, 'test_support.py'))): +if os.path.exists(os.path.join(__parent_dir, "test_support.py")): sys.path.append(__parent_dir) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index a9b7f5375..a9e984f2f 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -9,7 +9,7 @@ from e3.fs import rm from e3.os.process import Run -from SUITE.cutils import no_ext +from SUITE.cutils import no_ext, version env = Env() @@ -26,15 +26,15 @@ def xcov_pgm(auto_arch, for_target=True): architecture instead. """ arch = env.target if for_target else env.build - return 'gnatcov{bits}{ext}'.format( - bits=str(arch.cpu.bits) if auto_arch else '', - ext=env.host.os.exeext) + return "gnatcov{bits}{ext}".format( + bits=str(arch.cpu.bits) if auto_arch else "", ext=env.host.os.exeext + ) # Append .exe on windows for native tools -GPRBUILD = 'gprbuild' + env.host.os.exeext -GPRCONFIG = 'gprconfig' + env.host.os.exeext -GPRCLEAN = 'gprclean' + env.host.os.exeext +GPRBUILD = "gprbuild" + env.host.os.exeext +GPRCONFIG = "gprconfig" + env.host.os.exeext +GPRCLEAN = "gprclean" + env.host.os.exeext class LangInfo: @@ -61,13 +61,26 @@ class LangInfo: sidfile_for: A function which returns the name of the SID file for a given SOURCE file name. This is, for example, "x.sid" for "x.adb". + + in_gpr: + Whether this language can be mentionned in project files. """ - def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): + + def __init__( + self, + name, + src_ext, + comment, + scofile_for, + sidfile_for=None, + in_gpr=True, + ): self.name = name self.src_ext = src_ext self.comment = comment self.scofile_for = scofile_for self.sidfile_for = sidfile_for + self.in_gpr = in_gpr # A dictionary mapping a LangInfo instance to each known language. @@ -77,28 +90,38 @@ def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): LANGINFO = { "Ada": LangInfo( - name="Ada", src_ext=[".ads", ".adb"], comment='--', - scofile_for=lambda source: no_ext(source) + '.ali', - sidfile_for=lambda source: no_ext(source) + '.sid'), - + name="Ada", + src_ext=[".ads", ".adb"], + comment="--", + scofile_for=lambda source: no_ext(source) + ".ali", + sidfile_for=lambda source: no_ext(source) + ".sid", + ), "C": LangInfo( - name="C", src_ext=[".h", ".c"], comment='//', - scofile_for=lambda source: source + '.gli', - sidfile_for=lambda source: source + '.sid'), - + name="C", + src_ext=[".h", ".c"], + comment="//", + scofile_for=lambda source: source + ".gli", + sidfile_for=lambda source: source + ".sid", + ), "C++": LangInfo( - name="C++", src_ext=[".hh", ".cpp"], - comment='//', + name="C++", + src_ext=[".hh", ".cpp"], + comment="//", scofile_for=None, - sidfile_for=lambda source: source + '.sid'), - - "Asm": LangInfo( - name="Asm", src_ext=[".s"], comment='#', - scofile_for=None), - + sidfile_for=lambda source: source + ".sid", + ), + "Rust": LangInfo( + name="Rust", src_ext=[".rs"], comment="//", scofile_for=None + ), + "Asm": LangInfo(name="Asm", src_ext=[".s"], comment="#", scofile_for=None), "Cons": LangInfo( - name="Consolidation", src_ext=[".txt"], comment='--', - scofile_for=None)} + name="Consolidation", + src_ext=[".txt"], + comment="--", + scofile_for=None, + in_gpr=False, + ), +} # List of languages that gnatcov supports KNOWN_LANGUAGES = [li.name for li in LANGINFO.values() if li.scofile_for] @@ -137,8 +160,7 @@ def SCOV_CARGS(options): # Working from binary traces relies on specific properties: - if options.trace_mode == 'bin': - + if options.trace_mode == "bin": # Critical conditional branches must be preserved, source # coverage obligations need to be generated by the compiler, # and debug info is needed. @@ -156,10 +178,10 @@ def SCOV_CARGS(options): # info on partially linked objects, which we'll only get for long # calls on powerpc. - if 'vxworks' in Env().target.triplet: + if "vxworks" in Env().target.triplet: cargs.append("-gno-strict-dwarf") - if 'powerpc' in Env().target.triplet: + if "powerpc" in Env().target.triplet: cargs.append("-mlongcall") return cargs @@ -193,7 +215,6 @@ def RUN_CONFIG_SEQUENCE(toplev_options, toolchain_discriminant): # We build a temporary dummy project file in the current directory, # specifying languages only. with open("suite.gpr", "w") as tempgpr: - # Given GNAT 5.04a1 does not come with a C++ compiler, we'd # resort to the system one to link if C++ is in the list of # languages, causing compatibility issues with the toolchain. @@ -202,15 +223,20 @@ def RUN_CONFIG_SEQUENCE(toplev_options, toolchain_discriminant): # toolchain. added_languages = ( - ', "C++"' if toolchain_discriminant != "5.04a1" - else '') + ', "C++"' if toolchain_discriminant != "5.04a1" else "" + ) - tempgpr.write(""" + tempgpr.write( + """ project %(prjname)s is for Languages use ("Asm", "C", "Ada" %(added_languages)s); end %(prjname)s; - """ % {'prjname': os.path.basename(tempgpr.name).split('.')[0], - 'added_languages': added_languages}) + """ + % { + "prjname": os.path.basename(tempgpr.name).split(".")[0], + "added_languages": added_languages, + } + ) # We now run gprbuild -Ptemp.gpr --target=bla --RTS=blo, which # will complain about missing sources, but only after producing @@ -218,12 +244,19 @@ def RUN_CONFIG_SEQUENCE(toplev_options, toolchain_discriminant): # else (no other file). rm(BUILDER.SUITE_CGPR) - extraopts = ['--target={}'.format(env.target.triplet)] + extraopts = ["--target={}".format(env.target.triplet)] if toplev_options.RTS: - extraopts.append('--RTS=%s' % toplev_options.RTS) - - Run([GPRBUILD, '-P', tempgpr.name, - '--autoconf=%s' % BUILDER.SUITE_CGPR] + extraopts) + extraopts.append("--RTS=%s" % toplev_options.RTS) + + Run( + [ + GPRBUILD, + "-P", + tempgpr.name, + "--autoconf=%s" % BUILDER.SUITE_CGPR, + ] + + extraopts + ) rm(tempgpr.name) @@ -240,60 +273,71 @@ def __init__(self, runtime_name=None): self.has_ravenscar_runtime = False self.has_kernel_runtime = False self.has_light_runtime = False + self.has_exception_propagation = True + self.discrs = [] - if not self.runtime_name: + # Set specific scenario variables to always pass to any project loading + # command (gnatcov -P or gprbuild / gprinstall) + self.gpr_scenario_vars = [] + + if "aamp" in self.runtime_name: + self.gpr_scenario_vars = ["-XLIBRARY_SUPPORT=no"] + elif not self.runtime_name: self.has_full_runtime = True - elif 'embedded' in self.runtime_name: + self.discrs = ["RTS_FULL"] + elif "embedded" in self.runtime_name: self.has_ravenscar_runtime = True - elif 'light-tasking' in self.runtime_name: + self.discrs = ["RTS_RAVENSCAR", "RTS_EMBEDDED"] + elif "light-tasking" in self.runtime_name: self.has_ravenscar_runtime = True - elif self.runtime_name.startswith('zfp'): + self.has_exception_propagation = False + self.discrs = ["RTS_RAVENSCAR", "RTS_LIGHT_TASKING"] + elif self.runtime_name.startswith("zfp"): self.has_light_runtime = True - elif self.runtime_name.startswith('light-'): + self.has_exception_propagation = False + self.discrs = ["RTS_ZFP"] + elif self.runtime_name == "light" or self.runtime_name.startswith( + "light-" + ): self.has_light_runtime = True - elif self.runtime_name == 'kernel': + self.has_exception_propagation = False + self.discrs = ["RTS_ZFP"] + elif self.runtime_name == "kernel": self.has_kernel_runtime = True else: - assert False, 'Unknown runtime: {}'.format(runtime_name) + raise AssertionError("Unknown runtime: {}".format(runtime_name)) @property - def need_libsupport(self): - """Libsupport considerations. - - We rely on our support lib to provide a common last chance handler in - every configuration where this makes sense, in particular with light and - Ravenscar RTS libraries. - - * Light profiles because some of these don't provide a handler at all. - - * Ravenscar because some handlers fallthrough to a infinite idle loop, - unfriendly wrt testcase termination in automated nightly executions. + def gnatcov_rts_project(self): + """Name of the gnatcov_rts project to use in instrumented projects.""" - In addition, providing our last chance handler ensures we get - consistent output on unexpected exception, on any target configuration. + # gnatcov_rts_full and gnatcov_rts were merged with the introduction + # of gnatcov setup. - We can't override "last chance" handling and don't really need to for - full runtimes (which terminate on exceptions), native or cross. + return ( + "gnatcov_rts_full" + if (self.has_full_runtime and not gnatcov_info().has_setup) + else "gnatcov_rts" + ) - This function controls whether we build the library and link with it. - """ - return self.has_ravenscar_runtime or self.has_light_runtime - @property - def gnatcov_rts_project(self): - """Name of the gnatcov_rts project to use in instrumented projects.""" - return 'gnatcov_rts' +def _runtime_info(runtime, target): + if target == "c": + assert not runtime + # CCG's runtime has no name, but it is for our purposes equivalent + # to a light runtime. + runtime = "light" + return RuntimeInfo(runtime) -def runtime_info(runtime=None): - if runtime is None: - runtime = env.main_options.RTS - return RuntimeInfo(runtime) +def runtime_info(): + return _runtime_info(env.main_options.RTS, env.target.platform) # Target specificities. We don't have many variants but need to match each # against a few possible triplets. + class TargetInfo: """ Gather target specific information and behaviors @@ -307,11 +351,13 @@ class TargetInfo: symbol into a platform specific one, or None if they are the same. This enables us to use platform-independent symbol names in testcases. """ + def __init__(self, exeext, partiallinks, to_platform_specific_symbol=None): self.exeext = exeext self.partiallinks = partiallinks - self.to_platform_specific_symbol = ( - to_platform_specific_symbol or (lambda x: x)) + self.to_platform_specific_symbol = to_platform_specific_symbol or ( + lambda x: x + ) # For each family of targets we need to distinguish, a regexp to match against @@ -319,18 +365,20 @@ def __init__(self, exeext, partiallinks, to_platform_specific_symbol=None): TARGETINFO = { # VxWorks targets - '.*-vxworks': TargetInfo(exeext='.out', partiallinks=True), - + ".*-vxworks": TargetInfo(exeext=".out", partiallinks=True), # x86-windows targets - 'i686.*-mingw': TargetInfo( - exeext='.exe', partiallinks=False, - to_platform_specific_symbol=lambda x: '_{}'.format(x)), - + "i686.*-mingw": TargetInfo( + exeext=".exe", + partiallinks=False, + to_platform_specific_symbol=lambda x: "_{}".format(x), + ), # x86_64-windows targets - 'x86_64.*mingw': TargetInfo(exeext='.exe', partiallinks=False), - + "x86_64.*mingw": TargetInfo(exeext=".exe", partiallinks=False), + # AAMP target + "aamp": TargetInfo(exeext=".axe", partiallinks=False), # default - '.': TargetInfo(exeext='', partiallinks=False)} + ".": TargetInfo(exeext="", partiallinks=False), +} def target_info(target=None): @@ -347,38 +395,101 @@ def target_info(target=None): return TARGETINFO[re_target] +class GnatcovInfo: + def __init__(self): + p = re.search(pattern=r"GNATcoverage (\d+)", string=version("gnatcov")) + self._major = int(p.group(1)) if p else None + self.has_setup = self.major_at_least(23) + + def major_at_most(self, val): + """ + Returns whether the major version of gnatcov is less or equal than + val. Consider that development versions of gnatcov have a greater + major version than anything. + """ + return self._major is not None and self._major <= val + + def major_at_least(self, val): + """ + Returns whether the major version of gnatcov is greater or equal than + val. Consider that development versions of gnatcov have a greater + major version than anything. + """ + return self._major is None or self._major >= val + + def major(self): + """ + Major of gnatcov, if defined, or None if gnatcov is a development + version. + """ + return self._major + + +def gnatcov_info(): + return GnatcovInfo() + + +# Mapping between run-cross2 board names and gnatemu board names +BOARD_INFO = { + # generic + "qemu": "", + # aarch64-elf + "qemu-zynqmp": "", + # arm-elf + "qemu-stm32": "stm32f4", + "qemu-tms570": "tms570", + # ppc-elf: + "qemu-8641d": "", + None: "", +} + + +def gnatemu_board_name(name): + """ + Return the gnatemu board name corresponding to the run-cross2 board name + passed as argument. If name is unknown in the mapping, return it + unchanged. + """ + return BOARD_INFO.get(name, name) + + # Allowed pairs for the --gnatcov- family of command line options: -ALTRUN_GNATCOV_PAIRS = (('gnatcov', 'run'), ) +ALTRUN_GNATCOV_PAIRS = (("gnatcov", "run"),) # Allowed pairs for the --pre/post-testsuite/testcase family of command line # options: -ALTRUN_HOOK_PAIRS = (('pre', 'testsuite'), - ('post', 'testsuite'), - ('pre', 'testcase'), - ('post', 'testcase')) +ALTRUN_HOOK_PAIRS = ( + ("pre", "testsuite"), + ("post", "testsuite"), + ("pre", "testcase"), + ("post", "testcase"), +) +# Allowed alternatives for the --gpr family of command line options +ALTRUN_GPR = ("gprbuild",) -def altrun_opt_for(p0, p1): + +def altrun_opt_for(p0, p1=None): """Name of the command line option controlling the ALTRUN (P0, P1) pair.""" - return "%s_%s" % (p0, p1) + return "%s_%s" % (p0, p1) if p1 else p0 -def altrun_attr_for(p0, p1): +def altrun_attr_for(p0, p1=None): """Name of our internal controlling options attribute for the ALTRUN (P0, P1) pair.""" - return "%s_%s" % (p0, p1) + return "%s_%s" % (p0, p1) if p1 else p0 def cargs_opt_for(lang): """Name of the command line option to pass for language LANG.""" - return "cargs" + (':%s' % lang if lang else "") + return "cargs" + (":%s" % lang if lang else "") def cargs_attr_for(lang): """ Name of our internal options attribute to hold cargs for language LANG. """ - return "cargs" + ('_%s' % lang if lang else "") + return "cargs" + ("_%s" % lang if lang else "") def add_shared_options_to(parser, toplevel): @@ -391,58 +502,95 @@ def add_shared_options_to(parser, toplevel): # --gnatcov_ family for pgm, cmd in ALTRUN_GNATCOV_PAIRS: parser.add_argument( - '--%s' % altrun_opt_for(pgm, cmd), dest=altrun_attr_for(pgm, cmd), + "--%s" % altrun_opt_for(pgm, cmd), + dest=altrun_attr_for(pgm, cmd), metavar="CMD", - help='Use CMD instead of "%s %s"' % (pgm, cmd)) + help='Use CMD instead of "%s %s"' % (pgm, cmd), + ) + + # --gpr family + for pgm in ALTRUN_GPR: + parser.add_argument( + f"--{altrun_opt_for(pgm)}", + dest=altrun_attr_for(pgm), + metavar="CMD", + help=f'use CMD instead of "{pgm}"', + ) # Valgrind control parser.add_argument( - '--enable-valgrind', dest='enable_valgrind', - choices='memcheck callgrind'.split(), - help='Enable the use of Valgrind (memcheck or callgrind) during the' - ' test execution.') + "--enable-valgrind", + dest="enable_valgrind", + choices="memcheck callgrind".split(), + help="Enable the use of Valgrind (memcheck or callgrind) during the" + " test execution.", + ) # RTS for tested programs. Defaulting to "" instead of None lets us # perform RE searches unconditionally to determine profile. parser.add_argument( - '--RTS', dest='RTS', metavar='RTS', default="", + "--RTS", + dest="RTS", + metavar="RTS", + default="", help='--RTS option to pass to gprbuild, if any. Assume "full" profile' - ' by default.') + " by default.", + ) # --board parser.add_argument( - '--board', dest='board', metavar='BOARD', - help='Specific target board to exercize.') + "--board", + dest="board", + metavar="BOARD", + help="Specific target board to exercize.", + ) # --gprmode parser.add_argument( - '--gprmode', dest='gprmode', action='store_true', - help='Use -P instead of --scos for analysis on source coverage tests.') + "--gprmode", + dest="gprmode", + action="store_true", + help="Use -P instead of --scos for analysis on source coverage tests.", + ) # --kernel parser.add_argument( - '--kernel', dest='kernel', metavar='KERNEL', - help='KERNEL to pass to gnatcov run in addition to exe.') + "--kernel", + dest="kernel", + metavar="KERNEL", + help="KERNEL to pass to gnatcov run in addition to exe.", + ) # --trace-mode parser.add_argument( - '--trace-mode', dest='trace_mode', metavar='TRACE_MODE', - choices=('bin', 'src'), default='bin', - help='Kind of execution traces to use for SCOV driven tests.' - ' "bin" for binary traces out of valgrind or qemu,' - ' "src" for source traces out of source level instrumentation.') + "--trace-mode", + dest="trace_mode", + metavar="TRACE_MODE", + choices=("bin", "src"), + default="bin", + help="Kind of execution traces to use for SCOV driven tests." + ' "bin" for binary traces out of valgrind or qemu,' + ' "src" for source traces out of source level instrumentation.', + ) # --trace-size-limit parser.add_argument( - '--trace-size-limit', dest='trace_size_limit', metavar='TRSZ_LIMIT', - help='Best effort request to the execution environment to stop when' - ' the execution trace would grow beyond the provided size. Only' - ' effective for qemu based executions, with values like "10M".') + "--trace-size-limit", + dest="trace_size_limit", + metavar="TRSZ_LIMIT", + help="Best effort request to the execution environment to stop when" + " the execution trace would grow beyond the provided size. Only" + ' effective for qemu based executions, with values like "10M".', + ) # --largs parser.add_argument( - '--largs', dest='largs', metavar='LARGS', default='', - help='-largs to pass to gprbuild.') + "--largs", + dest="largs", + metavar="LARGS", + default="", + help="-largs to pass to gprbuild.", + ) # --cargs[:] family: a common, language agnostic, one + one for each # language we support. --cargs "" should be kept semantically equivalent @@ -450,40 +598,86 @@ def add_shared_options_to(parser, toplevel): # downstream. for lang in [None] + KNOWN_LANGUAGES: parser.add_argument( - '--%s' % cargs_opt_for(lang), dest=cargs_attr_for(lang), - metavar='CARGS', default='', - help='Additional arguments to pass to the %scompiler when' - ' building test programs.' % ('%s ' % lang if lang else '')) + "--%s" % cargs_opt_for(lang), + dest=cargs_attr_for(lang), + metavar="CARGS", + default="", + help="Additional arguments to pass to the %scompiler when" + " building test programs." % ("%s " % lang if lang else ""), + ) # --auto-arch parser.add_argument( - '--auto-arch', action='store_true', - help='Autodetect which "gnatcov" to use (32-bit or 64-bit one).') + "--auto-arch", + action="store_true", + help='Autodetect which "gnatcov" to use (32-bit or 64-bit one).', + ) # --consolidate parser.add_argument( - '--consolidate', dest='consolidate', default="traces", + "--consolidate", + dest="consolidate", + default="traces", help="Artifacts to be used for consolidation specs.", - choices=('traces', 'checkpoints')) + choices=("traces", "checkpoints"), + ) # --pretty-print parser.add_argument( - '--pretty-print', action='store_true', + "--pretty-print", + action="store_true", help='Whether to pretty-print generated sources (for "gnatcov' - ' instrument".') + ' instrument".', + ) # --spark-tests parser.add_argument( - '--spark-tests', dest="spark_tests", metavar='SPARK_TESTSUITE_PATH', - help='Path to the SPARK testsuite. Activate SPARK-specific' - ' tests. Implicitly appends -gnat12 to Ada cargs.') + "--spark-tests", + dest="spark_tests", + metavar="SPARK_TESTSUITE_PATH", + help="Path to the SPARK testsuite. Activate SPARK-specific" + " tests. Implicitly appends -gnat2022 to Ada cargs.", + ) # --all-warnings parser.add_argument( - '--all-warnings', action='store_true', - help='Whether to pass --all-warnings to gnatcov.') + "--all-warnings", + action="store_true", + help="Whether to pass --all-warnings to gnatcov.", + ) + + parser.add_argument( + "--rewrite", + action="store_true", + help="Rewrite test baselines according to current outputs.", + ) + + # --default-dump-trigger + parser.add_argument( + "--default-dump-trigger", + dest="default_dump_trigger", + help='Default dump trigger to be passed to "gnatcov instrument,"' + " unless the test specifically overrides it.", + ) + + # --default-dump-channel + parser.add_argument( + "--default-dump-channel", + dest="default_dump_channel", + help='Default dump channel to be passed to "gnatcov instrument,"' + " unless the test specifically overrides it.", + ) + + # --block + parser.add_argument( + "--block", + action="store_true", + help='Pass --block-instrument to "gnatcov instrument",' + " to enable block instrumentation.", + ) + # --community parser.add_argument( - '--rewrite', action='store_true', - help='Rewrite test baselines according to current outputs.') + "--community", action="store_true", help="Only run community tests." + ) diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index 605a13502..024f8ca56 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -11,9 +11,30 @@ import sys import tempfile -from e3.fs import mkdir +from typing import AnyStr, Optional + +from e3.fs import cp, mkdir from e3.os.fs import cd, which from e3.os.process import Run +from e3.testsuite.driver.diff import OutputRefiner + + +def unhandled_exception_in(log): + """ + Whether the provided execution log contains an indication + of a unhandled exception occurrence. + """ + + # Account for patterns emitted by either a regular runtime or + # our custom last_chance_handlers. + return re.search( + pattern=( + r"(!!! EXCEPTION RAISED !!!" + r"|" + r"raised [A-Z_]+ : [-._a-zA-Z]+:[0-9]+ \w+)" + ), + string=log, + ) def strip_prefix(prefix, string): @@ -21,7 +42,7 @@ def strip_prefix(prefix, string): If STRING starts with PREFIX, return STRING without the PREFIX part. Return the string unchanged otherwise. """ - return string[len(prefix):] if string.startswith(prefix) else string + return string[len(prefix) :] if string.startswith(prefix) else string def no_ext(filename): @@ -34,6 +55,11 @@ def ext(filename): return os.path.splitext(filename)[1] +def exists(filename): + """Return true if the filename exists""" + return os.path.exists(filename) + + def contents_of(filename): """Return contents of file FILENAME""" with open(filename) as fd: @@ -58,60 +84,63 @@ def to_list(blob): Turn input BLOB into a list if it isn't already. Handle None and whitespace separated strings. Return empty list otherwise. """ - return (list(blob) if isinstance(blob, (list, tuple)) - else blob.split() if isinstance(blob, str) - else []) + return ( + list(blob) + if isinstance(blob, (list, tuple)) + else blob.split() if isinstance(blob, str) else [] + ) -def indent(blob, indent=' '): +def indent(blob, indent=" "): """ Prefix each line in BLOB's with INDENT. BLOB can be either a single string or a list of strings. The result is a single string anyway. """ lines = list(blob) if isinstance(blob, list) else blob.splitlines() - return '\n'.join('{}{}'.format(indent, line) - for line in lines) + return "\n".join("{}{}".format(indent, line) for line in lines) -def indent_after_first_line(blob, prefix=' '): +def indent_after_first_line(blob, prefix=" "): """Like "indent", but do not change the first line.""" lines = list(blob) if isinstance(blob, list) else blob.splitlines() if len(lines) < 2: - return '\n'.join(lines) + return "\n".join(lines) else: - return '\n'.join(lines[0:1] + indent(lines[1:], prefix).splitlines()) + return "\n".join(lines[0:1] + indent(lines[1:], prefix).splitlines()) -def text_to_file(text, filename='tmp.list'): +def text_to_file(text, filename="tmp.list"): """ Write TEXT to file FILENAME. Overwrite current contents. Return FILENAME. """ - with open(filename, 'w') as fd: + with open(filename, "w") as fd: fd.write(text) return filename -def list_to_file(lines, filename='tmp.list'): +def list_to_file(lines, filename="tmp.list"): """ Write list LINES to file FILENAME, one item per line. Typical use is to generate response files. Return FILENAME. """ - return text_to_file('\n'.join(lines) + '\n', filename) + return text_to_file("\n".join(lines) + "\n", filename) -def list_to_tmp(lines, dir=None): +def list_to_tmp(lines, dirname=None): """ - Write list LINES to a temporary file in DIR (or the current directory), one - item per line. Return the temporary file name, chosen not to conflict with - already exisiting files. + Write list LINES to a temporary file in DIRNAME (or the current directory), + one item per line. Return the temporary file name, chosen not to conflict + with already exisiting files. """ # By default, create the temporary file in the current working directory. # Make sure the returned path is absolute, so that the result can be used # even after the current working directory changes (which happens often in # testcases). - dir = os.getcwd() if dir is None else os.path.abspath(dir) + dirname = os.getcwd() if dirname is None else os.path.abspath(dirname) return text_to_file( - '\n'.join(lines) + '\n', tempfile.mktemp(dir=dir, suffix='.list')) + "\n".join(lines) + "\n", + tempfile.mktemp(dir=dirname, suffix=".list"), + ) def match(pattern, filename, flags=0): @@ -119,7 +148,7 @@ def match(pattern, filename, flags=0): return re.search(pattern, contents_of(filename), flags) is not None -def re_filter(strings, pattern=''): +def re_filter(strings, pattern=""): """Compute the list of entries in STRINGS that match the PATTERN regexp.""" return [t for t in strings if re.search(pattern, t)] @@ -148,23 +177,26 @@ def version(tool, nlines=1): # probe, and if we happen to actually need the tool later on, we'll see # test failures anyway. if not which(tool): - return 'N/A' + return "N/A" # --version often dumps more than the version number on a line. A # copyright notice is typically found there as well. Our heuristic # here is to strip everything past the first comma. def version_on_line(text): - cprpos = text.find(',') + cprpos = text.find(",") return text[0:cprpos] if cprpos != -1 else text - tool_version_output = Run([tool, '--version']).out.split('\n') - version_info = '\n'.join( - [version_on_line(line) for line in tool_version_output[0:nlines]]) + tool_version_output = [ + line.strip() for line in Run([tool, "--version"]).out.split("\n") + ] + version_info = "\n".join( + [version_on_line(line) for line in tool_version_output[0:nlines]] + ) - if tool == 'gcc': - gcc_target = Run([tool, '-dumpmachine']).out.strip() - version_info += ' [%s]' % gcc_target + if tool == "gcc": + gcc_target = Run([tool, "-dumpmachine"]).out.strip() + version_info += " [%s]" % gcc_target return version_info @@ -180,14 +212,14 @@ def ndirs_in(path): return nsplits -def output_of(cmd, dir=None): +def output_of(cmd, dirname=None): """ - Execute CMD and return it's output, switching to DIR before if not None, - and switching back to the original cwd as needed. + Execute CMD and return it's output, switching to DIRNAME before if not + None, and switching back to the original cwd as needed. """ cwd = os.getcwd() - if dir is not None: - cd(dir) + if dirname is not None: + cd(dirname) output = Run(cmd.split()).out cd(cwd) return output @@ -207,16 +239,16 @@ def __init__(self, subdir=None): if subdir: self.to_subdir(subdir) - def to_subdir(self, dir): + def to_subdir(self, dirname): """ - Change the current directory to `dir`, relative to `self`'s home + Change the current directory to `dirname`, relative to `self`'s home directory. Create it if needed, after first removing it. """ self.to_homedir() - if os.path.exists(dir): - shutil.rmtree(dir) - mkdir(dir) - cd(dir) + if os.path.exists(dirname): + shutil.rmtree(dirname) + mkdir(dirname) + cd(dirname) def to_homedir(self): """ @@ -230,9 +262,9 @@ class FatalError(Exception): def __init__(self, comment, outfile=None, outstr=None): if outfile is not None: - comment += '. Output was:\n' + contents_of(outfile) + comment += ". Output was:\n" + contents_of(outfile) elif outstr is not None: - comment += '. Output was:\n' + outstr + comment += ". Output was:\n" + outstr self.comment = comment def __str__(self): @@ -245,10 +277,74 @@ def exit_if(t, comment): error status code. """ if t: - sys.stderr.write(comment + '\n') + sys.stderr.write(comment + "\n") exit(1) +def multi_range(*args, minus=None): + """ + Utility function for easily creating sets of numbers from inclusive ranges + or simple numbers. + This function takes any number of arguments, which must either be + integers or integer 2-tuple. + The returned value is a set that contains all single numbers and all the + *INCLUSIVE* ranges + + The named parameter `minus` is a list that follows the same principle, but + its result is removed from the result of the function. + + Example: `multi_range((1,3), 6, (10, 13)) == {1, 2, 3, 6, 10, 11, 12, 13}` + """ + result = set() + for arg in args: + if type(arg) is int: + result |= {arg} + else: + (start, end) = arg + result |= set(range(start, end + 1)) + + minus = minus or [] + for arg in minus: + if type(arg) is int: + result ^= {arg} + else: + (start, end) = arg + result ^= set(range(start, end + 1)) + + return result + + +class FilePathRefiner(OutputRefiner[AnyStr]): + """ + For each tag "@@FILE@@", find the file by looking at src_dir/FILE, and + replace the tag with the absolute path of the file. + """ + + TAG_REGEX = re.compile(r"@@(?P(?:\w|[./])+)@@") + + def __init__(self, src_dir: Optional[AnyStr] = None) -> None: + self.src_dir = src_dir or ".." + + def refine(self, output: AnyStr) -> AnyStr: + def _replace_tag(pat): + filename = pat.group("filename") + path = os.path.abspath(os.path.join(self.src_dir, filename)) + return path + + return re.sub(self.TAG_REGEX, _replace_tag, output) + + class Identifier: def __init__(self, name): self.name = name + + +def copy_to_dir(orig_dir, target_dir, filename): + """ + Copy filename from orig_dir to target_dir. + """ + if os.path.abspath(orig_dir) != os.path.abspath(target_dir): + cp( + os.path.join(orig_dir, filename), + os.path.join(target_dir, filename), + ) diff --git a/testsuite/SUITE/dutils.py b/testsuite/SUITE/dutils.py index 607abc75d..cd0f40644 100644 --- a/testsuite/SUITE/dutils.py +++ b/testsuite/SUITE/dutils.py @@ -17,13 +17,14 @@ # Pickle oriented facilities # + def pdump_to(filename, o): - with open(filename, 'wb') as f: + with open(filename, "wb") as f: pickle.dump(o, f) def pload_from(filename): - with open(filename, 'rb') as f: + with open(filename, "rb") as f: return pickle.load(f) @@ -31,13 +32,14 @@ def pload_from(filename): # JSON oriented facilities # + def jdump_to(filename, o): - with open(filename, 'w') as f: + with open(filename, "w") as f: json.dump(o, f) def jload_from(filename): - with open(filename, 'r') as f: + with open(filename, "r") as f: return json.load(f) @@ -51,15 +53,15 @@ def host_string_from(host): os_version = host.os.version # 2008[R2] or 2012[R2] for Windows conveys Server editions - if os_name == 'Windows' and re.match(os_version, '2008|2012'): - os_version = 'Server ' + os_version + if os_name == "Windows" and re.match(os_version, "2008|2012"): + os_version = "Server " + os_version # Fetch precise Redhat version - if os_name == 'Linux' and os_version.startswith('rhES'): - os_name = '' - os_version = contents_of('/etc/redhat-release') + if os_name == "Linux" and os_version.startswith("rhES"): + os_name = "" + os_version = contents_of("/etc/redhat-release") - return ' '.join((os_name, os_version)).strip() + return " ".join((os_name, os_version)).strip() def time_string_from(stamp): @@ -67,4 +69,4 @@ def time_string_from(stamp): Return a textual version of the timestamp in STAMP, a time.localtime() kind of object. """ - return time.strftime('%a %b %d, %Y. %H:%M', stamp) + return time.strftime("%a %b %d, %Y. %H:%M", stamp) diff --git a/testsuite/SUITE/gprutils.py b/testsuite/SUITE/gprutils.py index d63be9ab2..a7e68de34 100644 --- a/testsuite/SUITE/gprutils.py +++ b/testsuite/SUITE/gprutils.py @@ -31,24 +31,25 @@ def gprdep_for(reldir, wd): # make sure that each test operating with a given relative dir has its own # object dir there and can run in parallel with others. - locid = os.path.basename(reldir.rstrip('/')) - testid = os.path.basename(wd.homedir.rstrip('/')) + locid = os.path.basename(reldir.rstrip("/")) + testid = os.path.basename(wd.homedir.rstrip("/")) - prjname = '%s_%s' % (locid, testid) + prjname = "%s_%s" % (locid, testid) gprdep = os.path.join(wd.homedir, reldir, prjname) - with open(gprdep + '.gpr', 'w') as gprfile: + with open(gprdep + ".gpr", "w") as gprfile: gprfile.write( - contents_of(os.path.join(wd.homedir, '../template.gpr')) % { - 'prjname': prjname, - 'objdir': 'obj_' + testid, - 'pkg_emulator': gpr_emulator_package(), + contents_of(os.path.join(wd.homedir, "../template.gpr")) + % { + "prjname": prjname, + "objdir": "obj_" + testid, + "pkg_emulator": gpr_emulator_package(), } ) return gprdep -Csw = namedtuple('Csw', 'cmd switches') +Csw = namedtuple("Csw", "cmd switches") def __gprattr(attrname, value, aslist): @@ -60,12 +61,13 @@ def __gprattr(attrname, value, aslist): for value == None. Not for an empty list or string. """ if value is None: - return '-- empty %s' % attrname + return "-- empty %s" % attrname elif aslist: - return 'for %s use (%s);' % ( + return "for %s use (%s);" % ( attrname, - ','.join('"%s"' % v for v in value)) + ",".join('"%s"' % v for v in value), + ) else: return 'for %s use "%s";' % (attrname, value) @@ -78,16 +80,19 @@ def __gpr_uattr(value, for_list, to_exclude): have a single list-filename argument. """ return __gprattr( - attrname='%(prefix)s%(kind)s' % { - 'prefix': 'Excluded_' if to_exclude else '', - 'kind': 'Units_List' if for_list else 'Units' + attrname="%(prefix)s%(kind)s" + % { + "prefix": "Excluded_" if to_exclude else "", + "kind": "Units_List" if for_list else "Units", }, value=value, - aslist=not for_list) + aslist=not for_list, + ) -def gprcov_for(units_in=None, ulist_in=None, units_out=None, ulist_out=None, - switches=()): +def gprcov_for( + units_in=None, ulist_in=None, units_out=None, ulist_out=None, switches=() +): """ Compute and return the text of a Coverage GPR package from: @@ -100,28 +105,29 @@ def gprcov_for(units_in=None, ulist_in=None, units_out=None, ulist_out=None, the corresponding argument passed here is None. For SWITCHES, we expect a command->switches sequence of ("command", [options]) Csw tuples. """ - return '\n'.join([ - - 'package Coverage is', - - # Units - __gpr_uattr(for_list=False, to_exclude=False, value=units_in), - - # Excluded_Units - __gpr_uattr(for_list=False, to_exclude=True, value=units_out), - - # Units_List - __gpr_uattr(for_list=True, to_exclude=False, value=ulist_in), - - # Excluded_Units_List - __gpr_uattr(for_list=True, to_exclude=True, value=ulist_out) - ] + [ - # Switches (CMD) - __gprattr(attrname='Switches ("%s")' % csw.cmd, - value=csw.switches, - aslist=True) - for csw in switches - ] + ["end Coverage;"]) + return "\n".join( + [ + "package Coverage is", + # Units + __gpr_uattr(for_list=False, to_exclude=False, value=units_in), + # Excluded_Units + __gpr_uattr(for_list=False, to_exclude=True, value=units_out), + # Units_List + __gpr_uattr(for_list=True, to_exclude=False, value=ulist_in), + # Excluded_Units_List + __gpr_uattr(for_list=True, to_exclude=True, value=ulist_out), + ] + + [ + # Switches (CMD) + __gprattr( + attrname='Switches ("%s")' % csw.cmd, + value=csw.switches, + aslist=True, + ) + for csw in switches + ] + + ["end Coverage;"] + ) class GPRswitches: @@ -137,14 +143,18 @@ class GPRswitches: with the build step that precedes the gnatcov invocations (e.g. --subdirs). """ - def __init__(self, - root_project, - projects=None, - units=None, - no_subprojects=False, - externally_built_projects=False, - xvars=None, - subdirs=None): + def __init__( + self, + root_project, + projects=None, + units=None, + no_subprojects=False, + externally_built_projects=False, + relocate_build_tree=False, + root_dir=None, + xvars=None, + subdirs=None, + ): """ :param str root_project: Root project to consider (-P argument). :param list[str] projects: Optional list of projects for units of @@ -165,6 +175,8 @@ def __init__(self, self.units = units or [] self.no_subprojects = no_subprojects self.externally_built_projects = externally_built_projects + self.relocate_build_tree = relocate_build_tree + self.root_dir = root_dir self.xvars = xvars or [] self.subdirs = subdirs @@ -177,10 +189,16 @@ def build_switches(self): switches = [] for v in self.xvars: - switches.append('-X{}={}'.format(v[0], v[1])) + switches.append("-X{}={}".format(v[0], v[1])) if self.subdirs: - switches.append('--subdirs={}'.format(self.subdirs)) + switches.append("--subdirs={}".format(self.subdirs)) + + if self.relocate_build_tree: + switches.append("--relocate-build-tree") + + if self.root_dir: + switches.append("--root-dir={}".format(self.root_dir)) return switches @@ -189,18 +207,18 @@ def cov_switches(self): """ The switches for gnatcov commands, as a list of strings. """ - switches = ['-P{}'.format(self.root_project)] + switches = ["-P{}".format(self.root_project)] for p in self.projects: - switches.append('--projects={}'.format(p)) + switches.append("--projects={}".format(p)) for u in self.units: - switches.append('--units={}'.format(u)) + switches.append("--units={}".format(u)) if self.no_subprojects: - switches.append('--no-subprojects') + switches.append("--no-subprojects") if self.externally_built_projects: - switches.append('--externally-built-projects') + switches.append("--externally-built-projects") return switches + self.build_switches diff --git a/testsuite/SUITE/llvmutils.py b/testsuite/SUITE/llvmutils.py new file mode 100644 index 000000000..2083300ae --- /dev/null +++ b/testsuite/SUITE/llvmutils.py @@ -0,0 +1,34 @@ +"""LLVM trace utils functions. + +This modules exposes common utility functions specifically for testing the +handling of LLVM Trace Adapter inputs into GNATcov. +""" + +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import xcov + + +def check_llvm_reports( + json_file, expected_report, cov_level="stmt", path_prefix=".." +): + """ + Check that GNATcov produces the right report when given a JSON file + generated with the LLVM trace adapter. + + The test case should have this architecture : + testcase + +-- src + | +-- *.rs + +-- + +-- test.py + """ + xcov( + [ + "coverage", + f"--level={cov_level}", + f"--llvm-json-checkpoint=../{json_file}", + "--source-search=../src", + "-axcov", + ] + ) + check_xcov_reports(".", expected_report) diff --git a/testsuite/SUITE/qdata.py b/testsuite/SUITE/qdata.py index c313510c5..0b5f855c9 100644 --- a/testsuite/SUITE/qdata.py +++ b/testsuite/SUITE/qdata.py @@ -25,19 +25,19 @@ # List of languages we support qualification tests for -QLANGUAGES = ['Ada'] +QLANGUAGES = ["Ada"] # String that identifies a qualification test at the beginning of it's # sub-directory name relative to the testsuite root -QROOTDIR = 'Qualif' +QROOTDIR = "Qualif" # Extension of datafiles dumped for the purpose of the STR document # production -STREXT = '.dump' +STREXT = ".dump" # Name of a directory where context data aimed at the STR production engine # will be dropped by the testsuite execution driver -QSTRBOX_DIR = '_strbox' +QSTRBOX_DIR = "_strbox" # @@ -58,41 +58,45 @@ # Name of a file, relative to the testsuite toplevel directory, where the # testsuite data of use for the STR production will be made available. -CTXDATA_FILE = os.path.join(QSTRBOX_DIR, 'suite' + STREXT) +CTXDATA_FILE = os.path.join(QSTRBOX_DIR, "suite" + STREXT) def TOOL_info(exename, ver=None): """Context data for a tool involved in a testsuite run.""" - return {'exename': exename, - 'version': ver or version(exename)} + return {"exename": exename, "version": ver or version(exename)} def OPT_info_from(options): """Context data for the command line options info of relevance.""" - return {'target': options.target, - 'board': options.board, - 'trace_mode': options.trace_mode, - 'dolevel': options.qualif_level, - 'cargs': options.cargs, - 'cargs_Ada': options.cargs_Ada, - 'cargs_C': options.cargs_C} - - -def SUITE_context(treeref, runstamp, host, cmdline, options, gnatpro, gnatemu, - gnatcov, other): + return { + "target": options.target, + "board": options.board, + "trace_mode": options.trace_mode, + "dolevel": options.qualif_level, + "cargs": options.cargs, + "cargs_Ada": options.cargs_Ada, + "cargs_C": options.cargs_C, + } + + +def SUITE_context( + treeref, runstamp, host, cmdline, options, gnatpro, gnatemu, gnatcov, other +): """ Toplevel context data structure, wrapping up all the relevant items together. """ - return {'runstamp': runstamp, - 'treeref': treeref, - 'cmdline': cmdline, - 'options': options, - 'host': host, - 'gnatpro': gnatpro, - 'gnatemu': gnatemu, - 'gnatcov': gnatcov, - 'other': other} + return { + "runstamp": runstamp, + "treeref": treeref, + "cmdline": cmdline, + "options": options, + "host": host, + "gnatpro": gnatpro, + "gnatemu": gnatemu, + "gnatcov": gnatcov, + "other": other, + } class TC_status: @@ -112,6 +116,7 @@ def __init__(self, passed=None, xfail=None, status=None, comment=None): # Qualification Data classes, filled and dumped by testcases # + class QDentry: def __init__(self, xfile, drivers, xrnotes, wdir): """ @@ -132,6 +137,7 @@ class Qdata: sequence of QDentry instances; typically one per SCOV_helper execution (that is, per driver + consolidation spec). """ + def __init__(self, tcid): # These are filled and dumped by the testcase execution itself: self.entries = [] @@ -143,10 +149,10 @@ def register(self, ob): self.entries.append(ob) def flush(self): - dutils.pdump_to(qdaf_in('.'), o=self) + dutils.pdump_to(qdaf_in("."), o=self) -QUALDATA_FILE = 'tc' + STREXT +QUALDATA_FILE = "tc" + STREXT def qdaf_in(dirname): @@ -158,7 +164,22 @@ def qdaf_in(dirname): return os.path.join(dirname, QUALDATA_FILE) -STATUSDATA_FILE = 'tcs' + STREXT +def qdafs_from(dirname): + """ + List of filenames for qualification data to be pickled, from the directory + tree rooted at dirname. Each returned filename hosts instances of objects + representing test executions, each holding dictionaries of expected notes + together with their dischargers. + """ + return [ + os.path.join(d, f) + for (d, _, files) in os.walk(dirname) + for f in files + if f == QUALDATA_FILE + ] + + +STATUSDATA_FILE = "tcs" + STREXT def stdf_in(dirname): @@ -168,10 +189,10 @@ def stdf_in(dirname): def treeref_at(dirname): """ - A string representative of where the DIRNAME directory originates from - (e.g. svn rev or git commit), to be used for consistency checks when - multiple operations are done separately but should work over synchronized - directory trees. + A string representative of the git commit where the DIRNAME + directory originates from, to be used for consistency checks + when multiple operations are done separately but should work + over synchronized directory trees. """ # Assuming git, sha1 for the HEAD reference - return output_of('git rev-parse HEAD', dir=dirname).rstrip('\n') + return output_of("git rev-parse HEAD", dirname=dirname).rstrip("\n") diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 7f3d227e8..545e8ba46 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -15,32 +15,33 @@ trace_file_header_struct = Struct( - 'trace file header', - ('magic', '32s'), - ('format_version', 'I'), - ('alignment', 'B'), - ('endianity', 'B'), - ('padding', 'H'), + "trace file header", + ("magic", "32s"), + ("format_version", "I"), + ("alignment", "B"), + ("endianity", "B"), + ("padding", "H"), ) trace_info_header_struct = Struct( - 'trace info header', - ('kind', 'I'), - ('length', 'I'), + "trace info header", + ("kind", "I"), + ("length", "I"), ) trace_entry_header_struct = Struct( - 'trace entry header', - ('unit_name_length', 'I'), - ('project_name_length', 'I'), - ('stmt_bit_count', 'I'), - ('dc_bit_count', 'I'), - ('mcdc_bit_count', 'I'), - ('language', 'B'), - ('unit_part', 'B'), - ('bit_buffer_encoding', 'B'), - ('fingerprint', '20B'), - ('padding', '5B'), + "trace entry header", + ("unit_name_length", "I"), + ("stmt_bit_count", "I"), + ("dc_bit_count", "I"), + ("mcdc_bit_count", "I"), + ("language", "B"), + ("unit_part", "B"), + ("bit_buffer_encoding", "B"), + ("fingerprint", "20s"), + ("bit_maps_fingerprint", "20s"), + ("annotations_fingerprint", "20s"), + ("padding", "B"), ) @@ -62,8 +63,7 @@ def read_aligned(fp, count, alignment): padding_count = alignment - count % alignment if padding_count != alignment: padding = fp.read(padding_count) - assert (len(padding) == padding_count and - all(c == 0 for c in padding)) + assert len(padding) == padding_count and all(c == 0 for c in padding) return content @@ -84,7 +84,7 @@ def write_aligned(fp, data, alignment): # Write padding bytes padding_count = alignment - len(data) % alignment if padding_count != alignment: - padding = b'\x00' * padding_count + padding = b"\x00" * padding_count fp.write(padding) @@ -93,13 +93,13 @@ class SrcTraceFile(object): In-memory representation of a source trace file. """ - MAGIC = b'GNATcov source trace file' + b'\x00' * 7 + MAGIC = b"GNATcov source trace file" + b"\x00" * 7 - FORMAT_VERSION = 1 + FORMAT_VERSION = 4 ENDIANITY_NAMES = { - 0: 'little-endian', - 1: 'big-endian', + 0: "little-endian", + 1: "big-endian", } ENDIANITY_CODES = {value: key for key, value in ENDIANITY_NAMES.items()} @@ -109,7 +109,7 @@ def __init__(self, alignment, endianity, info_entries, entries): self.info_entries = info_entries self.entries = entries - self.big_endian = endianity == 'big-endian' + self.big_endian = endianity == "big-endian" @classmethod def read(cls, fp): @@ -118,27 +118,28 @@ def read(cls, fp): """ header = trace_file_header_struct.read(fp) - magic = header['magic'] + magic = header["magic"] if magic != cls.MAGIC: - raise ValueError('Invalid magic: {}'.format(magic)) + raise ValueError("Invalid magic: {}".format(magic)) - endianity = cls.ENDIANITY_NAMES[header['endianity']] + endianity = cls.ENDIANITY_NAMES[header["endianity"]] - format_version = header['format_version'] + format_version = header["format_version"] # We read the header as little-endian before knowing the trace file # endianity. This matters for the only multi-bytes field in this # header: the format version. Swap its bytes if the endianity is # actually big endian. - if endianity == 'big-endian': + if endianity == "big-endian": format_version = swap_bytes(format_version, 4) if format_version != cls.FORMAT_VERSION: - raise ValueError('Unsupported format version: {}' - .format(format_version)) + raise ValueError( + "Unsupported format version: {}".format(format_version) + ) - alignment = header['alignment'] - if alignment not in (1, 2, 4, 8): - raise ValueError('Invalid alignment: {}'.format(alignment)) + alignment = header["alignment"] + if alignment not in (1, 2, 4, 8, 16): + raise ValueError("Invalid alignment: {}".format(alignment)) info_entries = [] entries = [] @@ -146,7 +147,7 @@ def read(cls, fp): while True: entry = TraceInfoEntry.read(fp, result, result.big_endian) - if entry.kind == 'end': + if entry.kind == "end": break info_entries.append(entry) @@ -160,44 +161,65 @@ def read(cls, fp): def write(self, fp): """Write this source trace to the `fp` file.""" - big_endian = self.endianity == 'big-endian' - - trace_file_header_struct.write(fp, { - 'magic': self.MAGIC, - 'format_version': self.FORMAT_VERSION, - 'alignment': self.alignment, - 'endianity': self.ENDIANITY_CODES[self.endianity], - 'padding': 0, - }, big_endian=big_endian) + big_endian = self.endianity == "big-endian" + + trace_file_header_struct.write( + fp, + { + "magic": self.MAGIC, + "format_version": self.FORMAT_VERSION, + "alignment": self.alignment, + "endianity": self.ENDIANITY_CODES[self.endianity], + "padding": 0, + }, + big_endian=big_endian, + ) for entry in self.info_entries: entry.write(fp, big_endian, self.alignment) - TraceInfoEntry('end', None).write(fp, big_endian, self.alignment) + TraceInfoEntry("end", None).write(fp, big_endian, self.alignment) for entry in self.entries: entry.write(fp, big_endian, self.alignment) def dump(self): def format_buffer(b): - bounds = ('[{}-{}]'.format(0, len(b.bits) - 1) - if len(b.bits) else '[empty range]') - content = (' '.join(str(i) for i, bit in enumerate(b.bits) if bit) - or '') - return '{} {}'.format(bounds, content) - - print('Source trace file:') - print(' Alignment: {}'.format(self.alignment)) - print(' Endianity: {}'.format(self.endianity)) - print('') + bounds = ( + "[{}-{}]".format(0, len(b.bits) - 1) + if len(b.bits) + else "[empty range]" + ) + content = ( + " ".join(str(i) for i, bit in enumerate(b.bits) if bit) + or "" + ) + return "{} {}".format(bounds, content) + + print("Source trace file:") + print(" Alignment: {}".format(self.alignment)) + print(" Endianity: {}".format(self.endianity)) + print("") for e in self.entries: - print(' Unit {} ({}, fingerprint={})'.format( - e.unit_name, e.unit_part, - ''.join('{:02x}'.format(b) for b in e.fingerprint))) - print(' Project: {}'.format(e.project_name)) - print(' Stmt buffer: {}'.format(format_buffer(e.stmt_buffer))) - print(' Dc buffer: {}'.format(format_buffer(e.dc_buffer))) - print(' MCDC buffer: {}'.format(format_buffer(e.mcdc_buffer))) - print('') + print( + ( + " Unit {} ({}, SCOS hash={}, bit maps hash={}, " + " annotations hash={})" + ).format( + e.unit_name, + e.unit_part, + "".join("{:02x}".format(b) for b in e.fingerprint), + "".join( + "{:02x}".format(b) for b in e.bit_maps_fingerprint + ), + "".join( + "{:02x}".format(b) for b in e.annotations_fingerprint + ), + ) + ) + print(" Stmt buffer: {}".format(format_buffer(e.stmt_buffer))) + print(" Dc buffer: {}".format(format_buffer(e.dc_buffer))) + print(" MCDC buffer: {}".format(format_buffer(e.mcdc_buffer))) + print("") class TraceInfoEntry(object): @@ -206,10 +228,10 @@ class TraceInfoEntry(object): """ KIND_NAMES = { - 0: 'end', - 1: 'program-name', - 2: 'exec-date', - 3: 'user-data', + 0: "end", + 1: "program-name", + 2: "exec-date", + 3: "user-data", } KIND_CODES = {value: key for key, value in KIND_NAMES.items()} @@ -223,27 +245,31 @@ def read(cls, fp, trace_file, big_endian): Read a trace info entry from the `fp` file. Return a TraceInfoEntry instance. """ - with fp.label_context('trace info'): + with fp.label_context("trace info"): header = trace_info_header_struct.read(fp, big_endian=big_endian) if not header: return None - kind = cls.KIND_NAMES[header['kind']] + kind = cls.KIND_NAMES[header["kind"]] - if kind == 'end' and header['length']: + if kind == "end" and header["length"]: raise ValueError('invalid "end" marker') - with fp.label_context('data'): - data = read_aligned(fp, header['length'], trace_file.alignment) + with fp.label_context("data"): + data = read_aligned(fp, header["length"], trace_file.alignment) return cls(kind, data) def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" - trace_info_header_struct.write(fp, { - 'kind': self.KIND_CODES[self.kind], - 'length': len(self.data) if self.data else 0, - }, big_endian=big_endian) + trace_info_header_struct.write( + fp, + { + "kind": self.KIND_CODES[self.kind], + "length": len(self.data) if self.data else 0, + }, + big_endian=big_endian, + ) if self.data: write_aligned(fp, self.data, alignment) @@ -254,32 +280,39 @@ class TraceEntry(object): """ UNIT_PART_NAMES = { - 0: 'not_applicable_part', - 1: 'body', - 2: 'spec', - 3: 'separate', + 0: "not_applicable_part", + 1: "body", + 2: "spec", + 3: "separate", } UNIT_PART_CODES = {value: key for key, value in UNIT_PART_NAMES.items()} - LANGUAGE_NAMES = { - 0: 'unit_based', - 1: 'file_based' - } + LANGUAGE_NAMES = {0: "unit_based", 1: "file_based"} LANGUAGE_CODES = {value: key for key, value in LANGUAGE_NAMES.items()} - BIT_BUFFER_ENCODING_NAMES = { - 0: 'lsb_first_bytes' - } + BIT_BUFFER_ENCODING_NAMES = {0: "lsb_first_bytes"} BIT_BUFFER_ENCODING_CODES = { - value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items()} + value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items() + } - def __init__(self, language, unit_part, unit_name, project_name, - fingerprint, stmt_buffer, dc_buffer, mcdc_buffer): + def __init__( + self, + language, + unit_part, + unit_name, + fingerprint, + bit_maps_fingerprint, + annotations_fingerprint, + stmt_buffer, + dc_buffer, + mcdc_buffer, + ): self.language = language self.unit_part = unit_part self.unit_name = unit_name - self.project_name = project_name self.fingerprint = fingerprint + self.bit_maps_fingerprint = bit_maps_fingerprint + self.annotations_fingerprint = annotations_fingerprint self.stmt_buffer = stmt_buffer self.dc_buffer = dc_buffer self.mcdc_buffer = mcdc_buffer @@ -289,66 +322,83 @@ def read(cls, fp, trace_file, big_endian): """ Read a trace entry from the `fp` file. Return a TraceFile instance. """ - with fp.label_context('trace entry'): + with fp.label_context("trace entry"): header = trace_entry_header_struct.read(fp, big_endian=big_endian) if not header: return None - unit_part = cls.UNIT_PART_NAMES[header['unit_part']] + unit_part = cls.UNIT_PART_NAMES[header["unit_part"]] - language = cls.LANGUAGE_NAMES[header['language']] + language = cls.LANGUAGE_NAMES[header["language"]] - if header['padding'] != (0, ) * 5: - raise ValueError('Invalid padding: {}' - .format(header['padding'])) + if header["padding"] != 0: + raise ValueError( + "Invalid padding: {}".format(header["padding"]) + ) bit_buffer_encoding = cls.BIT_BUFFER_ENCODING_NAMES[ - header['bit_buffer_encoding']] + header["bit_buffer_encoding"] + ] - with fp.label_context('unit name'): + with fp.label_context("unit name"): unit_name = read_aligned( - fp, header['unit_name_length'], trace_file.alignment) + fp, header["unit_name_length"], trace_file.alignment + ) - with fp.label_context('project name'): - project_name = (read_aligned(fp, header['project_name_length'], - trace_file.alignment) - or "") - - with fp.label_context('stmt buffer'): + with fp.label_context("stmt buffer"): stmt_buffer = TraceBuffer.read( - fp, trace_file, bit_buffer_encoding, - header['stmt_bit_count']) - with fp.label_context('dc buffer'): + fp, + trace_file, + bit_buffer_encoding, + header["stmt_bit_count"], + ) + with fp.label_context("dc buffer"): dc_buffer = TraceBuffer.read( - fp, trace_file, bit_buffer_encoding, - header['dc_bit_count']) - with fp.label_context('mcdc buffer'): + fp, trace_file, bit_buffer_encoding, header["dc_bit_count"] + ) + with fp.label_context("mcdc buffer"): mcdc_buffer = TraceBuffer.read( - fp, trace_file, bit_buffer_encoding, - header['mcdc_bit_count']) - - return cls(language, unit_part, unit_name, project_name, - header['fingerprint'], stmt_buffer, dc_buffer, - mcdc_buffer) + fp, + trace_file, + bit_buffer_encoding, + header["mcdc_bit_count"], + ) + + return cls( + language, + unit_part, + unit_name, + header["fingerprint"], + header["bit_maps_fingerprint"], + header["annotations_fingerprint"], + stmt_buffer, + dc_buffer, + mcdc_buffer, + ) def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" - trace_entry_header_struct.write(fp, { - 'unit_name_length': len(self.unit_name), - 'project_name_length': len(self.project_name), - 'stmt_bit_count': len(self.stmt_buffer.bits), - 'dc_bit_count': len(self.dc_buffer.bits), - 'mcdc_bit_count': len(self.mcdc_buffer.bits), - 'language': self.LANGUAGE_CODES[self.language], - 'unit_part': self.UNIT_PART_CODES[self.unit_part], - 'bit_buffer_encoding': - self.BIT_BUFFER_ENCODING_CODES['lsb_first_bytes'], - 'fingerprint': self.fingerprint, - 'padding': (0, ) * 5, - }, big_endian=big_endian) + trace_entry_header_struct.write( + fp, + { + "unit_name_length": len(self.unit_name), + "stmt_bit_count": len(self.stmt_buffer.bits), + "dc_bit_count": len(self.dc_buffer.bits), + "mcdc_bit_count": len(self.mcdc_buffer.bits), + "language": self.LANGUAGE_CODES[self.language], + "unit_part": self.UNIT_PART_CODES[self.unit_part], + "bit_buffer_encoding": self.BIT_BUFFER_ENCODING_CODES[ + "lsb_first_bytes" + ], + "fingerprint": self.fingerprint, + "bit_maps_fingerprint": self.bit_maps_fingerprint, + "annotations_fingerprint": self.annotations_fingerprint, + "padding": 0, + }, + big_endian=big_endian, + ) write_aligned(fp, self.unit_name, alignment) - write_aligned(fp, self.project_name, alignment) self.stmt_buffer.write(fp, alignment) self.dc_buffer.write(fp, alignment) @@ -376,7 +426,7 @@ def byte_count(bit_count): @classmethod def read(cls, fp, trace_file, bit_buffer_encoding, bit_count): - assert bit_buffer_encoding == 'lsb_first_bytes' + assert bit_buffer_encoding == "lsb_first_bytes" bytes_count = cls.byte_count(bit_count) bytes_and_padding = read_aligned(fp, bytes_count, trace_file.alignment) @@ -409,15 +459,16 @@ def write(self, fp, alignment): write_aligned(fp, bytes(byte for byte in buffer), alignment) -parser = argparse.ArgumentParser('Decode a source trace file') -parser.add_argument('--debug', '-d', action='store_true', - help='Enable debug traces') -parser.add_argument('trace-file', help='Source trace file to decode') +parser = argparse.ArgumentParser("Decode a source trace file") +parser.add_argument( + "--debug", "-d", action="store_true", help="Enable debug traces" +) +parser.add_argument("trace-file", help="Source trace file to decode") -if __name__ == '__main__': +if __name__ == "__main__": args = parser.parse_args() - with open(getattr(args, 'trace-file'), 'rb') as f: + with open(getattr(args, "trace-file"), "rb") as f: tf = SrcTraceFile.read(ByteStreamDecoder(f, args.debug)) tf.dump() diff --git a/testsuite/SUITE/stream_decoder.py b/testsuite/SUITE/stream_decoder.py index 9c0040134..ab75d78ec 100644 --- a/testsuite/SUITE/stream_decoder.py +++ b/testsuite/SUITE/stream_decoder.py @@ -6,7 +6,7 @@ def swap_bytes(number, size): """Swap bytes in ``number``, assumed to be ``size``-bytes large.""" result = 0 for _ in range(size): - result = (result << 8) | (number & 0xff) + result = (result << 8) | (number & 0xFF) number = number >> 8 return result @@ -17,7 +17,7 @@ class ByteStreamDecoder(object): """ BYTES_PER_LINE = 16 - INDENT = ' ' + INDENT = " " def __init__(self, stream, enabled=False, max_indent=0): """ @@ -41,7 +41,7 @@ def _print(self, message, *args, **kwargs): return if args or kwargs: message = message.format(*args, **kwargs) - print('{}{}'.format(self._indent_prefix, message)) + print("{}{}".format(self._indent_prefix, message)) @contextmanager def label_context(self, label): @@ -51,7 +51,7 @@ def label_context(self, label): :param str label: Label to use. """ - self._print('{} ({:#0x}):', label, self.offset) + self._print("{} ({:#0x}):", label, self.offset) self.label_stack.append(label) yield self.label_stack.pop() @@ -63,7 +63,7 @@ def read(self, size): :param int size: Number of bytes to read. :rtype: str """ - bytes = self.stream.read(size) + byte_str = self.stream.read(size) if self.enabled: # Two characters per byte and one space in between. Adjust to # account for the maximum indentation. @@ -72,27 +72,28 @@ def read(self, size): reserved_indent = self.max_indent - len(self.label_stack) bytes_part_size += max(0, len(self.INDENT) * reserved_indent) - # Number of lines to represent bytes - lines_count = (len(bytes) + self.BYTES_PER_LINE - - 1) // self.BYTES_PER_LINE + # Number of lines to represent byte_str + lines_count = ( + len(byte_str) + self.BYTES_PER_LINE - 1 + ) // self.BYTES_PER_LINE for line in range(lines_count): start_byte = line * self.BYTES_PER_LINE end_byte = (line + 1) * self.BYTES_PER_LINE - bytes_slice = bytes[start_byte:end_byte] + bytes_slice = byte_str[start_byte:end_byte] - bytes_part = ' '.join( - '{:02x}'.format(b) for b in bytes_slice + bytes_part = " ".join( + "{:02x}".format(b) for b in bytes_slice ).ljust(bytes_part_size) - ascii_part = ''.join( - chr(ord('.') if b < ord(' ') or b > ord('~') else b) + ascii_part = "".join( + chr(ord(".") if b < ord(" ") or b > ord("~") else b) for b in bytes_slice ) - self._print('{} | {}'.format(bytes_part, ascii_part)) - self.offset += len(bytes) - return bytes + self._print("{} | {}".format(bytes_part, ascii_part)) + self.offset += len(byte_str) + return byte_str class Struct(object): @@ -108,13 +109,15 @@ def __init__(self, label, *fields): :type fields: list[(str, str)] """ self.label = label - self.le_fields = [(name, struct.Struct('<' + fmt)) - for name, fmt in fields] - self.be_fields = [(name, struct.Struct('>' + fmt)) - for name, fmt in fields] + self.le_fields = [ + (name, struct.Struct("<" + fmt)) for name, fmt in fields + ] + self.be_fields = [ + (name, struct.Struct(">" + fmt)) for name, fmt in fields + ] def _fields(self, big_endian=False): - return (self.be_fields if big_endian else self.le_fields) + return self.be_fields if big_endian else self.le_fields def read(self, fp, big_endian=False): """ @@ -148,22 +151,26 @@ def write(self, fp, field_values, big_endian=False): field_values = [dict_field_values.pop(name) for name, _ in fields] unknown_fields = sorted(dict_field_values) if unknown_fields: - raise ValueError('Unknown fields: {}' - .format(' '.join(unknown_fields))) + raise ValueError( + "Unknown fields: {}".format(" ".join(unknown_fields)) + ) if len(field_values) != len(fields): - raise ValueError('{} fields expected, got {}' - .format(len(fields), len(field_values))) + raise ValueError( + "{} fields expected, got {}".format( + len(fields), len(field_values) + ) + ) for value, (_, structure) in zip(field_values, fields): - pack_args = value if isinstance(value, tuple) else (value, ) + pack_args = value if isinstance(value, tuple) else (value,) fp.write(structure.pack(*pack_args)) -if __name__ == '__main__': +if __name__ == "__main__": assert swap_bytes(0, 1) == 0 assert swap_bytes(0, 2) == 0 assert swap_bytes(1, 1) == 1 assert swap_bytes(1, 2) == 0x100 - assert swap_bytes(0xff, 2) == 0xff00 - assert swap_bytes(-1, 2) == 0xffff + assert swap_bytes(0xFF, 2) == 0xFF00 + assert swap_bytes(-1, 2) == 0xFFFF diff --git a/testsuite/SUITE/tgen.py b/testsuite/SUITE/tgen.py index 5a142a0a0..308b447d2 100644 --- a/testsuite/SUITE/tgen.py +++ b/testsuite/SUITE/tgen.py @@ -8,7 +8,7 @@ def body_lines(lines): - return '\n'.join(lines) + '\n' + return "\n".join(lines) + "\n" class Evaluator: @@ -18,35 +18,42 @@ def __init__(self, expr, context): class Ada_Evaluator(Evaluator): - def __init__(self, expr, context): Evaluator.__init__(self, expr, context) def package_spec(self): - return (body_lines(["package This_Evaluator is"]) + - self.expr.predefs() + - body_lines(["end;"])) + return ( + body_lines(["package This_Evaluator is"]) + + self.expr.predefs() + + body_lines(["end;"]) + ) def package_body(self): - return (body_lines(["package body This_Evaluator is"]) + - self.proc_body() + - body_lines(["end;"])) + return ( + body_lines(["package body This_Evaluator is"]) + + self.proc_body() + + body_lines(["end;"]) + ) def proc_formals(self): - return ', '.join("%s : %s" % (op.formal_name, op.formal_type) - for op in expr.op) + return ", ".join( + "%s : %s" % (op.formal_name, op.formal_type) for op in expr.op + ) def proc_body_start(self): - return body_lines(["procedure Eval (%s) is" % (self.proc_formals()), - "begin"]) + return body_lines( + ["procedure Eval (%s) is" % (self.proc_formals()), "begin"] + ) def proc_body_end(self): return body_lines(["end;"]) def proc_body(self): - return (self.proc_body_start() + - self.context.body_for(expr=self.expr) + - self.proc_body_end()) + return ( + self.proc_body_start() + + self.context.body_for(expr=self.expr) + + self.proc_body_end() + ) class OP: @@ -81,8 +88,9 @@ def __init__(self, opclasses): self.vectors = None self.next_arg_index = 0 - self.op = [opclass(formal_name=self.next_arg_name()) - for opclass in opclasses] + self.op = [ + opclass(formal_name=self.next_arg_name()) for opclass in opclasses + ] self.opclass_set = set(opclasses) @@ -95,7 +103,7 @@ def body(self): return "EXPR_NOBODY" def predefs(self): - return '\n'.join(opclass.predefs() for opclass in self.opclass_set) + return "\n".join(opclass.predefs() for opclass in self.opclass_set) class EXPR_And(EXPR): @@ -131,12 +139,15 @@ def body_for(self, expr): class CTX_AdaIf(Context): def body_for(self, expr): - return body_lines([ - "if %s then -- # eval-all :d:" % expr.body(), - " return True; -- # on-true", - "else", - " return False; -- # on-false", - "end if;"]) + return body_lines( + [ + "if %s then -- # eval-all :d:" % expr.body(), + " return True; -- # on-true", + "else", + " return False; -- # on-false", + "end if;", + ] + ) class Tcgen: @@ -155,8 +166,7 @@ def __init__(self, xprname, opkinds, vectors, lang): del op_classnames -expr = EXPR_Ada_AndThen(op0_class=OP_Ada_Bool, - op1_class=OP_Ada_Bool) +expr = EXPR_Ada_AndThen(op0_class=OP_Ada_Bool, op1_class=OP_Ada_Bool) for ctx in [CTX_AdaIf, CTX_AdaReturn]: aev = Ada_Evaluator(expr=expr, context=ctx()) diff --git a/testsuite/SUITE/tracelib.py b/testsuite/SUITE/tracelib.py index 2d27f0fb9..066aa0819 100644 --- a/testsuite/SUITE/tracelib.py +++ b/testsuite/SUITE/tracelib.py @@ -39,10 +39,8 @@ def check(cls, value): """ Assert that `value` is in `cls`'s range. """ - assert cls.in_range(value), 'Invalid {}: {} not in {} .. {}'.format( - cls.__name__, - value, - cls.RANGE[0], cls.RANGE[1] + assert cls.in_range(value), "Invalid {}: {} not in {} .. {}".format( + cls.__name__, value, cls.RANGE[0], cls.RANGE[1] ) @@ -50,6 +48,7 @@ class TraceKind(Enum): """ Kind of trace file. See Trace_Kind in qemu_traces.ads. """ + Flat = 0 History = 1 Info = 2 @@ -62,6 +61,7 @@ class InfoKind(Enum): """ Kind of trace information record. See Info_Kind_Type in qemu_traces.ads. """ + InfoEnd = 0 ExecFileName = 1 CoverageOptions = 2 @@ -81,6 +81,7 @@ class TraceOp(Enum): """ Trace operation bitmasks. See Trace_Op_* in qemu_traces.ads. """ + Block = 0x10 Fault = 0x20 Br0 = 0x01 @@ -88,9 +89,13 @@ class TraceOp(Enum): Special = 0x80 # Helper for the format_flags method, below - flag_chars = [(Block, 'B'), (Fault, 'F'), - (Br0, 'b'), (Br1, 'f'), - (Special, 's')] + flag_chars = [ + (Block, "B"), + (Fault, "F"), + (Br0, "b"), + (Br1, "f"), + (Special, "s"), + ] @classmethod def format_flags(cls, flags): @@ -104,14 +109,16 @@ def format_flags(cls, flags): :param int flags: Integer value for the TraceOp to decode. This is the integer that is read directly from the trace file. """ - return ''.join(char if flags & v else '-' - for v, char in cls.flag_images) + return "".join( + char if flags & v else "-" for v, char in cls.flag_images + ) class TraceSpecial(Enum): """ Special trace operations. See Trace_Special_* in qemu_traces.ads. """ + Loadaddr = 1 LoadSharedObject = 2 UnloadSharedObject = 3 @@ -119,7 +126,7 @@ class TraceSpecial(Enum): RANGE = (1, 3) -TRACE_MAGIC = b'#QEMU-Traces' +TRACE_MAGIC = b"#QEMU-Traces" """ Exepected value of the Magic header field. See Qemu_Trace_Magic in qemu_traces.ads. @@ -143,55 +150,49 @@ def create_trace_header(kind, pc_size, big_endian, machine): pc_size, big_endian, machine >> 8, - machine & 0xff, - 0 + machine & 0xFF, + 0, ) TraceHeaderStruct = Struct( - 'trace file header', - + "trace file header", # See Trace_Header in qemu_traces.ads - ('magic', '12s'), - ('version', 'B'), - ('kind', 'B'), - - ('sizeof_target_pc', 'B'), - ('big_endian', 'B'), - - ('machine_hi', 'B'), - ('machine_lo', 'B'), - ('padding', 'H'), + ("magic", "12s"), + ("version", "B"), + ("kind", "B"), + ("sizeof_target_pc", "B"), + ("big_endian", "B"), + ("machine_hi", "B"), + ("machine_lo", "B"), + ("padding", "H"), ) TraceInfoHeaderStruct = Struct( - 'trace info header', - + "trace info header", # See Trace_Info_Header in qemu_traces.ads - ('kind', 'I'), - ('length', 'I'), + ("kind", "I"), + ("length", "I"), ) TraceEntry32Struct = Struct( - 'trace entry 32', - + "trace entry 32", # See Trace_Entry32 in qemu_traces.ads - ('pc', 'I'), - ('size', 'H'), - ('op', 'B'), - ('padding', 'B'), + ("pc", "I"), + ("size", "H"), + ("op", "B"), + ("padding", "B"), ) TraceEntry64Struct = Struct( - 'trace entry 64', - + "trace entry 64", # See Trace_Entry64 in qemu_traces.ads - ('pc', 'Q'), - ('size', 'H'), - ('op', 'B'), - ('padding0', 'B'), - ('padding1', 'I'), + ("pc", "Q"), + ("size", "H"), + ("op", "B"), + ("padding0", "B"), + ("padding1", "I"), ) @@ -301,8 +302,8 @@ def iter_entries(self, raw=False): while True: loadaddr = next(entries) if ( - loadaddr.is_special and - loadaddr.size == TraceSpecial.Loadaddr + loadaddr.is_special + and loadaddr.size == TraceSpecial.Loadaddr ): offset = loadaddr.pc break @@ -358,27 +359,27 @@ def read(cls, fp): Read a trace info entry from the `fp` file. Return a TraceInfo instance. """ - with fp.label_context('trace info'): + with fp.label_context("trace info"): hdr = unpack_from_file(fp, TraceInfoHeaderStruct) assert hdr kind, length = hdr InfoKind.check(kind) - with fp.label_context('data'): + with fp.label_context("data"): data = fp.read(length) assert len(data) == length - with fp.label_context('padding'): + with fp.label_context("padding"): padding_size = cls.padding_size(len(data)) padding = fp.read(padding_size) - assert len(padding) == padding_size, ( - 'Expected {} padding bytes but got {}'.format( - padding_size, len(padding) - ) - ) - assert padding == (b'\x00' * padding_size), ( - 'Some padding bytes are non-null: {}'.format(repr(padding)) + assert ( + len(padding) == padding_size + ), "Expected {} padding bytes but got {}".format( + padding_size, len(padding) ) + assert padding == ( + b"\x00" * padding_size + ), "Some padding bytes are non-null: {}".format(repr(padding)) return cls(kind, data) @@ -388,7 +389,7 @@ def write(self, fp): """ TraceInfoHeaderStruct.write(fp, (self.kind, len(self.data))) fp.write(self.data) - fp.write(b'\x00' * self.padding_size(len(self.data))) + fp.write(b"\x00" * self.padding_size(len(self.data))) class TraceInfoList(object): @@ -473,7 +474,7 @@ def read(cls, fp, bits): """ Read a trace entry from the `fp` file. Return a TraceEntry instance. """ - with fp.label_context('trace entry'): + with fp.label_context("trace entry"): fields = unpack_from_file(fp, cls.struct(bits)) if not fields: return None @@ -516,38 +517,38 @@ def create_exec_infos(filename, code_size=None): :rtype: TraceInfoList """ stat = os.stat(filename) - with open(filename, 'rb') as f: + with open(filename, "rb") as f: f_contents = f.read() - crc32 = binascii.crc32(f_contents) & 0xffffffff - mtime = datetime.datetime.utcfromtimestamp( - int(stat.st_mtime) - ) + crc32 = binascii.crc32(f_contents) & 0xFFFFFFFF + mtime = datetime.datetime.utcfromtimestamp(int(stat.st_mtime)) def create_trace_info(kind, data_str): - return TraceInfo(kind, data_str.encode('utf-8')) + return TraceInfo(kind, data_str.encode("utf-8")) infos = [ create_trace_info(InfoKind.ExecFileName, filename), - create_trace_info(InfoKind.ExecFileSize, ' ' + str(stat.st_size)), - create_trace_info(InfoKind.ExecTimeStamp, mtime.isoformat(' ')), - create_trace_info(InfoKind.ExecFileCRC32, ' ' + str(crc32)), + create_trace_info(InfoKind.ExecFileSize, " " + str(stat.st_size)), + create_trace_info(InfoKind.ExecTimeStamp, mtime.isoformat(" ")), + create_trace_info(InfoKind.ExecFileCRC32, " " + str(crc32)), ] if code_size: - infos.append(create_trace_info(InfoKind.ExecCodeSize, - ' ' + str(code_size))) + infos.append( + create_trace_info(InfoKind.ExecCodeSize, " " + str(code_size)) + ) return TraceInfoList({info.kind: info for info in infos}) -parser = argparse.ArgumentParser('Decode a binary trace file') -parser.add_argument('--debug', '-d', action='store_true', - help='Enable debug traces') -parser.add_argument('trace-file', help='Binary trace file to decode') +parser = argparse.ArgumentParser("Decode a binary trace file") +parser.add_argument( + "--debug", "-d", action="store_true", help="Enable debug traces" +) +parser.add_argument("trace-file", help="Binary trace file to decode") -if __name__ == '__main__': +if __name__ == "__main__": args = parser.parse_args() - with open(getattr(args, 'trace-file'), 'rb') as f: + with open(getattr(args, "trace-file"), "rb") as f: tf = TraceFile.read(ByteStreamDecoder(f, args.debug, 4)) # TODO: add trace-file dump capabilities diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index ee52d89e0..dc5138ee1 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -8,38 +8,108 @@ # *************************************************************************** +from dataclasses import dataclass import glob import os +import re +import sys import time -from e3.os.fs import touch, unixpath -from e3.os.process import DEVNULL, Run +from e3.fs import cp +from e3.os.fs import touch, unixpath, which +from e3.os.process import Run -# Expose a few other items as a test util-facilities as well +# Expose a few other items as a test util facilities as well from SUITE import control -from SUITE.control import (BUILDER, KNOWN_LANGUAGES, env, language_info, - xcov_pgm) +from SUITE.control import ( + BUILDER, + KNOWN_LANGUAGES, + env, + gnatemu_board_name, + language_info, + xcov_pgm, +) from SUITE.context import ROOT_DIR, thistest +# Then mind our own business -# Then mind our own buisness - -from SUITE.cutils import FatalError, contents_of, text_to_file, to_list +from SUITE.cutils import ( + FatalError, + contents_of, + indent, + list_to_file, + text_to_file, + to_list, + unhandled_exception_in, + Wdir, +) # Precompute some values we might be using repeatedly TARGET_INFO = control.target_info() RUNTIME_INFO = control.runtime_info() +GNATCOV_INFO = control.gnatcov_info() XCOV = xcov_pgm(thistest.options.auto_arch) -VALGRIND = 'valgrind' + env.host.os.exeext - -MEMCHECK_LOG = 'memcheck.log' -CALLGRIND_LOG = 'callgrind-{}.log' +VALGRIND = "valgrind" + env.host.os.exeext + +MEMCHECK_LOG = "memcheck.log" +CALLGRIND_LOG = "callgrind-{}.log" + +# Pattern to match the line in gprls' verbose output that specifies the full +# path to the project file to analyze. +GPRLS_PARSING_RE = re.compile(r'^.*\.gpr: info: Parsing "(.*)"$') + +# ---------------------------------------------------------------------------- +# Notes on program and command execution paths +# +# Our tests execute lots of commands to instrument and build programs, to run +# the programs themselves, to produce reports from coverage traces. +# +# For robustness, we strive to minimize the paths controlling such executions +# within the testsuite. This lets us place important checks at critical spots +# and retain confidence in what we are testing as the testsuite grows. +# +# Of particular interest are the paths used to execute test programs as the +# notion of exit status may vary across execution environments and extra +# checks on the program outputs are sometimes needed to detect some kinds of +# failures. +# +# Here's a sketch of how various functions/methods cooperate for src/bin +# trace modes and cross/native configurations. _Please_ keep the general +# issue in mind when considering changes in this area. +# +# [test.py(bin)] [test.py(bin/src)] +# | build_and_run +# v | | +# o-------(bin)---o o----(src)-------o +# | | +# | | +# | [driver.py(bin/src)] | +# | mode_execute | +# | | | | +# | o----(bin)---o o---(src)----o | +# | | | | +# v v | | +# xrun | | +# | | | +# v | | +# xcov v v +# | run_cov_program +# | | +# | gnatcov run pgm | pgm (native) +# | (now cross only) | -gnatemu pgm (cross) +# | | +# o-------------o o------------o +# | | +# v v +# cmdrun +# +# ---------------------------------------------------------------------------- run_processes = [] """ @@ -59,7 +129,7 @@ def run_and_log(*args, **kwargs): # Register the command for this process as well as the time it took to run # it. try: - cmd = kwargs['cmds'] + cmd = kwargs["cmds"] except KeyError: cmd = args[0] p.original_cmd = cmd @@ -69,9 +139,18 @@ def run_and_log(*args, **kwargs): return p -def gprbuild_gargs_with(thisgargs, - trace_mode=None, - runtime_project=None): +def effective_trace_mode(override_trace_mode): + """ + Compute the effective trace mode to be used from override_trace_mode + if available, or from the testsuite options otherwise. + """ + if override_trace_mode is None: + return thistest.options.trace_mode + else: + return override_trace_mode + + +def gprbuild_gargs_with(thisgargs, trace_mode=None, runtime_project=None): """ Compute and return all the toplevel gprbuild arguments to pass. Account for specific requests in THISGARGS. @@ -82,32 +161,25 @@ def gprbuild_gargs_with(thisgargs, If RUNTIME_PROJECT is not null, it will be used as the name of the instrumentation runtime project in source trace mode. """ - trace_mode = trace_mode or thistest.options.trace_mode + trace_mode = effective_trace_mode(trace_mode) # Force a few bits useful for practical reasons and without influence on # code generation result = [ - '-f', # always rebuild - '-XSTYLE_CHECKS=', # style checks off - '-p' # create missing directories (obj, typically) + "-f", # always rebuild + "-XSTYLE_CHECKS=", # style checks off + "-p", # create missing directories (obj, typically) ] - - # Add our testsuite configuration options (selecting target model and board - # essentially). - result.extend(thistest.gprconfoptions) - result.extend(thistest.gprvaroptions) result.extend(to_list(thisgargs)) # If we work with source instrumentation, add the dependency on the # instrumentation runtime project so that instrumented programs are # compilable in the generated projects. Also use instrumented sources in # the "*-gnatcov-instr" object directories. - if trace_mode == 'src': - runtime_project = ( - runtime_project or RUNTIME_INFO.gnatcov_rts_project - ) + if trace_mode == "src": + runtime_project = runtime_project or RUNTIME_INFO.gnatcov_rts_project result += [ - f"--implicit-with={runtime_project}.gpr", + f"--implicit-with={runtime_project}", "--src-subdirs=gnatcov-instr", ] @@ -129,10 +201,12 @@ def gprbuild_cargs_with(thiscargs, scovcargs=True, suitecargs=True): if thistest.options.qualif_level: thistest.stop_if( not scovcargs, - FatalError("SCOV_CARGS required for qualification test")) + FatalError("SCOV_CARGS required for qualification test"), + ) thistest.stop_if( thiscargs, - FatalError("Specific CARGS forbidden for qualification test")) + FatalError("Specific CARGS forbidden for qualification test"), + ) # Compute the language specific cargs, from testsuite args first: @@ -166,7 +240,7 @@ def gprbuild_cargs_with(thiscargs, scovcargs=True, suitecargs=True): other_cargs.extend(to_list(thiscargs)) if other_cargs: - other_cargs = ['-cargs'] + other_cargs + other_cargs = ["-cargs"] + other_cargs return lang_cargs + other_cargs @@ -182,26 +256,67 @@ def gprbuild_largs_with(thislargs): # On Windows, executables are made position independent by default, which # gnatcov does not handle, so instruct the linker to not create position # independent executables if running in bin trace mode. - if (thistest.env.build.os.name == 'windows' - and thistest.options.trace_mode == 'bin'): - all_largs.append('-no-pie') + if ( + thistest.env.build.os.name == "windows" + and thistest.options.trace_mode == "bin" + ): + all_largs.append("-no-pie") if all_largs: - all_largs.insert(0, '-largs') + all_largs.insert(0, "-largs") return all_largs -def gprbuild(project, - scovcargs=True, - suitecargs=True, - extracargs=None, - gargs=None, - largs=None, - trace_mode=None, - runtime_project=None, - out='gprbuild.out', - register_failure=True): +def gpr_common_args(project, auto_config_args=True): + """ + Return common GPR tools options for the current testsuite run. + + :param auto_config_args: if False, do not add the --config argument. + """ + gproptions = [] + + # If running in qualif mode, run with the verbose switch for verifiability + if thistest.options.qualif_level: + gproptions.append("-v") + if auto_config_args: + gproptions.append( + "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) + ) + + # Workaround a desynchronization between default build configuration + # for TMS570 and GNATemulator's settings: see O519-032. We may get rid + # of this kludge one day adapting GNATemulator. + if thistest.options.RTS and thistest.options.RTS.endswith("-tms570"): + gproptions.append("-XLOADER=LORAM") + + # For trace32 runs where the test is executed on a real board, we + # choose to have both the code and data in RAM. The default is to run + # from flash which would take more time for the probe to program. It + # would also wear out the flash memory. + if ( + thistest.options.gnatcov_run + and "trace32" in thistest.options.gnatcov_run + ): + gproptions.append("-XLOADER=RAM") + + # Add runtime specific scenario variables + return gproptions + RUNTIME_INFO.gpr_scenario_vars + + +def gprbuild( + project, + scovcargs=True, + suitecargs=True, + extracargs=None, + gargs=None, + largs=None, + trace_mode=None, + runtime_project=None, + out="gprbuild.out", + register_failure=True, + auto_config_args=True, +): """ Cleanup & build the provided PROJECT file using gprbuild, passing GARGS/CARGS/LARGS as gprbuild/cargs/largs command-line switches. Each @@ -220,6 +335,8 @@ def gprbuild(project, Stop with a FatalError if the execution status is not zero and REGISTER_FAILURE is True. Return the process descriptor otherwise. + + If AUTO_CONFIG_ARGS is False, do not pass the --config argument. """ # Fetch options, from what is requested specifically here @@ -230,41 +347,73 @@ def gprbuild(project, runtime_project=runtime_project, ) all_largs = gprbuild_largs_with(thislargs=largs) - all_cargs = gprbuild_cargs_with(scovcargs=scovcargs, - suitecargs=suitecargs, - thiscargs=extracargs) + all_cargs = gprbuild_cargs_with( + scovcargs=scovcargs, suitecargs=suitecargs, thiscargs=extracargs + ) + common_args = gpr_common_args(project, auto_config_args) # Now cleanup, do build and check status - thistest.cleanup(project) - args = (to_list(BUILDER.BASE_COMMAND) + - ['-P%s' % project] + all_gargs + all_cargs + all_largs) - p = run_and_log(args, output=out, timeout=thistest.options.timeout) + # TODO (gpr-issues#241) Temporary workaround for the gprclean problem + # As gpr2clean currently deletes .sid files, we should not call + # gprclean between the instrumentation and the build. + if effective_trace_mode(trace_mode) == "bin": + thistest.cleanup(project, common_args) + + # lookup the hook for the executable name without extension + builder = thistest.suite_gprpgm_for( + os.path.splitext(os.path.basename(BUILDER.BASE_COMMAND))[0] + ) + + has_altrun = builder is not None + + if builder is None: + builder = BUILDER.BASE_COMMAND + + args = ( + to_list(builder) + + ["-P%s" % project] + + common_args + + all_gargs + + all_cargs + + all_largs + ) + # If there is an altrun hook for gprbuild, it may be a script. + # Instruct the Run primitive to parse the shebang to invoke the correct + # interpreter in that case. + p = run_and_log( + args, + output=out, + timeout=thistest.options.timeout, + parse_shebang=has_altrun, + ) if register_failure: - thistest.stop_if(p.status != 0, - FatalError("gprbuild exit in error", out)) + thistest.stop_if( + p.status != 0, FatalError("gprbuild exit in error", out) + ) return p -def gprinstall(project, prefix=None): +def gprinstall(project, gargs=None): """ Run "gprinstall" on the provided project file. - :param None|str prefix: If a string is passed, add `--prefix=PREFIX` to the - gprinstall command-line. + :param None|list[str] gargs: list of command line switches to pass to + gprinstall """ - ofile = 'gprinstall.out' - args = ['gprinstall', '-P', project, '-p'] - if prefix: - args.append('--prefix={}'.format(prefix)) + ofile = "gprinstall.out" + args = ["gprinstall", "-P", project, "-p"] # Add mandatory options, such as target and RTS info - args.extend(thistest.gprconfoptions) - args.extend(thistest.gprvaroptions) + args.extend(gpr_common_args(project)) + + # Add user-provided arguments + args.extend(to_list(gargs)) p = run_and_log(args, output=ofile, timeout=thistest.options.timeout) - thistest.stop_if(p.status != 0, - FatalError('gprinstall exit in error', ofile)) + thistest.stop_if( + p.status != 0, FatalError("gprinstall exit in error", ofile) + ) def gpr_emulator_package(): @@ -272,15 +421,30 @@ def gpr_emulator_package(): If there is a board name, return a package Emulator to be included in a GPR file to provide this information to GNATemulator. """ - return ('package Emulator is\n' - ' for Board use "{}";\n' - 'end Emulator;'.format(env.target.machine) - if env.target.machine else '') + gnatemu_board = gnatemu_board_name(env.target.machine) + return ( + "package Emulator is\n" + ' for Board use "{}";\n' + "end Emulator;".format(gnatemu_board) + if gnatemu_board + else "" + ) -def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", - main_cargs=None, langs=None, deps=(), scenario_extra="", - compiler_extra="", extra=""): +def gprfor( + mains, + prjid="gen", + srcdirs="src", + objdir=None, + exedir=".", + main_cargs=None, + langs=None, + deps=None, + scenario_extra="", + compiler_extra="", + extra="", + cwd=None, +): """ Generate a simple PRJID.gpr project file to build executables for each main source file in the MAINS list, sources in SRCDIRS. Inexistant directories @@ -290,9 +454,15 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", COMPILER_EXTRA, if any, at the end of the Compiler package contents. Add EXTRA, if any, at the end of the project file contents. Return the gpr file name. + + If CWD is None, generate the project file in the current directory. + Generate it in the CWD directory otherwise. + + If PRJID contains any '.', they are replaced by '-' in the project + filename. """ - deps = '\n'.join('with "%s";' % dep for dep in deps) + cwd = cwd or os.getcwd() mains = to_list(mains) srcdirs = to_list(srcdirs) langs = to_list(langs) @@ -304,31 +474,53 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # Turn the list of main sources into the proper comma separated sequence # of string literals for the Main GPR attribute. - gprmains = ', '.join('"%s"' % m for m in mains) + gprmains = ", ".join('"%s"' % m for m in mains) if gprmains: - gprmains = 'for Main use (%s);' % gprmains + gprmains = "for Main use (%s);" % gprmains # Likewise for source dirs. Filter on existence, to allow widening the set # of tentative dirs while preventing complaints from gprbuild about # inexistent ones. - srcdirs_list = [d for d in srcdirs if os.path.exists(d)] + srcdirs_list = [d for d in srcdirs if os.path.exists(os.path.join(cwd, d))] # Determine the language(s) from the sources if they are not explicitly # passed as parameters. if not langs: - lang_infos = [language_info(src) - for srcdir in srcdirs_list - for src in os.listdir(srcdir)] - langs = set(li.name for li in lang_infos if li) + lang_infos = [ + language_info(src) + for srcdir in srcdirs_list + for src in os.listdir(os.path.join(cwd, srcdir)) + ] + langs = {li.name for li in lang_infos if li and li.in_gpr} + + srcdirs = ", ".join('"%s"' % d for d in srcdirs_list) + languages = ", ".join('"%s"' % lang for lang in langs) - srcdirs = ', '.join('"%s"' % d for d in srcdirs_list) - languages = ', '.join('"%s"' % lang for lang in langs) + # In addition to the provided dependencies, figure out if this project + # should extend or with some support or helper facilities. These are + # designed with projects for test *programs* in mind, not for libraries, + # and would actually be plain incompatible with shared Library projects. + for_library = "Library" in extra - # The base project file we need to extend, and the way to refer to it - # from the project contents. This provides a default last chance handler - # on which we rely to detect termination on exception occurrence. - basegpr = (("%s/support/base" % ROOT_DIR) - if RUNTIME_INFO.need_libsupport else None) + # The base project file we need to extend, which drags libsupport, + # and the way to refer to it from the project contents. + basegpr = ( + "{}/support/base.gpr".format(ROOT_DIR) if not for_library else None + ) + + # For projects with an Ada main, provide visibility on the alternative + # last chance handlers. Restricting this to Ada mains ensures that the + # dedicated object file for a given handler only gets included in the + # closure if the program requests the corresponding unit explicitly via + # a "with" clause, e.g. "with Silent_Last_Chance;". + # + # Account for callers that expect the "deps" argument they provide to + # remain unmodified, or which provide a tuple on input (unmutable). + deps = list(deps) if deps else [] + if not for_library and ".adb" in gprmains: + deps.append("{}/support/lch.gpr".format(ROOT_DIR)) + + deps = "\n".join('with "%s";' % dep for dep in deps) # If we have specific flags for the mains, append them. This is # typically something like: @@ -336,32 +528,47 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # for Switches("test_blob.adb") use # Compiler'Default_Switches("Ada") & ("-fno-inline") - compswitches = ( - '\n'.join( - ['for Switches("%s") use \n' - ' Compiler\'Default_Switches ("%s") & (%s);' % ( - main, language_info(main).name, ','.join( - ['"%s"' % carg for carg in to_list(main_cargs)])) - for main in mains] - ) + '\n') + compswitches = "" + if main_cargs: + compswitches = ( + "\n".join( + [ + 'for Switches("%s") use \n' + ' Compiler\'Default_Switches ("%s") & (%s);' + % ( + main, + language_info(main).name, + ",".join( + ['"%s"' % carg for carg in to_list(main_cargs)] + ), + ) + for main in mains + ] + ) + + "\n" + ) # Now instanciate, dump the contents into the target gpr file and return gprtext = template % { - 'prjname': prjid, - 'extends': ('extends "%s"' % basegpr) if basegpr else "", - 'scenario': scenario_extra, - 'srcdirs': srcdirs, - 'exedir': exedir, - 'objdir': objdir or (exedir + "/obj"), - 'compswitches': compswitches, - 'languages': languages, - 'gprmains': gprmains, - 'deps': deps, - 'compiler_extra': compiler_extra, - 'pkg_emulator': gpr_emulator_package(), - 'extra': extra} - - return text_to_file(text=gprtext, filename=prjid + ".gpr") + "prjname": prjid, + "extends": ('extends "%s"' % basegpr) if basegpr else "", + "scenario": scenario_extra, + "srcdirs": srcdirs, + "exedir": exedir, + "objdir": objdir or (exedir + "/obj"), + "compswitches": compswitches, + "languages": languages, + "gprmains": gprmains, + "deps": deps, + "compiler_extra": compiler_extra, + "pkg_emulator": gpr_emulator_package(), + "extra": extra, + } + + return text_to_file( + text=gprtext, + filename=os.path.join(cwd, prjid.replace(".", "-") + ".gpr"), + ) # The following functions abstract away the possible presence of extensions at @@ -370,6 +577,7 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # PGNNAME is a program name, in the main subprogram name sense. An empty # PGMNAME is allowed, in which case the functions return only the extensions. + def exename_for(pgmname): """Name of the executable for the given program name""" return pgmname + TARGET_INFO.exeext @@ -380,12 +588,25 @@ def tracename_for(pgmname): return exename_for(pgmname) + ".trace" -def srctrace_pattern_for(pgmname): - """Glob pattern for the source trace file for the given program name""" - return exename_for(pgmname) + "*.srctrace" +def srctrace_pattern_for(pgmname, manual=False, manual_prj_name=None): + """ + Glob pattern for the source trace file for the given program name. + + :param bool manual: Indicates if the trace file was created as a result of + a manual dump buffers procedure call. + :param None|str manual_prj_name: Trace files emitted in manual dump trigger + mode contain the name of the relevant project in their name. + manual_prj_name is the name of the project which trace we want to find. + """ + # Do not take into account the executable extension as under some + # configurations (e.g. integrated instrumentation), we use the main + # basename. + return (manual_prj_name if manual else pgmname) + "*.srctrace" -def srctracename_for(pgmname, register_failure=True): +def srctracename_for( + pgmname, register_failure=True, manual=False, manual_prj_name=None +): """ Name for the source trace file for the given program name. @@ -397,7 +618,7 @@ def srctracename_for(pgmname, register_failure=True): stops the testcase. If "register_failure" is False, we just return None in that case. """ - pattern = srctrace_pattern_for(pgmname) + pattern = srctrace_pattern_for(pgmname, manual, manual_prj_name) trace_files = glob.glob(pattern) if len(trace_files) == 1: @@ -425,6 +646,7 @@ def ckptname_for(pgmname): # tests that are going to search for exe filenames in outputs using regular # expressions, where backslashes as directory separators introduce confusion. + def exepath_to(pgmname): """ Return the absolute path to the executable file expected in the current @@ -449,16 +671,22 @@ def maybe_valgrind(command): """ if not thistest.options.enable_valgrind: prefix = [] - elif thistest.options.enable_valgrind == 'memcheck': - prefix = [VALGRIND, '-q', '--log-file=%s' % MEMCHECK_LOG] - elif thistest.options.enable_valgrind == 'callgrind': + elif thistest.options.enable_valgrind == "memcheck": + prefix = [VALGRIND, "-q", "--log-file=%s" % MEMCHECK_LOG] + elif thistest.options.enable_valgrind == "callgrind": log_file = CALLGRIND_LOG.format(thistest.create_callgrind_id()) prefix = [ - VALGRIND, '-q', '--tool=callgrind', - '--callgrind-out-file=%s' % log_file] + VALGRIND, + "-q", + "--tool=callgrind", + "--callgrind-out-file=%s" % log_file, + ] else: - raise ValueError('Invalid Valgrind tool: {}'.format( - thistest.options.enable_valgrind)) + raise ValueError( + "Invalid Valgrind tool: {}".format( + thistest.options.enable_valgrind + ) + ) return prefix + command @@ -472,10 +700,38 @@ def platform_specific_symbols(symbols): return [TARGET_INFO.to_platform_specific_symbol(sym) for sym in symbols] -def xcov_suite_args(covcmd, covargs, - auto_config_args=True, - auto_target_args=True, - force_project_args=False): +def locate_gpr_file(gprswitches): + """ + Use gprls to locate the GPR file for ``gprswitches``'s root project. + """ + # Run gprls to let GPR code do the complex project file resolution, enable + # verbose mode so that it prints the full path to the resolved file. + filename = gprswitches.root_project + args = ["gprls", "-P", filename, "-v"] + gprswitches.build_switches + if thistest.options.target: + args.append(f"--target={thistest.options.target}") + if thistest.options.RTS: + args.append(f"--RTS={thistest.options.RTS}") + gprls_output = Run(args).out + + # Look for the resolved project filename in the output, complain if we + # could not find one. + for line in gprls_output.splitlines(): + m = GPRLS_PARSING_RE.match(line) + if m is not None: + return m.group(1) + raise ValueError( + f"could not locate {filename} with gprls:\n{gprls_output}" + ) + + +def xcov_suite_args( + covcmd, + covargs, + auto_config_args=True, + auto_target_args=True, + force_project_args=False, +): """ Arguments we should pass to gnatcov to obey what we received on the command line, in particular --config and --target/--RTS. @@ -487,36 +743,48 @@ def xcov_suite_args(covcmd, covargs, are True. """ project_handling_enabled = ( - force_project_args or any(arg.startswith('-P') for arg in covargs) + force_project_args + or covcmd in ("setup", "setup-integration") + or any(arg.startswith("-P") for arg in covargs) ) + result = [] + + # If --config is asked and project handling is involved, pass it and stop + # there. If there is a board, it must be described in the project file + # (gnatcov's -P argument). + if project_handling_enabled and auto_config_args: + result.append( + "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) + ) + result.extend(RUNTIME_INFO.gpr_scenario_vars) + return result + # If --config is asked and project handling is involved, pass it and stop # there. If there is a board, it must be described in the project file # (gnatcov's -P argument). if auto_config_args and project_handling_enabled: - return ['--config={}' - .format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR))] + return result - # Nothing to do if the caller does not want automatic --target/--RTS + # Nothing to add if the caller does not want automatic --target/--RTS # arguments. if not auto_target_args: - return [] + return result # Otherwise, handle target and board information. # # Remember that the testsuite determines the target from the machine that # hosts the testsuite and from its own --host/--build/--target arguments... - - result = [] - + # # If we have a specific target board specified with --board, use that: # # --target=p55-elf --board=iSystem-5554 # --> gnatcov run --target=iSystem-5554 # # Such board indications are intended for probe based targets. - if thistest.options.board: - targetarg = thistest.options.board + gnatemu_board = gnatemu_board_name(thistest.options.board) + if gnatemu_board: + targetarg = gnatemu_board # Otherwise, pass the target triplet indication, completed by a board # extension if we also have a target "machine": @@ -533,14 +801,15 @@ def xcov_suite_args(covcmd, covargs, # --target argument to "gnatcov" as soon as we work with a 32bit target. elif thistest.options.target or env.target.cpu.bits != 64: targetarg = env.target.triplet - if env.target.machine and env.target.machine != "unknown": - targetarg += ",%s" % env.target.machine + board_name = gnatemu_board_name(env.target.machine) + if board_name and board_name != "unknown": + targetarg += ",%s" % board_name else: targetarg = None if targetarg: - result.append('--target=' + targetarg) + result.append("--target=" + targetarg) # Handle --RTS # @@ -548,18 +817,39 @@ def xcov_suite_args(covcmd, covargs, # *and* we pass a project file (proper GPR loading can require the # runtime information). if project_handling_enabled and thistest.options.RTS: - result.append('--RTS=' + thistest.options.RTS) + result.append("--RTS=" + thistest.options.RTS) return result -def cmdrun(cmd, inp=None, out=None, err=None, env=None, register_failure=True): +def cmdrun( + cmd, + for_pgm, + inp=None, + out=None, + err=None, + env=None, + register_failure=True, + expect_non_zero_code=False, +): """ Execute the command+args list in CMD, redirecting its input, output and error streams to INP, OUT and ERR when not None, respectively. If ENV is - not None, pass it as the subprocess environment. Stop with a FatalError if - the execution status is not zero and REGISTER_FAILURE is True. Return the - process descriptor otherwise. + not None, pass it as the subprocess environment. + + FOR_PGM tells if this execution actually runs a user/test program. + + Stop with a FatalError if the execution status is not zero and + REGISTER_FAILURE is True. If FOR_PGM is also True (in addition to + REGISTER_FAILURE) also check the program's output for an occurrence + of unhandled exception in cross configurations. + + In case EXPECT_NON_ZERO_CODE is True, and the command runs successfully + and returns a null exit code, will stop the test with FatalError. + + EXPECT_NON_ZERO_CODE=True overrides REGISTER_FAILURE=False + + In absence of fatal error, return the process descriptor. """ # Setup a dictionary of Run input/output/error arguments for which a @@ -567,87 +857,193 @@ def cmdrun(cmd, inp=None, out=None, err=None, env=None, register_failure=True): kwargs = { key: value - for key, value in [('input', inp), ('output', out), ('error', err), - ('env', env)] + for key, value in [ + ("input", inp), + ("output", out), + ("error", err), + ("env", env), + ] if value } p = run_and_log(cmd, timeout=thistest.options.timeout, **kwargs) - thistest.stop_if( - register_failure and p.status != 0, - FatalError('"%s"' % ' '.join(cmd) + ' exit in error', - outfile=out, outstr=p.out)) + # Check for FatalError conditions. Minimize the situations where we look + # into the program's output as this is a central spot. - return p + if expect_non_zero_code: + if p.status == 0: + thistest.stop( + FatalError( + '"%s"' % " ".join(cmd) + ": expected non-zero exit code", + outfile=out, + ) + ) + elif register_failure and p.status != 0: + output = contents_of(out) if out else p.out + thistest.stop( + FatalError( + '"%s"' % " ".join(cmd) + " exit in error", + outfile=out, + outstr=output, + ) + ) + if register_failure and for_pgm and thistest.options.target: + output = contents_of(out) if out else p.out + thistest.stop_if( + unhandled_exception_in(output), + FatalError( + '"%s"' % " ".join(cmd) + " raised an unhandled exception", + outfile=out, + outstr=output, + ), + ) -def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, - auto_config_args=True, auto_target_args=True, - force_project_args=False, auto_languages=True): - """ - Run xcov with arguments ARGS, timeout control, valgrind control if - available and enabled, output directed to OUT and failure registration if - register_failure is True. Return the process status descriptor. ARGS may be - a list or a whitespace separated string. + return p - If AUTO_LANGUAGES is True, the gnatcov sub-command is "instrument" and the - testsuite is not in qualification mode, automatically pass the - --restricted-to-languages argument to enable all the languages to test. - See xcov_suite_args for the meaning of AUTO_*_ARGS and FORCE_PROJECT_ARGS - arguments. +def xcov( + args, + out=None, + err=None, + inp=None, + env=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, + force_project_args=False, + tolerate_messages=None, +): + """ + Run "gnatcov". + + :param list[str] args: arguments to pass to gnatcov. + :param None|str out: if not None, redirect gnatcov output to out. + :param None|str err: if not None, redirect gnatcov error output to err. + :param None|str inp: if not None, redirect gnatcov input to inp. + :param None|dict[str, str] env: If not none, environment variables for the + program to run. + :param bool register_failure: If True, register execution failure. + :param bool auto_config_args: see xcov_suite_args. + :param bool auto_target_args: see xcov_suite_args. + :param bool force_project_args: see xcov_suite_args. + :param None|str tolerate_messages: If not None, a re pattern of warning + or error messsages tolerated in the tool output. Messages not matching + this pattern will cause a test failure when register_failure is True. + + :rtype: Run + :return: Process status descriptor for the gnatcov invocation. """ + # Defensive code: running "gnatcov setup" with no prefix will install + # gnatcov_rts in gprbuild's prefix, i.e. the current test will try to + # modify a global resource. This is always an error, so reject it before it + # causes hard to trace damage elsewhere. + assert args[0] != "setup" or any( + arg.startswith("--prefix") for arg in args + ) + # Make ARGS a list from whatever it is, to allow unified processing. # Then fetch the requested command, always first: args = to_list(args) covcmd = args[0] covargs = args[1:] - # gnatcov testsuite exercises C/C++ instrumentation, which are not - # activated by default. - if ( - auto_languages - and not thistest.options.qualif_level - and covcmd == "instrument" - ): - covargs = ['--restricted-to-languages=Ada,C,C++'] + covargs - if thistest.options.all_warnings: - covargs = ['--all-warnings'] + covargs - - covargs = xcov_suite_args(covcmd, covargs, auto_config_args, - auto_target_args, force_project_args) + covargs + covargs = ["--all-warnings"] + covargs + + covargs = ( + xcov_suite_args( + covcmd, + covargs, + auto_config_args, + auto_target_args, + force_project_args, + ) + + covargs + ) # Determine which program we are actually going launch. This is # "gnatcov " unless we are to execute some designated program # for this: covpgm = thistest.suite_covpgm_for(covcmd) - covpgm = ([covpgm] if covpgm is not None - else maybe_valgrind([XCOV]) + [covcmd]) + covpgm = ( + [covpgm] if covpgm is not None else maybe_valgrind([XCOV]) + [covcmd] + ) # Execute, check status, raise on error and return otherwise. # # The gprvar options are only needed for the "libsupport" part of our # projects. They are pointless wrt coverage run or analysis activities # so we don't include them here. - p = cmdrun(cmd=covpgm + covargs, inp=inp, out=out, err=err, env=env, - register_failure=register_failure) + p = cmdrun( + cmd=covpgm + covargs, + inp=inp, + out=out, + err=err, + env=env, + register_failure=register_failure, + for_pgm=(covcmd == "run"), + ) - if thistest.options.enable_valgrind == 'memcheck': + # When no message is to be tolerated, fallback to an actual regexp + # that will never match: + re_tolerate_messages = tolerate_messages or "__NEVER_IN_A_WARNING___" + + # Do not check warnings when running the testsuite in binary traces mode, + # as it would require modifying / adapting too many tests. + if register_failure and thistest.options.trace_mode == "src": + output = contents_of(out) if out else p.out + + # Check for unexpected messages. Beware that the "warning:" + # indication at least is not necessarily at the beginning of + # a line, as in + # + # app.gpr:4:23: warning: object directory "obj" not found + + messages = re.findall( + pattern=r"(?:!!!|\*\*\*|warning:).*$", + string=output, + flags=re.MULTILINE, + ) + + unexpected_messages = [ + w + for w in messages + if not re.search(pattern=re_tolerate_messages, string=w) + ] + thistest.fail_if( + unexpected_messages, + f"Unexpected messages in the output of 'gnatcov {covcmd}':" + f"\n{indent(output)}" + + ( + f"\n(allowed: {tolerate_messages})" + if tolerate_messages + else "" + ), + ) + + if thistest.options.enable_valgrind == "memcheck": memcheck_log = contents_of(MEMCHECK_LOG) thistest.fail_if( memcheck_log, - 'MEMCHECK log not empty' + "MEMCHECK log not empty" '\nFROM "%s":' - '\n%s' % (' '.join(covpgm + covargs), memcheck_log)) + "\n%s" % (" ".join(covpgm + covargs), memcheck_log), + ) return p -def xrun(args, out=None, env=None, register_failure=True, - auto_config_args=True, auto_target_args=True): +def xrun( + args, + out=None, + env=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, +): """ Run with arguments ARGS for the current target, performing operations only relevant to invocations intended to execute a program (for @@ -672,28 +1068,41 @@ def xrun(args, out=None, env=None, register_failure=True, runargs = [] if thistest.options.kernel: - runargs.append('--kernel=' + thistest.options.kernel) + runargs.append("--kernel=" + thistest.options.kernel) runargs.extend(to_list(args)) if ( - thistest.options.trace_size_limit and - thistest.options.target and - not thistest.options.board + thistest.options.trace_size_limit + and thistest.options.target + and not gnatemu_board_name(thistest.options.board) ): - if '-eargs' not in runargs: - runargs.append('-eargs') - runargs.extend(["-exec-trace-limit", - thistest.options.trace_size_limit]) + if "-eargs" not in runargs: + runargs.append("-eargs") + runargs.extend( + ["-exec-trace-limit", thistest.options.trace_size_limit] + ) - return xcov(['run'] + runargs, inp=nulinput, out=out, env=env, - register_failure=register_failure, - auto_config_args=auto_config_args, - auto_target_args=auto_target_args) + return xcov( + ["run"] + runargs, + inp=nulinput, + out=out, + env=env, + register_failure=register_failure, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, + tolerate_messages=".", + ) -def run_cov_program(executable, out=None, env=None, exec_args=None, - register_failure=True): +def run_cov_program( + executable, + out=None, + env=None, + exec_args=None, + register_failure=True, + expect_non_zero_code=False, +): """ Assuming that `executable` was instrumented, run it according to the current target. @@ -702,57 +1111,394 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, args = [] exec_args = exec_args or [] inp = None - - # If we are in a cross configuration, run the program using GNATemulator + use_pycross = False if thistest.options.target: - kernel = thistest.options.kernel - board = thistest.options.board or thistest.env.target.machine - args.append('{}-gnatemu'.format(thistest.env.target.triplet)) - if kernel: - args.append('--kernel=' + kernel) - if board: - args.append('--board=' + board) - - # If GNATemulator runs as a background process in an interactive shell, - # the Linux kernel will send a SIGTTIN when GNATemulator tries to read - # the standard input (which is the interactive shell by default). This - # will result in an abnormal GNATemulator termination, and the test - # failing. Redirecting the standard input to /dev/null works around - # this issue. - inp = DEVNULL + # If we are testing for AAMP, use the facade simulator. It expects a + # configuration file (facade.cfg) in the executable dir, and the + # executable must be run through an executable.sod file, which sets + # up the simulator environment. This .sod file should be in the same + # directory as the executable. + if "aamp" in control.env.target.platform: + args.append("dosfsod.exe") + list_to_file( + [ + "sw tx on", + '$TEXTIO = ""', + "switch batch on", + "fill 0000..ffff 0", + "load " + executable, + "go", + "halt", + ], + "test.sod", + ) + args.append("@test.sod") + cp(os.path.join(ROOT_DIR, "facade.cfg"), "facade.cfg") + args.extend(exec_args) + out = cmdrun( + args, + out=out, + env=env, + register_failure=register_failure, + for_pgm=True, + ) + return out + + # If we are in a cross configuration, run the program using run-cross2 + if thistest.options.target and thistest.env.target.platform != "c": + use_pycross = True + + # We absolutely need a machine name to run programs with run-cross2 + assert thistest.options.board or thistest.env.target.machine + + target = thistest.env.target.platform + os_ver = ( + thistest.env.target.os.version if thistest.env.target.os else "" + ) + + target += f",{os_ver}" + + if thistest.options.board: + target += f",{thistest.options.board}" + else: + target += f",{thistest.env.target.machine}" + + # run-cross2 is a python script. As Windows does not parse shebangs, + # use the python executable as main program instead of the script. + args += [ + sys.executable, + which("run-cross2"), + f"--target={target}", + # Instruct pycross to preserve temporary files, which includes the + # directory that is mounted in the target's filesystem. This is + # where the source trace may be created (see below). + "--save-temps", + ] + + # pycross might obfuscate the error exit code in light runtime cases + # and for embedded-leon3. + expect_non_zero_code = expect_non_zero_code and not ( + RUNTIME_INFO.has_light_runtime + or RUNTIME_INFO.runtime_name == "embedded-leon3" + ) + else: + # Native programs using a light runtime can't set the exit code, and + # will often terminate with a non-zero status code even though nothing + # went wrong. There is thus no point in checking the exit code in this + # configuration. + register_failure = ( + register_failure and not RUNTIME_INFO.has_light_runtime + ) args.append(executable) args.extend(exec_args) - return cmdrun(args, out=out, inp=inp, env=env, register_failure=register_failure) + result = cmdrun( + args, + out=out, + inp=inp, + env=env, + register_failure=register_failure, + expect_non_zero_code=expect_non_zero_code, + for_pgm=True, + ) + + # If the program was run under pycross, hoist source traces that the + # program may have created on the target filesystem so that the rest of the + # testsuite finds sources traces where they expect: in the current + # directory. + if use_pycross: + for filename in glob.glob("hostfs-*/test/*.srctrace"): + cp(filename, ".") + + return result def do(command): """ Execute COMMAND. Abort and dump output on failure. Return output otherwise. """ - p = cmdrun(cmd=to_list(command), register_failure=True) + p = cmdrun(cmd=to_list(command), register_failure=True, for_pgm=False) return p.out class frame: - def register(self, text): if len(text) > self.width: self.width = len(text) def display(self): - thistest.log('\n' * self.pre + self.char * (self.width + 6)) + thistest.log("\n" * self.pre + self.char * (self.width + 6)) for text in self.lines: - thistest.log("%s %s %s" % ( - self.char * 2, text.center(self.width), self.char*2)) - thistest.log(self.char * (self.width + 6) + '\n' * self.post) + thistest.log( + "%s %s %s" + % (self.char * 2, text.center(self.width), self.char * 2) + ) + thistest.log(self.char * (self.width + 6) + "\n" * self.post) - def __init__(self, text, char='o', pre=1, post=1): + def __init__(self, text, char="o", pre=1, post=1): self.pre = pre self.post = post self.char = char self.width = 0 - self.lines = text.split('\n') + self.lines = text.split("\n") for text in self.lines: self.register(text) + + +@dataclass +class Ext_Annotation: + """Base external annotation""" + + # File to which the annotation applies + source_file: str + + # Start location for the annotation + start_sloc: str + + # End location for the annotation, if relevant + end_sloc: str | None + + def __init__(self, start_sloc, source_file, end_sloc=None): + self.start_sloc = start_sloc + self.source_file = source_file + self.end_sloc = end_sloc + + # Use the local directory separator if we are dealing with a relative + # source file path. + if not os.path.isabs(self.source_file): + self.source_file = self.source_file.replace("/", os.path.sep) + self.source_file = self.source_file.replace("\\", os.path.sep) + + def cmd_line_args(self): + args = [self.source_file] + args.append(f"--kind={self.__class__.__name__}") + if self.end_sloc: + args.append(f"--start-location={self.start_sloc}") + args.append(f"--end-location={self.end_sloc}") + else: + args.append(f"--location={self.start_sloc}") + return args + + +@dataclass +class Exempt_On(Ext_Annotation): + """Represents an external Exempt_On annotation""" + + # Justification for the exempted region + justification: str | None = None + + def cmd_line_args(self): + return super().cmd_line_args() + ( + [f"--justification={self.justification}"] + if self.justification + else [] + ) + + +@dataclass +class Exempt_Region(Exempt_On): + """ + Represents an external Exempt_Region annotation + + Requires end_sloc to be specified + """ + + def __post_init__(self): + assert self.end_sloc + + +@dataclass +class Exempt_Off(Ext_Annotation): + """Represents an external Exempt_Off annotation""" + + pass + + +@dataclass +class Cov_Off(Exempt_On): + """Represents an external Cov_Off annotation""" + + pass + + +@dataclass +class Cov_On(Ext_Annotation): + """Represents an external Cov_On annotation""" + + pass + + +@dataclass +class Reset_Buffers(Ext_Annotation): + """Represents an external Reset_Buffer annotation""" + + # Whether the annotation should be inserted before or after the + # statement designated by start_sloc + insert_after: bool = False + + def cmd_line_args(self): + return super().cmd_line_args() + ( + ["--annotate-after"] if self.insert_after else [] + ) + + +@dataclass +class Dump_Buffers(Reset_Buffers): + """Represents an external Dump_Buffers annotation""" + + # Optionnal trace prefix to be used when dumping the coverage buffers + trace_prefix: str | None = None + + def cmd_line_args(self): + return super().cmd_line_args() + ( + [f"--dump-filename-prefix={self.trace_prefix}"] + if self.trace_prefix + else [] + ) + + +def xcov_annotate( + annotation: Ext_Annotation, + annot_out_file: str, + annot_in_files: list[str] | None = None, + extra_args: list[str] | None = None, + out=None, + env=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, + tolerate_messages=None, +): + """ + Invoke "gnatcov annotate" with the correct arguments to generate + an external annotation. + + No validation is performed on the function arguments before being + transformed to a command line. + + :param Ext_Annotation) annotation: Annotation to be generated by gnatcov + :param str source_file: source file to be annotated + :param str annot_out_file: File to which the annotations should be written. + This will overwrite any pre-existing file. + :param list[str] | None annot_in_files : List of filenames containing + pre-existing annotations, to be loaded and to which the new annotation + will be added. Defaults to None. + :param list[str] | None extra_args: extra arguments passed on the command + line. Defaults to None. + :param str | None tolerate_messages: see documentation of xcov. + """ + args = ["add-annotation"] + args.extend(annotation.cmd_line_args()) + args.append(f"--output={annot_out_file}") + if annot_in_files: + args.extend( + [f"--external-annotations={file}" for file in annot_in_files] + ) + if extra_args: + args.extend(extra_args) + + xcov( + args, + out=out, + env=env, + register_failure=register_failure, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, + tolerate_messages=tolerate_messages, + ) + + +def generate_annotations(annotations, subdir="", tolerate_messages=None): + """ + Setup a temporary working directory in which an annotation file + will be generated from annotations, using gnatcov add-annotation + invocations. + Returns the absolute path to the annotation file + + :param list[Ext_Annotation] annotations: List of annotation to be generated + through the gnatcov add-annotation command + """ + # Create a common temporary working dir in which the annotations will be + # generated. + tmp = Wdir(subdir if subdir else "tmp_annotations") + + # Create an empty annotation file, to simplify command line generation + annot_file = os.path.abspath("annotations.toml") + touch(annot_file) + + # Move to the home dir so that annotations are relative to the home + # directory of the test. + tmp.to_homedir() + + # Generate the annotations + for annotation in annotations: + xcov_annotate( + annotation, + annot_in_files=[annot_file], + annot_out_file=annot_file, + tolerate_messages=tolerate_messages, + ) + return annot_file + + +def driver_for_lang(lang: str) -> str | None: + """ + Inspect the contents of suite.cgpr to determine what the compiler driver + for the given language is. lang is case sensitive. This returns None if + the driver was not found. + """ + driver_match = re.search( + r'for Driver *\("' + re.escape(lang) + r'"\) use "(.*)";', + contents_of(os.path.join(ROOT_DIR, "suite.cgpr")), + ) + + return driver_match.group(1) if driver_match else None + + +# Mapping from the CPU name to the C BSP example in the gnat installation tree +BSP_MAP = { + "zynqmp": "zcu102", + "stm32f4": "stm32f429disco", + "leon3": "leon3", + "mpc8641": "mpc8641", +} + + +def bsp_project(cpu): + """ + Return the name of the bsp project (without extension) for the given cpu + """ + return BSP_MAP.get(cpu, None) + + +def get_c_bsp(rts, destdir): + """ + Build & install the C BSP project that is shipped with gnat. The BSP + exposes a subset of stdio that can be used to dump traces. + + RTS is used to locate the correct BSP, we assume that: + - RTS is of the form - + - in the gnat installation tree there is a /share/examples/gnat-c/ directory, in which there is a + bsp_map[].gpr project (see above for bsp_map). + + This function will copy destdir, and return the name of the project. + """ + + cpu_name = rts.split("-")[-1] + + thistest.fail_if( + not cpu_name, + f"Could not deduce CPU name from RTS: {rts}", + ) + + gcc = driver_for_lang("C") + thistest.fail_if(not gcc, "Could not locate gcc executable") + + bsp_original_location = os.path.join( + os.path.dirname(gcc), "..", "share", "examples", "gnat-c", cpu_name + ) + cp(os.path.join(bsp_original_location, "*"), destdir, recursive=True) + + return bsp_project(cpu_name) diff --git a/testsuite/altrun/ccg_native/cgprbuild.py b/testsuite/altrun/ccg_native/cgprbuild.py new file mode 100755 index 000000000..b6adcab2e --- /dev/null +++ b/testsuite/altrun/ccg_native/cgprbuild.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python + +import argparse +import json +import os +import pathlib + +from e3.os.process import Run +from e3.platform import Platform + + +def parse_scenario(arg: str): + """ + Helper to parse -XVAR[=VAL] command line options. + If VAL is not specified in the argument, consider this an ill formed + argument and ignore it. + """ + return arg.split("=", maxsplit=1) if "=" in arg else None + + +def get_attr(obj, attr_name, idx=0): + """ + Get the value of the attribute named attr_name, at index idx if relevant. + If no such attribute exists, returns None. + """ + attrs = obj["projects"][0]["attributes"] + for attr_ob in attrs: + if attr_ob["name"] == attr_name: + if attr_ob["kind"] == "single": + return attr_ob["value"] + else: + return attr_ob["values"][idx] + return None + + +def run(cmd, what): + """ + Run the command represented by cmd in a subprocess, appending the + executable extension for the platform to the first element of cmd. If the + exit status is not success and ignore_failure is True, print + f"{what} failed" followed by the command output on the standard output and + exit with an error. Otherwise, return the output of the command execution. + """ + cmd[0] = cmd[0] + Platform.get().os.exeext + p = Run(cmd) + if p.status != 0: + print(f"{what} failed:") + print(p.command_line_image()) + print(p.out) + exit(1) + return p.out + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-P", dest="project") + parser.add_argument("--config", dest="config") + parser.add_argument("--target", dest="target") + parser.add_argument("--RTS", dest="rts") + parser.add_argument("--src-subdirs", dest="src_subdirs") + parser.add_argument("--implicit-with", dest="implicit_with") + parser.add_argument( + "-X", + dest="scenario", + action="append", + type=parse_scenario, + ) + parser.add_argument("-v", dest="verbose", action="store_true") + + args, extra = parser.parse_known_args() + + altrun_dir = os.path.dirname(os.path.realpath(__file__)) + + # Substitute the "--implicit-with=gnatcov_rts.gpr" to point it toward our + # own custom RTS. + ccg_gnatcov_rts = os.path.join( + altrun_dir, + "ccg_gnatcov_rts", + "gnatcov_rts.gpr", + ) + custom_rts_dir = None + if args.implicit_with and "gnatcov_rts" in args.implicit_with: + custom_rts_dir = os.path.dirname(ccg_gnatcov_rts) + args.implicit_with = ccg_gnatcov_rts + + # Build common args for all gpr commands + common_args = ["--target=c"] + common_args += ["-P", args.project] + if args.src_subdirs: + common_args += [f"--src-subdirs={args.src_subdirs}"] + if args.implicit_with: + common_args += [f"--implicit-with={args.implicit_with}"] + for key, val in args.scenario: + common_args += [f"-X{key}={val}"] + + # Add specific scenario for our custom version of gnatcov rts: + common_args.append("-XGNATCOV_RTS_RTS_PROFILE=embedded") + common_args.append("-XGNATCOV_RTS_FOR_CCG=true") + + if "-cargs" in extra: + cargs_index = extra.index("-cargs") + extra.insert(cargs_index + 1, f"-mtriple={Platform.get().triplet}") + else: + extra += ["-cargs", f"-mtriple={Platform.get().triplet}"] + + # Generate C files + gprbuild_args = ["gprbuild"] + common_args + extra + run(gprbuild_args, "gprbuild invocation") + + # Gather information about the project structure, we need the name of the + # main (to generate an executable of the same name), the list of object + # directories, the root directory of the project (as all other directories + # are relatives to this), and the directory in which to place the + # executable. + gprinspect_args = ( + ["gprinspect"] + + common_args + + ["--attributes", "--display=json-compact"] + ) + prj_txt = run(gprinspect_args, "gprinspect invocation") + prj = json.loads(prj_txt) + + # Assume single main per project file + main_name = os.path.basename(get_attr(prj, "Main")).split(".")[0] + prj_dir = get_attr(prj, "Project_Dir") + exec_dir = os.path.join(prj_dir, get_attr(prj, "Exec_Dir")) + obj_dir = os.path.join(prj_dir, get_attr(prj, "Object_Dir")) + + # Get the list of all the generated C files that need to be compiled. gprls + # will return a list of ".o" files, so replace the extension to ".c" + gprls_args = ["gprls"] + common_args + ["-o", "-U"] + + c_files = run(gprls_args, "gprls invocation").splitlines() + c_files = [f for f in c_files if f[-2:] == ".c"] + # Add the generated binder file in order to be able to link the executable + c_files.append(os.path.join(obj_dir, "b__" + main_name + ".c")) + + # Hack: given the characteristics passed to the runtime (light runtime), + # it will always add a "last_chance_dumper" unit which defines the symbol + # __lch_enter. This symbol is also defined in the Libsupport unit, as part + # of the Libsupport library. This normally is a static library, and thus + # the object for __lch_enter should not be pulled during the link, but with + # ccg we don't build any libraries. as such we must exclude libsupport.c + # from the gcc invocation to avoid having multiple definitions of + # __lch_enter. + c_files = [ + filename + for filename in c_files + if os.path.basename(filename) != "libsupport.c" + ] + + gcc_args = ["gcc"] + + if "-g" in extra: + gcc_args += ["-g"] + + gcc_args += c_files + + # Add the list of native C files from gnatcov_rts: the project was modified + # to not include C as a language (to avoid gprbuild issues), but these are + # still required for a successful build. + if custom_rts_dir: + rts_dir = pathlib.Path(custom_rts_dir) + gcc_args += [ + str(pth.absolute()) for pth in rts_dir.glob("gnatcov_rts_c*") + ] + + # Add the runtime library in the mix. The pre-testsuite script compile the + # library and does not bother to create a separate adalib directory for the + # compilation results + gcc_args += [os.path.join(altrun_dir, "adainclude", "libgnat.a")] + + # Compile the executable + gcc_args += [ + "-o", + os.path.join(exec_dir, main_name + Platform.get().os.exeext), + ] + run(gcc_args, "gcc invocation") + + +if __name__ == "__main__": + main() diff --git a/testsuite/altrun/ccg_native/libgnat.gpr b/testsuite/altrun/ccg_native/libgnat.gpr new file mode 100644 index 000000000..c6de94576 --- /dev/null +++ b/testsuite/altrun/ccg_native/libgnat.gpr @@ -0,0 +1,6 @@ +project Libgnat is + + for Source_Dirs use ("adainclude"); + for Object_Dir use "adainclude"; + +end Libgnat; diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py new file mode 100644 index 000000000..0c43bd137 --- /dev/null +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -0,0 +1,233 @@ +""" +Setup everything needed to be able to compile an instrumented executable with +CCG. This includes as custom version of gnatcov_rts, building the Ada runtime +for the proper platform, and pre-building libsupport. +""" + +import json +import os +from pathlib import Path +from shutil import which + +from e3.fs import rm, cp, mkdir, mv +from e3.os.process import Run +from e3.platform import Platform + +altrun_dir = os.path.dirname(os.path.realpath(__file__)) + +custom_rts_dir = os.path.join(altrun_dir, "ccg_gnatcov_rts") +custom_rts_prj = os.path.join(custom_rts_dir, "gnatcov_rts.gpr") + +exeext = Platform.get().os.exeext + +gnatcov = which("gnatcov" + exeext) +base_rts_dir = os.path.join( + os.path.dirname(gnatcov), "..", "share", "gnatcoverage", "gnatcov_rts" +) + + +def run(cmd, what): + """ + Run the command represented by cmd in a subprocess, appending the + executable extension for the platform to the first element of cmd. If the + exit status is not success and ignore_failure is True, print + f"{what} failed" followed by the command output on the standard output and + exit with an error. Otherwise, return the output of the command execution. + """ + cmd[0] = cmd[0] + exeext + p = Run(cmd) + if p.status != 0: + print(f"{what} failed:") + print(p.command_line_image()) + print(p.out) + exit(1) + return p.out + + +def amend_file(filename, substs): + """ + Given a list of (pattern, subst) tuple of strings, search for each line, if + some pattern is present in the line (string comparison), and replace the + whole line with the corresponding substitution string. Otherwise, leave the + line unchanged. + The substitution string corresponding to the first matching pattern is + applied, then processing moves on to the next line in the source file. + """ + source = filename + ".source" + mv(filename, source) + found = False + with open(source, "r") as src: + with open(filename, "w") as dest: + for line in src.readlines(): + found = False + for pat, sub in substs: + if pat in line: + found = True + dest.write(sub + "\n") + break + if not found: + dest.write(line) + rm(source) + + +def prepare_rts(): + rm(custom_rts_dir, recursive=True) + mkdir(custom_rts_dir) + + # Copy the runtime and remove obj and lib dirs if they exist + cp(os.path.join(base_rts_dir, "*"), custom_rts_dir, recursive=True) + rm(os.path.join(custom_rts_dir, "obj-*"), recursive=True) + rm(os.path.join(custom_rts_dir, "lib-*"), recursive=True) + + # Remove gnatcov_rts_c-base_io*.c as it would interfere with the symbols + # defined in gnatcov_rts-base_io.adb, and the C files that should not + # be compiled when the RTS profile is "embedded". + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-base_io*.c")) + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-os_interface*")) + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-traces-output-files*")) + + # Amend gnatcov_rts-base_io.adb to remove the dependency on GNAT.IO (it is + # not available in the CCG runtime) and to directly use the libc instead. + amend_file( + os.path.join(custom_rts_dir, "gnatcov_rts-base_io.adb"), + substs=[ + ("with GNAT.IO;", ""), + ( + "pragma Warnings (On);", + " pragma Warnings (On);" + "\n function Putchar (C : Integer) return Integer;" + "\n pragma Import (C, Putchar);" + "\n Ignored : Integer;", + ), + ( + "GNAT.IO.Put (Str);", + " for C of Str loop" + "\n Ignored := Putchar (Character'Pos (C));" + "\n end loop;", + ), + ], + ) + + # Pre-build gnatcov_rts + run( + [ + "gprbuild", + "--target=c", + "-P", + custom_rts_prj, + "-XGNATCOV_RTS_FOR_CCG=true", + "-XGNATCOV_RTS_RTS_PROFILE=embedded", + "-cargs", + f"-mtriple={Platform.get().triplet}", + ], + what="Custom gnatcov rts build", + ) + + # Flag it as externally built + amend_file( + custom_rts_prj, + [ + ( + "end GNATcov_RTS;", + 'for Externally_Built use "True"; end GNATcov_RTS;', + ) + ], + ) + + +# Prepare custom rts +prepare_rts() + +# Re-build the lib support with the correct target: +# First, clean any previous libsupport build +libsupport_home = os.path.join("..", "..", "support") +run( + ["make", "-C", libsupport_home, "-f", "Makefile.libsupport", "clean"], + what="libsupport cleaning", +) + +rm(os.path.join(libsupport_home, "silent_last_chance-*")) + +# Then build the libsupport with the correct configuration and cflags +run( + [ + "make", + "--debug", + "-C", + libsupport_home, + "-f", + "Makefile.libsupport", + "TARGET=c", + f"LIBSUPPORT_CFLAGS=-mtriple={Platform.get().triplet}", + "SILENT_LCH=exit", + ], + what="build of libsupport", +) + +# Build the Ada runtime for the correct target + +# First, determine where the runtime sources are located +prj_str = run( + [ + "gprinspect", + "-P", + custom_rts_prj, + "-XGNATCOV_RTS_FOR_CCG=true", + "-XGNATCOV_RTS_RTS_PROFILE=embedded", + "--target=c", + "--display=json-compact", + ], + what="gprinspect invocation", +) +try: + prj_info = json.loads(prj_str) +except Exception: + print("failed parsing project info:") + print(prj_str) + exit(1) + +adainclude_dir = None +for path in prj_info["tree"]["source-search-paths"]: + if "adainclude" in path: + adainclude_dir = path + break +if not adainclude_dir: + print("could no find adainclude directory from gprinspect output") + print(prj_str) + exit(1) + +# Copy the sources in the altrun directory, in order not to modify the CCG +# build space. +local_rt = os.path.join(altrun_dir, "adainclude") +rm(local_rt, recursive=True) +cp(adainclude_dir, local_rt, recursive=True) + +# Transpile the runtime to C +run( + [ + "gprbuild", + "-P", + os.path.join(altrun_dir, "libgnat.gpr"), + "--target=c", + "-cargs", + f"-mtriple={Platform.get().triplet}", + "-gnatpg", + ], + what="compilation of the Ada runtime", +) + +# Compile all the C files +all_rt_src = [str(pth.absolute()) for pth in Path(local_rt).glob("*.c")] +all_obj_files = [] +for f in all_rt_src: + all_obj_files.append(f[:-2] + ".o") + run( + ["gcc", "-c", f, "-o", all_obj_files[-1], "-I", adainclude_dir], + what=f"compilation of {f}", + ) + +# Create the library per se. +run( + ["ar", "rcs", os.path.join(local_rt, "libgnat.a")] + all_obj_files, + what="archival of the Ada runtime", +) diff --git a/testsuite/altrun/example/altrun.gpr b/testsuite/altrun/example/altrun.gpr index b0614abe2..96a5c3f3e 100644 --- a/testsuite/altrun/example/altrun.gpr +++ b/testsuite/altrun/example/altrun.gpr @@ -2,4 +2,4 @@ project ALTRUN is for Source_Dirs use ("."); for Exec_Dir use "."; for Object_Dir use "obj"; -end ALTRUN; \ No newline at end of file +end ALTRUN; diff --git a/testsuite/altrun/example/crun.py b/testsuite/altrun/example/crun.py index 87c86c238..eefeee3f2 100755 --- a/testsuite/altrun/example/crun.py +++ b/testsuite/altrun/example/crun.py @@ -24,9 +24,7 @@ class Runner: - def __init__(self): - self.parse_command_line() self.run() @@ -37,31 +35,25 @@ def parse_command_line(self): # --level and --target are expected to always be there: - op.add_option( - "--level", dest="covlevel", default=None) - op.add_option( - "--target", dest="target", default=None) + op.add_option("--level", dest="covlevel", default=None) + op.add_option("--target", dest="target", default=None) # For source coverage tests not using project files: - op.add_option( - "--scos", dest="scos", default=None) + op.add_option("--scos", dest="scos", default=None) # For tests using project files + op.add_option("-P", dest="gpr", default=None) op.add_option( - "-P", dest="gpr", default=None) - op.add_option( - "--recursive", dest="recurse", default=False, action='store_true') - op.add_option( - "--projects", dest="projects", default=None) - op.add_option( - "--units", dest="units", default=None) + "--recursive", dest="recurse", default=False, action="store_true" + ) + op.add_option("--projects", dest="projects", default=None) + op.add_option("--units", dest="units", default=None) # Then a few optional items - op.add_option( - "-o", dest="ofile", default=None) + op.add_option("-o", dest="ofile", default=None) (self.options, self.args) = op.parse_args() @@ -92,7 +84,6 @@ def run_command_line(self): return args def run(self): - print("============== GNATCOV RUN ===================") if not self.args: @@ -100,7 +91,8 @@ def run(self): os.exit(1) e3.os.process.Run( - ['gnatcov', 'run'] + self.run_command_line() + self.args) + ["gnatcov", "run"] + self.run_command_line() + self.args + ) print("==============================================") diff --git a/testsuite/altrun/example/setup.py b/testsuite/altrun/example/setup.py index 37231dcf8..337a93333 100644 --- a/testsuite/altrun/example/setup.py +++ b/testsuite/altrun/example/setup.py @@ -6,8 +6,10 @@ from e3.os.process import Run import sys -p = Run(['gnatmake', '-f', '-g', '-p', '-Paltrun', 'pre_testsuite.adb'], - output=sys.stdout) +p = Run( + ["gnatmake", "-f", "-g", "-p", "-Paltrun", "pre_testsuite.adb"], + output=sys.stdout, +) if p.status != 0: sys.exit(1) diff --git a/testsuite/altrun/isys_nexus_5634/README.md b/testsuite/altrun/isys_nexus_5634/README.md deleted file mode 100644 index 0bf2e657d..000000000 --- a/testsuite/altrun/isys_nexus_5634/README.md +++ /dev/null @@ -1,25 +0,0 @@ -This directory contains programs and data for running the gnatcov testsuite -tests in a particular way when using the iSystem Blue Box attached to a sytem -running the MPC5634M SOC. - -`./testsuite.py` can be passed the argument: - -```shell ---altrun=altrun/isys_nexus_5634 -``` - -to cause: - -* `setup.py` to be called, which builds `crun.exe` from `crun.adb`, which will - be run in place of `gnatcov run` (with the same args that would normally be - passed to `gnatcov run`). - -* `pre_testsuite.py` to be called before the test sequence starts. - -* `post_testsuite.py` to be called one all the tests are finished. - -Crun creates a winIDEA workspace subdirectory (`isyswspace`) under the test -directory and populates it with the `justrun*` workspace and trace doc files, -and then calls `python get_trace.py` to run the target excutable and create a -nexus trace file in `isyswpace/nexus_trace.bin`. Then `crun` runs `gnatcov -convert` to convert the nexus trace into a gnatcov trace. diff --git a/testsuite/altrun/isys_nexus_5634/altrun.gpr b/testsuite/altrun/isys_nexus_5634/altrun.gpr deleted file mode 100644 index 96a5c3f3e..000000000 --- a/testsuite/altrun/isys_nexus_5634/altrun.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project ALTRUN is - for Source_Dirs use ("."); - for Exec_Dir use "."; - for Object_Dir use "obj"; -end ALTRUN; diff --git a/testsuite/altrun/isys_nexus_5634/crun.adb b/testsuite/altrun/isys_nexus_5634/crun.adb deleted file mode 100644 index d8d4cb22c..000000000 --- a/testsuite/altrun/isys_nexus_5634/crun.adb +++ /dev/null @@ -1,262 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2012-2015, AdaCore -- --- -- --- GNATcoverage is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This software is distributed in the hope that it will be useful -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- --- License for more details. You should have received a copy of the GNU -- --- General Public License distributed with this software; see file -- --- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- --- of the license. -- ------------------------------------------------------------------------------- - -with Text_IO; use Text_IO; -with Ada.Command_Line; use Ada.Command_Line; -with GNAT.OS_Lib; use GNAT.OS_Lib; -with GNAT.Directory_Operations; use GNAT.Directory_Operations; -with Ada.Directories; - -procedure crun is - - Executable_Path : String_Access; - - Success : Boolean; - - CWD : String := Get_Current_Dir; - - Python_P : String_Access; - Python_Args : Argument_List (1 .. 2); - - Gnatcov_P : String_Access; - Gnatcov_Args : Argument_List (1 .. 11); - Next_Arg_Idx : Natural; - - Crun_Dir : Dir_Type; - Isys_Pfile : String (1 .. 15); - Lasti : Natural; - Crun_Dir_Name : String := Normalize_Pathname ("..", Command_Name); - - Wspace_Dir_Name : String := Normalize_Pathname ("isyswspace"); - - Itmp_Dir_Name : String := Normalize_Pathname ("isystemps", Crun_Dir_Name); - Temp_Dir : Dir_Type; - Temp_Name : String (1 .. 80); - - procedure Empty_Temps_Dir; - procedure Put_Error (Error_Str : String); - - --------------------- - -- Empty_Temps_Dir -- - --------------------- - - procedure Empty_Temps_Dir is - begin - Open (Temp_Dir, Itmp_Dir_Name); - loop - Read (Temp_Dir, Temp_Name, Lasti); - exit when Lasti = 0; - Delete_File - (Normalize_Pathname (Temp_Name (1 .. Lasti), Itmp_Dir_Name), Success); - end loop; - Close (Temp_Dir); - end Empty_Temps_Dir; - - --------------- - -- Put_Error -- - --------------- - - procedure Put_Error (Error_Str : String) is - Prefix : constant String := Command_Name & " error:"; - begin - Put_Line (Standard_Error, Prefix & Error_Str); - end Put_Error; - - type Poss_Arg is record - Arg_Name : String_Access; - Required : Boolean; - Seen : Boolean; - end record; - type Poss_Arg_Array is array (Natural range <>) of Poss_Arg; - Poss_Args : Poss_Arg_Array := ( - (new String'("--target"), True, False), - (new String'("--output"), False, False), - (new String'("--tag"), False, False), - (new String'("--level"), False, False), - (new String'("--scos"), False, False)); - Target_Exec_Seen : Boolean := False; - - Argslog_File : File_Type; - Argslog_Name : String := "runargs.log"; -begin - Create (File => Argslog_File, Name => Argslog_Name); - Put_Line (Argslog_File, "INCOMING......"); - for J in 1 .. Argument_Count loop - Put_Line (Argslog_File, Argument (J)); - end loop; - Close (Argslog_File); - - Executable_Path := new String'(Normalize_Pathname (Argument (2))); - - declare - begin - Remove_Dir (Wspace_Dir_Name, Recursive => True); - exception - when Directory_Error => - null; - end; - declare - begin - Make_Dir (Wspace_Dir_Name); - exception - when Directory_Error => - Put_Error ("Directory_Error creating workspace."); - OS_Exit (1); - end; - declare - begin - Make_Dir (Itmp_Dir_Name); - exception - when Directory_Error => - null; -- Okay if temp dir already exists - end; - - Open (Crun_Dir, Crun_Dir_Name); - loop - Read (Crun_Dir, Isys_Pfile, Lasti); - exit when Lasti = 0; - if Lasti >= 8 and then Isys_Pfile (1 .. 8) = "justrun." then - - Copy_File ( - Normalize_Pathname (Isys_Pfile (1 .. Lasti), Crun_Dir_Name), - Normalize_Pathname (Isys_Pfile (1 .. Lasti), Wspace_Dir_Name), - Success); - end if; - end loop; - CLose (Crun_Dir); - - Python_P := Locate_Exec_On_Path ("python"); - if Python_P = null then - Put_Error ("python not found."); - OS_Exit (1); - end if; - Python_Args (1) := - new String'(Normalize_Pathname ("get_trace.py", Crun_Dir_Name)); - - Python_Args (2) := new String'(Executable_Path.all); - - Open (Argslog_File, Append_File, Argslog_Name); - New_Line (Argslog_File); - Put_Line (Argslog_File, "PYTHON ARGS...."); - Put_Line (Argslog_File, Python_Args (1).all); - Put_Line (Argslog_File, Python_Args (2).all); - Close (Argslog_File); - - - Setenv ("ISYSTEM_TEMP", Itmp_Dir_Name); - Spawn (Python_P.all, Python_Args, Success); - if not Success then - Put_Error ("winIDEA python script failed."); - Empty_Temps_Dir; - OS_Exit (1); - end if; - - Gnatcov_P := Locate_Exec_On_Path ("gnatcov"); - if Gnatcov_P = null then - Put_Error ("gnatcov not found."); - OS_Exit (1); - end if; - Gnatcov_Args (1) := new String'("convert"); - Next_Arg_Idx := 2; - for J in 1 .. Argument_Count loop - if Argument (J) (1) /= '-' then - if Target_Exec_Seen then - Put_Error ("Multiple exec args seen."); - OS_Exit (1); - else - Gnatcov_Args (Next_Arg_Idx) := - new String'("--exec=" & Argument (J)); - Next_Arg_Idx := Next_Arg_Idx + 1; - - Gnatcov_Args (Next_Arg_Idx) := - new String'("--output=" & - Ada.Directories.Base_name (Argument (J)) & - ".trace"); - Next_Arg_Idx := Next_Arg_Idx + 1; - - Target_Exec_Seen := True; - end if; - elsif Argument (J)'Length > 2 and then Argument (J) (1 .. 2) = "-P" then - Gnatcov_Args (Next_Arg_Idx) := new String'(Argument (J)); - Next_Arg_Idx := Next_Arg_Idx + 1; - elsif Argument (J)'Length = 2 and then Argument (J) = "-P" then - Put_Error ("Project switch format ('-P', '')" & - " is not supported. Only ('-P') works."); - OS_Exit (1); - else - for K in Poss_Args'Range loop - if Argument (J)'Length > Poss_Args (K).Arg_Name'Length + 1 - and then Argument (J) (1 .. Poss_Args (K).Arg_Name'Length) - = Poss_Args (K).Arg_Name.all - then - if Poss_Args (K).Seen then - Put_Line (Standard_Error, - Poss_Args (K).Arg_Name.all & " seen twice"); - OS_Exit (1); - end if; - if Poss_Args (K).Arg_Name'Length = 8 and then - Poss_Args (K).Arg_Name.all = "--target" - then - Gnatcov_Args (Next_Arg_Idx) := new String'(Argument (J)); - Next_Arg_Idx := Next_Arg_Idx + 1; - - Gnatcov_Args (Next_Arg_Idx) := - new String'("--trace-source=iSystem-5634"); - else - Gnatcov_Args (Next_Arg_Idx) := new String'(Argument (J)); - end if; - Next_Arg_Idx := Next_Arg_Idx + 1; - Poss_Args (K).Seen := True; - exit; - elsif K = Poss_Args'Last then - Put_Line (Standard_Error, - "Argument """ & Argument (J) & """ not recognized."); - OS_Exit (1); - end if; - end loop; - end if; - end loop; - for K in Poss_Args'Range loop - if Poss_Args (k).Required and then not Poss_Args (K).Seen then - Put_Error (Poss_Args (K).Arg_Name.all & " missing."); - OS_Exit (1); - end if; - end loop; - Gnatcov_Args (Next_Arg_Idx) := - new String'("--hw-trigger-traces=IAC1,main,IAC2"); - Next_Arg_Idx := Next_Arg_Idx + 1; - Gnatcov_Args (Next_Arg_Idx) := - new String'("--input=" & Wspace_Dir_Name & "\nexus_trace.bin"); - - Open (Argslog_File, Append_File, Argslog_Name); - New_Line (Argslog_File); - Put_Line (Argslog_File, "GNATCOV ARGS...."); - for J in 1 .. Next_Arg_Idx loop - Put_Line (Argslog_File, Gnatcov_Args (J).all); - end loop; - Close (Argslog_File); - - Spawn (Gnatcov_P.all, Gnatcov_Args (1 .. Next_Arg_Idx), Success); - if not Success then - Put_Error ("gnatcov convert failed."); - OS_Exit (1); - end if; - - Empty_Temps_Dir; - -end crun; diff --git a/testsuite/altrun/isys_nexus_5634/get_trace.py b/testsuite/altrun/isys_nexus_5634/get_trace.py deleted file mode 100644 index a7104e584..000000000 --- a/testsuite/altrun/isys_nexus_5634/get_trace.py +++ /dev/null @@ -1,134 +0,0 @@ -import time -import sys -import os -executable = sys.argv [1] - -import isystem.connect as ic - -cmgr = ic.ConnectionMgr() -cmgr.connectMRU() -wspaceControl = ic.CWorkspaceController (cmgr) -wspaceControl.open(os.path.abspath('.\isyswspace\justrun.xjrf')) - -print 'WinIDEA workspace is now open' - -traceDoc = ic.CTraceController (cmgr, 'new_trigger.trd', 'w') -triggerIdx = traceDoc.createTrigger ('new_trigger') -traceDoc.select (triggerIdx) - -# Full list of available option can be found in WinIDEA Help->Display Options... -traceDoc.setTriggerOption (triggerIdx, "UseAdvancedTrigger", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "EnableProfiler", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "EnableCoverage", "FALSE") -#traceDoc.setTriggerOption (triggerIdx, "Trigger.Global.ProfilerOperationMode", "Range") - -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.Start", "Immediately") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.BufferSize", "1 GB") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.TriggerPosition", "Begin") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.StallCPU ", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.BreakOnTrigger", "FALSE") - -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.Enabled", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].Enabled", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].Anything", "FALSE") - -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].IAC_Enable[0]", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].IAC_Enable[1]", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].IAC_Combination[0]", "None") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.e200[0].IAC_Address[0]", "main") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.e200[0].IAC_Address[1]", "_exit") - -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordProgram", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordData", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordOTM", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].PeriodicOTM", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordWP", "All") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].ProgramTrace", "BranchMsg") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].PgmStart", "IAC1") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].PgmEnd", "IAC2") - -loader = ic.CLoaderController (cmgr) -executer = ic.CExecutionController (cmgr) -debug = ic.CDebugFacade(cmgr) -status = debug.getCPUStatus() - -print 'Trying to connect to the probe/board...' - -for try_nb in range(10): - debug = ic.CDebugFacade(cmgr) - status = debug.getCPUStatus() - isConnected = (not status.isMustInit()) - print 'is connected: ' + str(isConnected) - print status.toString() - - if isConnected: - break - - try: - debug.reset() - except: - print 'exception in debug.reset()' - - executer = ic.CExecutionController (cmgr) - try: - executer.reset() - except: - print 'exception in executer.reset()' - try: - executer.stop() - except: - print 'exception in executer.stop()' - - time.sleep (1) - -executer.reset () -executer.stop () -MPCCtrl = ic.CMPC5xxxController (cmgr) -TLB = MPCCtrl.getTLB (0) -TLB.m_dwMAS0 = 0x10030000 -TLB.m_dwMAS1 = 0xC0000400 -TLB.m_dwMAS2 = 0x40000008 -TLB.m_dwMAS3 = 0x4000003F -TLB.m_dwMAS4 = 0x00030413 -TLB.m_dwMAS5 = 0x00000000 -MPCCtrl.setTLB (0, TLB) - -downloadConfig = ic.CDownloadConfiguration () -downloadConfig.setCodeOffset (0).setSymbolsOffset (0). \ - setUsedInFullDownload (True). \ - setDownloadFileFormat (ic.CDownloadConfiguration.ftELF); - -dbg = ic.CDebugFacade(cmgr) -loader.targetDownload (downloadConfig, executable, -' LoadSymbols(Global) LoadZeros(0) LoadDwarfSection(1) ReverseBitFields(0) DumpELFHeaders(0) LoadCode(Virtual) CallStack(Automatic) MergeTypes(0) GCC_ARM_double_Format(Swapped) RemoveOptimizedLines(1) InsertInlinedFunctions(0) IgnoreNonStatementLines(1) ') -isyminfo = dbg.getSymbolInfo (ic.IConnectDebug.fMonitor | - ic.IConnectDebug.gafExpression, '_start') -dbg.gotoAddress (0, isyminfo.getAddress () ) -isyminfo = dbg.getSymbolInfo (ic.IConnectDebug.fMonitor | - ic.IConnectDebug.gafExpression, '_exit') - -traceDoc.start () - -print 'Start execution...' - -executer.runUntilAddress (0, isyminfo.getAddress () ) -if not executer.waitUntilStopped (pollingInterval=5000, timeout=400000): - print '!!! EXECUTION TIMEOUT !!!' - -print '... execution stoped.' - -last_chance = dbg.evaluate(ic.IConnectDebug.fRealTime, '__gnat_unexpected_last_chance_call') -if last_chance.getInt() != 0: - print '!!! EXCEPTION RAISED !!!' - -traceDoc.waitUntilLoaded (0, 100) -formatter = ic.CTraceBinExportFormat () -formatter.setTraceItemFlags (0) -formatter.setHeader (False) \ - .addTraceItem (ic.CTraceBinExportFormat.EOCDItem) -exportCfg = ic.CTraceExportConfig () -exportCfg.setFileName ('nexus_trace.bin').setFormatter (formatter) -traceDoc.exportData (exportCfg) -traceDoc.closeAll () - -cmgr.disconnect (0) diff --git a/testsuite/altrun/isys_nexus_5634/justrun.xjrf b/testsuite/altrun/isys_nexus_5634/justrun.xjrf deleted file mode 100755 index cf4f6cc6d..000000000 --- a/testsuite/altrun/isys_nexus_5634/justrun.xjrf +++ /dev/null @@ -1,4244 +0,0 @@ - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - HODGDFEIGHBIMPAB - FFOIJOFDLBGFEHEPLMCGJJGGPCJIBEJH - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - 0 - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - MKGJKBGOKIIJMOAB - HMFBCKJFLOPDDHEDJCOMAJLCICINJJMK - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - 0 - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - HASYST - 1258881024 - - 0 - - - False - - - - 0 - justrun.trd - - - ..\..\..\..\..\calib\justrun.trd - - - - 0 - 0 - 0 - 0 - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 1 - 0 - 0 - 0 - -1 - - 0 - 600 - 0 - -1 - - 1 - 28 - 2 - -1 - - 1 - 227 - File - 10 - 7 - - - 1 - 2 - 6 - -1 - - - 1 - 369 - View - 10 - 8 - - - 1 - 0 - 6 - -1 - - - - 1 - 2 - 6 - -1 - - - 1 - 200 - Project Workspace - 0 - 1 - - - 1 - 5 - 6 - -1 - - - 1 - 700 - 1 - -2 - - - 1 - 0 - 6 - -1 - - - - 1 - 5 - 6 - -1 - - - 0 - 200 - 0 - -1 - - 1 - 200 - Output - 0 - 0 - - - 1 - 5 - 6 - -1 - - - 1 - 480 - DocWnd - 0 - 21 - - justrun.trd - - - - 1 - 0 - 6 - -1 - - - - 1 - 0 - 6 - -1 - - - - - - - True - True - - - - False - - - - 0 - - - 1 - - - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - - - 0 - 0 - - - - -1 - 0 - - - 0 - 0 - - main - 0 - 0 - 1 - 0 - 1 - True - 0 - 0 - main - 0 - False - 0 - - -1 - 0 - - - - False - False - False - history.txt - True - False - True - 0 - True - False - True - - - $Download.xml - 0 - 1 - 1 - 1 - - - 0 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - - <__.0> - DEFAULT - 0 - 0 - - 0 - - - - - - 0 - - - 0 - - - 0 - 0 - 1 - - - - 0xCC - 2 - - - 0 - - - True - True - True - True - symbols.txt - True - True - - - 0 - 1 - 0 - True - 1 - 2 - False - False - False - False - False - 0 - 1 - 0 - 0 - False - 1 - 1 - True - 256 - 1 - _ - 0 - 0 - 0.0000100000000000 - - - 0 - - - - False - True - 1 - False - 200 - True - False - True - False - True - False - False - - 0 - 0 - 0 - 0 - 1 - - - - 1 - - 0 - 0 - 1 - - - - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - AAABACADAEAFAGAHAIAJAKALAMANAOAPBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBP - 0 - - - 1 -
0
- - - 0 - True - -
- - -1 - 0 - - - <__> - 0 - 0 - 0 - - - - <__> - 0 - 0 - 0 - - - - 0 - 0 - -
- - - 0 - - - - - - - - - - - - - - - - - 0 - 1 - 1 - - - - - - - - - - 0 - 0 - - - - - - Build 9.12.144 - - - - 0 - 0 - - - 1 - 0 - 1 - 0 - 1 - - - - - - - - - - - - - - - 0 - - - 2 - - - 0 - 1 - 0 - 0 - 2 - 0 - - - -1 - - 0 - - 0 - 0 - 9600 - COM1 - 8 - 0 - 0 - 0 - 0 - 24 - 80 - 500 - 0 - 1 - 0 - - - - - 0 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - - - 1 - 1 - 1 - 0 - <_166> - 0 - - <_68k> - 0 - - - 1 - 0 - - - 0 - - 1 - - - - 0 - - - - - - - - - - - <_-Cs08>1 - - - 0 - - - 0 - - 0 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - 1 - - - - - 1 - 1 - True - 1 - 0 - 0 - 1 - 0 - 0 - False - False - True - 16 - - 100 - 1 - True - - - - - - - - - - - <__> - Files - 4 - - - - - - - - - - -
- - <_76946E39-78E2-4625-9BF0-751C4C11A09F> - - - 0 - 0 - 0 - 5544 - 1 - - - - -
-
- - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - 60 - 20 - 70 - 60 - 20 - 70 - 10 - - - 0.0000000000000000 - 0 - 0 - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - - - - 0 - - 0 - 0 - - 1 - - - 0.0000000000000000 - 0 - 0 - - 0 - - - - - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - 1 - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 1 - -
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
-
-
-
- - - 0 - - - 0 - - - 0 - - 0 - 0 - 0 - Default - 2 - 0 - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - - - - - 16000 - - - 0 - - -
- - - 1 - 0 - 0 - 0 - - - - - AIN0 - - - AIN1 - - - AIN0 - - - AIN1 - - - DIN0 - - - DIN1 - - - DIN10 - - - DIN11 - - - DIN12 - - - DIN13 - - - DIN14 - - - DIN15 - - - DIN16 - - - DIN17 - - - DIN18 - - - DIN19 - - - DIN2 - - - DIN20 - - - DIN21 - - - DIN22 - - - DIN23 - - - DIN24 - - - DIN25 - - - DIN26 - - - DIN27 - - - DIN28 - - - DIN29 - - - DIN3 - - - DIN30 - - - DIN31 - - - DIN4 - - - DIN5 - - - DIN6 - - - DIN7 - - - DIN8 - - - DIN9 - - - DOUT0 - - - DOUT1 - - - DOUT10 - - - DOUT11 - - - DOUT12 - - - DOUT13 - - - DOUT14 - - - DOUT15 - - - DOUT16 - - - DOUT17 - - - DOUT18 - - - DOUT19 - - - DOUT2 - - - DOUT20 - - - DOUT21 - - - DOUT22 - - - DOUT23 - - - DOUT24 - - - DOUT25 - - - DOUT26 - - - DOUT27 - - - DOUT28 - - - DOUT29 - - - DOUT3 - - - DOUT30 - - - DOUT31 - - - DOUT4 - - - DOUT5 - - - DOUT6 - - - DOUT7 - - - DOUT8 - - - DOUT9 - - - 1 - 4 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 0 - 0 - 0 - - - - - 1 - 1 - 1 - 1 - 1 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - -
0
- 0 - False - 0 - 0 - 1 - 0 - 0 - 0 - 0 -
- - 0 - - AAAAAAAA - 0 - - - 1 - #g_TConn - 1 - - #g_TWBuffer - 1 - 0 - - - #g_TRBuffer - 1 - 0 - - - - - 0 - 2 - 0 - 0 - 0 - - - 0 - - - -
- - - 1 - 1 ns - - - 1 - - - 0 - - - 1 - - -
- - 144 - 0 - 9 - 1 - 12 - 151781664 - - - 50 - 0 - 127 - 1 - 11 - 7 - - - <_55xx_AllowFLASHPgmOnlyDuringDL>0 - <_55xx_DCI_CR>-2048 - <_55xx_EnableShadowMemoryProgramming>0 - <_55xx_EVTOOnlyOnBP>0 - <_55xx_InitMMU>0 - <_55xx_InitMMU_VLE>0 - <_55xx_InitRAM>2 - <_55xx_LowPowerDebug>0 - <_55xx_LowPowerDebug_Run>0 - <_55xx_LowPowerDebug_StopBefore>0 - <_55xx_MassEraseDataFLASH>0 - <_55xx_MassEraseProgramFLASH>0 - <_55xx_Mode>0 - <_55xx_NexusEBI>0 - <_55xx_Password type="B">AAAAAAAAAAAAAAAA - <_55xx_PINCR>0 - <_55xx_StopTimerDuringStep>0 - <_55xx_StopWhenReleasedFromReset>0 - <_55xx_UseBDMMemAccessWhenStopped>0 - <_55xx_UsePassword>0 - <_55xx_UseTrapForSWBPsinPowerPCMode>0 - <_83xx_RCWH>0 - <_83xx_RCWL>0 - <_83xx_RCWOverride>0 - True - 0 - False - True - 0 - 0 - 0 - 67108864 - -1048320 - 0 - - 0 - 0 - - - 0x0 - 0 - - - - 0 - 0 - 0 - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 10 - 114 - 1 - 0 - 4000 - 0 - 0 - 0 - 0 - 10 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 2 - 1 - 1 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - -
0
- 0 - 0 - 0 - 0 - 0 - 0 - 0 -
- - 0 - 1 - 0 - 0 - -
0
- 0 - 0 - 0 -
-
-
- - -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
-
- - 0 - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0 - 1000 - 0 - 0 - 500 - 0 - 0 - 0 - 0 - 1 - 0 - - - 1 - 0 - 3300 - False - 0 - 0 - 1 - 1500 - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - - 0 - - - 0 - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - -
- - 1 - 2 - - 2 - 0 - - - - 10.10.10.10 - 0 - 0 - 3 - 1 - 0 - 5313 - iC5000 (SN 68020) - - - - 0 - - 0 - - -
-
-
-
-
diff --git a/testsuite/altrun/isys_nexus_5634/post_testcase.py b/testsuite/altrun/isys_nexus_5634/post_testcase.py deleted file mode 100755 index 82752b0f5..000000000 --- a/testsuite/altrun/isys_nexus_5634/post_testcase.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python - - -import time -import sys -import os - -altrun_dir = sys.argv[1] -ws_file = altrun_dir + '\ws\j.xjrf' - -import isystem.connect as ic - -# Switch to dummy workspace after test to allow cleanup - - -cmgr = ic.ConnectionMgr() -cmgr.connectMRU() - -wspaceControl = ic.CWorkspaceController (cmgr) -wspaceControl.open(os.path.abspath(ws_file)) - -cmgr.disconnect (0) diff --git a/testsuite/altrun/isys_nexus_5634/post_testsuite.py b/testsuite/altrun/isys_nexus_5634/post_testsuite.py deleted file mode 100755 index 011f6879e..000000000 --- a/testsuite/altrun/isys_nexus_5634/post_testsuite.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -# Stop all running instances of winIDEA - -import isystem.connect as ic - -cmgr = ic.ConnectionMgr () - -connectionConfig = ic.CConnectionConfig () - -port = 0 -while (1): - port = cmgr.findExistingInstance ('', connectionConfig) - if (port < 0): - break; - else: - print 'stopping winIDEA at port: ', port - cmgr.connect('', port) - cmgr.disconnect (ic.IConnect.dfCloseServerUnconditional | ic.IConnect.dfCloseAutoSaveNone) diff --git a/testsuite/altrun/isys_nexus_5634/pre_testsuite.py b/testsuite/altrun/isys_nexus_5634/pre_testsuite.py deleted file mode 100755 index 5d7b8ed07..000000000 --- a/testsuite/altrun/isys_nexus_5634/pre_testsuite.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python - -# Stop all running instances of winIDEA and then -# start a single instance using the simple workspace -# in the 'ws' directory. - -import os -import isystem.connect as ic -import time - -cmgr = ic.ConnectionMgr () - -connectionMgr = ic.ConnectionMgr() -connectionConfig = ic.CConnectionConfig() -winIDEAInstances = ic.VectorWinIDEAInstanceInfo() - -hostAddress = '' # enumerate instances on local host. You may also specify remote host - # here, for example as IP address: '10.1.2.91' -connectionMgr.enumerateWinIDEAInstances(hostAddress, connectionConfig, winIDEAInstances) - -# Now we'll connect to each of found winIDEA instances and close them -for instance in winIDEAInstances: - instanceCMgr = ic.ConnectionMgr() - instanceCMgr.connect(hostAddress, instance.getTcpPort()) - instanceCMgr.disconnect (ic.IConnect.dfCloseServerUnconditional | ic.IConnect.dfCloseAutoSaveNone) - print 'Kill WinIDEA at port: ', instance.getTcpPort() - -ws1 = os.path.abspath('ws/j.xjrf') -cmgr = ic.ConnectionMgr() -connectionConfig = ic.CConnectionConfig() -connectionConfig.visibility(ic.IConnect.lfShowHidden) - -print "Openning workspace at '%s'" % ws1 -connectionConfig.workspace (ws1) - -port = cmgr.startNewInstance (connectionConfig) -print 'new winIDEA at port: ', port - -cMgr = ic.ConnectionMgr() -cMgr.connectMRU('') - -ide = ic.CIDEController(cMgr) -print 'winIDEA version : ' + ide.getWinIDEAVersion().toString() - -# Set probe communication options -ide.setOption('/IOPEN/Communication.USBDeviceName', 'iC5000 (SN 68020)') -ide.setOption('/IOPEN/Communication.IPAddress', 'iC5000 (SN 68020) : 5313') -ide.setOption('/IOPEN/Communication.Mode', 'USB') -ide.commitOptions('/IOPEN/') - -for try_nb in range(10): - debug = ic.CDebugFacade(cMgr) - status = debug.getCPUStatus() - isConnected = (not status.isMustInit()) - print 'is connected: ' + str(isConnected) - if isConnected: - break - - executer = ic.CExecutionController (cMgr) - try: - executer.reset() - except: - print 'exception in executer.reset()' - try: - executer.stop() - except: - print 'exception in executer.reset()' - - time.sleep (1) - -executer = ic.CExecutionController (cMgr) -executer.reset () -executer.stop () -# the steps above are included because the retrieval -# of the firmware info from the ic5000 doesn't work -# until some action has occured. diff --git a/testsuite/altrun/isys_nexus_5634/setup.py b/testsuite/altrun/isys_nexus_5634/setup.py deleted file mode 100644 index 6858ebf5b..000000000 --- a/testsuite/altrun/isys_nexus_5634/setup.py +++ /dev/null @@ -1,14 +0,0 @@ -# This holds "setup" code for the example altrun/ subdir. - -# This is called before looking for binaries to setup testsuite and testcase -# hooks. Here, we produce one such binary from ada sources. - -from gnatpython.ex import Run -import sys - -p = Run (['gnatmake', '-f', '-g', '-p', '-Paltrun', "crun.adb"], - output=sys.stdout) - -if p.status != 0: - sys.exit(1) - diff --git a/testsuite/altrun/isys_nexus_5634/ws/j.xjrf b/testsuite/altrun/isys_nexus_5634/ws/j.xjrf deleted file mode 100755 index 245795517..000000000 --- a/testsuite/altrun/isys_nexus_5634/ws/j.xjrf +++ /dev/null @@ -1,3950 +0,0 @@ - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - MKGJKBGOKIIJMOAB - HMFBCKJFLOPDDHEDJCOMAJLCICINJJMK - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - 0 - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - HASYST - 1258881024 - - 0 - - - False - - - - - -31812 - -32168 - -31672 - -32164 - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 1 - 0 - 0 - 0 - -1 - - 0 - 600 - 0 - -1 - - 1 - 28 - 2 - -1 - - 1 - 227 - File - 10 - 7 - - - 1 - 2 - 6 - -1 - - - 1 - 369 - View - 10 - 8 - - - 1 - 0 - 6 - -1 - - - - 1 - 2 - 6 - -1 - - - 1 - 200 - Project Workspace - 0 - 1 - - - 1 - 5 - 6 - -1 - - - 1 - 700 - 1 - -2 - - - 1 - 0 - 6 - -1 - - - - 1 - 5 - 6 - -1 - - - 1 - 200 - Output - 0 - 0 - - - 1 - 0 - 6 - -1 - - - - - - - True - True - - - - False - - - - 0 - - - 1 - - - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - - - 0 - 0 - - - - -1 - 0 - - - 0 - 0 - - main - 0 - 0 - 1 - 0 - 1 - True - 0 - 0 - main - 0 - False - 0 - - -1 - 0 - - - - False - False - False - history.txt - True - False - True - 0 - True - False - True - - - $Download.xml - 0 - 1 - 1 - 1 - - - 0 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - - <__.0> - DEFAULT - 0 - 0 - - 0 - - - - - - 0 - - - 0 - - - 0 - 0 - 1 - - - - 0xCC - 2 - - - 0 - - - True - True - True - True - symbols.txt - True - True - - - 0 - 1 - 0 - True - 1 - 2 - False - False - False - False - False - 0 - 1 - 0 - 0 - False - 1 - 1 - True - 256 - 1 - _ - 0 - 0 - 0.0000100000000000 - - - 0 - - - - False - True - 1 - False - 200 - True - False - True - False - True - False - False - - 0 - 0 - 0 - 0 - 1 - - - - 1 - - 0 - 0 - 1 - - - - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - AAABACADAEAFAGAHAIAJAKALAMANAOAPBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBP - 0 - - - 1 -
0
- - - 0 - True - -
- - -1 - 0 - - - <__> - 0 - 0 - 0 - - - - <__> - 0 - 0 - 0 - - - - 0 - 0 - -
- - - 0 - - - - - - - - - - - - - - - - - 0 - 1 - 1 - - - - - - - - - - 0 - 0 - - - - - - Build 9.12.144 - - - - 0 - 0 - - - 1 - 0 - 1 - 0 - 1 - - - - - - - - - - - - - - - 0 - - - 2 - - - 0 - 1 - 0 - 0 - 2 - 0 - - - -1 - - 0 - - 0 - 0 - 9600 - COM1 - 8 - 0 - 0 - 0 - 0 - 24 - 80 - 500 - 0 - 1 - 0 - - - - - 0 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - - - 1 - 1 - 1 - 0 - <_166> - 0 - - <_68k> - 0 - - - 1 - 0 - - - 0 - - 1 - - - - 0 - - - - - - - - - - - <_-Cs08>1 - - - 0 - - - 0 - - 0 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - 1 - - - - - 1 - 1 - True - 1 - 0 - 0 - 1 - 0 - 0 - False - False - True - 16 - - 100 - 1 - True - - - - - - - - - - - <__> - Files - 4 - - - - - - - - - - -
- - <_76946E39-78E2-4625-9BF0-751C4C11A09F> - - - 0 - 0 - 0 - 5544 - 1 - - - - -
-
- - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - 60 - 20 - 70 - 60 - 20 - 70 - 10 - - - 0.0000000000000000 - 0 - 0 - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - - - - 0 - - 0 - 0 - - 1 - - - 0.0000000000000000 - 0 - 0 - - 0 - - - - - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - 1 - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 1 - -
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
-
-
-
- - - 0 - - - 0 - - - 0 - - 0 - 0 - 0 - Default - 2 - 0 - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - - - - - 16000 - - - 0 - - -
- - - 1 - 0 - 0 - 0 - - - - - AIN0 - - - AIN1 - - - AIN0 - - - AIN1 - - - DIN0 - - - DIN1 - - - DIN10 - - - DIN11 - - - DIN12 - - - DIN13 - - - DIN14 - - - DIN15 - - - DIN16 - - - DIN17 - - - DIN18 - - - DIN19 - - - DIN2 - - - DIN20 - - - DIN21 - - - DIN22 - - - DIN23 - - - DIN24 - - - DIN25 - - - DIN26 - - - DIN27 - - - DIN28 - - - DIN29 - - - DIN3 - - - DIN30 - - - DIN31 - - - DIN4 - - - DIN5 - - - DIN6 - - - DIN7 - - - DIN8 - - - DIN9 - - - DOUT0 - - - DOUT1 - - - DOUT10 - - - DOUT11 - - - DOUT12 - - - DOUT13 - - - DOUT14 - - - DOUT15 - - - DOUT16 - - - DOUT17 - - - DOUT18 - - - DOUT19 - - - DOUT2 - - - DOUT20 - - - DOUT21 - - - DOUT22 - - - DOUT23 - - - DOUT24 - - - DOUT25 - - - DOUT26 - - - DOUT27 - - - DOUT28 - - - DOUT29 - - - DOUT3 - - - DOUT30 - - - DOUT31 - - - DOUT4 - - - DOUT5 - - - DOUT6 - - - DOUT7 - - - DOUT8 - - - DOUT9 - - - 1 - 4 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 0 - 0 - 0 - - - - - 1 - 1 - 1 - 1 - 1 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - -
0
- 0 - False - 0 - 0 - 1 - 0 - 0 - 0 - 0 -
- - 0 - - AAAAAAAA - 0 - - - 1 - #g_TConn - 1 - - #g_TWBuffer - 1 - 0 - - - #g_TRBuffer - 1 - 0 - - - - - 0 - 2 - 0 - 0 - 0 - - - 0 - - - -
- - - 1 - 1 ns - - - 1 - - - 0 - - - 1 - - -
- - 144 - 0 - 9 - 1 - 12 - 151781664 - - - 50 - 0 - 127 - 1 - 11 - 7 - - - <_55xx_AllowFLASHPgmOnlyDuringDL>0 - <_55xx_DCI_CR>-2048 - <_55xx_EnableShadowMemoryProgramming>0 - <_55xx_EVTOOnlyOnBP>0 - <_55xx_InitMMU>0 - <_55xx_InitMMU_VLE>0 - <_55xx_InitRAM>2 - <_55xx_LowPowerDebug>0 - <_55xx_LowPowerDebug_Run>0 - <_55xx_LowPowerDebug_StopBefore>0 - <_55xx_MassEraseDataFLASH>0 - <_55xx_MassEraseProgramFLASH>0 - <_55xx_Mode>0 - <_55xx_NexusEBI>0 - <_55xx_Password type="B">AAAAAAAAAAAAAAAA - <_55xx_PINCR>0 - <_55xx_StopTimerDuringStep>0 - <_55xx_StopWhenReleasedFromReset>0 - <_55xx_UseBDMMemAccessWhenStopped>0 - <_55xx_UsePassword>0 - <_55xx_UseTrapForSWBPsinPowerPCMode>0 - <_83xx_RCWH>0 - <_83xx_RCWL>0 - <_83xx_RCWOverride>0 - True - 0 - False - True - 0 - 0 - 0 - 67108864 - -1048320 - 0 - - 0 - 0 - - - 0x0 - 0 - - - - 0 - 0 - 0 - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 10 - 114 - 1 - 0 - 4000 - 0 - 0 - 0 - 0 - 10 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 2 - 1 - 1 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - -
0
- 0 - 0 - 0 - 0 - 0 - 0 - 0 -
- - 0 - 1 - 0 - 0 - -
0
- 0 - 0 - 0 -
-
-
- - -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
-
- - 0 - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0 - 1000 - 0 - 0 - 500 - 0 - 0 - 0 - 0 - 1 - 0 - - - 1 - 0 - 3300 - False - 0 - 0 - 1 - 1500 - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - - 0 - - - 0 - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - -
- - 1 - 2 - - 2 - 0 - - - - 10.10.10.10 - 0 - 0 - 3 - 1 - 0 - 5313 - iC5000 (SN 68020) - - - - 0 - - 0 - - -
-
-
-
-
diff --git a/testsuite/altrun/trace32/crun.py b/testsuite/altrun/trace32/crun.py index 72f3e0cba..2d7e53ed4 100755 --- a/testsuite/altrun/trace32/crun.py +++ b/testsuite/altrun/trace32/crun.py @@ -22,8 +22,8 @@ # --------- # -- log -- # --------- -def log(str): - print("trace32/crun.py:" + str) +def log(msg): + print("trace32/crun.py:" + msg) # ------------- @@ -34,10 +34,10 @@ def to_list(blob): and whitespace separated strings. Return empty list otherwise.""" return ( - blob if isinstance(blob, list) - else blob.split() if isinstance(blob, str) - else [] - ) + blob + if isinstance(blob, list) + else blob.split() if isinstance(blob, str) else [] + ) # ----------------- @@ -68,9 +68,7 @@ def do(command): class Runner: - def __init__(self): - log("============== CRUN FOR TRACE32 ===================") self.parse_command_line() self.run_with_trace32() @@ -88,55 +86,31 @@ def parse_command_line(self): # --level and --target are expected to always be there: - op.add_option( - "--level", dest="covlevel", default=None - ) - op.add_option( - "--target", dest="target", default=None - ) - op.add_option( - "--RTS", dest="RTS", default=None - ) - op.add_option( - "--config", dest="config", default=None - ) + op.add_option("--level", dest="covlevel", default=None) + op.add_option("--target", dest="target", default=None) + op.add_option("--RTS", dest="RTS", default=None) + op.add_option("--config", dest="config", default=None) # For source coverage tests not using project files: - op.add_option( - "--scos", dest="scos", default=None - ) + op.add_option("--scos", dest="scos", default=None) # For tests using project files + op.add_option("-P", dest="gpr", default=None) op.add_option( - "-P", dest="gpr", default=None - ) - op.add_option( - "--recursive", dest="recurse", default=False, action='store_true' - ) - op.add_option( - "--projects", dest="projects", default=None - ) - op.add_option( - "--units", dest="units", default=None - ) - op.add_option( - "--subdirs", dest="subdirs", default=None - ) - op.add_option( - "-v", "--verbose", dest="verbose", default=None - ) + "--recursive", dest="recurse", default=False, action="store_true" + ) + op.add_option("--projects", dest="projects", default=None) + op.add_option("--units", dest="units", default=None) + op.add_option("--subdirs", dest="subdirs", default=None) + op.add_option("-v", "--verbose", dest="verbose", default=None) - op.add_option( - "--exec-prefix", dest="execprefix", default=None - ) + op.add_option("--exec-prefix", dest="execprefix", default=None) # Then a few optional items - op.add_option( - "-o", dest="ofile", default=None - ) + op.add_option("-o", dest="ofile", default=None) (self.options, self.args) = op.parse_args() @@ -227,7 +201,7 @@ def get_gnatcov_trace_filename(self): return os.path.basename(self.get_executable_filename()) + ".trace" def get_t32_trace_filename(self): - return self.get_gnatcov_trace_filename() + '.t32_branchflow' + return self.get_gnatcov_trace_filename() + ".t32_branchflow" def run_with_trace32(self): print("=============== RUN ON TRACE32 ===================") @@ -236,7 +210,7 @@ def run_with_trace32(self): sys.exit(1) log("Executable is: " + str(self.args)) - handled_targets = ['trace32-stm32f7'] + handled_targets = ["trace32-stm32f7"] if self.options.target not in handled_targets: print("unknown target %s" % self.options.target) return @@ -244,7 +218,7 @@ def run_with_trace32(self): t32api.connect() t32api.basic_setup() - if self.options.target == 'trace32-stm32f7': + if self.options.target == "trace32-stm32f7": t32api.init_trace_stm32f7() t32api.load_executable(self.get_executable_filename()) diff --git a/testsuite/altrun/trace32/pre_testsuite.py b/testsuite/altrun/trace32/pre_testsuite.py index 2c5d1e87c..f34378e68 100644 --- a/testsuite/altrun/trace32/pre_testsuite.py +++ b/testsuite/altrun/trace32/pre_testsuite.py @@ -7,16 +7,17 @@ # --------- # -- log -- # --------- -def log(str): - print("trace32/pre_testsuite.py:" + str) +def log(msg): + print("trace32/pre_testsuite.py:" + msg) altrun_dir_path = os.path.dirname(os.path.realpath(__file__)) -os.environ['T32SYS'] = PATH_TO_T32_HOME -os.environ['T32TMP'] = "/tmp" -os.environ['T32PDFVIEWER'] = \ +os.environ["T32SYS"] = PATH_TO_T32_HOME +os.environ["T32TMP"] = "/tmp" +os.environ["T32PDFVIEWER"] = ( PATH_TO_T32_HOME + "/bin/pc_linux64/t32_startpdfviewer.sh" +) # Run t32usbchecker to reset the probe in case it is already connected. # @@ -27,15 +28,16 @@ def log(str): # It should be possble to achive the same result with the # CONNECTIONMODE=AUTOCONNECT parameter of the configuration, however this # parameter doesn't work with the SCREEN=OFF mode. -p = e3.os.process.Run([os.path.dirname(PATH_TO_T32) + '/t32usbchecker'], - output="t32usbchecker.out", - bg=False) - -p = e3.os.process.Run([PATH_TO_T32, - "-c", - os.path.join(altrun_dir_path, 'config.t32') - ], - output="t32.out", - bg=True) +p = e3.os.process.Run( + [os.path.dirname(PATH_TO_T32) + "/t32usbchecker"], + output="t32usbchecker.out", + bg=False, +) + +p = e3.os.process.Run( + [PATH_TO_T32, "-c", os.path.join(altrun_dir_path, "config.t32")], + output="t32.out", + bg=True, +) sleep(20) diff --git a/testsuite/altrun/trace32/t32api.py b/testsuite/altrun/trace32/t32api.py index d47f8b890..8e94ab33e 100644 --- a/testsuite/altrun/trace32/t32api.py +++ b/testsuite/altrun/trace32/t32api.py @@ -8,43 +8,40 @@ T32_OK = 0 EXIT_FAILURE = 1 -PATH_TO_T32 = find_executable('t32marm-qt') +PATH_TO_T32 = find_executable("t32marm-qt") # We can't continue without a t32 executable assert PATH_TO_T32, "no Trace32 executable on path" -PATH_TO_T32_HOME = os.path.join(os.path.dirname(PATH_TO_T32), '../../') -PATH_TO_T32_PY_API = os.path.join(PATH_TO_T32_HOME, 'demo/api/python/legacy') +PATH_TO_T32_HOME = os.path.join(os.path.dirname(PATH_TO_T32), "../../") +PATH_TO_T32_PY_API = os.path.join(PATH_TO_T32_HOME, "demo/api/python/legacy") # auto-detect the correct library -if (platform.system() == 'Windows') or (platform.system()[0:6] == 'CYGWIN'): +if (platform.system() == "Windows") or (platform.system()[0:6] == "CYGWIN"): if ctypes.sizeof(ctypes.c_voidp) == 4: # WINDOWS 32bit t32 = ctypes.cdll.t32api else: # WINDOWS 64bit t32 = ctypes.cdll.t32api64 -elif platform.system() == 'Darwin': +elif platform.system() == "Darwin": # Mac OS X - t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, - "./t32api.dylib")) + t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, "./t32api.dylib")) else: if ctypes.sizeof(ctypes.c_voidp) == 4: # Linux 32bit - t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, - "./t32api.so")) + t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, "./t32api.so")) else: # Linux 64bit - t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, - "./t32api64.so")) + t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, "./t32api64.so")) # ----------------- # -- cmd_wrapper -- # ----------------- -def cmd_wrapper(cmd, wait_for_completion=False): +def cmd_wrapper(cmd, wait_for_completion=False): t32.T32_Cmd(cmd.encode()) if wait_for_completion: @@ -62,37 +59,48 @@ def cmd_wrapper(cmd, wait_for_completion=False): # -- connect -- # ------------- + def connect(node="localhost", port=20000, packlen=1024): t32.T32_Config(b"NODE=", node.encode()) t32.T32_Config(b"PORT=", str(port).encode()) t32.T32_Config(b"PACKLEN=", str(packlen).encode()) - print(' Connecting...') + print(" Connecting...") for i in range(1, 3): if t32.T32_Init() == T32_OK: if t32.T32_Attach(1) == T32_OK: - print('Successfully established a remote connection with' + - ' TRACE32 PowerView.') + print( + "Successfully established a remote connection with" + + " TRACE32 PowerView." + ) break else: if i == 1: - print('Failed once to established a remote connection' + - ' with TRACE32 PowerView.') + print( + "Failed once to established a remote connection" + + " with TRACE32 PowerView." + ) t32.T32_Exit() elif i == 2: - print('Failed twice to established a remote connection' + - ' with TRACE32 PowerView.') - print('Terminating ...') + print( + "Failed twice to established a remote connection" + + " with TRACE32 PowerView." + ) + print("Terminating ...") sys.exit(EXIT_FAILURE) else: if i == 1: - print(' Failed once to initialize a remote connection with' + - ' TRACE32 PowerView.') + print( + " Failed once to initialize a remote connection with" + + " TRACE32 PowerView." + ) t32.T32_Exit() elif i == 2: - print(' Failed twice to initialize a remote connection with' + - ' TRACE32 PowerView.') - print(' Terminating ...') + print( + " Failed twice to initialize a remote connection with" + + " TRACE32 PowerView." + ) + print(" Terminating ...") sys.exit(EXIT_FAILURE) @@ -100,6 +108,7 @@ def connect(node="localhost", port=20000, packlen=1024): # -- basic_setup -- # ----------------- + def basic_setup(): cmd_wrapper("RESet") cmd_wrapper("SYStem.RESet") @@ -115,6 +124,7 @@ def basic_setup(): # -- init_trace_stm32f7 -- # ------------------------ + def init_trace_stm32f7(): # initialize Offchip-Trace # DBGMCU_CR @@ -129,16 +139,19 @@ def init_trace_stm32f7(): cmd_wrapper("Data.Set E:0x40023830 %Long Data.Long(E:0x40023830)|0x10") # GPIOE_MODER - cmd_wrapper("Data.Set E:0x40021000 %Long" + - " Data.Long(E:0x40021000)|0x00002aa0") + cmd_wrapper( + "Data.Set E:0x40021000 %Long" + " Data.Long(E:0x40021000)|0x00002aa0" + ) # GPIOE_OSPEEDR - cmd_wrapper("Data.Set E:0x40021008 %Long" + - " Data.Long(E:0x40021008)|0x00003ff0") + cmd_wrapper( + "Data.Set E:0x40021008 %Long" + " Data.Long(E:0x40021008)|0x00003ff0" + ) # GPIOE_AFRL - cmd_wrapper("Data.Set E:0x40021020 %Long" + - " Data.Long(E:0x40021020)&0xf00000ff") + cmd_wrapper( + "Data.Set E:0x40021020 %Long" + " Data.Long(E:0x40021020)&0xf00000ff" + ) cmd_wrapper("TPIU.PortSize 4", wait_for_completion=True) cmd_wrapper("ETM.Trace ON", wait_for_completion=True) @@ -149,23 +162,24 @@ def init_trace_stm32f7(): # -- load_executable -- # --------------------- -def load_executable(path): +def load_executable(path): # The old breakpoints don't make sense with a new executable so we remove # them all. clear_breakpoints() - cmd_wrapper(f"Data.Load.auto \"{path}\"", wait_for_completion=True) + cmd_wrapper(f'Data.Load.auto "{path}"', wait_for_completion=True) # ------------------- # -- get_cpu_state -- # ------------------- + def get_cpu_state(): systemstate = ctypes.c_uint(0) retval = t32.T32_GetState(ctypes.byref(systemstate)) - if (retval == T32_OK): + if retval == T32_OK: states = ["down", "halted", "stopped", "running"] # Safeguard the little trick @@ -181,8 +195,8 @@ def get_cpu_state(): # -- run_until -- # --------------- -def run_until(symbol, timeout_sec): +def run_until(symbol, timeout_sec): # FIXME: It seems like we have to first do at least one step before using # go.direct. I don't know why at this point. cmd_wrapper("Step.Single 1", wait_for_completion=True) @@ -190,8 +204,7 @@ def run_until(symbol, timeout_sec): cmd_wrapper(f"go.direct {symbol}") # Wait for the CPU to stop or timeout - cmd_wrapper(f"WAIT !STATE.RUN() {timeout_sec}.s", - wait_for_completion=True) + cmd_wrapper(f"WAIT !STATE.RUN() {timeout_sec}.s", wait_for_completion=True) if get_cpu_state() == "running": # Stop the CPU @@ -203,28 +216,32 @@ def run_until(symbol, timeout_sec): # -- set_breakpoint -- # -------------------- + def set_breakpoint(symbol): T32_MEMORY_ACCESS_PROGRAM = 0x1 T32_BPCONFIG_PROGRAM = 0x001 addr = ctypes.c_uint32(get_symbol_address(symbol)) - return t32.T32_WriteBreakpoint(addr, T32_MEMORY_ACCESS_PROGRAM, - T32_BPCONFIG_PROGRAM, 1) + return t32.T32_WriteBreakpoint( + addr, T32_MEMORY_ACCESS_PROGRAM, T32_BPCONFIG_PROGRAM, 1 + ) # ------------------------ # -- get_symbol_address -- # ------------------------ -def get_symbol_address(symbol_name): +def get_symbol_address(symbol_name): addr = ctypes.c_uint32(0) size = ctypes.c_uint32(0) access = ctypes.c_uint32(0) - ret = t32.T32_GetSymbol(symbol_name, - ctypes.byref(addr), - ctypes.byref(size), - ctypes.byref(access)) + ret = t32.T32_GetSymbol( + symbol_name, + ctypes.byref(addr), + ctypes.byref(size), + ctypes.byref(access), + ) if ret == T32_OK: return addr.value @@ -236,12 +253,13 @@ def get_symbol_address(symbol_name): # -- read_register_by_name -- # --------------------------- + def read_register_by_name(name): upper = ctypes.c_uint32(0) lower = ctypes.c_uint32(0) - ret = t32.T32_ReadRegisterByName(name, - ctypes.byref(lower), - ctypes.byref(upper)) + ret = t32.T32_ReadRegisterByName( + name, ctypes.byref(lower), ctypes.byref(upper) + ) if ret == T32_OK: return upper.value * 2**32 + lower.value else: @@ -252,16 +270,20 @@ def read_register_by_name(name): # -- export_trace -- # ------------------ + def export_trace(path): cmd_wrapper("Trace.FLOWPROCESS", wait_for_completion=True) - cmd_wrapper(f"Trace.export.BranchFlow {path} /NOSYMBOL /CALLER", - wait_for_completion=True) + cmd_wrapper( + f"Trace.export.BranchFlow {path} /NOSYMBOL /CALLER", + wait_for_completion=True, + ) # --------------------------- # -- CPU_stopped_at_symbol -- # --------------------------- + def CPU_stopped_at_symbol(symbol): sym_addr = get_symbol_address(symbol) pc_addr = read_register_by_name("PC") @@ -273,6 +295,7 @@ def CPU_stopped_at_symbol(symbol): # -- clear_breakpoints -- # ----------------------- + def clear_breakpoints(): cmd_wrapper("Break.Reset") @@ -281,6 +304,7 @@ def clear_breakpoints(): # -- kill_trace32 -- # ------------------ + def kill_trace32(): connect() t32.T32_Terminate(0) diff --git a/testsuite/cleanup.sh b/testsuite/cleanup.sh index fb9cc9fd7..a1fe3fc61 100644 --- a/testsuite/cleanup.sh +++ b/testsuite/cleanup.sh @@ -16,9 +16,9 @@ rm -rf $(find -type d -name 'obj_*') rm -rf $(find -type f -name 'tmp*.list') rm -rf $(find -type f -name '*~') -rm -rf $(find -type f -name 'test.py.???' | grep -v svn) -rm -rf $(find -type f -name '*.adb.*' | grep -v svn) -rm -rf $(find -type f -name '*.dump' | grep -v svn) +rm -rf $(find -type f -name 'test.py.???') +rm -rf $(find -type f -name '*.adb.*') +rm -rf $(find -type f -name '*.dump') rm -rf $(find -type d -name 'memcheck.log') rm -rf $(find -type d -name 'callgrind-*.log') diff --git a/testsuite/facade.cfg b/testsuite/facade.cfg new file mode 100644 index 000000000..453b53408 --- /dev/null +++ b/testsuite/facade.cfg @@ -0,0 +1,30 @@ +[FACADE] ## *MUST* be first line of file + ## switches must begin in column 1 + ## no spaces allowed before the "=" + ## see config.h for valid switches and types + +[T5] ## test equipment section +BASE_ADDR= 0000 # T5 base address (hex) +DHC_BASE_ADDR= 00000 # deep history card base address (hex) +BUS_TIMEOUT= 10 # milliseconds (decimal) +XFR_TIMEOUT= 10 # milliseconds (decimal) +CONS_TIMEOUT= 10 # milliseconds (decimal) +T5_RESET_HOLD= 8 # target clock ticks (decimal) +#TARGET_RESET_HOLD= 40 # target clock ticks (decimal) +#POD_FREQ_SELECT= 20 # pod freq select for AAMP5vr1 pods + # target freq must be in one of following ranges: + # 15-30 MHz (default) + # 30-50 MHz + # 5-15 MHz + +[DBG] ## debug engine section +SHOW_PC= 1 # Update the PC in the console window + +[GUI] ## GUI section +SCREEN_BUFSIZE= 500 # number of lines saved in console window (250-2500) +MAX_SRC_WIN= 1 # specifies the maximum number of source windows + # open at any given time (must be 1, 2, or 3) +TITLE=v3.5 # String to use in the Title bar after Facade +#TMPPATH=C:/TMP # specifies the directory for scratch files + # (history and memory buffers) + # default: working directory specified at installation diff --git a/testsuite/nexus_info.py b/testsuite/nexus_info.py index b98ec17ca..051d713e6 100644 --- a/testsuite/nexus_info.py +++ b/testsuite/nexus_info.py @@ -2,7 +2,7 @@ import isystem.connect as ic cmgr = ic.ConnectionMgr() -cmgr.connectMRU('') +cmgr.connectMRU("") ideController = ic.CIDEController(cmgr) @@ -11,31 +11,32 @@ def winIDEA_version(): def firmware_revision(): - firmwareDateInstalledUrl = '/iOPEN/SystemConfig.Firmware.DateInstalled' + firmwareDateInstalledUrl = "/iOPEN/SystemConfig.Firmware.DateInstalled" firmwareDateInstalled = ideController.getOptionInt( - firmwareDateInstalledUrl) + firmwareDateInstalledUrl + ) year = firmwareDateInstalled >> 16 month = (firmwareDateInstalled & 0xFF00) >> 8 - date = (firmwareDateInstalled & 0xFF) + date = firmwareDateInstalled & 0xFF - return '{}{:02d}{:02d}'.format(year, month, date) + return "{}{:02d}{:02d}".format(year, month, date) def probe_model(): # No way to retrieve this automatically. This is what we have: - return 'iSystem iC5000' + return "iSystem iC5000" def workspace_file(): - return ' '.join(fu.find(root="altrun", pattern="justrun.xjrf")) + return " ".join(fu.find(root="altrun", pattern="justrun.xjrf")) -print ( +print( "Nexus Framework ## " "Probe Model: %s, " "Firmware: %s, " "winIDEA: %s, " - "Workspace: %s") % \ - (probe_model(), firmware_revision(), winIDEA_version(), workspace_file()) + "Workspace: %s" +) % (probe_model(), firmware_revision(), winIDEA_version(), workspace_file()) cmgr.disconnect(0) diff --git a/testsuite/tests/104-pragma-directives/src/test_pragma.c b/testsuite/tests/104-pragma-directives/src/test_pragma.c new file mode 100644 index 000000000..7cf24fd60 --- /dev/null +++ b/testsuite/tests/104-pragma-directives/src/test_pragma.c @@ -0,0 +1,15 @@ +#define DISABLE_WARNINGS \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") + +DISABLE_WARNINGS + +int +main () +{ + return 0; // # return +} + +//# test_pragma.c +// +// /return/ l+ ## 0 diff --git a/testsuite/tests/104-pragma-directives/test.py b/testsuite/tests/104-pragma-directives/test.py new file mode 100644 index 000000000..5bcbaf871 --- /dev/null +++ b/testsuite/tests/104-pragma-directives/test.py @@ -0,0 +1,11 @@ +""" +Check that the instrumentation of a test with pragma preprocessing directives +works fine. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/106-externally-built-header/main/main.c b/testsuite/tests/106-externally-built-header/main/main.c new file mode 100644 index 000000000..644ed33e9 --- /dev/null +++ b/testsuite/tests/106-externally-built-header/main/main.c @@ -0,0 +1,8 @@ +#include "mylib.h" + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.c b/testsuite/tests/106-externally-built-header/mylib/mylib.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.gpr b/testsuite/tests/106-externally-built-header/mylib/mylib.gpr new file mode 100644 index 000000000..afc15b221 --- /dev/null +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.gpr @@ -0,0 +1,6 @@ +library project Mylib is + for Library_Name use "mylib"; + for Library_Dir use "lib"; + for Object_Dir use "obj"; + for Languages use ("C"); +end Mylib; diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.h b/testsuite/tests/106-externally-built-header/mylib/mylib.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/106-externally-built-header/test.py b/testsuite/tests/106-externally-built-header/test.py new file mode 100644 index 000000000..fb4cd94aa --- /dev/null +++ b/testsuite/tests/106-externally-built-header/test.py @@ -0,0 +1,48 @@ +""" +Check that GNATcoverage passes the right source directories to the +preprocessing command, including externally built projects source directories. + +It used to skip externally built projects when the --externally-built-project +switch was not passed to the gnatcov command line. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, gprbuild, gprinstall + +tmp = Wdir("tmp_") + +# Create the installation directory and add it to gprbuild's project lookup +# path. +install_dir = os.path.abspath("install") +gpr_install_dir = os.path.join(install_dir, "share", "gpr") +os.mkdir(install_dir) +env.add_search_path("GPR_PROJECT_PATH", gpr_install_dir) + +# Build and install the library project +cp(os.path.join("..", "mylib"), ".", recursive=True) +mylib_gpr = os.path.join("mylib", "mylib.gpr") +gprbuild(mylib_gpr) +gprinstall(mylib_gpr, f"--prefix={install_dir}") + +# Build the main project using this and run it to produce a trace file +main_gpr = gprfor( + mains=["main.c"], srcdirs=os.path.join("..", "main"), deps=["mylib"] +) +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=."], +) + +check_xcov_reports(".", {"main.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/124-no-trace/main.adb b/testsuite/tests/124-no-trace/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/124-no-trace/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/124-no-trace/test.py b/testsuite/tests/124-no-trace/test.py new file mode 100644 index 000000000..ebd87f6b6 --- /dev/null +++ b/testsuite/tests/124-no-trace/test.py @@ -0,0 +1,33 @@ +""" +Check that gnatcov coverage produces a report even when the user did not +specify traces or checkpoints. Also check that the tool warns in this case. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor, xcov + +Wdir("tmp_") + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +# Do not pass the trace to the gnatcov coverage invocation +print("cov args are " + str(cov_args[:-1])) +xcov(cov_args[:-1], tolerate_messages=".*", out="coverage.log") + +thistest.fail_if_not_equal( + '"gnatcov coverage" output', + "warning: No trace files specified. GNATcoverage will still generate a" + " report", + contents_of("coverage.log").strip(), +) + +check_xcov_reports("obj", {"main.adb.xcov": {"-": {5}}}) + +thistest.result() diff --git a/testsuite/tests/127-check-line-endings/main.adb b/testsuite/tests/127-check-line-endings/main.adb new file mode 100644 index 000000000..0cbd4a8d5 --- /dev/null +++ b/testsuite/tests/127-check-line-endings/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/127-check-line-endings/test.py b/testsuite/tests/127-check-line-endings/test.py new file mode 100644 index 000000000..01f55c2ff --- /dev/null +++ b/testsuite/tests/127-check-line-endings/test.py @@ -0,0 +1,36 @@ +""" +Check that we do not have CRCRLF line endings in instrumented files. This used +to be the case on windows, as we were opening the instrumented file as a text +file, and not as a binary file when writing it. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +# Check line endings +with open(os.path.join("obj", "gen-gnatcov-instr", "main.adb"), "rb") as f: + content = f.read() + thistest.fail_if( + b"\r\r\n" in content, + comment="wrong line ending in instrumented source", + ) + +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/129-instr-progress/c_unit.c b/testsuite/tests/129-instr-progress/c_unit.c new file mode 100644 index 000000000..60583b508 --- /dev/null +++ b/testsuite/tests/129-instr-progress/c_unit.c @@ -0,0 +1,9 @@ +extern void cpp_func (void); +extern void print_msg (const char *); + +void +c_func (void) +{ + print_msg ("c:c_func"); + cpp_func (); +} diff --git a/testsuite/tests/129-instr-progress/cpp_unit.cpp b/testsuite/tests/129-instr-progress/cpp_unit.cpp new file mode 100644 index 000000000..4b539078f --- /dev/null +++ b/testsuite/tests/129-instr-progress/cpp_unit.cpp @@ -0,0 +1,11 @@ +extern "C" +{ + extern void print_msg (const char *); + extern void cpp_func (void); +} + +void +cpp_func (void) +{ + print_msg ("cpp:cpp_func"); +} diff --git a/testsuite/tests/129-instr-progress/main.adb b/testsuite/tests/129-instr-progress/main.adb new file mode 100644 index 000000000..d418c7650 --- /dev/null +++ b/testsuite/tests/129-instr-progress/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + procedure C_Func; + pragma Import (C, C_Func, "c_func"); +begin + Put_Line ("Ada:main"); + C_Func; +end Main; diff --git a/testsuite/tests/129-instr-progress/print.c b/testsuite/tests/129-instr-progress/print.c new file mode 100644 index 000000000..46c10c20c --- /dev/null +++ b/testsuite/tests/129-instr-progress/print.c @@ -0,0 +1,4 @@ +void +print_msg (const char *) +{ +} diff --git a/testsuite/tests/129-instr-progress/test.opt b/testsuite/tests/129-instr-progress/test.opt new file mode 100644 index 000000000..183279b61 --- /dev/null +++ b/testsuite/tests/129-instr-progress/test.opt @@ -0,0 +1 @@ +!C++ DEAD Testcase uses a Ada/C/C++ mixed project diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py new file mode 100644 index 000000000..a269042d9 --- /dev/null +++ b/testsuite/tests/129-instr-progress/test.py @@ -0,0 +1,81 @@ +""" +Check that "gnatcov instrument" correctly reports progress about the +instrumented units. +""" + +import dataclasses + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + langs=["Ada", "C", "C++"], + mains=["main.adb"], + srcdirs=[".."], + ), + units=["main", "c_unit.c", "cpp_unit.cpp"], + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + quiet=False, + trace_mode="src", +) + +# Sanity check: the insrument-build-coverage process completed with the +# expected results. +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {7, 8}}, + "c_unit.c.xcov": {"+": {7, 8}}, + "cpp_unit.cpp.xcov": {"+": {10}}, + }, +) + + +# Units are not instrumented in a particular order: we only want to check that +# all of them are listed with the expected formatting. +@dataclasses.dataclass +class Section: + label: str + lines: list[str] + + +sections = [Section("", [])] +for line in lines_of("instrument.log"): + if line.startswith(" "): + sections[-1].lines.append(line) + else: + sections.append(Section(line, [])) + +sorted_lines = [] +for section in sections: + sorted_lines.append(section.label) + sorted_lines += sorted(section.lines) + +thistest.fail_if_not_equal( + "'gnatcov instrument' output", + "\n".join( + [ + "", + "Coverage instrumentation", + " [Ada] main", + " [C++] cpp_unit.cpp", + " [C] c_unit.c", + "Main instrumentation", + " [Ada] main", + ] + ), + "\n".join(sorted_lines), +) + +thistest.result() diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads b/testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads new file mode 100644 index 000000000..c3dcb2f41 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pkg is + type T is (Boolean, String); + function F (I : Integer) return Integer is (I + 1); -- # stmt +end Pkg; diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb b/testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb new file mode 100644 index 000000000..cc00ec17a --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb @@ -0,0 +1,10 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.ads +-- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb b/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb new file mode 100644 index 000000000..6e9672594 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb @@ -0,0 +1,12 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Full is +begin + Assert (F (0) = 1); +end Test_Full; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/131-hidden-bool-exprfunc/test.opt b/testsuite/tests/131-hidden-bool-exprfunc/test.opt new file mode 100644 index 000000000..4102be8d5 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Expr functions not supported by 5.04a1 +7.1.2 DEAD Expr functions not supported by 5.04a1 diff --git a/testsuite/tests/131-hidden-bool-exprfunc/test.py b/testsuite/tests/131-hidden-bool-exprfunc/test.py new file mode 100644 index 000000000..a4211aff7 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/test.py @@ -0,0 +1,13 @@ +""" +Regression test: when the "Boolean" standard entity is hidden by a user-defined +entity, the stmt instrumentation of expression functions used to generate +invalid code. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt b/testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt new file mode 100644 index 000000000..36bea91e6 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt @@ -0,0 +1 @@ +:= diff --git a/testsuite/tests/138-ada-preprocessing/errors/eval_error.txt b/testsuite/tests/138-ada-preprocessing/errors/eval_error.txt new file mode 100644 index 000000000..4fc5f1c9d --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/eval_error.txt @@ -0,0 +1 @@ +* -c diff --git a/testsuite/tests/138-ada-preprocessing/errors/main.adb b/testsuite/tests/138-ada-preprocessing/errors/main.adb new file mode 100644 index 000000000..5db011f19 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/138-ada-preprocessing/errors/pkg.ads b/testsuite/tests/138-ada-preprocessing/errors/pkg.ads new file mode 100644 index 000000000..6444959e9 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is +# if Log then + procedure Log; +# end if ; +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/errors/test.py b/testsuite/tests/138-ada-preprocessing/errors/test.py new file mode 100644 index 000000000..1129274c5 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/test.py @@ -0,0 +1,61 @@ +""" +Check various error cases related to the use of preprocessing in Ada. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +for basename, expected_msg in [ + ( + "no_such_file", + ".*gnatcov.*: error while loading preprocessor data from project" + "\n.*gnatcov.*: no such file: .*no_such_file\\.txt", + ), + ( + "bad_syntax", + ".*gnatcov.*: error while loading preprocessor data from project" + "\n.*gnatcov.*: .*bad_syntax\\.txt:1:1: Ada source filename expected", + ), + ( + "eval_error", + ".*gnatcov.*: instrumentation failed for .*pkg\\.ads" + "\n.*gnatcov.*: please make sure the original project can be" + " compiled" + '\n.*gnatcov.*: pkg\\.ads:2:6: unknown symbol "Log"', + ), +]: + thistest.log(f"== {basename} ==") + log_filename = f"{basename}-out.txt" + p = xcov_instrument( + gprsw=GPRswitches( + root_project=gprfor( + prjid=basename, + mains=["main.adb"], + srcdirs=[".."], + compiler_extra=( + 'for Default_Switches ("Ada")' + ' use ("-gnatep="' + " & Project'Project_Dir" + f' & "/../{basename}.txt");' + ), + ) + ), + covlevel="stmt", + register_failure=False, + out=log_filename, + ) + thistest.fail_if(p.status == 0, "'gnatcov instrument' is supposed to fail") + output = contents_of(log_filename) + thistest.fail_if_no_match( + "'gnatcov instrument' output", + expected_msg, + contents_of(log_filename).strip(), + ) + +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/example/prep.txt b/testsuite/tests/138-ada-preprocessing/example/prep.txt new file mode 100644 index 000000000..b5e172856 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/prep.txt @@ -0,0 +1 @@ +* -Dlog=false -c diff --git a/testsuite/tests/138-ada-preprocessing/example/test.py b/testsuite/tests/138-ada-preprocessing/example/test.py new file mode 100644 index 000000000..6d94608eb --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/test.py @@ -0,0 +1,87 @@ +""" +Check that the instrumentation of Ada sources with preprocessing enabled works +as expected on an example project. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Test the working case. The "log" preprocessing symbol is set to "false" in +# "prep.txt", so all logging lines are supposed to be disabled and thus not +# create coverage obligations. Yet the line numbers for the code remaining are +# supposed to be preserved. +thistest.log("== Up to the coverage report ==") +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_eval.adb"], + srcdirs=[".."], + compiler_extra=( + 'for Default_Switches ("Ada")' + ' use ("-gnatep=" & Project\'Project_Dir & "/../prep.txt");' + ), + ) + ), + covlevel="stmt+decision", + mains=["test_eval"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "test_eval.adb.xcov": {"+": {4}, "!": {12}, "-": {13}}, + "vm.ads.xcov": {"+": {3, 4, 6, 7, 16, 17}}, + "vm.adb.xcov": { + "+": { + # Eval header + 13, + # Pop + 27, + 31, + # Push + 43, + 44, + # Eval loop + 61, + 62, + 70, + 72, + 87, + 89, + 90, + 96, + # Eval wrapper + 117, + 118, + 121, + 122, + 123, + 125, + 126, + 127, + }, + "!": { + # Branch condition evaluation + 78 + }, + "-": { + # Jump + 75, + # Branch jump + 79, + # Push_Lit, Add + 83, + 94, + }, + }, + }, +) + +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/example/test_eval.adb b/testsuite/tests/138-ada-preprocessing/example/test_eval.adb new file mode 100644 index 000000000..7af26d072 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/test_eval.adb @@ -0,0 +1,15 @@ +with VM; use VM; + +procedure Test_Eval is + Program : constant Program_Type := + (1 => (Kind => Clone), + 2 => (Kind => Branch, Jump_Dest => 4), + 3 => (Kind => Halt), + 4 => (Kind => Push_Lit, Push_Value => -1), + 5 => (Kind => Add), + 6 => (Kind => Jump, Jump_Dest => 1)); +begin + if Eval (Program, 5, (1 => 0)) /= 0 then + raise Program_Error; + end if; +end Test_Eval; diff --git a/testsuite/tests/138-ada-preprocessing/example/vm.adb b/testsuite/tests/138-ada-preprocessing/example/vm.adb new file mode 100644 index 000000000..7f1f393a8 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/vm.adb @@ -0,0 +1,130 @@ +#if Log then +with Ada.Text_IO; use Ada.Text_IO; +#end if; + +package body VM is + + procedure Eval + (Program : Program_Type; + PC : in out PC_Type; + Stack : in out Stack_type; + SP : in out SP_Type) + is + Continue : Boolean := True; + + function Pop return Integer; + procedure Push (Value : Integer); + + --------- + -- Pop -- + --------- + + function Pop return Integer is + begin +#if Log then + Put_Line ("Popping the stack"); +#end if; + SP := SP - 1; +#if Log then + Put_Line ("SP:" & SP_Type'Image (SP)); +#end if; + return Stack (SP); + end Pop; + + ---------- + -- Push -- + ---------- + + procedure Push (Value : Integer) is + begin +#if Log then + Put_Line ("Pushing the stack"); +#end if; + Stack (SP) := Value; + SP := SP + 1; +#if Log then + Put_Line ("SP:" & SP_Type'Image (SP)); +#end if; + end Push; + + begin + +#if Log then + Put_Line ("Program starting:"); + Put_Line ("PC:" & PC_Type'Image (PC)); + Put_Line ("SP:" & SP_Type'Image (SP)); + New_Line; +#end if; + + while Continue loop + declare + Inst : Instruction_Type renames Program (PC); + Next_PC : PC_Type := PC + 1; + begin +#if Log then + Put_Line + ("Execute: " + & Opcode'Image (Inst.Kind) + & " at" & PC_Type'Image (PC)); +#end if; + case Inst.Kind is + when Halt => + Continue := False; + + when Jump => + Next_PC := Inst.Jump_Dest; + + when Branch => + if Pop /= 0 then + Next_PC := Inst.Jump_Dest; + end if; + + when Push_Lit => + Push (Inst.Push_Value); + + when Clone => + declare + Value : constant Integer := Pop; + begin + Push (Value); + Push (Value); + end; + + when Add => + Push (Pop + Pop); + end case; + PC := Next_PC; + end; + end loop; + +#if Log then + New_Line; + Put_Line ("Program stopped"); + Put_Line ("PC:" & PC_Type'Image (PC)); + Put_Line ("SP:" & SP_Type'Image (SP)); +#end if; + end Eval; + + ---------- + -- Eval -- + ---------- + + function Eval + (Program : Program_Type; + Stack_Size : Natural; + Initial_Values : Stack_Type) return Integer + is + SP_First : constant SP_Type := Initial_Values'First; + SP_Last : constant SP_Type := + Initial_Values'First + SP_Type (Stack_Size) - 1; + + Stack : Stack_Type (SP_First .. SP_Last); + PC : PC_Type := Program'First; + SP : SP_Type := Initial_Values'Last + 1; + begin + Stack (Initial_Values'Range) := Initial_Values; + Eval (Program, PC, Stack, SP); + return Stack (SP - 1); + end Eval; + +end VM; diff --git a/testsuite/tests/138-ada-preprocessing/example/vm.ads b/testsuite/tests/138-ada-preprocessing/example/vm.ads new file mode 100644 index 000000000..ab54260c6 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/vm.ads @@ -0,0 +1,30 @@ +package VM is + + type PC_Type is new Positive; + type SP_Type is new Positive; + + type Opcode is (Halt, Jump, Branch, Push_Lit, Clone, Add); + type Instruction_Type (Kind : Opcode := Opcode'First) is record + case Kind is + when Halt => null; + when Jump | Branch => Jump_Dest : PC_Type; + when Push_Lit => Push_Value : Integer; + when Clone | Add => null; + end case; + end record; + + type Stack_Type is array (SP_Type range <>) of Integer; + type Program_Type is array (PC_Type range <>) of Instruction_Type; + + procedure Eval + (Program : Program_Type; + PC : in out PC_Type; + Stack : in out Stack_type; + SP : in out SP_Type); + + function Eval + (Program : Program_Type; + Stack_Size : Natural; + Initial_Values : Stack_Type) return Integer; + +end VM; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt new file mode 100644 index 000000000..c986293b6 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt @@ -0,0 +1 @@ +X := diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb new file mode 100644 index 000000000..05d1a6622 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin + $X Put_Line ("Hello, world!"); + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt new file mode 100644 index 000000000..bd2ce2cfd --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt @@ -0,0 +1 @@ +* "defs.txt" diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb new file mode 100644 index 000000000..ad434c260 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + Word : constant String := $X; + begin + if Word = "world" then + Put_Line ("Hello, " & Word & "!"); + end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt new file mode 100644 index 000000000..c25e3de83 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt @@ -0,0 +1 @@ +* -DX="world" diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb new file mode 100644 index 000000000..ebc61abec --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + Word : constant String := "world"; + begin + if $X = "world" then + Put_Line ("Hello, " & $X & "!"); + end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt new file mode 100644 index 000000000..f1fb4c0bf --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt @@ -0,0 +1 @@ +* -DX=Word diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb new file mode 100644 index 000000000..10c58c803 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin + Put_Line ("Hello, " & $X & "!"); + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt new file mode 100644 index 000000000..25f403e0f --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt @@ -0,0 +1,2 @@ +"pkg.ads" -DY=foo +* -DX="world" diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb new file mode 100644 index 000000000..10c58c803 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin + Put_Line ("Hello, " & $X & "!"); + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt new file mode 100644 index 000000000..90f0fd6b0 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt @@ -0,0 +1,2 @@ +"pkg.adb" -DX="world" +* -DY=foo diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/main.adb b/testsuite/tests/138-ada-preprocessing/prep_data/main.adb new file mode 100644 index 000000000..c6304b2e7 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Run; +end Main; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb new file mode 100644 index 000000000..388a3eece --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin +#if X then + Put_Line ("X"); +#else + Put_Line ("not X"); +#end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt new file mode 100644 index 000000000..28d0582d1 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt @@ -0,0 +1 @@ +* -DY=foo diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads b/testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads new file mode 100644 index 000000000..28fc6b094 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Run; +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py new file mode 100644 index 000000000..031fc6499 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -0,0 +1,115 @@ +""" +Exhaustively check that the features of preprocessing configuration are +correctly used. +""" + +from dataclasses import dataclass + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +@dataclass +class BaseTestcase: + label: str + + +@dataclass +class InstrErrorTestcase(BaseTestcase): + """Testcase that expects an instrumentation error.""" + + expected_msg: str + """Regexp for the expected instrumentation error message.""" + + +@dataclass +class ReportTestcase(BaseTestcase): + """Testcase that expects successful instrumentation+build+coverage.""" + + expected_cov: dict[str, set[int]] + """Expected coverage report for "pkg.adb".""" + + +# Run a full instrument+build+coverage cycle on test projects that have their +# own "pkg.adb" implementation and "prep.txt" preprocesor configuration data. +# Both exercise a particular preprocessor configuration feature: the +# compilation would fail with a misimplementation for that feature. +for t in [ + ReportTestcase("def_empty", {"+": {7}}), + ReportTestcase("def_string", {"+": {6, 8, 9}}), + ReportTestcase("def_symbol", {"+": {6, 8, 9}}), + ReportTestcase("undef_is_false", {"+": {10, 14}}), + InstrErrorTestcase( + "no_undef_is_false", + ".*gnatcov.*: instrumentation failed for .*pkg\\.adb" + "\n.*gnatcov.*: please make sure the original project can be" + " compiled" + '\n.*gnatcov.*: pkg\\.adb:7:5: unknown symbol "X"', + ), + ReportTestcase("default_config", {"+": {7}}), + ReportTestcase("file_config", {"+": {7}}), +]: + thistest.log(f"== {t.label} ==") + tmp = Wdir(f"tmp_{t.label}") + + gprsw = GPRswitches( + root_project=gprfor( + mains=["main.adb"], + srcdirs=["..", f"../{t.label}"], + compiler_extra=( + 'for Default_Switches ("Ada")' + ' use ("-gnatep=" & Project\'Project_Dir' + f' & "/../{t.label}/prep.txt", ' + f' "-I" & Project\'Project_Dir & "../{t.label}");' + ), + ), + units=["pkg"], + ) + + if isinstance(t, InstrErrorTestcase): + # We expect an instrumentation error: check its message + log_filename = f"{t.label}-out.txt" + p = xcov_instrument( + gprsw=gprsw, + covlevel="stmt", + register_failure=False, + out=log_filename, + extra_args=["--save-temps"], + ) + thistest.fail_if( + p.status == 0, + "'gnatcov instrument' is supposed to fail", + ) + output = contents_of(log_filename) + thistest.fail_if_no_match( + "'gnatcov instrument' output", + t.expected_msg, + contents_of(log_filename).strip(), + ) + + else: + assert isinstance(t, ReportTestcase) + # If we expect a coverage report, compute it and check its contents + + build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_args=["--save-temps"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + ) + check_xcov_reports( + "xcov", + {"pkg.adb.xcov": t.expected_cov, "pkg.ads.xcov": {}}, + discard_empty=False, + ) + + tmp.to_homedir() + thistest.log("") + +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb new file mode 100644 index 000000000..9334c6a0e --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin +#if X then + Invalid Statement +#else + Put_Line ("Hello, world!"); +#end if; + +#if not X then + Put_Line ("Hello, world!"); +#else + Invalid Statement +#end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt new file mode 100644 index 000000000..97dd10651 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt @@ -0,0 +1 @@ +* -DY=foo -u diff --git a/testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb b/testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb new file mode 100644 index 000000000..130a667d6 --- /dev/null +++ b/testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb @@ -0,0 +1,5 @@ +separate (Pkg) +procedure Bar is +begin + null; +end Bar; diff --git a/testsuite/tests/14-unused-separate/compilable/test.py b/testsuite/tests/14-unused-separate/compilable/test.py new file mode 100644 index 000000000..9ab1e8d71 --- /dev/null +++ b/testsuite/tests/14-unused-separate/compilable/test.py @@ -0,0 +1,38 @@ +""" +Check that instrumenting a project that contains an "orphan" subunit (i.e. a +subunit never referenced in its parent unit) works as expected. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=["main.adb"], srcdirs=["../src", "../../src"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +thistest.fail_if( + os.path.exists("obj/gen-gnatcov-instr/pkg-bar.adb"), + "separate orphan unit instrumented", +) + +expected_cov = { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {"+": {2}}, + "pkg.adb.xcov": {"-": {2}}, +} +check_xcov_reports("obj", expected_cov) + +thistest.result() diff --git a/testsuite/tests/14-unused-separate/src/main.adb b/testsuite/tests/14-unused-separate/src/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/14-unused-separate/src/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/14-unused-separate/src/pkg.adb b/testsuite/tests/14-unused-separate/src/pkg.adb new file mode 100644 index 000000000..d66dec94e --- /dev/null +++ b/testsuite/tests/14-unused-separate/src/pkg.adb @@ -0,0 +1,3 @@ +package body Pkg is + procedure Bar is null; +end Pkg; diff --git a/testsuite/tests/14-unused-separate/src/pkg.ads b/testsuite/tests/14-unused-separate/src/pkg.ads new file mode 100644 index 000000000..0b1273231 --- /dev/null +++ b/testsuite/tests/14-unused-separate/src/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Foo is null; + procedure Bar; +end Pkg; diff --git a/testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb b/testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb new file mode 100644 index 000000000..98c680c56 --- /dev/null +++ b/testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb @@ -0,0 +1 @@ +uncompilable unit diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.opt b/testsuite/tests/14-unused-separate/uncompilable/test.opt new file mode 100644 index 000000000..9f9485829 --- /dev/null +++ b/testsuite/tests/14-unused-separate/uncompilable/test.opt @@ -0,0 +1 @@ +src-traces XFAIL Unsupported with instrumentation for now, fix in #18 diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.py b/testsuite/tests/14-unused-separate/uncompilable/test.py new file mode 100644 index 000000000..6f49980cc --- /dev/null +++ b/testsuite/tests/14-unused-separate/uncompilable/test.py @@ -0,0 +1,40 @@ +""" +Check that instrumenting a project that contains an "orphan" subunit (i.e. a +subunit never referenced in its parent unit) that does not compile works as +expected, i.e. does not issue analysis warnings at `gnatcov instrument` time. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=["main.adb"], srcdirs=["../src", "../../src"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + tolerate_coverage_messages="no ALI file found for unit pkg.bar", +) + +thistest.fail_if( + os.path.exists("obj/gen-gnatcov-instr/pkg-bar.adb"), + "separate orphan unit instrumented", +) + +expected_cov = { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {"+": {2}}, + "pkg.adb.xcov": {"-": {2}}, +} +check_xcov_reports("obj", expected_cov) + +thistest.result() diff --git a/testsuite/tests/147-slug_collision/src/pkg-child.adb b/testsuite/tests/147-slug_collision/src/pkg-child.adb new file mode 100644 index 000000000..c3d877af2 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg-child.adb @@ -0,0 +1,8 @@ +package body Pkg.Child is + + function Foo (X : Integer) return Integer is + begin + return X; -- # stmt + end Foo; + +end Pkg.Child; diff --git a/testsuite/tests/147-slug_collision/src/pkg-child.ads b/testsuite/tests/147-slug_collision/src/pkg-child.ads new file mode 100644 index 000000000..fc63faf53 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg-child.ads @@ -0,0 +1,3 @@ +package Pkg.Child is + function Foo (X : Integer) return Integer; +end Pkg.Child; diff --git a/testsuite/tests/147-slug_collision/src/pkg.ads b/testsuite/tests/147-slug_collision/src/pkg.ads new file mode 100644 index 000000000..2db1f1de6 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg.ads @@ -0,0 +1,2 @@ +package Pkg is +end Pkg; diff --git a/testsuite/tests/147-slug_collision/src/pkg_child.adb b/testsuite/tests/147-slug_collision/src/pkg_child.adb new file mode 100644 index 000000000..a47ded692 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg_child.adb @@ -0,0 +1,8 @@ +package body Pkg_Child is + + function Bar (X : Integer) return Integer is + begin + return X; -- # stmt + end Bar; + +end Pkg_Child; diff --git a/testsuite/tests/147-slug_collision/src/pkg_child.ads b/testsuite/tests/147-slug_collision/src/pkg_child.ads new file mode 100644 index 000000000..899b28c78 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg_child.ads @@ -0,0 +1,3 @@ +package Pkg_Child is + function Bar (X : Integer) return Integer; +end Pkg_Child; diff --git a/testsuite/tests/147-slug_collision/src/test_collision.adb b/testsuite/tests/147-slug_collision/src/test_collision.adb new file mode 100644 index 000000000..4996fd17d --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/test_collision.adb @@ -0,0 +1,13 @@ +with Support; use Support; + +with Pkg.Child; +with Pkg_Child; + +procedure Test_Collision is +begin + Assert (Pkg.Child.Foo (3) = Pkg_Child.Bar (3)); +end Test_Collision; + +--# pkg-child.adb pkg_child.adb +-- +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/147-slug_collision/test.py b/testsuite/tests/147-slug_collision/test.py new file mode 100644 index 000000000..e571a41e8 --- /dev/null +++ b/testsuite/tests/147-slug_collision/test.py @@ -0,0 +1,14 @@ +""" +Regression test: gnatcov used to generated homonym buffer units for a +"Pkg.Child" unit and a "Pkg_Child" unit, as well as duplicate constant +declarations in some generated units, which prevented the build of the +instrumented sources. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/15-non-instr-cons/pkg.ads b/testsuite/tests/15-non-instr-cons/pkg.ads new file mode 100644 index 000000000..378529f9a --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/pkg.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Pkg is + + type T is tagged record + X : Boolean; + end record; + + function Store_AT (L : Boolean; R : Boolean) return T is + (X => L and then R); + +end Pkg; diff --git a/testsuite/tests/15-non-instr-cons/test.opt b/testsuite/tests/15-non-instr-cons/test.opt new file mode 100644 index 000000000..4d7631d98 --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Bug reproducer requires expression functions diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py new file mode 100644 index 000000000..9df736242 --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -0,0 +1,53 @@ +""" +Regression test: the relocation logic for non instrumented SCOs when loading +SCOs/checkpoints contained a logic error, resulting in trying to get the +previous element from a No_Element cursor, resulting in a constraint error. +This only happened if the last SCO of a checkpoint was not instrumented, and +that SCO had already been loaded through another checkpoint. + +In this test we use an expression function which is a primitive of a tagged +type, and that type is its return type, to create non-instrumented SCOs. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["test_f.adb", "test_t.adb"], srcdirs=[".."]) + + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr, units=["pkg"]), + extra_coverage_args=[], + covlevel="stmt", + mains=["test_f", "test_t"], + trace_mode="src", + tolerate_instrument_messages=( + "gnatcov limitation: cannot instrument an expression function" + ), +) + +trace_t = xcov_args.pop() +trace_f = xcov_args.pop() + +# Create a checkpoint from each trace +xcov(xcov_args + ["--save-checkpoint=test_t.ckpt", trace_t]) +xcov(xcov_args + ["--save-checkpoint=test_f.ckpt", trace_f]) + +# Try to consolidate the checkpoint +xcov( + xcov_args + ["-Ctest_t.ckpt", "-Ctest_f.ckpt", "-axcov"], + tolerate_messages=( + "warning: Specifying units of interest through --units" + " has no effect on checkpoints" + ), +) + +check_xcov_reports("obj", {"pkg.ads.xcov": {"?": {10}, "+": {5, 6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/15-non-instr-cons/test_f.adb b/testsuite/tests/15-non-instr-cons/test_f.adb new file mode 100644 index 000000000..b2c09002e --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test_f.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Test_F is +begin + if Pkg.Store_AT (True, False).X /= False then + raise Program_Error; + end if; +end Test_F; diff --git a/testsuite/tests/15-non-instr-cons/test_t.adb b/testsuite/tests/15-non-instr-cons/test_t.adb new file mode 100644 index 000000000..bc00817c4 --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test_t.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Test_T is +begin + if Pkg.Store_AT (True, True).X /= True then + raise Program_Error; + end if; +end Test_T; diff --git a/testsuite/tests/152-shared_setup/main.adb b/testsuite/tests/152-shared_setup/main.adb new file mode 100644 index 000000000..57d139b4a --- /dev/null +++ b/testsuite/tests/152-shared_setup/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world!"); +end Main; diff --git a/testsuite/tests/152-shared_setup/test.opt b/testsuite/tests/152-shared_setup/test.opt new file mode 100644 index 000000000..86eb0c85f --- /dev/null +++ b/testsuite/tests/152-shared_setup/test.opt @@ -0,0 +1,3 @@ +!native DEAD Test requires both shared lib support and available light runtime +7.1.2 DEAD Light runtime not provided by this toolchain +5.04a1 DEAD Light runtime not provided by this toolchain diff --git a/testsuite/tests/152-shared_setup/test.py b/testsuite/tests/152-shared_setup/test.py new file mode 100644 index 000000000..403b33647 --- /dev/null +++ b/testsuite/tests/152-shared_setup/test.py @@ -0,0 +1,125 @@ +""" +Check that "gnatcov setup" does not try to build a shared version of the +coverage runtime when the Ada runtime is not available as a shared library. + +This is the case for all of our light runtimes: even though the platform might +support them, we generally don't build the shared version of the runtime. +""" + +import os + +from SCOV.instr import xcov_convert_base64, xcov_instrument +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import ( + exepath_to, + gprfor, + run_and_log, + run_cov_program, + xcov, +) +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Name of the installed runtime project, to avoid conflict with the one setup +# by the testing infrastructure. +rt_prj = "rt_prj" + +# Installation directory for the instrumentation runtime project and directory +# for the project path. +rt_install_dir = os.path.abspath("install") +rt_path_dir = os.path.join(rt_install_dir, "share", "gpr") + +prj = gprfor( + mains=["main.adb"], + objdir="obj", + srcdirs=[".."], + extra=' for Runtime ("Ada") use "light";', +) + +gprsw = GPRswitches(root_project=prj) + +light_log = "setup_light.log" + +# Setup the coverage runtime for a light Ada runtime. Disable the automatic +# passing of --config / --target / --rts as we are doing something custom. +xcov( + [ + "setup", + "--RTS=light", + f"--install-name={rt_prj}", + f"--prefix={rt_install_dir}", + "-v", + ], + out=light_log, + auto_target_args=False, + auto_config_args=False, +) + +thistest.fail_if( + "Library support: STATIC_ONLY" not in contents_of(light_log), + "Incorrect library support for light runtime", +) + +# Make this install available to GPR tools +env.add_search_path("GPR_PROJECT_PATH", rt_path_dir) + +# As we want to override the config generated for the testsuite, we have to +# manually re-do all the coverage workflow to ensure no "--config" argument is +# used in the process. + +xcov_instrument( + gprsw, + covlevel="stmt", + dump_channel="base64-stdout", + dump_trigger="main-end", + runtime_project=rt_prj, + auto_config_args=False, + auto_target_args=False, +) + +build_log = "gprbuild.log" + +p = run_and_log( + cmds=[ + "gprbuild", + f"-P{prj}", + f"--implicit-with={rt_prj}", + "--src-subdirs=gnatcov-instr", + ], + output=build_log, + env=env.environ, +) + +thistest.fail_if(p.status != 0, "GPRbuild exit in error") + +run_log = "run.log" + +# Ignore exit status as there's no way with a light runtime to set the exit +# status to 0. +run_cov_program( + exepath_to("main"), + out=run_log, + register_failure=False, +) + +main_srctrace = "main.srctrace" + +xcov_convert_base64(run_log, main_srctrace) + +xcov( + [ + "coverage", + f"-P{prj}", + "-cstmt", + "-axcov", + main_srctrace, + ] +) + +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/16-check-html/foo.adb b/testsuite/tests/16-check-html/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/16-check-html/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/16-check-html/test.py b/testsuite/tests/16-check-html/test.py new file mode 100644 index 000000000..5f06b8490 --- /dev/null +++ b/testsuite/tests/16-check-html/test.py @@ -0,0 +1,27 @@ +""" +Check that --annotate=html produces a dynamic html report. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["foo.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["--annotate=html", "--output-dir=html"], +) + +js_file = os.path.join("html", "foo.adb.hunk.js") +thistest.fail_if( + not os.path.exists(js_file), "expecting a dynamic html report" +) + +thistest.result() diff --git a/testsuite/tests/185-setup-warnings/test.py b/testsuite/tests/185-setup-warnings/test.py new file mode 100644 index 000000000..3acd3af8f --- /dev/null +++ b/testsuite/tests/185-setup-warnings/test.py @@ -0,0 +1,16 @@ +""" +Check that "gnatcov setup" does not emit warnings about missing object/library +directories when loading the "gnatcov_rts.gpr" project file. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +tmp = Wdir("tmp_") + +filename = "setup.log" +xcov(["setup", "--prefix=.", "-q"], out=filename, force_project_args=True) +thistest.fail_if_not_equal("gnatcov setup output", "", contents_of(filename)) +thistest.result() diff --git a/testsuite/tests/199-setup-summary/test.py b/testsuite/tests/199-setup-summary/test.py new file mode 100644 index 000000000..5b41a4d26 --- /dev/null +++ b/testsuite/tests/199-setup-summary/test.py @@ -0,0 +1,84 @@ +""" +Check that "gnatcov setup" displays a summary of env updates needed after a +successful run. +""" + +import os.path +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +tmp = Wdir("tmp_") + +filename = "setup.log" +xcov(["setup", "--prefix=foo"], out=filename) +output = contents_of(filename) + +output_re = re.compile( + "(.|\n)*" + "\nThe coverage runtime has been successfully installed." + "\nIt was installed in: foo" + "\nIn order to use it, remember to add:" + "\n" + "\n (?P.*)" + "\n" + "\nto the GPR_PROJECT_PATH environment variable, and" + "\n" + "\n (?P.*)" + "\n" + "\nto the (?P.*) environment variable." +) +m = output_re.match(output) +thistest.fail_if_no_match("gnatcov setup output", output_re.pattern, output) +if m is not None: + if thistest.env.build.os.name == "windows": + shared_lib_dirname = "bin" + shared_lib_var = "PATH" + shared_lib_filename = "libgnatcov_rts.dll" + else: + shared_lib_dirname = "lib" + shared_lib_var = "LD_LIBRARY_PATH" + shared_lib_filename = "libgnatcov_rts.so" + + gpr_dir = m.group("gpr_dir") + shared_lib_dir = m.group("shared_lib_dir") + + # Check what gnatcov prints + thistest.fail_if_not_equal( + "Mentionned GPR directory", + os.path.realpath("foo/share/gpr"), + os.path.realpath(gpr_dir), + ) + thistest.fail_if_not_equal( + "Mentionned shared lib directory", + os.path.realpath(f"foo/{shared_lib_dirname}"), + os.path.realpath(shared_lib_dir), + ) + thistest.fail_if_not_equal( + "Mentionned shared lib env var", + shared_lib_var, + m.group("shared_lib_var"), + ) + + # Sanity check: the mentionned directories should contain the expected + # files. + thistest.fail_if( + not os.path.exists(os.path.join(gpr_dir, "gnatcov_rts.gpr")), + f"Cannot find {filename}", + ) + if not thistest.env.is_cross: + thistest.fail_if( + not os.path.exists( + os.path.join(shared_lib_dir, shared_lib_filename) + ), + f"Cannot find {filename}", + ) + +# Note that we cannot test here the summary when --prefix is not passed, since +# that would install gnatcov_rts in the toolchain prefix, which the testsuite +# is not allowed to do. + +thistest.result() diff --git a/testsuite/tests/207-srctrace-version/foo.c b/testsuite/tests/207-srctrace-version/foo.c new file mode 100644 index 000000000..daa6f4c2f --- /dev/null +++ b/testsuite/tests/207-srctrace-version/foo.c @@ -0,0 +1,7 @@ +extern int or_else (int l, int r); + +int +or_else (int l, int r) +{ + return l || r; +} diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid new file mode 100644 index 000000000..d0ecec554 Binary files /dev/null and b/testsuite/tests/207-srctrace-version/foo.c.sid differ diff --git a/testsuite/tests/207-srctrace-version/main.adb b/testsuite/tests/207-srctrace-version/main.adb new file mode 100644 index 000000000..0d78b898a --- /dev/null +++ b/testsuite/tests/207-srctrace-version/main.adb @@ -0,0 +1,23 @@ +with Interfaces.C; use Interfaces.C; + +procedure Main is + + + function Or_Else (L, R : int) return int; + pragma Import (C, Or_Else, "or_else"); + + procedure Assert (B : Boolean) is + begin + if not B then + raise Program_Error; + end if; + end Assert; + + function And_Then (L, R : Boolean) return Boolean is + begin + return L and then R; + end And_Then; +begin + Assert (And_Then (True, True)); + Assert (Or_Else (0, 1) = 1); +end Main; diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid new file mode 100644 index 000000000..ca05865ae Binary files /dev/null and b/testsuite/tests/207-srctrace-version/main.sid differ diff --git a/testsuite/tests/207-srctrace-version/p.gpr b/testsuite/tests/207-srctrace-version/p.gpr new file mode 100644 index 000000000..c2454791b --- /dev/null +++ b/testsuite/tests/207-srctrace-version/p.gpr @@ -0,0 +1,7 @@ +project P is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Exec_Dir use "obj"; + for Languages use ("Ada", "C"); + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace new file mode 100644 index 000000000..c715c37e5 Binary files /dev/null and b/testsuite/tests/207-srctrace-version/reference.srctrace differ diff --git a/testsuite/tests/207-srctrace-version/test.opt b/testsuite/tests/207-srctrace-version/test.opt new file mode 100644 index 000000000..e18554f17 --- /dev/null +++ b/testsuite/tests/207-srctrace-version/test.opt @@ -0,0 +1 @@ +block DEAD Hard-coded SID files diff --git a/testsuite/tests/207-srctrace-version/test.py b/testsuite/tests/207-srctrace-version/test.py new file mode 100644 index 000000000..824fab80b --- /dev/null +++ b/testsuite/tests/207-srctrace-version/test.py @@ -0,0 +1,67 @@ +""" +Test that when loading a trace with gnatcov, either everything works correctly +or there is a specific error message concerning the trace version number that +is emitted. If a change in format is detected between the trace and the current +gnatcov version, force the user to update the trace. +""" + +from SCOV.minicheck import xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of + +tmp = Wdir("tmp_") + +# Create a coverage report from the trace under version control. +# Its format is either the same as the one expected by the current gnatcov, in +# which case there should be no problems, or the formats differ, in which case +# we only expect an error message concerning the trace version number. +coverage_log = "coverage_log.txt" +p = xcov( + [ + "coverage", + "--output-dir=.", + "-axcov", + "-cstmt+mcdc", + "--sid=../main.sid", + "--sid=../foo.c.sid", + "--source-search=..", + "-T=../reference.srctrace", + ], + register_failure=False, + out=coverage_log, +) + +# If there was an error, the trace format changed between when the trace was +# generated and now. Look for the appropriate error message. +if p.status != 0: + thistest.fail_if_no_match( + "Unexpected error message from 'gnatcov coverage'.\n" + "*** Ensure the trace format version was properly bumped if you made a" + " breaking change in the trace format ***\n", + regexp=r".*gnatcov(\.exe)?: ../reference.srctrace:" + r" unsupported format version", + actual=contents_of(coverage_log), + ) + + # If the correct message was found then great, the trace format number was + # indeed bumped. Now prompt for the test to be updated otherwise we could + # end up with an old trace in the test, and stop testing with the latest + # trace format. + thistest.failed( + "Update the trace and SIDs in this test to the latest" + " format to make test pass again.\n" + "This is simply a matter of running './update.sh' in the test" + " directory." + ) + +# Otherwise, check the coverage report +else: + check_xcov_reports( + ".", + { + "main.adb.xcov": {"+": {21, 22}, "!": {11, 18}, "-": {12}}, + "foo.c.xcov": {"!": {6}}, + }, + ) + +thistest.result() diff --git a/testsuite/tests/207-srctrace-version/update.sh b/testsuite/tests/207-srctrace-version/update.sh new file mode 100755 index 000000000..ae7f7979c --- /dev/null +++ b/testsuite/tests/207-srctrace-version/update.sh @@ -0,0 +1,17 @@ +#! /bin/sh + +# Script to generate SID and traces. + +set -ex + +expected_cwd="/tmp/207-srctrace-version" +if [ "$expected_cwd" != "$PWD" ] +then + echo "Please run this script from the $expected_cwd directory" + exit 1 +fi + +gnatcov instrument -P p.gpr -cstmt+mcdc +cp obj/*.sid . +gprbuild -P p.gpr --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr +GNATCOV_TRACE_FILE=reference.srctrace ./obj/main diff --git a/testsuite/tests/213-sarif-report/ada/full/ref.sarif b/testsuite/tests/213-sarif-report/ada/full/ref.sarif new file mode 100644 index 000000000..8fbe45c9e --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/ref.sarif @@ -0,0 +1,546 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 8, + "startLine": 5 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 10 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.ads" + }, + "region": { + "startColumn": 31, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement was not instrumented" + }, + "ruleId": "UNDET" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "b.ads" + }, + "region": { + "startColumn": 40, + "startLine": 2 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 14, + "startLine": 16 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 15, + "startLine": 17 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 44, + "startLine": 30 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 10, + "startLine": 14 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 8, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 32, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 42, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 22, + "startLine": 22 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "ATC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.ads" + }, + "region": { + "startColumn": 42, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 10 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 11 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 14 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 20 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads b/testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads new file mode 100644 index 000000000..248add341 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Lib is + function Id (B : Boolean) return Boolean is (B) + with Pre => B or else not B or else B, + Post => Id'Result = B; +end Lib; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/a.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/a.adb new file mode 100644 index 000000000..f57e05802 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/a.adb @@ -0,0 +1,15 @@ +package body A is + procedure A_Proc (Dummy : Boolean) is + begin + pragma Annotate (Xcov, Exempt_On, "Justification"); + if Dummy and then not Dummy then + pragma Assert (Dummy); + declare + Dummy_2 : Boolean := not Dummy and then Dummy; + begin + null; + end; + end if; + pragma Annotate (Xcov, Exempt_Off); + end A_Proc; +end A; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/a.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/a.ads new file mode 100644 index 000000000..ed422ab7b --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/a.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package A is + procedure A_Proc (Dummy : Boolean); + + type T is tagged null record; + + function Create return T is (null record); +end A; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/main.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/main.adb new file mode 100644 index 000000000..bcb0d65d0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/main.adb @@ -0,0 +1,25 @@ +with A; +with Foo; +with Lib; + +procedure Main is + T : Boolean := True; + F : Boolean := False; + Rec : A.T := A.Create; +begin + if Lib.Id (T) or else F then + T := T and then True; + end if; + + if F and then Foo then + F := F and then False; + end if; + + pragma Annotate (Xcov, Exempt_On, "Test"); + if not Foo then + T := not F; + end if; + pragma Annotate (Xcov, Exempt_Off); + + A.A_Proc (True); +end Main; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads new file mode 100644 index 000000000..89a3e5a35 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads @@ -0,0 +1,3 @@ +package B is + function Return_T return Boolean is (True); +end B; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb new file mode 100644 index 000000000..92c7a5edc --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +with Bar; +with Lib; + +function Foo return Boolean +is + T : Boolean := Bar; + F : Boolean := False; +begin + if not T then + T := T and then T; + end if; + + begin + if T then + pragma Assert (T); + pragma Assert (T or else T or else T); + pragma Assert (T and then Lib.Id (F)); + end if; + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return T; +end Foo; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads new file mode 100644 index 000000000..b7cfdb3ca --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads @@ -0,0 +1 @@ +function Foo return Boolean; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb new file mode 100644 index 000000000..b23814520 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +function Bar return Boolean +is + T : Boolean := True; + F : Boolean := False; + + Res : Boolean := False; + + function MCDC_Violation (A, B : Boolean) return Boolean is + begin + if (A and + then not B) + or else A then + return True; + end if; + return True; + end MCDC_Violation; + +begin + Res := MCDC_Violation (T, F); + Res := MCDC_Violation (F, F); + + begin + pragma Assert (Res); + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return Res; +end Bar; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads new file mode 100644 index 000000000..f51db2cee --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads @@ -0,0 +1 @@ +function Bar return Boolean; diff --git a/testsuite/tests/213-sarif-report/ada/full/test.opt b/testsuite/tests/213-sarif-report/ada/full/test.opt new file mode 100644 index 000000000..dc69ef071 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD SARIF reports are only generated for source traces +5.04a1 DEAD Test uses expression function and Ada_2012 +7.1.2 DEAD Test uses Ada_2012 features diff --git a/testsuite/tests/213-sarif-report/ada/full/test.py b/testsuite/tests/213-sarif-report/ada/full/test.py new file mode 100644 index 000000000..73105c741 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/test.py @@ -0,0 +1,64 @@ +""" +Check the SARIF coverage report emitted for an Ada project containing +statement, decision, mcdc, atc, and atcc violations, some of which are +exempted. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.adb"], + objdir="obj-foo", + deps=["bar", "lib"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.adb"], + objdir="obj-bar", +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.adb"], + objdir="obj", + deps=["lib", "foo"], +) + +instr_msg = ( + r"\*\*\* a.ads:8:3: warning: gnatcov limitation: cannot instrument an" + " expression function which is a primitive of its return type, when this" + r" type is a tagged type\. Consider turning it into a regular function" + r" body\." +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif"], + tolerate_instrument_messages=instr_msg, +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/main.adb b/testsuite/tests/213-sarif-report/ada/no-violations/main.adb new file mode 100644 index 000000000..afbdbab88 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end; diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif new file mode 100644 index 000000000..c20f7bec8 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif @@ -0,0 +1,39 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/test.opt b/testsuite/tests/213-sarif-report/ada/no-violations/test.opt new file mode 100644 index 000000000..5fb8b75f0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/test.opt @@ -0,0 +1 @@ +bin-traces DEAD SARIF reports are only generated for source traces diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/test.py b/testsuite/tests/213-sarif-report/ada/no-violations/test.py new file mode 100644 index 000000000..7cf0dc77e --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/test.py @@ -0,0 +1,27 @@ +""" +Check the validity of the SARIF report generated for an Ada project in which no +coverage violations were found. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", srcdirs=[".."], mains=["main.adb"], langs=["Ada"]) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif new file mode 100644 index 000000000..39f4563cc --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -0,0 +1,840 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 8, + "startLine": 5 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 10 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.ads" + }, + "region": { + "startColumn": 31, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement was not instrumented" + }, + "ruleId": "UNDET" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "b.ads" + }, + "region": { + "startColumn": 40, + "startLine": 2 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 14, + "startLine": 16 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 15, + "startLine": 17 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 44, + "startLine": 30 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 13, + "startLine": 8 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 20, + "startLine": 8 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 25, + "startLine": 8 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 27 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 34 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 36 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 13, + "startLine": 9 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 20, + "startLine": 9 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 25, + "startLine": 9 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 27 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 34 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 36 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 10, + "startLine": 14 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 8, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 32, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 42, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 22, + "startLine": 22 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "ATC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.ads" + }, + "region": { + "startColumn": 42, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 18 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 22 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 23 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 27 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 28 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads new file mode 100644 index 000000000..248add341 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Lib is + function Id (B : Boolean) return Boolean is (B) + with Pre => B or else not B or else B, + Post => Id'Result = B; +end Lib; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb new file mode 100644 index 000000000..f57e05802 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb @@ -0,0 +1,15 @@ +package body A is + procedure A_Proc (Dummy : Boolean) is + begin + pragma Annotate (Xcov, Exempt_On, "Justification"); + if Dummy and then not Dummy then + pragma Assert (Dummy); + declare + Dummy_2 : Boolean := not Dummy and then Dummy; + begin + null; + end; + end if; + pragma Annotate (Xcov, Exempt_Off); + end A_Proc; +end A; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads new file mode 100644 index 000000000..ed422ab7b --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package A is + procedure A_Proc (Dummy : Boolean); + + type T is tagged null record; + + function Create return T is (null record); +end A; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c b/testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c new file mode 100644 index 000000000..2e8505763 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c @@ -0,0 +1,41 @@ +#include + +extern int cpp_func (int a); + +bool +MCDC_Violation (bool t, bool f) +{ + if ((t || f) && (t || f)) + { + return true; + } + + return true; +} + +int +c_func (int a, int b) +{ + + bool t = true; + bool f = false; + + // DECISISON violation + if (!t) + { + // STMT violation + t = false; + } + + t = MCDC_Violation (f, f); + t = MCDC_Violation (t, f); + + /* GNATCOV_EXEMPT_ON "c_justification"*/ + if (!t) + { + t = false; + } + /* GNATCOV_EXEMPT_OFF */ + + return cpp_func (a) + cpp_func (b); +} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp b/testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp new file mode 100644 index 000000000..3c31ac1f3 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp @@ -0,0 +1,41 @@ +extern "C" +{ + extern int cpp_func (int a); +} + +bool +MCDC_Violation (bool t, bool f) +{ + if ((t || f) && (t || f)) + { + return true; + } + + return true; +} + +int +cpp_func (int a) +{ + bool t = true; + bool f = false; + + // DECISISON violation + if (!t) + { + // STMT violation + t = false; + } + + MCDC_Violation (f, f); + MCDC_Violation (t, f); + + /* GNATCOV_EXEMPT_ON "cpp justification"*/ + if (!t) + { + t = false; + } + /* GNATCOV_EXEMPT_OFF */ + + return a; +} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb new file mode 100644 index 000000000..5762643dc --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb @@ -0,0 +1,34 @@ +with A; +with Foo; +with Lib; + +procedure Main +is + + function C_Func (A : Integer; B : Integer) return Integer; + pragma Import (C, C_Func, "c_func"); + + T : Boolean := True; + F : Boolean := False; + Rec : A.T := A.Create; + Dummy_I : Integer := C_Func (1, 2); + +begin + + if Lib.Id (T) or else F then + T := T and then True; + end if; + + if F and then Foo then + F := F and then False; + end if; + + pragma Annotate (Xcov, Exempt_On, "Test"); + if not Foo then + T := not F; + end if; + pragma Annotate (Xcov, Exempt_Off); + + A.A_Proc (True); + +end Main; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads new file mode 100644 index 000000000..89a3e5a35 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads @@ -0,0 +1,3 @@ +package B is + function Return_T return Boolean is (True); +end B; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb new file mode 100644 index 000000000..92c7a5edc --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +with Bar; +with Lib; + +function Foo return Boolean +is + T : Boolean := Bar; + F : Boolean := False; +begin + if not T then + T := T and then T; + end if; + + begin + if T then + pragma Assert (T); + pragma Assert (T or else T or else T); + pragma Assert (T and then Lib.Id (F)); + end if; + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return T; +end Foo; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads new file mode 100644 index 000000000..b7cfdb3ca --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads @@ -0,0 +1 @@ +function Foo return Boolean; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb new file mode 100644 index 000000000..b23814520 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +function Bar return Boolean +is + T : Boolean := True; + F : Boolean := False; + + Res : Boolean := False; + + function MCDC_Violation (A, B : Boolean) return Boolean is + begin + if (A and + then not B) + or else A then + return True; + end if; + return True; + end MCDC_Violation; + +begin + Res := MCDC_Violation (T, F); + Res := MCDC_Violation (F, F); + + begin + pragma Assert (Res); + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return Res; +end Bar; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads new file mode 100644 index 000000000..f51db2cee --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads @@ -0,0 +1 @@ +function Bar return Boolean; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/test.opt b/testsuite/tests/213-sarif-report/all-lang/full/test.opt new file mode 100644 index 000000000..9a428d8ac --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test needs C++ compiler diff --git a/testsuite/tests/213-sarif-report/all-lang/full/test.py b/testsuite/tests/213-sarif-report/all-lang/full/test.py new file mode 100644 index 000000000..4d74d3d2f --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/test.py @@ -0,0 +1,65 @@ +""" +Check the SARIF coverage report emitted for a project containing statement, +decision, mcdc, atc, and atcc violations, some of which are exempted. The +project contains Ada, C and C++ sources. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.adb"], + objdir="obj-foo", + deps=["bar", "lib"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.adb"], + objdir="obj-bar", +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.adb"], + objdir="obj", + deps=["lib", "foo"], + langs=["Ada", "C", "C++"], +) + +instr_msg = ( + r"\*\*\* a.ads:8:3: warning: gnatcov limitation: cannot instrument an" + " expression function which is a primitive of its return type, when this" + r" type is a tagged type\. Consider turning it into a regular function" + r" body\." +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif,report"], + tolerate_instrument_messages=instr_msg, +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c b/testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c new file mode 100644 index 000000000..8ca8567b9 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c @@ -0,0 +1,7 @@ +extern int cpp_func (int a); + +int +c_func (int a, int b) +{ + return cpp_func (a) + cpp_func (b); +} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp b/testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp new file mode 100644 index 000000000..5eee65489 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp @@ -0,0 +1,10 @@ +extern "C" +{ + extern int cpp_func (int a); +} + +int +cpp_func (int a) +{ + return a; +} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb b/testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb new file mode 100644 index 000000000..8a92a0426 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb @@ -0,0 +1,9 @@ +procedure Main +is + function C_Func (A : Integer) return Integer; + pragma Import (C, C_Func, "c_func"); + + Dummy_I : Integer := 1; +begin + Dummy_I := C_Func (Dummy_I); +end; diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif new file mode 100644 index 000000000..c20f7bec8 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif @@ -0,0 +1,39 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt new file mode 100644 index 000000000..9a428d8ac --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test needs C++ compiler diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py new file mode 100644 index 000000000..a8c022da9 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py @@ -0,0 +1,32 @@ +""" +Check the validity of the SARIF report generated for a project in which no +coverage violations were found. The project contains Ada, C, and C++ sources. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="test", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif new file mode 100644 index 000000000..bdd0c1513 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -0,0 +1,336 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.c" + }, + "region": { + "startColumn": 14, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.c" + }, + "region": { + "startColumn": 20, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.c" + }, + "region": { + "startColumn": 7, + "startLine": 9 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.c" + }, + "region": { + "startColumn": 7, + "startLine": 11 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.c" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.c" + }, + "region": { + "startColumn": 7, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 13 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 11, + "startLine": 15 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 18 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 20 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 26 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-lib/lib.c b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.c new file mode 100644 index 000000000..def98f8a9 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.c @@ -0,0 +1,12 @@ +#include "lib.h" + +bool +lib_identity (bool b) +{ + if (!b && b) + { + return b; + } + + return b; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-lib/lib.h b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.h new file mode 100644 index 000000000..09a57fce0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.h @@ -0,0 +1,3 @@ +#include + +bool lib_identity (bool b); diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/main.c b/testsuite/tests/213-sarif-report/c/full/src-root/main.c new file mode 100644 index 000000000..e3ae22b08 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/main.c @@ -0,0 +1,31 @@ +#include + +#include "bar.h" +#include "foo.h" +#include "lib.h" + +int +main (void) +{ + int t = bar (); + int f = false; + + if (lib_identity (t) || f) + { + t = t && true; + } + + if (f && foo ()) + { + f = f && false; + } + + /* GNATCOV_EXEMPT_ON "justification" */ + if (!foo ()) + { + t = !f; + } + /* GNATCOV_EXEMPT_OFF */ + + return 0; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c new file mode 100644 index 000000000..cfef6e064 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c @@ -0,0 +1,7 @@ +#include "b.h" + +bool +return_t () +{ + return true; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h new file mode 100644 index 000000000..b5da8581c --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h @@ -0,0 +1,3 @@ +#include + +bool return_t (); diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c new file mode 100644 index 000000000..1f484b130 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c @@ -0,0 +1,15 @@ +#include "foo.h" +#include "b.h" + +bool +foo () +{ + bool t = true; + + if (!t) + { + t = return_t () && t; + } + + return return_t (); +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h new file mode 100644 index 000000000..cfd5aee9d --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h @@ -0,0 +1,3 @@ +#include + +bool foo (); diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c new file mode 100644 index 000000000..59935f8cb --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c @@ -0,0 +1,27 @@ +#include "bar.h" + +bool +mcdc_violation (int a, int b) +{ + if ((a && !b) || a) + { + return true; + } + else + { + return true; + } +} + +bool +bar () +{ + bool t = true; + bool f = false; + bool res = false; + + res = mcdc_violation (t, f); + res = mcdc_violation (f, f); + + return res; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h new file mode 100644 index 000000000..4310c9378 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h @@ -0,0 +1,3 @@ +#include + +bool bar (); diff --git a/testsuite/tests/213-sarif-report/c/full/test.opt b/testsuite/tests/213-sarif-report/c/full/test.opt new file mode 100644 index 000000000..5fb8b75f0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/test.opt @@ -0,0 +1 @@ +bin-traces DEAD SARIF reports are only generated for source traces diff --git a/testsuite/tests/213-sarif-report/c/full/test.py b/testsuite/tests/213-sarif-report/c/full/test.py new file mode 100644 index 000000000..2e352a913 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/test.py @@ -0,0 +1,59 @@ +""" +Check the SARIF coverage report emitted for a C project containing statement, +decision, mcdc violations some of which are exempted. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", + langs=["C"], +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.c"], + objdir="obj-foo", + deps=["bar", "lib"], + langs=["C"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.c"], + objdir="obj-bar", + langs=["C"], +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.c"], + objdir="obj", + deps=["lib", "foo"], + langs=["C"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif"], +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/c/no-violations/main.c b/testsuite/tests/213-sarif-report/c/no-violations/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif new file mode 100644 index 000000000..c20f7bec8 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif @@ -0,0 +1,39 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/c/no-violations/test.opt b/testsuite/tests/213-sarif-report/c/no-violations/test.opt new file mode 100644 index 000000000..5fb8b75f0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/test.opt @@ -0,0 +1 @@ +bin-traces DEAD SARIF reports are only generated for source traces diff --git a/testsuite/tests/213-sarif-report/c/no-violations/test.py b/testsuite/tests/213-sarif-report/c/no-violations/test.py new file mode 100644 index 000000000..26f36b3ce --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/test.py @@ -0,0 +1,27 @@ +""" +Check the validity of the SARIF report generated for a C project in which no +coverage violations were found. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", srcdirs=[".."], mains=["main.c"], langs=["C"]) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif new file mode 100644 index 000000000..01c84475b --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -0,0 +1,336 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.cpp" + }, + "region": { + "startColumn": 14, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.cpp" + }, + "region": { + "startColumn": 20, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 9 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 11 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 13 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 11, + "startLine": 15 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 18 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 20 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 26 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp new file mode 100644 index 000000000..498e18812 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp @@ -0,0 +1,12 @@ +#include "lib.hpp" + +bool +lib_identity (bool b) +{ + if (!b && b) + { + return b; + } + + return b; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp new file mode 100644 index 000000000..09a57fce0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp @@ -0,0 +1,3 @@ +#include + +bool lib_identity (bool b); diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp new file mode 100644 index 000000000..111e576c4 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp @@ -0,0 +1,31 @@ +#include + +#include "bar.hpp" +#include "foo.hpp" +#include "lib.hpp" + +int +main (void) +{ + int t = bar (); + int f = false; + + if (lib_identity (t) || f) + { + t = t && true; + } + + if (f && foo ()) + { + f = f && false; + } + + /* GNATCOV_EXEMPT_ON "justification" */ + if (!foo ()) + { + t = !f; + } + /* GNATCOV_EXEMPT_OFF */ + + return 0; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp new file mode 100644 index 000000000..e6baafc5d --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp @@ -0,0 +1,7 @@ +#include "b.hpp" + +bool +return_t () +{ + return true; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp new file mode 100644 index 000000000..b5da8581c --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp @@ -0,0 +1,3 @@ +#include + +bool return_t (); diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp new file mode 100644 index 000000000..c318eaf6e --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp @@ -0,0 +1,15 @@ +#include "foo.hpp" +#include "b.hpp" + +bool +foo () +{ + bool t = true; + + if (!t) + { + t = return_t () && t; + } + + return return_t (); +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp new file mode 100644 index 000000000..cfd5aee9d --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp @@ -0,0 +1,3 @@ +#include + +bool foo (); diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp new file mode 100644 index 000000000..5d10705c3 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp @@ -0,0 +1,27 @@ +#include "bar.hpp" + +bool +mcdc_violation (int a, int b) +{ + if ((a && !b) || a) + { + return true; + } + else + { + return true; + } +} + +bool +bar () +{ + bool t = true; + bool f = false; + bool res = false; + + res = mcdc_violation (t, f); + res = mcdc_violation (f, f); + + return res; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp new file mode 100644 index 000000000..c51c698e8 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp @@ -0,0 +1,3 @@ +#include + +bool bar(); diff --git a/testsuite/tests/213-sarif-report/cpp/full/test.opt b/testsuite/tests/213-sarif-report/cpp/full/test.opt new file mode 100644 index 000000000..5af7cdcf7 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test uses expression function and Ada_2012 +7.1.2 DEAD Test uses Ada_2012 features diff --git a/testsuite/tests/213-sarif-report/cpp/full/test.py b/testsuite/tests/213-sarif-report/cpp/full/test.py new file mode 100644 index 000000000..a987f8138 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/test.py @@ -0,0 +1,59 @@ +""" +Check the SARIF coverage report emitted for a C++ project containing statement, +decision, mcdc violations, some of which are exempted. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", + langs=["C++"], +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.cpp"], + objdir="obj-foo", + deps=["bar", "lib"], + langs=["C++"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.cpp"], + objdir="obj-bar", + langs=["C++"], +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.cpp"], + objdir="obj", + deps=["lib", "foo"], + langs=["C++"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif"], +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp b/testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif new file mode 100644 index 000000000..c20f7bec8 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif @@ -0,0 +1,39 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/test.opt b/testsuite/tests/213-sarif-report/cpp/no-violations/test.opt new file mode 100644 index 000000000..9a428d8ac --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test needs C++ compiler diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/test.py b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py new file mode 100644 index 000000000..8586a43fe --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py @@ -0,0 +1,27 @@ +""" +Check the validity of the SARIF report generated for a C++ project in which no +coverage violations were found. +""" + +from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", srcdirs=[".."], mains=["main.cpp"], langs=["C++"]) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +check_sarif_report("../ref.sarif", "obj/coverage.sarif") + +thistest.result() diff --git a/testsuite/tests/222-scope-expr-func/main.adb b/testsuite/tests/222-scope-expr-func/main.adb new file mode 100644 index 000000000..7a52cf12f --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +with Support; + +procedure Main is +begin + Support.Assert (Zero = 0); +end Main; diff --git a/testsuite/tests/222-scope-expr-func/pkg.adb b/testsuite/tests/222-scope-expr-func/pkg.adb new file mode 100644 index 000000000..f2e21aeca --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/pkg.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package body Pkg is + + function Zero return Integer is (0); + + function One return Integer is (1); + +end Pkg; diff --git a/testsuite/tests/222-scope-expr-func/pkg.ads b/testsuite/tests/222-scope-expr-func/pkg.ads new file mode 100644 index 000000000..ce3ee636c --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function Zero return Integer; + function One return Integer; +end Pkg; diff --git a/testsuite/tests/222-scope-expr-func/test.opt b/testsuite/tests/222-scope-expr-func/test.opt new file mode 100644 index 000000000..a2edd5445 --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD --subprograms not supported in bin trace mode +5.04a1 DEAD test uses Ada 2012 features +7.1.2,CARGS_O1 DEAD expression functions and optimization diff --git a/testsuite/tests/222-scope-expr-func/test.py b/testsuite/tests/222-scope-expr-func/test.py new file mode 100644 index 000000000..e32b0aeb3 --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/test.py @@ -0,0 +1,28 @@ +""" +Test that the subprogram of interest feature works correctly for expression +functions which have a previous declaration. + +gnatcov used to register the actual expression function's sloc as identifier +instead of it first declaration, resulting in an error message being emitted. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), units=["Pkg"] + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--subprograms=../pkg.ads:2", "-axcov"], +) + +check_xcov_reports("obj", {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/222-subp-line-computation/main.adb b/testsuite/tests/222-subp-line-computation/main.adb new file mode 100644 index 000000000..28560e8ca --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +with Support; + +procedure Main is +begin + Support.Assert (Pkg.Get_Bool); +end Main; diff --git a/testsuite/tests/222-subp-line-computation/pkg.ads b/testsuite/tests/222-subp-line-computation/pkg.ads new file mode 100644 index 000000000..9079d4dd7 --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/pkg.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pkg is + + Bool_Val : Boolean := True; function Get_Bool return Boolean is (Bool_Val); + +end Pkg; diff --git a/testsuite/tests/222-subp-line-computation/test.opt b/testsuite/tests/222-subp-line-computation/test.opt new file mode 100644 index 000000000..a2edd5445 --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD --subprograms not supported in bin trace mode +5.04a1 DEAD test uses Ada 2012 features +7.1.2,CARGS_O1 DEAD expression functions and optimization diff --git a/testsuite/tests/222-subp-line-computation/test.py b/testsuite/tests/222-subp-line-computation/test.py new file mode 100644 index 000000000..2f36c032d --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/test.py @@ -0,0 +1,28 @@ +""" +Test that line state computation is done for lines which contains both SCOs for +a subprogram of interest and SCOs outside of all subprograms of interest. + +Gnatcov used to not compute the coverage state of a line if it contained a SCO +not in the subprogram of interest. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), units=["pkg"] + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--subprograms=../pkg.ads:5", "-axcov+"], +) + +check_xcov_reports("obj", {"pkg.ads.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/222-subp-of-interest-cplx/main.adb b/testsuite/tests/222-subp-of-interest-cplx/main.adb new file mode 100644 index 000000000..3be21d40b --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +with Support; + +procedure Main is +begin + Support.Assert (One = 1); +end Main; diff --git a/testsuite/tests/222-subp-of-interest-cplx/pkg.adb b/testsuite/tests/222-subp-of-interest-cplx/pkg.adb new file mode 100644 index 000000000..d93ae1e13 --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/pkg.adb @@ -0,0 +1,28 @@ +pragma Ada_2012; + +package body Pkg is + + function Zero return Integer is + begin + return 0; + end Zero; + + function One return Integer is + begin + return (if String'(String_Identity ("this is a very long decision") + & String_Identity ("that spans multiple lines"))'Length = 1 + then 2 + else 1); + end One; + + function Two return Integer is + begin + return 2; + end Two; + + function String_Identity (S : String) return String is + begin + return S; + end String_Identity; + +end Pkg; diff --git a/testsuite/tests/222-subp-of-interest-cplx/pkg.ads b/testsuite/tests/222-subp-of-interest-cplx/pkg.ads new file mode 100644 index 000000000..d3a8fa4b1 --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/pkg.ads @@ -0,0 +1,6 @@ +package Pkg is + function Zero return Integer; + function One return Integer; + function Two return Integer; + function String_Identity (S : String) return String; +end Pkg; diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.opt b/testsuite/tests/222-subp-of-interest-cplx/test.opt new file mode 100644 index 000000000..ae2e6e8ac --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD --subprograms not supported in bin trace mode +5.04a1 DEAD test uses Ada 2012 features diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.py b/testsuite/tests/222-subp-of-interest-cplx/test.py new file mode 100644 index 000000000..dd077de22 --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/test.py @@ -0,0 +1,58 @@ +""" +Test that the scope mechanism (and thus the subprogram of interest feature) +correctly traverses the scopes, even when the traversal is not done with SCOs +in a contiguous order. + +The One subprogram in the sources used to trigger two related issues: + - The decision in One spanning multiple lines, the scope traversal was done + back and forth on the statement SCO then the decision SCO on each line, thus + breaking the precondition for Traverse_SCO; + + - The scope traversal when loading the trace was done on the first covered + statement SCO, which is not in the first scope. The trace entries were thus + silently discarded. + + More details bellow, making references to the old implementation. + + To be more precise, the previous implementation relied on forward iterators + in multi-way trees to traverse the scope tree, in depth first order until it + found a scope that did not contain the traversed SCO. When loading the + coverage buffers from a given trace, Traverse_SCO is only called on SCOs for + which the correspond buffer bit is set. As such, in this example, the first + SCO on which Traverse_SCO will be called is the statement SCO for the return + statement in One. + + When initiating the traversal, Next_SE point to the scope for the whole + CU, which contains the SCO of interest. The traversal then moves to the next + one, which is the scope for Zero. This does not contain SCO, so the + traversal stops, and current_SE thus points to the scope for the whole CU. + While it is true that this scope contains SCO, it is not the deepest one. + The current scope in the traversal is then checked against the set of scopes + of interest, which only consist in the scope for One, so this returns False. + The coverage information is then wrongfully discarded. + +This test checks both bugs. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), units=["Pkg"] + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--subprograms=../pkg.ads:3", "-axcov"], +) + +check_xcov_reports( + "obj", {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"!": {12, 13}, "+": {14, 15}}} +) + +thistest.result() diff --git a/testsuite/tests/24_mixed_c_c++/pkg.c b/testsuite/tests/24_mixed_c_c++/pkg.c new file mode 100644 index 000000000..5d74411a2 --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/pkg.c @@ -0,0 +1,5 @@ +int +id (int x) +{ + return x; +} diff --git a/testsuite/tests/24_mixed_c_c++/test.cpp b/testsuite/tests/24_mixed_c_c++/test.cpp new file mode 100644 index 000000000..548d53dba --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/test.cpp @@ -0,0 +1,8 @@ +extern "C" int id (int x); + +int +main () +{ + int a = id (1); + return 0; +} diff --git a/testsuite/tests/24_mixed_c_c++/test.opt b/testsuite/tests/24_mixed_c_c++/test.opt new file mode 100644 index 000000000..2313ab6b6 --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/test.opt @@ -0,0 +1,2 @@ +!C++ DEAD test requires C++ compiler +bin-traces DEAD Test requires support for C++ source coverage diff --git a/testsuite/tests/24_mixed_c_c++/test.py b/testsuite/tests/24_mixed_c_c++/test.py new file mode 100644 index 000000000..25d5f4f68 --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/test.py @@ -0,0 +1,28 @@ +""" +Check that the instrumentation of a project mixing C and C++ works. It used to +produce files with the same object name, resulting in an error at build time. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["test.cpp"])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports( + "obj", + { + "test.cpp.xcov": {"+": {6, 7}}, + "pkg.c.xcov": {"+": {4}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb b/testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/255-warnings-as-errors/regular/main.adb b/testsuite/tests/255-warnings-as-errors/regular/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/255-warnings-as-errors/regular/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/255-warnings-as-errors/test.py b/testsuite/tests/255-warnings-as-errors/test.py new file mode 100644 index 000000000..b373ab86a --- /dev/null +++ b/testsuite/tests/255-warnings-as-errors/test.py @@ -0,0 +1,98 @@ +""" +Check that --warnings-as-errors works as expected. +""" + +import re + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + + +def check(slug, project, warning, extra_args): + """ + Check that "gnatcov instrument" on the given project yields the expected + warning, and that it exits with an error when --warnings-as-errors is + passed. + """ + + # Run "gnatcov instrument" once with default arguments, just to check that + # gnatcov succeeds and emits a warning. + thistest.log(f"== {slug}: sanity check ==") + log = f"{slug}-sc.txt" + process = xcov_instrument( + gprsw=GPRswitches(root_project=project), + extra_args=extra_args, + covlevel="stmt", + register_failure=False, + out=log, + ) + thistest.fail_if(process.status != 0, "'gnatcov instrument' exit in error") + thistest.fail_if_no_match( + "'gnatcov instrument' output", warning, contents_of(log) + ) + + # Then pass --warnings-as-errors to check the exit code + thistest.log(f"== {slug}: warnings-as-errors ==") + log = f"{slug}-err.txt" + process = xcov_instrument( + gprsw=GPRswitches(root_project=project), + covlevel="stmt", + extra_args=["--warnings-as-errors"] + extra_args, + register_failure=False, + out=log, + ) + thistest.fail_if( + process.status == 0, "'gnatcov instrument' exit without error" + ) + thistest.fail_if_no_match( + "'gnatcov instrument' output", warning, contents_of(log) + ) + + +# Check the handling of warnings emitted before command line options (including +# --warnings-as-errors) are fully loaded: this happens for warnings emitted by +# LibGPR2. +# +# To trigger them, just try to load a project with both --target and --config +# arguments. Note that we expect the warning twice: once for the wrapper +# gnatcov program, and one for the gnatcov64 program (both need to load the +# project). +project = gprfor( + prjid="regular", + mains=["main.adb"], + srcdirs=["../regular"], +) +check( + "project-warning", + project, + "suite.cgpr:.*: error: --target: 'foo' is different from the target value" + " in the configuration project '.*'" + "\nsuite.cgpr:.*: error: --target: 'foo' is different from the target" + " value in the configuration project '.*'", + extra_args=["--target=foo"], +) + +# Create a project with a missing source file, on which the Ada instrumenter +# will complain. This checks the handling of warnings emitted after command +# line options are fully loaded. +check( + "instrumenter-warning", + gprfor( + prjid="missing_srcfile", + mains=["main.adb"], + srcdirs=["../missing-srcfile"], + ), + re.escape( + "warning: While instrumenting main.adb..." + "\nwarning: Cannot find required source file: pkg.ads" + ), + extra_args=[], +) + +thistest.result() diff --git a/testsuite/tests/275-dump-trigger-last/main.adb b/testsuite/tests/275-dump-trigger-last/main.adb new file mode 100644 index 000000000..fb43c3230 --- /dev/null +++ b/testsuite/tests/275-dump-trigger-last/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("This is a first statement"); + pragma Annotate (Xcov, Dump_Buffers); + Put_Line ("This is a second statement"); +end Main; diff --git a/testsuite/tests/275-dump-trigger-last/test.opt b/testsuite/tests/275-dump-trigger-last/test.opt new file mode 100644 index 000000000..a31a7dfe1 --- /dev/null +++ b/testsuite/tests/275-dump-trigger-last/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD test specific to source traces +5.04a1 DEAD Compiler tries to resolve symbols in pragma annotate diff --git a/testsuite/tests/275-dump-trigger-last/test.py b/testsuite/tests/275-dump-trigger-last/test.py new file mode 100644 index 000000000..03fea8e33 --- /dev/null +++ b/testsuite/tests/275-dump-trigger-last/test.py @@ -0,0 +1,98 @@ +""" +Test that "gnatcov instrument" only uses the last --dump-trigger option +present on the command line or project file. This was no longer the case when +--dump-trigger=manual started accepting files to be searched as a comma +separated string. +""" + +import glob + +from SCOV.instr import default_dump_trigger +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches, gprcov_for, Csw +from SUITE.tutils import gprfor + +expected_cov = {"main.adb.xcov": {"+": {5, 7}}} + +tmp = Wdir() + + +def check_one(tc_id, extra_instr_args=None, extra_prj_content=""): + """ + Run a build, run, coverage and report-check workflow. The expected coverage + shall always be expected_cov. + + tc_prefix is used to differentiate artefact names from each invocation, + namely the temporary directory name. + + extra_instr_args is forwarded to build_and_run's homonym parameter, note + that if it is left empty, no --dump-trigger switch will be passed to the + gnatcov instrument invocation. + + extra_prj_content is passed to gprfor's extra parameter if not None. + """ + + tmp.to_subdir(f"tmp_{tc_id}") + thistest.log(f"========= {tc_id} =========") + prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra=extra_prj_content, + ) + build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + dump_trigger=None, + mains=["main"], + extra_instr_args=extra_instr_args, + extra_coverage_args=["-axcov"], + ) + check_xcov_reports("obj", expected_cov) + + # Check that a single trace was created + nb_traces = len(glob.glob("*.srctrace")) + thistest.fail_if_not_equal( + "Unexpected number of traces", expected=1, actual=nb_traces + ) + + +# Auto dump trigger to be used in the test +dump_trigger = default_dump_trigger(["main.adb"]) + +# Test that with two arguments on the command line, only the second one is +# taken into account. +check_one( + "cmd_line", + extra_instr_args=[ + "--dump-trigger=manual", + f"--dump-trigger={dump_trigger}", + ], +) + +# Test that if there is a dump trigger indication in the project file, and on +# the command line, the later will be used. +check_one( + "prj_and_cmd", + extra_instr_args=[f"--dump-trigger={dump_trigger}"], + extra_prj_content=gprcov_for( + switches=[Csw("instrument", ["--dump-trigger=manual"])] + ), +) + +# Test that if there are multiple occurrences of the --dump-trigger switch in +# the project Switches attribute, only the last one is used. +check_one( + "prj_switches", + extra_prj_content=gprcov_for( + switches=[ + Csw( + "instrument", + ["--dump-trigger=manual", f"--dump-trigger={dump_trigger}"], + ) + ] + ), +) + +thistest.result() diff --git a/testsuite/tests/280-incompatible-srctrace-formats/p.gpr b/testsuite/tests/280-incompatible-srctrace-formats/p.gpr new file mode 100644 index 000000000..cc2637d0b --- /dev/null +++ b/testsuite/tests/280-incompatible-srctrace-formats/p.gpr @@ -0,0 +1,3 @@ +project P is + for object_dir use "obj"; +end p; diff --git a/testsuite/tests/280-incompatible-srctrace-formats/p0-23-2.srctrace b/testsuite/tests/280-incompatible-srctrace-formats/p0-23-2.srctrace new file mode 100644 index 000000000..4773feabe Binary files /dev/null and b/testsuite/tests/280-incompatible-srctrace-formats/p0-23-2.srctrace differ diff --git a/testsuite/tests/280-incompatible-srctrace-formats/p0.adb b/testsuite/tests/280-incompatible-srctrace-formats/p0.adb new file mode 100644 index 000000000..37a5b708c --- /dev/null +++ b/testsuite/tests/280-incompatible-srctrace-formats/p0.adb @@ -0,0 +1,4 @@ +procedure P0 is +begin + null; +end; diff --git a/testsuite/tests/280-incompatible-srctrace-formats/test.py b/testsuite/tests/280-incompatible-srctrace-formats/test.py new file mode 100644 index 000000000..1453baa53 --- /dev/null +++ b/testsuite/tests/280-incompatible-srctrace-formats/test.py @@ -0,0 +1,47 @@ +""" +Verify that gnatcov errors out when requested to process a source +trace advertising a trace format version other than the one it (gnatcov) +knows to handle, and that the error message contains an indication of +the trace format versions involved. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov + +# The test dir contains a dummy program and a corresponding coverage +# srctrace produced from instrumentation by an old version of gnatcov +# (release 23.2) in a native configuration. + +# Try to analyze this srctrace and expect the trace version check to +# fail immediately. The check is so early that the actual contents of +# the stored trace doesn't really matter, in particular the target/RTS +# configuration for which the trace was produced compared to that for +# which this test is being run. + +tmp = Wdir("tmp_") + +gpr = gprfor(srcdirs=[".."], langs=["Ada"], mains=["p0.adb"]) + +p = xcov( + [ + "coverage", + "--level=stmt", + "-P{}".format(gpr), + "../p0-23-2.srctrace", + ], + register_failure=False, +) + +thistest.fail_if(p.status == 0, "analysis succeeded but was expected to fail") + +thistest.fail_if_no_match( + what="output from gnatcov coverage", + regexp=( + r"(?s:.*p0-23-2.srctrace: Trace format v2 is not supported " + "by this version of gnatcov. Handling v[0-9]+ only.)" + ), + actual=p.out, +) + +thistest.result() diff --git a/testsuite/tests/281_aggr_reject/a.gpr b/testsuite/tests/281_aggr_reject/a.gpr new file mode 100644 index 000000000..940fb9670 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/a.gpr @@ -0,0 +1,5 @@ +project A is + for Object_Dir use "obj_a"; + for Source_Dirs use ("../src_a"); + for Main use ("main.adb"); +end A; diff --git a/testsuite/tests/281_aggr_reject/aggr.gpr b/testsuite/tests/281_aggr_reject/aggr.gpr new file mode 100644 index 000000000..1b0c97248 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/aggr.gpr @@ -0,0 +1,5 @@ +aggregate project Aggr is + + for Project_Files use ("./a.gpr", "./b.gpr"); + +end Aggr; diff --git a/testsuite/tests/281_aggr_reject/b.gpr b/testsuite/tests/281_aggr_reject/b.gpr new file mode 100644 index 000000000..5c21c2f5a --- /dev/null +++ b/testsuite/tests/281_aggr_reject/b.gpr @@ -0,0 +1,5 @@ +project B is + for Object_Dir use "obj_b"; + for Source_Dirs use ("../src_b"); + for Main use ("main.adb"); +end B; diff --git a/testsuite/tests/281_aggr_reject/src_a/main.adb b/testsuite/tests/281_aggr_reject/src_a/main.adb new file mode 100644 index 000000000..e4ff0a810 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/src_a/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("This is the A main, it only has a single statement."); +end Main; diff --git a/testsuite/tests/281_aggr_reject/src_b/main.adb b/testsuite/tests/281_aggr_reject/src_b/main.adb new file mode 100644 index 000000000..87a07299f --- /dev/null +++ b/testsuite/tests/281_aggr_reject/src_b/main.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put ("This is the B main,"); + Put_Line (" it has a two statements."); +end Main; diff --git a/testsuite/tests/281_aggr_reject/test.py b/testsuite/tests/281_aggr_reject/test.py new file mode 100644 index 000000000..eb574f830 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/test.py @@ -0,0 +1,63 @@ +""" +Test that gnatcov properly reject non-library aggregate projects +""" + +from e3.fs import cp + +from SCOV.minicheck import xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import contents_of + + +def check_cmd(cmd, extra_args=None, trace_mode=None): + """ + Check that the gnatcov command cmd properly rejects the aggregate project + aggr.gpr, emitting the EXPECTED_ERR_MSG error message. + + The check is only performed the the current trace mode matches trace_mode, + if not None. + + extra_args are concatenated to the arguments passed to xcov. + """ + if trace_mode and thistest.options.trace_mode != trace_mode: + return + + log = f"{cmd}.log" + p_cmd = xcov( + [cmd, "-Paggr.gpr", "-q", "-cstmt"] + + (extra_args if extra_args else []), + register_failure=False, + out=log, + ) + thistest.fail_if( + p_cmd.status == 0, + comment=f"'gnatcov {cmd}' did not exit with an error status", + ) + thistest.fail_if_no_match( + f"unexpected or empty 'gnatcov {cmd}' error message", + regexp=r".*gnatcov(.exe)?:" + r" non-library aggregate projects are not supported", + actual=contents_of(log).strip(), + ) + + +tmp = Wdir("tmp_") + +# copy the projects in the test directory to avoid having lingering artifacts +cp("../*.gpr", ".") + +trace_suffix = "srctrace" if thistest.options.trace_mode == "src" else "trace" + +# Test all the gnatcov subcommands, when relevant to the trace mode, properly +# reject aggregate projects. +tests = [ + ("instrument", None, "src"), + ("run", ["dummy_exe"], "bin"), + ("coverage", [f"dummy.{trace_suffix}"], None), +] + +for cmd, extra, mode in tests: + check_cmd(cmd, extra, mode) + +thistest.result() diff --git a/testsuite/tests/285-violations-display/ref.xcov b/testsuite/tests/285-violations-display/ref.xcov new file mode 100644 index 000000000..fd4405d10 --- /dev/null +++ b/testsuite/tests/285-violations-display/ref.xcov @@ -0,0 +1,51 @@ +(.|\n)* +21% of 19 lines covered +67% statement coverage \(6 out of 9\) +50% decision coverage \(1 out of 2\) +20% MC\/DC coverage \(1 out of 5\) + +Coverage level: stmt\+mcdc + 1 \.: procedure Main + 2 \.: is + 3 \+: T : Boolean := True; + 4 \+: F : Boolean := False; + 5 \.: + 6 \.: function Concat \(S1, S2, S3: String\) return String is + 7 \.: begin + 8 -: return S1 & S2 & S3; +statement "return S1\.\.\." at 8:9 not executed + 9 \.: end Concat; + 10 \.: + 11 \.: procedure Test \(B : Boolean\) is + 12 \.: begin + 13 !: if B + 14 !: and then + 15 !: \(T + 16 !: or else F\) +condition "T" at 15:18 has no independent influence pair, MC/DC not achieved +condition "F" at 16:25 has no independent influence pair, MC/DC not achieved + 17 \.: then + 18 !: if F + 19 !: or else + 20 !: F +decision "F" at 18:16 outcome TRUE never exercised + 21 \.: then + 22 \.: declare + 23 -: Dummy : String := Concat + 24 -: \( + 25 -: "B", + 26 -: "C", + 27 -: "D" + 28 -: \); +statement "Dummy : S\.\.\." at 23:21 not executed + 29 \.: begin + 30 -: null; +statement "null;" at 30:21 not executed + 31 \.: end; + 32 \.: end if; + 33 \.: end if; + 34 \.: end Test; + 35 \.: begin + 36 \+: Test \(T\); + 37 \+: Test \(F\); + 38 \.: end Main; diff --git a/testsuite/tests/285-violations-display/src/main.adb b/testsuite/tests/285-violations-display/src/main.adb new file mode 100644 index 000000000..5880ee71f --- /dev/null +++ b/testsuite/tests/285-violations-display/src/main.adb @@ -0,0 +1,38 @@ +procedure Main +is + T : Boolean := True; + F : Boolean := False; + + function Concat (S1, S2, S3: String) return String is + begin + return S1 & S2 & S3; + end Concat; + + procedure Test (B : Boolean) is + begin + if B + and then + (T + or else F) + then + if F + or else + F + then + declare + Dummy : String := Concat + ( + "B", + "C", + "D" + ); + begin + null; + end; + end if; + end if; + end Test; +begin + Test (T); + Test (F); +end Main; diff --git a/testsuite/tests/285-violations-display/test.py b/testsuite/tests/285-violations-display/test.py new file mode 100644 index 000000000..31d7d3ca3 --- /dev/null +++ b/testsuite/tests/285-violations-display/test.py @@ -0,0 +1,38 @@ +""" +Check the display of violations in xcov reports. They should always be +attached to the last line of the statement/decision and displayed after +its last line. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +root = gprfor( + prjid="gen", + srcdirs="../src", + mains=["main.adb"], + objdir="obj", +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=xcov+"], +) + +# Check the contents of the report by comparing it to the exact expected report +# as we want to make sure the violations are displayed where they should. +thistest.fail_if_no_match( + "xcov+ report", + contents_of("../ref.xcov"), + contents_of("obj/main.adb.xcov"), +) + +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb new file mode 100644 index 000000000..8a924bd0e --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb @@ -0,0 +1,28 @@ +pragma Ada_2012; + +with Pkg; use Pkg; + +procedure Access_To_Subp -- # fun +is + + type Pt_Acc is access function (X, Y : Float) return Point; -- # decl + + function Run_Callback (Callback : Pt_Acc) return Point is -- # fun + begin + return Callback (1.0, 2.00); -- # call_1 + end; + + Set_Acc : constant Pt_Acc := Set'Access; -- # decl + Reset_Acc : constant Pt_Acc := Reset'Access; -- # decl + + Dispatch_Table : constant array (1 .. 2) of Pt_Acc := -- # decl + (Set_Acc, Reset_Acc); -- # dstmt + + -- LIMITATION: Selected component with a call expression for a prefix + -- F : Float := Run_Callback (Set_Acc).X; + P : Point := Run_Callback (Set_Acc); -- # call_2 +begin + P := Run_Callback (Set_Acc); -- # call_3 + P := Set_Acc.all (1.0, 2.0); -- # call_4 + P := Dispatch_Table (2) (1.0, 3.0); -- # call_5 +end Access_To_Subp; diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads b/testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads new file mode 100644 index 000000000..5e855cf8f --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pkg is + + type Point is record -- # decl + X, Y : Float; -- # decl + end record; -- # decl + + function Set (X, Y : Float) return Point is (X, Y); -- # stmt + + function Reset (X, Y : Float) return Point is (0.0, 0.0); -- # stmt + +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb new file mode 100644 index 000000000..55a2eecb6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb @@ -0,0 +1,20 @@ +with Access_To_Subp; + +-- Check function and call coverage for an acces to a subprogram. +-- Here, all calls and functions are executed. + +procedure Test_Called is +begin + Access_To_Subp; +end; + +--# access_to_subp.adb +-- /decl/ l+ ## 0 +-- /dstmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 + +--# pkg.ads +-- /decl/ l+ ## 0 +-- /dstmt/ l+ ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb new file mode 100644 index 000000000..acbad33b9 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb @@ -0,0 +1,20 @@ +with Access_To_Subp; + +-- Check function and call coverage for an acces to a subprogram. +-- Here, no calls are made so expect function and call violation for all such +-- SCOs. + +procedure Test_Not_Called is +begin + null; +end; + +--# access_to_subp.adb +-- /decl/ l- ## s- +-- /dstmt/ l- ## 0 +-- /fun/ l- ## f- +-- /call/ l- ## s=>s-, f=>s-,c- + +--# pkg.ads +-- /decl/ l+ ## 0 +-- /stmt/ l- ## s=><-, f=>s-,f- diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/test.py b/testsuite/tests/287-function_call_cov/access_to_subp/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/contracts/src/contracts.adb b/testsuite/tests/287-function_call_cov/contracts/src/contracts.adb new file mode 100644 index 000000000..f7d3cb9c1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/contracts.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package body Contracts is + + procedure Foo (B : Boolean) -- # foo + is + function T return Boolean is (True); -- # t + begin + pragma Assert (T or else T); -- # assert + null; -- # null + end Foo; +end; diff --git a/testsuite/tests/287-function_call_cov/contracts/src/contracts.ads b/testsuite/tests/287-function_call_cov/contracts/src/contracts.ads new file mode 100644 index 000000000..402909b8c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/contracts.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Contracts is + procedure Foo (B : Boolean) + with Pre => B or else B; -- # pre +end; diff --git a/testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb new file mode 100644 index 000000000..825834140 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb @@ -0,0 +1,17 @@ +with Contracts; + +-- Test the absence of crash and the correctness of the coverage report when +-- both assertion and function/call coverage are activated simultaneously +-- when calling a function with a precondition. + +procedure Test_Contracts is +begin + Contracts.Foo (True); +end Test_Contracts; + +--# contracts.ads +-- /pre/ l! ## ac! +--# contracts.adb +-- /t/ l+ ## 0 +-- /assert/ l! ## ac!,c- +-- /null/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb new file mode 100644 index 000000000..969b210ed --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb @@ -0,0 +1,16 @@ +-- Test the absence of crash and the correctness of the coverage report when +-- both assertion and function/call coverage are activated simultaneously +-- when never calling a function with a precondition. + +procedure Test_Contracts_Not_Called is +begin + null; +end Test_Contracts_Not_Called; + +--# contracts.ads +-- /pre/ l- ## a- +--# contracts.adb +-- /foo/ l- ## f- +-- /t/ l- ## s-,f- +-- /assert/ l- ## s-,c-,c- +-- /null/ l- ## s- diff --git a/testsuite/tests/287-function_call_cov/contracts/test.py b/testsuite/tests/287-function_call_cov/contracts/test.py new file mode 100644 index 000000000..a29493644 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + category=CAT.mcdc, + assert_lvl="atcc", + fun_call_lvl=True, +).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/call.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/call.adb new file mode 100644 index 000000000..7e5ce0608 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/call.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +With Pkg; + +procedure Call +is + Dummy : Integer := 8; -- #decl +begin + if Pkg.A.B.F then -- # if_cond + Pkg.A.B.P (Dummy); -- # v_call_stmt + Dummy := Pkg.A.B.P (2); -- # v_call_expr + end if; +end Call; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb new file mode 100644 index 000000000..d929df0e7 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; + +-- Dotted_Name in the context of an explicit dereference + +procedure Deref is + + type String_Access is access String; -- # ok + + S : String_Access := new String'("Hello World!"); -- # ok + + Function Id (S : String_Access) return String_Access is (S); -- # ok + + Dummy : String := Id (S).all; -- # deref1 + F : Boolean := False; -- # ok +begin + if F then -- # if + Dummy := Id (S).all; -- # deref2 + end if; +end Deref; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb new file mode 100644 index 000000000..800e12fea --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package body Pkg is + package body A is + package body B is + procedure P (X : out Integer) is -- # v_fun + begin + X := 42; -- # v_stmt + end P; + + function P (X : Integer) return Integer is -- # v_fun + begin + return 42; -- # v_stmt + end P; + end B; + end A; +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads new file mode 100644 index 000000000..cce56f67d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Pkg is + package A is + package B is + function F return Boolean is (False); -- # stmt + procedure P (X : out Integer); + function P (X : Integer) return Integer; + end B; + end A; +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb new file mode 100644 index 000000000..24fe52633 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb @@ -0,0 +1,16 @@ +with Deref; + +-- LIMITATION +-- For now, gnatcov is unable to instrument calles as prefix of dotted names, +-- which includes explicit dereferences. + +procedure Test_Deref is +begin + Deref; +end Test_Deref; + +--# deref.adb +-- /ok/ l+ ## 0 +-- /deref1/ l? ## c? +-- /if/ l! ## dT- +-- /deref2/ l- ## s-,c? diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb new file mode 100644 index 000000000..35ce9e1d6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb @@ -0,0 +1,17 @@ +with Call; + +procedure Test_Dotted is +begin + Call; +end Test_Dotted; + +--# call.adb +-- /decl/ l+ ## 0 +-- /if_cond/ sdf=>l! ## s=>0, d=>dT-, f=>dT- +-- /v_call_stmt/ l- ## s=>s-, f=>s-,c- +-- /v_call_expr/ sf=>l- ## s=>s-, f=>s-,c- +--# pkg.adb +-- /v_fun/ l- ## f- +-- /v_stmt/ l- ## s- +--# pkg.ads +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/dotted_name/test.py b/testsuite/tests/287-function_call_cov/dotted_name/test.py new file mode 100644 index 000000000..91e3738b6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/test.py @@ -0,0 +1,10 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages=(r"cannot instrument calls within dotted names"), +).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb b/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb new file mode 100644 index 000000000..f3609a04b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb @@ -0,0 +1,52 @@ +pragma Ada_2012; + +with Pkg5; + +procedure Make_Call -- # fun +is + package Pkg1 is + + subtype T1 is Integer; -- # decl + type New_T1 is new Integer; -- # decl + + function F1 (X : T1) return T1 is (X); -- # fun + function New_F1 (X : New_T1) return New_T1 is (X); -- # fun + + package Pkg2 is + + subtype T2 is Boolean; -- # decl + + function F2 (X : T2) return T2 is (X); -- # fun + + package Pkg3 is + + subtype T3 is Float; -- # decl + + function F3 (X : T3) return T3 is (X); -- # fun + + end Pkg3; + end Pkg2; + end Pkg1; + + Dummy1 : Integer := Pkg1.F1 (8); -- # call + Dummy2 : Boolean := Pkg1.Pkg2.F2 (True); -- # call + Dummy3 : Float := Pkg1.Pkg2.Pkg3.F3 (0.0); -- # call + Dummy4 : Boolean := Pkg5.F.B; -- # dummy4 +begin + if -- # if + Pkg1.Pkg2.F2 -- # d_f2 + (Pkg1.F1 (42) -- # d_f1 + = 42 -- # deci + and then -- # deci + Pkg1.Pkg2.Pkg3.F3 (5.0) -- # d_f3 + = 5.0 -- # deci + and then -- # deci + Integer(Pkg1.New_F1 (0)) -- # d_nf1 + /= 0 -- # deci + and then -- # deci + Pkg5.F.B) -- # p_pkg5 + and then False -- # false + then + null; -- # null + end if; +end Make_Call; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads new file mode 100644 index 000000000..e0c721dc1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads @@ -0,0 +1,5 @@ +package Pkg4 is + type T is record -- # decl + B : Boolean; -- # decl + end record; -- # decl +end Pkg4; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads new file mode 100644 index 000000000..c7c5d6ee6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +with Pkg4; + +package Pkg5 is + function F return Pkg4.T is ((B => True)); -- # fun +end Pkg5; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb b/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb new file mode 100644 index 000000000..a578eff5a --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb @@ -0,0 +1,30 @@ +with Make_Call; + +-- Test function and call coverage on functions taking and returning types +-- with dotted names. + +procedure Test_Dotted_Type is +begin + Make_Call; +end Test_Dotted_Type; + +--# make_call.adb +-- /fun/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /call/ l+ ## 0 +-- /dummy4/ l? ## c? +-- /if/ l+ ## 0 +-- /d_f2/ l+ ## 0 +-- /d_f1/ l! ## eT- +-- /d_call/ l! ## c- +-- /d_f3/ l! ## 0 +-- /d_nf1/ l! ## 0 +-- /deci/ l! ## 0 +-- /v_dec/ l- ## 0 +-- /p_pkg5/ l! ## c? +-- /false/ l+ ## 0 +-- /null/ l- ## s- +--# pkg4.ads +-- /decl/ l+ ## 0 +--# pkg5.ads +-- /fun/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/dotted_type/test.py b/testsuite/tests/287-function_call_cov/dotted_type/test.py new file mode 100644 index 000000000..91e3738b6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/test.py @@ -0,0 +1,10 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages=(r"cannot instrument calls within dotted names"), +).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb new file mode 100644 index 000000000..ffbea1acb --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb @@ -0,0 +1,32 @@ +pragma Ada_2012; + +With Pkg; use Pkg; + +procedure Make_Call +is + Create_Acc : constant Pt_Acc := Create'Access; -- # decl + + A : Float := Run_Callback (Create_Acc) -- # A1 + .X; -- # A2 + + B : Float := Run_Callback (Create_Acc) -- # B1 + .Get_X; -- # B2 + + C : Point'Class := Id -- # C1 + (Run_Callback (Create_Acc)); -- # C2 + + D : Float := Id -- # D1 + (Run_Callback (Create_Acc) -- # D2 + .Get_X); -- # D3 + + E : Float := Id -- # E1 + (Run_Callback (Create_Acc)) -- # E2 + .Id -- # E3 + .Get_X; -- # E4 + + F : Float := Point'(1.0, 2.0) -- # F1 + .Id -- # F2 + .Get_X; -- # F3 +begin + null; -- # stmt +end Make_Call; diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb new file mode 100644 index 000000000..4d99b594b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package body Pkg is + + function Run_Callback (Callback : Pt_Acc) return Point is -- # fun + begin + return Callback (1.0, 2.00); -- # call + end; +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads new file mode 100644 index 000000000..c06cd1d5b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads @@ -0,0 +1,18 @@ +pragma Ada_2012; + +package Pkg is + type Point is tagged record -- # decl + X, Y : Float; -- # dstmt + end record; -- # dstmt + + function Create (X, Y : Float) return Point is (X, Y); -- # expr_pri + + type Pt_Acc is access function (X, Y : Float) return Point; -- # decl + + function Run_Callback (Callback : Pt_Acc) return Point; + + function Id (P : Point) return Point'Class is (P); -- # expr_fun + function Id (F : Float) return Float is (F); -- # expr_fun + function Get_X (P : Point) return Float is (P.X); -- # expr_fun + +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb new file mode 100644 index 000000000..9c3104605 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb @@ -0,0 +1,34 @@ +with Make_Call; + +procedure Test_Dotted_Type_Not_Imported is +begin + Make_Call; +end Test_Dotted_Type_Not_Imported; + +--#make_call.adb +-- /decl/ l+ ## 0 +-- /A1/ l! ## c? +-- /A2/ l+ ## 0 +-- /B1/ l! ## c? +-- /B2/ l+ ## 0 +-- /C1/ l+ ## 0 +-- /C2/ l+ ## 0 +-- /D1/ l+ ## 0 +-- /D2/ l! ## c? +-- /D3/ l+ ## 0 +-- /E1/ l! ## c? +-- /E2/ l! ## 0 +-- /E3/ l! ## c? +-- /E4/ l+ ## 0 +-- /F1/ l! ## c? +-- /F2/ l! ## c? +-- /F3/ l+ ## 0 +-- /stmt/ l+ ## 0 +--#pkg.ads +-- /expr_pri/ l- ## s?,f- +-- /decl/ l+ ## 0 +-- /dstmt/ l+ ## 0 +-- /expr_fun/ l+ ## 0 +--#pkg.adb +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/extra.opt b/testsuite/tests/287-function_call_cov/extra.opt new file mode 100644 index 000000000..13f556330 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/extra.opt @@ -0,0 +1,3 @@ +bin-traces XFAIL Function and call coverage not supported for binary traces +5.04a1 DEAD Test contains expression functions and Ada_2012 features +7.1.2 DEAD Test contains expression functions and Ada_2012 features diff --git a/testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb b/testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb new file mode 100644 index 000000000..db36fc70c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb @@ -0,0 +1,59 @@ +pragma Ada_2012; + +procedure In_Proc_Decls -- # p +is + Dummy : Integer := 0; -- # decl + + -- Generic procedure + + generic + Type A is private; + procedure P1 (X : A); + + procedure P1 (X : A) is -- # fun + begin + Dummy := 1; -- # stmt + end P1; + + -- Generic null procedure + + generic + Type D is private; + procedure P2 (X : D); + + procedure P2 (X : D) is null; -- # null_fun + + -- Generic function + + generic + Type B is private; + function F1 (X : B) return B; + + function F1 (X : B) return B -- # fun + is + Dummy : B := X; -- # stmt + begin + return Dummy; -- # stmt + end F1; + + -- Generic expression function + + generic + Type C is private; + function F2 (X : C) return C; + + function F2 (X : C) return C is (X); -- # exp_fun + + -- Instanciations + -- LIMITATION : function coverage is currently not computed for + -- instanciations of generic subprograms + procedure Inst_P1 is new P1 (Integer); -- # stmt + procedure Inst_P2 is new P1 (Integer); -- # stmt + function Inst_F1 is new F1 (Integer); -- # stmt + function Inst_F2 is new F2 (Integer); -- # stmt +begin + Inst_P1 (42); -- # cstmt + Inst_P2 (42); -- # cstmt + Dummy := Inst_F1 (42); -- # cstmt + Dummy := Inst_F2 (42); -- # cstmt +end In_Proc_Decls; diff --git a/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb new file mode 100644 index 000000000..562f65e48 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb @@ -0,0 +1,19 @@ +with In_Proc_Decls; + +-- Check the coverage of a generic procedure, generic null procedure, generic +-- function and a generic expression function declared in a regular procedure +-- when called. We expect the generic subprograms to be covered. Currently, +-- the coverage of instanciations of generic subprograms is not computed. + +procedure Test_In_Proc_Decls_Called is +begin + In_Proc_Decls; +end Test_In_Proc_Decls_Called; + +--# in_proc_decls.adb +-- /p/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /exp_fun/ l? ## s=>s?, f=>s?,f? +-- /null_fun/ l? ## s=>s?, f=>s?,f? diff --git a/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb new file mode 100644 index 000000000..484f5ebbb --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb @@ -0,0 +1,21 @@ +with In_Proc_Decls; + +-- Check the coverage of a generic procedure, generic null, procedure, generic +-- function and a generic expression function declared in a regular procedure +-- when not called. We expect the generic subprograms to not be covered. +-- Currently, the coverage of instanciations of generic subprograms is not +-- computed. + +procedure Test_In_Proc_Decls_Not_Called is +begin + null; +end Test_In_Proc_Decls_Not_Called; + +--# in_proc_decls.adb +-- /p/ l- ## f- +-- /decl/ l- ## s- +-- /stmt/ l- ## s- +-- /fun/ l- ## f- +-- /exp_fun/ l? ## s=>s?, f=>s?,f? +-- /null_fun/ l? ## s=>s?, f=>s?,f? +-- /cstmt/ l- ## s-,c- diff --git a/testsuite/tests/287-function_call_cov/generics/test.py b/testsuite/tests/287-function_call_cov/generics/test.py new file mode 100644 index 000000000..c9c73843c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/test.py @@ -0,0 +1,14 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages=( + r"cannot instrument generic expression functions|" + r"cannot instrument generic null procedures" + ), +).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/import_call/src/add.c b/testsuite/tests/287-function_call_cov/import_call/src/add.c new file mode 100644 index 000000000..a76197af4 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/add.c @@ -0,0 +1,5 @@ +int +add (int x, int y) +{ + return x + y; +} diff --git a/testsuite/tests/287-function_call_cov/import_call/src/call_add.adb b/testsuite/tests/287-function_call_cov/import_call/src/call_add.adb new file mode 100644 index 000000000..417d5a0dc --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/call_add.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; + +procedure Call_Add -- # fun +is + function Add (X, Y : Integer) return Integer; + pragma Import (C, Add); + + Dummy : Integer := 0; -- # stmt +begin + if Add (40, 2) /= 42 then -- # if_1 + Dummy := Add (42, 2); -- # call_1 + end if; + + if Dummy = 50 then -- # if_2 + if Add (40, 2) /= 42 then -- # if_3 + Dummy := Add (42, 2); -- # call_2 + end if; + end if; + + if Add (40, 2) = 42 then -- # if_4 + Dummy := Add (42, 2); -- # call_3 + end if; + +end Call_Add; diff --git a/testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb b/testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb new file mode 100644 index 000000000..36ef7c109 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb @@ -0,0 +1,17 @@ +with Call_Add; + +procedure Test_Import_Called is +begin + Call_Add; +end Test_Import_Called; + +--# call_add.adb +-- /fun/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /if_1/ l! ## dT- +-- /call_1/ l- ## s=>s-, f=>s-,c- +-- /if_2/ l! ## dT- +-- /if_3/ l- ## s=>s-, f=>s-,c- +-- /call_2/ l- ## s=>s-, f=>s-,c- +-- /if_4/ l! ## dF- +-- /call_3/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb b/testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb new file mode 100644 index 000000000..a2ec0ddb2 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb @@ -0,0 +1,17 @@ +with Call_Add; + +procedure Test_Import_Not_Called is +begin + null; +end Test_Import_Not_Called; + +--# call_add.adb +-- /fun/ l- ## f- +-- /stmt/ l- ## s- +-- /if_1/ l- ## s=>s-, f=>s-,c- +-- /call_1/ l- ## s=>s-, f=>s-,c- +-- /if_2/ l- ## s- +-- /if_3/ l- ## s=>s-, f=>s-,c- +-- /call_2/ l- ## s=>s-, f=>s-,c- +-- /if_4/ l- ## s=>s-, f=>s-,c- +-- /call_3/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/import_call/test.py b/testsuite/tests/287-function_call_cov/import_call/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb new file mode 100644 index 000000000..993f35792 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb @@ -0,0 +1,32 @@ +pragma Ada_2012; + +procedure Nested +is + I : Integer := 1; -- # stmt + + function B (X : Integer := 5; Y : Boolean := True) return Integer -- # fun + is + begin + if Y then -- # stmt + return X; -- # stmt + else + return X; -- # stmt + end if; + end B; + +begin + I := -- # stmt + B -- # call + (B -- # call + (B), -- # call + False); -- # call + + if I = 42 then -- # if + I := -- # v_stmt + B -- # v_call + (B -- # v_call + (B), -- # v_call + False); -- # v_false + end if; + +end Nested; diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb new file mode 100644 index 000000000..41b5c2847 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb @@ -0,0 +1,19 @@ +with Nested; + +-- Check that nested calls are all instrumented and that the correct call +-- violations are reported. Calls made in a function spec as a parameter's +-- default value should never be instrumented. + +procedure Test_Nested is +begin + Nested; +end Test_Nested; + +--# nested.adb +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 +-- /if/ l! ## dT- +-- /v_stmt/ l- ## s- +-- /v_call/ l- ## f=>c- +-- /v_false/ l- ## 0 diff --git a/testsuite/tests/287-function_call_cov/nested_calls/test.py b/testsuite/tests/287-function_call_cov/nested_calls/test.py new file mode 100644 index 000000000..0bab4771c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/nested_calls/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, assert_lvl="atc", fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb new file mode 100644 index 000000000..1cf6a3c9a --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb @@ -0,0 +1,4 @@ +package body Pkg is + procedure P1 is null; -- # p + procedure P2 (I : Integer; J : Natural) is null; -- # p +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads new file mode 100644 index 000000000..29dce71dc --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + procedure P1; + procedure P2 (I : Integer; J : Natural); + procedure P3 is null; -- # p +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb new file mode 100644 index 000000000..a757062f8 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb @@ -0,0 +1,13 @@ +with Pkg; use Pkg; + +procedure Test_Called is +begin + P1; + P2 (1, 2); + P3; +end Test_Called; + +--# pkg.adb +-- /p/ l+ ## 0 +--# pkg.ads +-- /p/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb new file mode 100644 index 000000000..923faeb0e --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb @@ -0,0 +1,11 @@ +with Pkg; use Pkg; + +procedure Test_Not_Called is +begin + null; +end Test_Not_Called; + +--# pkg.adb +-- /p/ l- ## s=>s-, f=>s-,f- +--# pkg.ads +-- /p/ l- ## s=>s-, f=>s-,f- diff --git a/testsuite/tests/287-function_call_cov/null_procedures/test.py b/testsuite/tests/287-function_call_cov/null_procedures/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/foo.adb b/testsuite/tests/287-function_call_cov/protected_body/src/foo.adb new file mode 100644 index 000000000..6ed38862b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/foo.adb @@ -0,0 +1,26 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +package body Foo is + + protected body Obj_Type is + + function F return Integer is -- # fun + begin + return 8; -- # stmt + end F; + + function E (I : Integer) return Boolean is (True); -- # expr_fun + + procedure P (S : String) is -- # fun + begin + Put_Line (S); -- # call_stmt + null; -- # stmt + end P; + + procedure NP is -- # fun + null; -- # stmt + end Obj_Type; + +end Foo; diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/foo.ads b/testsuite/tests/287-function_call_cov/protected_body/src/foo.ads new file mode 100644 index 000000000..b0f5ef620 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/foo.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Foo is + + protected type Obj_Type is + function F return Integer; + function E (I : Integer) return Boolean; + procedure P (S : String); + procedure NP; + + end Obj_Type; + + Obj : Obj_Type; -- # decl + +end Foo; diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb b/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb new file mode 100644 index 000000000..24798453c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb @@ -0,0 +1,26 @@ +pragma Ada_2012; + +with Foo; use Foo; + +-- Check that function coverage violations are correctly reported for a +-- function, an expression function, a procedure and a null procedure inside +-- a protected body. + +procedure Test_Called +is + I : Integer := 42; +begin + I := Obj.F; + if Obj.E (I) then + Obj.P ("Hello"); + end if; + Obj.NP; +end Test_Called; + +--# foo.ads +-- /decl/ l+ ## 0 +--# foo.adb +-- /fun/ l+ ## 0 +-- /expr_fun/ l+ ## 0 +-- /call_stmt/ l+ ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb new file mode 100644 index 000000000..9f264fedc --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Foo; use Foo; + +-- Check that function coverage violations are correctly reported for a +-- function, an expression function, a procedure and a null procedure inside +-- a protected body. + +procedure Test_Not_Called is +begin + null; +end Test_Not_Called; + +--# foo.ads +-- /decl/ l+ ## 0 +--# foo.adb +-- /fun/ l- ## f- +-- /expr_fun/ l- ## s=>s-, f=>s-,f- +-- /call_stmt/ f=>l- ## s=>s-, f=>s-,c- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/287-function_call_cov/protected_body/test.opt b/testsuite/tests/287-function_call_cov/protected_body/test.opt new file mode 100644 index 000000000..6a8d1597d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Test uses tasking constructs, not available on light RTS diff --git a/testsuite/tests/287-function_call_cov/protected_body/test.py b/testsuite/tests/287-function_call_cov/protected_body/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb b/testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb new file mode 100644 index 000000000..2c058fd74 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +procedure Discriminant is + type Color is (Red, Green, Blue, Not_On); -- # a + + type Disc_Rec (Disc : Color) is -- # a + record + null; -- # a + end record; + + My_Rec : constant Disc_Rec := (Disc => Red); -- # a +begin + null; +end Discriminant; diff --git a/testsuite/tests/287-function_call_cov/static_call/src/enum.adb b/testsuite/tests/287-function_call_cov/static_call/src/enum.adb new file mode 100644 index 000000000..b7d24e784 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/enum.adb @@ -0,0 +1,31 @@ +pragma Ada_2012; + +procedure Enum is + type Color is (Red, Green, Blue, Not_On); -- # decl + + Pixel_1 : Color := Red; -- # decl + Pixel_2 : Color := Green; -- # decl + Pixel_3 : Color := Blue; -- # decl + + Nb_Red : Integer := 0; -- # decl +begin + + -- In an if statement + if Pixel_1 not in Red then -- # if + Nb_Red := Nb_Red + 1; -- # stmt_no + end if; + + -- In a case expression + Nb_Red := Nb_Red + -- # stmt_yes + (case Pixel_2 is -- # stmt_yes + when Red => 1, -- # stmt_yes + when Green .. Green => 0, -- # stmt_yes + when Blue | Not_On => 0); -- # stmt_yes + + -- In a case statement + case Pixel_3 is -- # stmt_yes + when Red => Nb_Red := Nb_Red + 1; -- # stmt_no + when Green .. Green => null; -- # stmt_no + when Blue | Not_On => null; -- # stmt_yes + end case; +end Enum; diff --git a/testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb b/testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb new file mode 100644 index 000000000..6b6b9832d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb @@ -0,0 +1,14 @@ +with Discriminant; + +-- Test that the use of enum values, which are calls, are not instrumented as +-- calls. This is checked with an enum value used in a record discriminant +-- that needs it to be a static value. Instrumenting it as a call would +-- result in a compilation error as they would no longer be static. + +procedure Test_Discriminant is +begin + Discriminant; +end Test_Discriminant; + +--# discriminant.adb +-- /a/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb b/testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb new file mode 100644 index 000000000..1e1825f09 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb @@ -0,0 +1,17 @@ +with Enum; + +-- Test that the use of enum values, which are calls, are not instrumented as +-- calls. This is checked with enum values used in case statements that need +-- them to be static values. Instrumenting them as calls would result in a +-- compilation error as they would no longer be static. + +procedure Test_Enum is +begin + Enum; +end Test_Enum; + +--# enum.adb +-- /decl/ l+ ## 0 +-- /if/ l! ## dT- +-- /stmt_no/ l- ## s- +-- /stmt_yes/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/static_call/test.py b/testsuite/tests/287-function_call_cov/static_call/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb new file mode 100644 index 000000000..ab0bc850a --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb @@ -0,0 +1,109 @@ +pragma Ada_2012; + +procedure No_Decls_Called is -- # p + + I : Integer := 8; + + function Func return Integer is -- # fun + begin + return 42; -- # stmt + end Func; + + procedure Proc is -- # fun + begin + I := I + 1 - 1; -- # stmt + end Proc; + + function Fun_Param (X : Integer := 1) return Integer -- # fun + is + begin + return X; -- # stmt + end Fun_Param; + + procedure Proc_Param (X : out Integer; Y : Boolean := True) -- # fun + is + begin + X := (if Y then 5 else 6); -- # stmt + end Proc_Param; + + function Expr_Func return Integer -- # fun + is (42); -- # stmt + + function Expr_Func_Param (X : Integer := 1) return Integer -- # fun + is (X); -- # stmt + + function Over (A : Integer) return Integer is -- # fun + begin + return A; -- # stmt + end Over; + + function Over (A, B : Integer) return Boolean is -- # fun + begin + return A /= B; -- # stmt + end Over; + + procedure Over (A : Integer) is -- # fun + begin + I := A; -- # stmt + end Over; + + procedure Over (A, B : Integer) is -- # fun + begin + I := A + B; -- # stmt + end Over; + + Dummy : Integer := 0; -- # decl + F : Boolean := False; -- # decl +begin + -- For each subprogram, make one call executed and another not + + -------------------- + -- Executed calls -- + -------------------- + + -- Functions + Dummy := Func -- # call + + Fun_Param (8) -- # call + + Fun_Param; -- # call + Dummy := Expr_Func -- # call + - Expr_Func_Param -- # call + - Expr_Func_Param (-100); -- # call + Dummy := Over (1); -- # call + F := Over (10, 2); -- # call + + -- Procedures + Proc; -- # call + Proc_Param (Dummy); -- # call + Proc_Param (Dummy, False); -- # call + Over (5); -- # call + Over (1, 2); -- # call + + ------------------------ + -- Non-executed calls -- + ------------------------ + + F := False and then F; -- # set_f + if F then -- # if_cond + -- Functions + Dummy := -- # v_dummy + Func -- # v_call + + Fun_Param (8) -- # v_call + + Fun_Param; -- # v_call + Dummy := -- # v_dummy + Expr_Func -- # v_call + - Expr_Func_Param -- # v_call + - Expr_Func_Param (-100); -- # v_call + Dummy := Over (1); -- # v_scall + F := Over (10, 2); -- # v_scall + + -- Procedures + -- Call statements that are not executed are simply reported as + -- statement violations. + Proc; -- # v_stmt + Proc_Param (Dummy); -- # v_stmt + Proc_Param (Dummy, False); -- # v_stmt + Over (5); -- # v_stmt + Over (1, 2); -- # v_stmt + end if; + +end No_Decls_Called; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb new file mode 100644 index 000000000..8f5d77ec9 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb @@ -0,0 +1,57 @@ +pragma Ada_2012; + +procedure No_Decls_Not_Called is -- # p + + I : Integer := 8; -- # stmt + + function Func return Integer is -- # fun + begin + return 42; -- # stmt + end Func; + + procedure Proc is -- # fun + begin + I := I + 1 - 1; -- # stmt + end Proc; + + function Fun_Param (X : Integer := 1) return Integer -- # fun + is + begin + return X; -- # stmt + end Fun_Param; + + procedure Proc_Param (X : out Integer; Y : Boolean := True) -- # fun + is + begin + X := (if Y then 5 else 6); -- # stmt + end Proc_Param; + + function Expr_Func return Integer -- # fun + is (42); -- # stmt + + function Expr_Func_Param (X : Integer := 1) return Integer -- # fun + is (X); -- # stmt + + function Over (A : Integer) return Integer is -- # fun + begin + return A; -- # stmt + end Over; + + function Over (A, B : Integer) return Boolean is -- # fun + begin + return A /= B; -- # stmt + end Over; + + procedure Over (A : Integer) is -- # fun + begin + I := A; -- # stmt + end Over; + + procedure Over (A, B : Integer) is -- # fun + begin + I := A + B; -- # stmt + end Over; + +begin + null; -- # stmt +end No_Decls_Not_Called; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb new file mode 100644 index 000000000..aa8a55147 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb @@ -0,0 +1,21 @@ +with No_Decls_Called; + +-- Call the subprograms which have a previous declaration. + +procedure Test_No_Decls_Called is +begin + No_Decls_Called; +end Test_No_Decls_Called; + +--# no_decls_called.adb +-- /p/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /call/ l+ ## 0 +-- /set_f/ l+ ## 0 +-- /if_cond/ l! ## dT- +-- /v_dummy/ l- ## s- +-- /v_stmt/ l- ## s-,c- +-- /v_call/ l- ## c- +-- /v_scall/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb new file mode 100644 index 000000000..238d6d2de --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb @@ -0,0 +1,16 @@ +with No_Decls_Not_Called; + +-- Import subprograms which all have a previous declarations. +-- None of the subprograms in the imported package are called here, so all of +-- them should have function coverage violations. + +procedure Test_No_Decls_Not_Called is +begin + null; +end Test_No_Decls_Not_Called; + +--# no_decls_not_called.adb +-- /p/ l- ## f- +-- /decl/ l+ ## 0 +-- /stmt/ l- ## s- +-- /fun/ l- ## f- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/test.py b/testsuite/tests/287-function_call_cov/subp_kinds/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb new file mode 100644 index 000000000..d12e80d39 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb @@ -0,0 +1,61 @@ +pragma Ada_2012; + +with With_Decls; use With_Decls; + +procedure Call_With_Decls +is + Dummy : Integer := 0; -- # stmt + F : Boolean := False; -- # stmt +begin + -- For each subprogram, make one call executed and another not + + -------------------- + -- Executed calls -- + -------------------- + + -- Functions + Dummy := Func -- # fun + + Fun_Param (8) -- # fun + + Fun_Param; -- # fun + Dummy := Expr_Func -- # fun + - Expr_Func_Param -- # fun + - Expr_Func_Param (-100); -- # fun + Dummy := Over (1); -- # fun + F := Over (10, 2); -- # fun + + -- Procedures + Proc; -- # fun + Proc_Param (Dummy); -- # fun + Proc_Param (Dummy, False); -- # fun + Over (5); -- # fun + Over (1, 2); -- # fun + + ------------------------ + -- Non-executed calls -- + ------------------------ + + F := False and then F; -- # set_f + if F then -- # if_cond + -- Functions + Dummy := -- # v_stmt + Func -- # v_fun + + Fun_Param (8) -- # v_fun + + Fun_Param; -- # v_fun + Dummy := -- # v_stmt + Expr_Func -- # v_fun + - Expr_Func_Param -- # v_fun + - Expr_Func_Param (-100); -- # v_fun + Dummy := Over (1); -- # v_sfun + F := Over (10, 2); -- # v_sfun + + -- Procedures + -- Call statements that are not executed are simply reported as + -- statement violations. + Proc; -- # v_cstmt + Proc_Param (Dummy); -- # v_cstmt + Proc_Param (Dummy, False); -- # v_cstmt + Over (5); -- # v_cstmt + Over (1, 2); -- # v_cstmt + end if; + +end Call_With_Decls; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb new file mode 100644 index 000000000..150cbd682 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb @@ -0,0 +1,23 @@ +with Call_With_Decls; + +-- Call the subprograms which have a previous declaration. + +procedure Test_With_Decls_Called is +begin + Call_With_Decls; +end Test_With_Decls_Called; + +--# call_with_decls.adb +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /set_f/ l+ ## 0 +-- /if_cond/ l! ## dT- +-- /v_stmt/ l- ## s- +-- /v_fun/ l- ## c- +-- /v_sfun/ l- ## s-,c- +-- /v_cstmt/ l- ## s-,c- +--# with_decls.ads +-- /stmt/ l+ ## 0 +--# with_decls.adb +-- /fun/ l+ ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb new file mode 100644 index 000000000..647500691 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb @@ -0,0 +1,16 @@ +with With_Decls; + +-- Import subprograms which all have a previous declarations. +-- None of the subprograms in the imported package are called here, so all of +-- them should have function coverage violations. + +procedure Test_With_Decls_Not_Called is +begin + null; +end Test_With_Decls_Not_Called; + +--# with_decls.ads +-- /stmt/ l+ ## 0 +--# with_decls.adb +-- /stmt/ l- ## s- +-- /fun/ l- ## f- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb new file mode 100644 index 000000000..4430c632c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb @@ -0,0 +1,53 @@ +pragma Ada_2012; + +package body With_Decls is + + function Func return Integer is -- # fun + begin + return 42; -- # stmt + end Func; + + procedure Proc is -- # fun + begin + I := I + 1 - 1; -- # stmt + end Proc; + + function Fun_Param (X : Integer := 1) return Integer -- # fun + is + begin + return X; -- # stmt + end Fun_Param; + + procedure Proc_Param (X : out Integer; Y : Boolean := True) -- # fun + is + begin + X := (if Y then 5 else 6); -- # stmt + end Proc_Param; + + function Expr_Func return Integer -- # fun + is (42); -- # stmt + + function Expr_Func_Param (X : Integer := 1) return Integer -- # fun + is (X); -- # stmt + + function Over (A : Integer) return Integer is -- # fun + begin + return A; -- # stmt + end Over; + + function Over (A, B : Integer) return Boolean is -- # fun + begin + return A /= B; -- # stmt + end Over; + + procedure Over (A : Integer) is -- # fun + begin + I := A; -- # stmt + end Over; + + procedure Over (A, B : Integer) is -- # fun + begin + I := A + B; -- # stmt + end Over; + +end With_Decls; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads new file mode 100644 index 000000000..16d7cc42f --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package With_Decls is + + I : Integer := 1; -- # stmt + + -- No parameters + function Func return Integer; + procedure Proc; + + -- With parameters + function Fun_Param (X : Integer := 1) return Integer; + procedure Proc_Param (X : out Integer; Y : Boolean := True); + + -- Expression function + function Expr_Func return Integer; + function Expr_Func_Param (X : Integer := 1) return Integer; + + -- Overloaded + function Over (A : Integer) return Integer; + function Over (A, B : Integer) return Boolean; + procedure Over (A : Integer); + procedure Over (A, B : Integer); + +end With_Decls; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/op.adb b/testsuite/tests/287-function_call_cov/user_operator/src/op.adb new file mode 100644 index 000000000..723057cc6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/src/op.adb @@ -0,0 +1,66 @@ +pragma Ada_2012; + +with Reversed; use Reversed; + +procedure Op +is + T : Boolean := True; -- # decl + F : Boolean := False; -- # decl + Dummy : Boolean := True; -- # decl + + function "+" (Left, Right : Boolean) return Boolean -- # fun + is (Left and Right); -- # fun + + function "+" (Arg : Reversed.T) return Reversed.T -- # fun + is (0 - Arg); -- # fun + + function "&" (L,R : Float) return Float -- # fun + is (42.0); -- # fun + + function "&" (L : Integer; R : String) return Integer -- # fun + is (42); -- # fun + + function "&" (L : String; R : Integer) return Integer -- # fun + is (42); -- # fun + +begin + Dummy := F + T; -- # ok + Dummy := "+" (T, F); -- # ok + Dummy := F + T + F + T; -- # ok + Dummy := "+" (T, "+" (T, F)); -- # ok + + Dummy := One < Two; -- # ok + Dummy := Reversed."<" (One, Two); -- # ok + + Dummy := +One = -1; -- # ok + Dummy := Reversed.Inner."+" (One) = -1; -- # ok + + Dummy := (40 & "Two") = 42; -- # ok + Dummy := (1.3 & 3.2 & 2.1) = 42.0; -- # ok + + Dummy := F + ("&" ("A", 8) = 42); -- # ok + Dummy := "+" (F, ("&" ("A", 8) = 42)); -- # ok + + Dummy := ("A" & "B" & 42 & "D" & "E") = 42; -- # ok + + if F then -- # if + Dummy := F + T; -- # ko + Dummy := "+" (T, F); -- # ko + Dummy := F + T + F + T; -- # A_ko + Dummy := "+" (T, "+" (T, F)); -- # B_ko + + Dummy := One < Two; -- # ko + Dummy := Reversed."<" (One, Two); -- # ko + + Dummy := +One = -1; -- # ko + Dummy := Reversed.Inner."+" (One) = -1; -- # ko + + Dummy := (40 & "Two") = 42; -- # ko + Dummy := (1.3 & 3.2 & 2.1) = 42.0; -- # C_ko + + Dummy := F + ("&" ("A", 8) = 42); -- # D_ko + Dummy := "+" (F, ("&" ("A", 8) = 42)); -- # E_ko + + Dummy := ("A" & "B" & 42 & "D" & "E") = 42; -- # F_ko + end if; +end Op; diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads b/testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads new file mode 100644 index 000000000..d6752c0b2 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Reversed is + type T is new Integer; -- # ok + + One : T := 1; -- # ok + Two : T := 2; -- # ok + + -- Let's make it go the other way to keep things interesting + function "<" (L, R : T) return Boolean is (L > R); -- # ok + + package Inner is + function "+" (Arg : T) return T is (0 - Arg); -- # ok + end Inner; +end Reversed; diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb b/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb new file mode 100644 index 000000000..c6a0bbb40 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb @@ -0,0 +1,21 @@ +with Op; + +procedure Test_Op is +begin + Op; +end Test_Op; + +--# op.adb +-- /decl/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /ok/ l+ ## 0 +-- /ko/ l- ## s=>s-,f=>s-,c- +-- /A_ko/ l- ## s=>s-,f=>s-,c-,c-,c- +-- /B_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /C_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /D_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /E_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /F_ko/ l- ## s=>s-,f=>s-,c-,c-,c- +-- /if/ l! ## dT- +--# reversed.ads +-- /ok/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/user_operator/test.py b/testsuite/tests/287-function_call_cov/user_operator/test.py new file mode 100644 index 000000000..226fb54d3 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/test.py @@ -0,0 +1,10 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages="cannot instrument calls to user-defined operators", +).run() +thistest.result() diff --git a/testsuite/tests/292-rts-syms/test.opt b/testsuite/tests/292-rts-syms/test.opt new file mode 100644 index 000000000..323e3c035 --- /dev/null +++ b/testsuite/tests/292-rts-syms/test.opt @@ -0,0 +1,4 @@ +!native DEAD Test need full gnatcov RTS +5.04a1 DEAD This compiler does not ship nm +7.1.2 DEAD The nm version in 7.1.2 does not support the required options +!x86_64 DEAD Additional symbols unrelated to gnatcov_rts exported under x86 diff --git a/testsuite/tests/292-rts-syms/test.py b/testsuite/tests/292-rts-syms/test.py new file mode 100644 index 000000000..ef88cdedf --- /dev/null +++ b/testsuite/tests/292-rts-syms/test.py @@ -0,0 +1,47 @@ +""" +Check that all external symbols exported by gnatcov_rts are prefixed +with "gnatcov_rts" to avoid conflicts with user code. +""" + +import os + +from e3.os.fs import which + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import contents_of, exename_for, run_and_log, xcov + +tmp = Wdir("tmp_") + +nm = which(exename_for("nm")) + +gcvrt_prefix = "gnatcov_rts" + +# Setup gnatcov locally so we don't need to search for the archive +xcov(["setup", "--prefix", gcvrt_prefix]) + +gnatcov_rts_lib = os.path.join( + gcvrt_prefix, "lib", "gnatcov_rts.static", "libgnatcov_rts.a" +) + +symbol_file = "gnatcov_rts_symbols.txt" +run_and_log( + [ + nm, + "-g", # Only print external symbols + "-U", # Only print symbols defined in the library + "-j", # Only print the symbol name + gnatcov_rts_lib, + ], + output=symbol_file, +) + +symbols = contents_of(symbol_file).splitlines() +for symbol in symbols: + thistest.fail_if( + not symbol.startswith("gnatcov_rts"), + comment=f"gnatcov_rts exports a symbol not prefixed by 'gnatcov_rts'" + f": {symbol}", + ) + +thistest.result() diff --git a/testsuite/tests/300-no-sco-msg/main.adb b/testsuite/tests/300-no-sco-msg/main.adb new file mode 100644 index 000000000..dcdaff132 --- /dev/null +++ b/testsuite/tests/300-no-sco-msg/main.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + type String_Acc is access all String; + Str : aliased String := "Hello World!"; + Str_Acc : constant String_Acc := Str'Access; + Cond : Boolean := True; + pragma Volatile(Cond); + Ptr : String_Acc := (if Cond then Str_Acc else Str_Acc); +begin + Put_Line ("Yay!"); + if Cond then + Ptr := Str_Acc; + else + Ptr := Str_Acc; + end if; + Put_Line (Ptr.all); +end Main; diff --git a/testsuite/tests/300-no-sco-msg/test.opt b/testsuite/tests/300-no-sco-msg/test.opt new file mode 100644 index 000000000..3bab65018 --- /dev/null +++ b/testsuite/tests/300-no-sco-msg/test.opt @@ -0,0 +1,4 @@ +!bin-traces DEAD requires bin traces to produce the proper message +CARGS_O1 DEAD optimization deletes branch leading to required message +CARGS_gnatp DEAD runtime checks required to produce branch leading to message +5.04a1 DEAD Test requires Ada 2012 diff --git a/testsuite/tests/300-no-sco-msg/test.py b/testsuite/tests/300-no-sco-msg/test.py new file mode 100644 index 000000000..3f833132c --- /dev/null +++ b/testsuite/tests/300-no-sco-msg/test.py @@ -0,0 +1,47 @@ +""" +Test that gnatcov does not crash when messages are not attached to any SCO. +It used to crash when generating a --annotate=report coverage report in +presence of such messages. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +root = gprfor( + srcdirs="..", + mains=["main.adb"], + objdir="obj", +) + +rep = "test.rep" + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=[ + "--annotate=report", + "--log=BRANCH_STATS", + "--all-messages", + ], + out=rep, +) + +# Check the contents of the report to ensure the expected message is indeed +# emitted (otherwise the test is pointless). +thistest.fail_if_no_match( + "missing warning message", + regexp=r"(.|\n)*2.3. OTHER ERRORS" + r"(.|\n)+-----------------" + r"(.|\n)+main\.adb:19:4: non-traceable: cond branch for" + r" OTHER_STATEMENT" + r"(.|\n)*", + actual=contents_of(rep), +) + +thistest.result() diff --git a/testsuite/tests/300-non-cov-decision/src/pkg.adb b/testsuite/tests/300-non-cov-decision/src/pkg.adb new file mode 100644 index 000000000..9a8ebc9b9 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Ada.Text_IO; + +package body Pkg is + + procedure Foo (X : Boolean) is + type String_Acc is access all String; + Str : aliased String := "Hello World!"; -- # st + Str_Acc : constant String_Acc := Str'Access; -- # st + Cond : Boolean := True; -- # st + pragma Volatile(Cond); + Ptr : String_Acc := (if Cond then Str_Acc else Str_Acc); -- # dc + begin + Ada.Text_IO.Put_Line (Ptr.all); -- # st + end Foo; + +end Pkg; diff --git a/testsuite/tests/300-non-cov-decision/src/pkg.ads b/testsuite/tests/300-non-cov-decision/src/pkg.ads new file mode 100644 index 000000000..8965cb39b --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Foo (X : Boolean); + +end Pkg; diff --git a/testsuite/tests/300-non-cov-decision/src/test_pkg.adb b/testsuite/tests/300-non-cov-decision/src/test_pkg.adb new file mode 100644 index 000000000..d20ff9aa4 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/src/test_pkg.adb @@ -0,0 +1,16 @@ +with Pkg; + +procedure Test_Pkg is +begin + Pkg.Foo(True); +end Test_Pkg; + +--# pkg.adb +-- /st/ l+ ## 0 +-- /dc/ l+ ## 0 + +-- %opts: --trace-mode=src +-- =/dc/ l! ## dF- + +-- %cov: --non-coverable +-- =/dc/ l0 ## d0 diff --git a/testsuite/tests/300-non-cov-decision/test.opt b/testsuite/tests/300-non-cov-decision/test.opt new file mode 100644 index 000000000..371d64be9 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Test requires Ada 2012 support +7.1.2 DEAD optimization on this compiler is too aggressive on Ada 2012 diff --git a/testsuite/tests/300-non-cov-decision/test.py b/testsuite/tests/300-non-cov-decision/test.py new file mode 100644 index 000000000..8ac0d3ed9 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/test.py @@ -0,0 +1,19 @@ +""" +Test that gnatcov reports decisions for which no conditional branches have been +generated, and which does not dominate any statement as not-coverable instead +of a violation. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() + +if thistest.options.trace_mode == "bin": + TestCase(category=CAT.decision).run( + covcontrol=CovControl(covoptions="--non-coverable"), subdirhint="nc_" + ) + +thistest.result() diff --git a/testsuite/tests/308-print-gpr-registry/test.py b/testsuite/tests/308-print-gpr-registry/test.py new file mode 100644 index 000000000..30b3b2e24 --- /dev/null +++ b/testsuite/tests/308-print-gpr-registry/test.py @@ -0,0 +1,100 @@ +""" +Check that the special --print-gpr-registry command line switch works as +expected. + +Specifically, run "gnatcov --print-gpr-registry" with the 4 possible format +options and check that they have roughly the same content (same summary: list +of attributes). +""" + +import json + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +tmp = Wdir("tmp_") + + +def summarize_json(f): + result = [] + doc = json.load(f) + for pkg in doc["packages"]: + for attr in pkg["attributes"]: + result.append(f"{pkg['package_name']}.{attr['attribute_name']}") + result.sort() + return "\n".join(result) + + +def summarize_text(f): + result = [] + for line in f: + line = line.strip() + if not line: + continue + elif " " not in line: + pkg = line + elif ( + line.endswith(": list") + or line.endswith(": single") + or line.endswith(": list, indexed") + or line.endswith(": single, indexed") + ): + attr = line.split()[0][:-1] + result.append(f"{pkg}.{attr}") + result.sort() + return "\n".join(result) + + +baseline = ( + "Coverage.Excluded_Routines" + "\nCoverage.Excluded_Routines_List" + "\nCoverage.Excluded_Units" + "\nCoverage.Excluded_Units_List" + "\nCoverage.Ignored_Source_Files" + "\nCoverage.Ignored_Source_Files_List" + "\nCoverage.Routines" + "\nCoverage.Routines_List" + "\nCoverage.Switches" + "\nCoverage.Units" + "\nCoverage.Units_List" +) + + +for fmt, summarize in [ + (None, summarize_json), + ("text", summarize_text), + ("json", summarize_json), + ("json-compact", summarize_json), +]: + thistest.log(f"== {fmt} ==") + + args = ["--print-gpr-registry"] + if fmt is None: + out_filename = "default.txt" + else: + args.append(f"--gpr-registry-format={fmt}") + out_filename = f"{fmt}.txt" + + xcov(args, out=out_filename, auto_target_args=False) + + with open(out_filename) as f: + actual = summarize(f) + thistest.fail_if_not_equal("Output of " + " ".join(args), baseline, actual) + + +thistest.log("== invalid ==") +args = ["--print-gpr-registry", "--gpr-registry-format=invalid"] +p = xcov( + args, out="invalid.txt", auto_target_args=False, register_failure=False +) +thistest.fail_if_not_equal("gnatcov exit code", 1, p.status) +thistest.fail_if_no_match( + "Output of " + " ".join(args), + "^.*gnatcov.*: Bad GPR registry format: invalid$", + contents_of("invalid.txt").strip(), +) + + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/extra.opt b/testsuite/tests/320-varying-scos/extra.opt new file mode 100644 index 000000000..53cb5a548 --- /dev/null +++ b/testsuite/tests/320-varying-scos/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Tests specific to source traces diff --git a/testsuite/tests/320-varying-scos/varying_header/src/bar.c b/testsuite/tests/320-varying-scos/varying_header/src/bar.c new file mode 100644 index 000000000..fbe564ba3 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/bar.c @@ -0,0 +1,2 @@ +#define B +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.c b/testsuite/tests/320-varying-scos/varying_header/src/foo.c new file mode 100644 index 000000000..355ae477a --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/foo.c @@ -0,0 +1,2 @@ +#define A +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.h b/testsuite/tests/320-varying-scos/varying_header/src/foo.h new file mode 100644 index 000000000..76a1e6520 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/foo.h @@ -0,0 +1,15 @@ +#ifdef A +int +foo () +{ + return 0; +} +#endif + +#ifdef B +int +bar () +{ + return 0; +} +#endif; diff --git a/testsuite/tests/320-varying-scos/varying_header/src/main.c b/testsuite/tests/320-varying-scos/varying_header/src/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/320-varying-scos/varying_header/test.py b/testsuite/tests/320-varying-scos/varying_header/test.py new file mode 100644 index 000000000..de5644023 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/test.py @@ -0,0 +1,29 @@ +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "bar.c.xcov": {}, + "foo.c.xcov": {}, + "foo.h.xcov": {"-": {5, 13}}, + "main.c.xcov": {"+": {4}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c new file mode 100644 index 000000000..fbe564ba3 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c @@ -0,0 +1,2 @@ +#define B +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c new file mode 100644 index 000000000..355ae477a --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c @@ -0,0 +1,2 @@ +#define A +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h new file mode 100644 index 000000000..e36a63966 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h @@ -0,0 +1,10 @@ +int +foo () +{ +#ifdef A + return 0; +#endif +#ifdef B + return 1; +#endif; +} diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/test.py b/testsuite/tests/320-varying-scos/varying_in_scope/test.py new file mode 100644 index 000000000..487e4ab1b --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/test.py @@ -0,0 +1,54 @@ +""" +Check that gnatcov correctly load checkpoints when a source has a version that +varies across runs, and when the varying part is in the same scope for both +versions. Check that the scope metrics are as expected by inspecting the XML +report. +""" + +from lxml import etree + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "-axml", "--output-dir=report"], + trace_mode="src", +) +check_xcov_reports( + "report/xcov", + { + "bar.c.xcov": {}, + "foo.c.xcov": {}, + "foo.h.xcov": {"-": {5, 8}}, + "main.c.xcov": {"+": {4}}, + }, + discard_empty=False, +) + +# Check scope metrics +xml = etree.parse("report/xml/foo.h.xml") +xpath_query = ( + ".//scope_metric/obligation_stats/metric" + '[@kind="total_obligations_of_relevance"]' +) + +# Find all matching metrics +metrics = xml.xpath(xpath_query) + +# We expect 2 statement violations for the header and the associated function +thistest.fail_if( + int(metrics[0].get("count")) != 2 or int(metrics[1].get("count")) != 2, + "unexpected scope metrics", +) + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/bar.c b/testsuite/tests/320-varying-scos/varying_meta/src/bar.c new file mode 100644 index 000000000..289891d9f --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/bar.c @@ -0,0 +1,2 @@ +#define NAME bcd +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.c b/testsuite/tests/320-varying-scos/varying_meta/src/foo.c new file mode 100644 index 000000000..ac771fcbc --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/foo.c @@ -0,0 +1,2 @@ +#define NAME a +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.h b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h new file mode 100644 index 000000000..959587eeb --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h @@ -0,0 +1,6 @@ +int +foo () +{ + int NAME; // # foo-decl + return 0; // # foo-return +} diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c new file mode 100644 index 000000000..b14025e4a --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c @@ -0,0 +1,12 @@ +int +main () +{ + return 0; +} + +//# foo.h +// /foo-decl/ l- ## s- +// /foo-return/ l- ## s- +// +//# foo.c +//# bar.c diff --git a/testsuite/tests/320-varying-scos/varying_meta/test.py b/testsuite/tests/320-varying-scos/varying_meta/test.py new file mode 100644 index 000000000..b7842ac2c --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/test.py @@ -0,0 +1,35 @@ +""" +Check that gnatcov correctly discards coverage data for a compilation unit +version that conflicts with a previously loaded version. Note: the use of the +TestCase driver framework matters here, as if we do not discard source coverage +obligations (those coming from bar.h, or foo.h: it does not really matter +which), we end up with four coverage obligations in foo.h, and thus four +violations. This is actually checked through the report format check by the +TestCase framework. +""" + +from SUITE.context import thistest +from SUITE.cutils import contents_of +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +tolerate_cov_messages = "|".join( + [ + r"warning: Discarding source coverage data for unit" + r".*foo.h \(from .*bar.c\), loaded from .*foo.c.sid", + r"warning: traces for .*foo.h .* are inconsistent .*", + ] +) +TestCase( + category=CAT.stmt, + tolerate_cov_messages=tolerate_cov_messages, +).run() + +# Check that gnatcov output contains the expected error messages +thistest.fail_if_no_match( + "gnatcov coverage output", + tolerate_cov_messages, + contents_of("s_1/xcov.out").strip(), +) + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_source/src1/main.adb b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb new file mode 100644 index 000000000..05ad557f7 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("World"); +end Main; diff --git a/testsuite/tests/320-varying-scos/varying_source/src2/main.adb b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb new file mode 100644 index 000000000..78cf5e255 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello"); +end Main; diff --git a/testsuite/tests/320-varying-scos/varying_source/test.py b/testsuite/tests/320-varying-scos/varying_source/test.py new file mode 100644 index 000000000..3e5f31ea8 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source/test.py @@ -0,0 +1,71 @@ +""" +Check that gnatcov rejects the checkpoint information for different source +versions. +""" + +from e3.fs import mkdir + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +root_project = gprfor(srcdirs=["."], langs=["ada"], mains=["main.adb"]) + + +def generate_checkpoint(source_body, ckpt_name): + + with open("main.adb", "w+") as f: + f.write( + f"""procedure Main is + begin + {source_body} + end Main;""" + ) + + build_run_and_coverage( + gprsw=GPRswitches(root_project=root_project), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[ + "--cancel-annotate", + "--save-checkpoint", + ckpt_name, + ], + trace_mode="src", + ) + + +generate_checkpoint("null;", "v1.ckpt") +generate_checkpoint("null;\nnull;", "v2.ckpt") + +coverage_log = "coverage.log" +mkdir("xcov") +p = xcov( + [ + "coverage", + "-P", + root_project, + "--level=stmt", + "-Cv1.ckpt", + "-Cv2.ckpt", + "-axcov", + "--output-dir", + "xcov", + ], + out=coverage_log, + register_failure=False, +) + +thistest.fail_if_no_match( + "Unexpected error message from 'gnatcov coverage'.", + regexp=r"warning: unexpected fingerprint, cannot merge coverage" + r" information for main.adb \(from v2.ckpt\)", + actual=contents_of(coverage_log), +) + +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {3}}}) +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c new file mode 100644 index 000000000..f14f9e495 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c @@ -0,0 +1,10 @@ +int +main () +{ +#ifdef A + return 0; +#endif +#ifdef B + return 0; +#endif +} diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py new file mode 100644 index 000000000..59b831a4c --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py @@ -0,0 +1,48 @@ +""" +Check that gnatcov coverage correctly aggregates coverage data of a file that +has various version according to the preprocessing configuration. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +prj = gprfor(srcdirs=[".."], mains=["main.c"]) + +# Compute coverage data with the A configuration +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c-opts=-DA"], + extra_coverage_args=["--cancel-annotate", "--save-checkpoint", "a.ckpt"], + trace_mode="src", +) + +# Compute coverage data for the B configuration +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c-opts=-DB"], + extra_coverage_args=["--cancel-annotate", "--save-checkpoint", "b.ckpt"], + trace_mode="src", +) + +# Aggregate the coverage data to produce an xcov report +xcov( + ["coverage", "-P", prj, "--level=stmt", "-axcov", "-Ca.ckpt", "-Cb.ckpt"], + tolerate_messages="warning: inconsistent preprocessing information.*", +) + +check_xcov_reports( + "obj", + {"main.c.xcov": {"+": {5, 8}}}, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/334-unexpected-exemption/main.adb b/testsuite/tests/334-unexpected-exemption/main.adb new file mode 100644 index 000000000..aab012f4a --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/main.adb @@ -0,0 +1,6 @@ +with Proc; + +procedure Main is +begin + Proc (0); +end Main; diff --git a/testsuite/tests/334-unexpected-exemption/proc.adb b/testsuite/tests/334-unexpected-exemption/proc.adb new file mode 100644 index 000000000..1a74dd145 --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/proc.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Proc (N : Natural) is +begin + if N = 1 then + Put_Line ("got one argument"); + elsif N in 2 .. 10 then + pragma Annotate (Xcov, Exempt_On, "2 .. 10"); + Put_Line ("got between 2 and 10 arguments"); + pragma Annotate (Xcov, Exempt_Off); + else + pragma Annotate (Xcov, Exempt_On, "others"); + Put_Line ("other cases"); + pragma Annotate (Xcov, Exempt_Off); + end if; +end Proc; diff --git a/testsuite/tests/334-unexpected-exemption/test.opt b/testsuite/tests/334-unexpected-exemption/test.opt new file mode 100644 index 000000000..d53c552fd --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Cannot compile pragmas marking begin and end of exempted regions diff --git a/testsuite/tests/334-unexpected-exemption/test.py b/testsuite/tests/334-unexpected-exemption/test.py new file mode 100644 index 000000000..9e93dca0c --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/test.py @@ -0,0 +1,55 @@ +""" +Check that --annotate=xcov,report produces expected '*' lines for +exempted-and-uncovered code. It used to generate '#' lines +(exempte-and-covered) instead. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[ + "-axcov,report", + "--output-dir=xcov", + "-o", + "report.txt", + ], +) + +# Check that the xcov report contains the expected '*' and '#' lines +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "proc.adb.xcov": { + "+": {5, 7}, + "-": {6}, + "#": {12, 13, 14}, + "*": {8, 9, 10}, + }, + }, +) + +# Check that the "report" report has the right count for exempted violations +lines = [ + line + for line in lines_of("report.txt") + if line.startswith("proc.adb:") and "exempted violation" in line +] +thistest.fail_if_not_equal( + 'Exempted violations in the "report" report', + "proc.adb:8:7-10:7: 1 exempted violation, justification:" + "\nproc.adb:12:7-14:7: 0 exempted violation, justification:", + "\n".join(lines), +) + +thistest.result() diff --git a/testsuite/tests/345-live-observability/libpkg.gpr b/testsuite/tests/345-live-observability/libpkg.gpr new file mode 100644 index 000000000..8b72adf89 --- /dev/null +++ b/testsuite/tests/345-live-observability/libpkg.gpr @@ -0,0 +1,7 @@ +library project LibPkg is + for Source_Dirs use ("src-lib"); + for Object_Dir use "obj-lib"; + + for Library_Name use "pkg"; + for Library_Dir use "lib"; +end LibPkg; diff --git a/testsuite/tests/345-live-observability/src-lib/pkg.adb b/testsuite/tests/345-live-observability/src-lib/pkg.adb new file mode 100644 index 000000000..57f409981 --- /dev/null +++ b/testsuite/tests/345-live-observability/src-lib/pkg.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Foo (B : Boolean) is + begin + if B then -- if-stmt is 1 SCO + Put_Line("B is True"); -- 1 SCO, unless --block + Put_Line("I swear it is True"); -- 1 SCO + else + Put_Line("B is False :("); -- 1 SCO + end if; + end Foo; + + procedure Bar (A : Integer) is + I : Integer := 155 + A; -- 1 SCO, unless --block + begin + Put_Line (Integer'Image (I)); -- 1 SCO + end Bar; + +end Pkg; diff --git a/testsuite/tests/345-live-observability/src-lib/pkg.ads b/testsuite/tests/345-live-observability/src-lib/pkg.ads new file mode 100644 index 000000000..45f0bfb96 --- /dev/null +++ b/testsuite/tests/345-live-observability/src-lib/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + procedure Foo (B : Boolean); + + procedure Bar (A : Integer); + +end Pkg; diff --git a/testsuite/tests/345-live-observability/src/main.adb b/testsuite/tests/345-live-observability/src/main.adb new file mode 100644 index 000000000..32a450257 --- /dev/null +++ b/testsuite/tests/345-live-observability/src/main.adb @@ -0,0 +1,30 @@ +with Ada.Text_IO; use Ada.Text_IO; +with GCVRT.Gen.Observe; use GCVRT.Gen.Observe; +with Pkg; + +procedure Main is +begin + -- No statement should be covered yet here. + Put_Line ("First: " & Positive'Image (Sum_Buffer_Bits)); + + Pkg.Foo (False); + + -- 2 statements were executed since last call. + -- (if stmt + False Put_Line) + Put_Line ("Second: " & Positive'Image (Sum_Buffer_Bits)); + + Pkg.Foo (True); + + -- 2 statements were executed since last call. + -- (if stmt is already covered, + 2 Put_Lines) + Put_Line ("Third: " & Positive'Image (Sum_Buffer_Bits)); + + -- No change since last call + Put_Line ("Third-bis: " & Positive'Image (Sum_Buffer_Bits)); + + Pkg.Bar (42); + + -- 2 more statements covered + -- (Integer declaration, Put_Line) + Put_Line ("Fourth: " & Positive'Image (Sum_Buffer_Bits)); +end Main; diff --git a/testsuite/tests/345-live-observability/test.opt b/testsuite/tests/345-live-observability/test.opt new file mode 100644 index 000000000..31322518a --- /dev/null +++ b/testsuite/tests/345-live-observability/test.opt @@ -0,0 +1 @@ +!src-traces DEAD Test is specific to source traces diff --git a/testsuite/tests/345-live-observability/test.py b/testsuite/tests/345-live-observability/test.py new file mode 100644 index 000000000..e6c952c33 --- /dev/null +++ b/testsuite/tests/345-live-observability/test.py @@ -0,0 +1,69 @@ +""" +This test ensures that the live observability of coverage data provides +sound data. +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +wd = Wdir("tmp_") + + +build_and_run( + gprsw=GPRswitches( + root_project=gprfor( + mains=["main.adb"], srcdirs=["../src"], deps=["../libpkg.gpr"] + ), + projects=["libpkg"], + ), + mains=["main"], + covlevel="stmt", + extra_gprbuild_args=[], + extra_coverage_args=[], +) + +# In case block instrumentation is enabled, the number of bits set to 1 in the +# buffers is not equivalent to the number of statements executed. +if thistest.options.block: + counts = [0, 2, 3, 4] +else: + counts = [0, 2, 4, 6] + +OUTPUT = contents_of("main_output.txt") + +thistest.fail_if_no_match( + "Wrong first buffer sum", + re.compile(f".*First: *{counts[0]}.*", re.S), + OUTPUT, +) + +thistest.fail_if_no_match( + "Wrong second buffer sum", + re.compile(f".*Second: *{counts[1]}.*", re.S), + OUTPUT, +) + +thistest.fail_if_no_match( + "Wrong third buffer sum", + re.compile(f".*Third: *{counts[2]}.*", re.S), + OUTPUT, +) + +thistest.fail_if_no_match( + "Wrong third-bis buffer sum", + re.compile(f".*Third-bis: *{counts[2]}.*", re.S), + OUTPUT, +) + +thistest.fail_if_no_match( + "Wrong fourth buffer sum", + re.compile(f".*Fourth: *{counts[3]}.*", re.S), + OUTPUT, +) + +thistest.result() diff --git a/testsuite/tests/354-source-encoding/latin1.ads b/testsuite/tests/354-source-encoding/latin1.ads new file mode 100644 index 000000000..590a15a46 --- /dev/null +++ b/testsuite/tests/354-source-encoding/latin1.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; +package Latin1 is + function Id (V : Boolean) return Boolean is (V); + function F (A, B : Boolean) return Boolean + is (Id (-- ÉaÉ + A) and then B); +end Latin1; diff --git a/testsuite/tests/354-source-encoding/main.adb b/testsuite/tests/354-source-encoding/main.adb new file mode 100644 index 000000000..23d4203b0 --- /dev/null +++ b/testsuite/tests/354-source-encoding/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Latin1; +with UTF8; + +procedure Main is +begin + if Latin1.F (True, True) and then UTF8.F (True, True) then + Put_Line ("Hello world!"); + end if; +end Main; diff --git a/testsuite/tests/354-source-encoding/test.opt b/testsuite/tests/354-source-encoding/test.opt new file mode 100644 index 000000000..a9cfee6c3 --- /dev/null +++ b/testsuite/tests/354-source-encoding/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Use of Ada 20212 constructs diff --git a/testsuite/tests/354-source-encoding/test.py b/testsuite/tests/354-source-encoding/test.py new file mode 100644 index 000000000..6bd3041c2 --- /dev/null +++ b/testsuite/tests/354-source-encoding/test.py @@ -0,0 +1,271 @@ +"""Check that XML reports are valid for non-ASCII sources.""" + +import xml.dom.minidom as minidom + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +def xml_src_summary(filename): + """ + Read the given XML source file coverage report and extract a summary of + the quoted lines it contains. + """ + result = [] + + def append(level, tag, content=None): + prefix = " " * level + tag + result.append( + f"{prefix}: {ascii(content)}" if content is not None else prefix + ) + + def element_nodes(parent): + return [n for n in parent.childNodes if isinstance(n, minidom.Element)] + + def process_src_mapping(n): + assert n.tagName == "src_mapping" + append(0, "src_mapping") + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, 1) + case "statement": + process_statement(c, 1) + case "decision": + process_decision(c, 1) + case "message": + pass + case _: + raise AssertionError( + f"unexpected src_mapping child element: {c.tagName}" + ) + + def process_src(n, level): + assert n.tagName == "src" + append(level, "src") + for c in element_nodes(n): + match c.tagName: + case "line": + append( + level + 1, + f"line {c.getAttribute('num')}", + c.getAttribute("src"), + ) + case _: + raise AssertionError( + f"unexpected src child element: {c.tagName}" + ) + + def process_statement(n, level): + append(level, "statement", n.getAttribute("text")) + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, level + 1) + case _: + raise AssertionError( + f"unexpected statement child element: {c.tagName}" + ) + + def process_decision(n, level): + append(level, "decision", n.getAttribute("text")) + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, level + 1) + case "condition": + process_condition(c, level + 1) + case _: + raise AssertionError( + f"unexpected decision child element: {c.tagName}" + ) + + def process_condition(n, level): + append(level, "condition", n.getAttribute("text")) + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, level + 1) + case _: + raise AssertionError( + f"unexpected condition child element: {c.tagName}" + ) + + doc = minidom.parse(filename) + source = doc.documentElement + for n in element_nodes(source): + if n.tagName == "src_mapping": + process_src_mapping(n) + return "\n".join(result) + + +def check_xml_srclines(filename, expected_summary): + """ + Read "filename" using xml_src_summary and check that it yields the given + expected summary. + """ + baseline = "tmp.txt" + with open(baseline, "w") as f: + f.write(expected_summary) + thistest.fail_if_diff_internal( + baseline, + xml_src_summary(filename), + failure_message=f"unexpected source excerpts in {filename}", + ignore_white_chars=False, + ) + + +def create_summary( + name, + full_content, + truncated_content, +): + """ + Create a XML source file summary compatible with xml_src_summary for one of + this testcase's source file. + """ + + # Adjust expectations for binary traces, which provide imprecise slocs + line_6_cond = "A)" if thistest.options.trace_mode == "src" else "A" + + result = [ + "src_mapping", + " src", + " line 1: 'pragma Ada_2012;'", + "src_mapping", + " src", + f" line 2: 'package {name} is'", + "src_mapping", + " src", + " line 3: ' function Id (V : Boolean) return Boolean is (V);'", + " statement: 'V'", + " src", + " line 3: ' V'", + "src_mapping", + " src", + " line 4: ' function F (A, B : Boolean) return Boolean'", + "src_mapping", + " src", + f" line 5: {ascii(f' is (Id (-- {full_content}')}", + f" statement: {ascii(f'Id (-- {truncated_content}...')}", + " src", + f" line 5: {ascii(f' Id (-- {full_content}')}", + " line 6: ' A) and then B'", + f" decision: {ascii(f'Id (-- {truncated_content}...')}", + " src", + f" line 5: {ascii(f' Id (-- {full_content}')}", + " line 6: ' A) and then B'", + f" condition: {ascii(f'Id (-- {truncated_content}...')}", + " src", + f" line 5: {ascii(f' Id (-- {full_content}')}", + f" line 6: ' {line_6_cond}'", + " condition: 'B'", + " src", + " line 6: ' B'", + "src_mapping", + " src", + " line 6: ' A) and then B);'", + "src_mapping", + " src", + f" line 7: 'end {name};'", + ] + return "\n".join(result) + + +tmp = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--annotate=xml"], +) + + +def check_report( + label: str, + encoding: str | None, + expected_warnings: list[str], + latin1_summary: str, + utf8_summary: str, +): + """ + Check XML report production. + + :param label: Name for this check. + :param encoding: Optional non-default encoding to pass to "gnatcov + coverage". + :param expected_warnings: Exhaustive list of warnings that are expected + from "gnatcov coverage". + :param latin1_summary: Expected summary of the XML report for latin1.ads. + :param utf8_summary: Expected summary of the XML report for utf8.ads. + """ + thistest.log(f"== {label} ==") + + log_file = f"coverage-{label}.log" + + # Make gnatcov produce the XML report for the given encoding + argv = xcov_args + [f"--output-dir=out-{label}"] + if encoding is not None: + argv.append(f"--source-encoding={encoding}") + + tolerate_messages = ( + "|".join(expected_warnings) if expected_warnings else None + ) + xcov(argv, out=log_file, tolerate_messages=tolerate_messages) + + # Check that we have exacly the expected warnings + thistest.fail_if_not_equal( + "'gnatcov coverage' output", + "\n".join(expected_warnings), + contents_of(log_file).strip(), + ) + + # Check the content of the XML report for both sources + check_xml_srclines(f"out-{label}/latin1.ads.xml", latin1_summary) + check_xml_srclines(f"out-{label}/utf8.ads.xml", utf8_summary) + + +# By default, all sources are interpreted as Latin-1. Note that truncation +# changes depending on the encoding as the same sequence of bytes may not yield +# the same number of codepoints. +check_report( + label="default", + encoding=None, + expected_warnings=[], + latin1_summary=create_summary("Latin1", "\xc9a\xc9", "\xc9a"), + utf8_summary=create_summary("UTF8", "\xc3\x89a\xc3\x89", "\xc3\x89"), +) + +# Check report production when the same set of sources is interpreted as UTF-8. +# Invalid UTF-8 byte sequences (in latin1.ads) are turned into U+FFFD +# codepoints. +check_report( + label="utf-8", + encoding="utf-8", + expected_warnings=["warning: latin1.ads:5: cannot decode as utf-8"], + latin1_summary=create_summary("Latin1", "\ufffda\ufffd", "\ufffda"), + utf8_summary=create_summary("UTF8", "\xc9a\xc9", "\xc9a"), +) + +# Check that we correctly reject invalid encodings +thistest.log("== invalid ==") +p = xcov( + xcov_args + ["--source-encoding=invalid"], + out="coverage-invalid.log", + register_failure=False, +) +thistest.fail_if( + p.status == 0, + "[invalid] failure expected, but 'gnatcov coverage' succeeded", +) +thistest.fail_if_no_match( + "'gnatcov coverage' output", + ".*gnatcov.*: unsupported encoding for sources: 'invalid'", + contents_of("coverage-invalid.log").strip(), +) + +thistest.result() diff --git a/testsuite/tests/354-source-encoding/utf8.ads b/testsuite/tests/354-source-encoding/utf8.ads new file mode 100644 index 000000000..d57e6cd69 --- /dev/null +++ b/testsuite/tests/354-source-encoding/utf8.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; +package UTF8 is + function Id (V : Boolean) return Boolean is (V); + function F (A, B : Boolean) return Boolean + is (Id (-- ÉaÉ + A) and then B); +end UTF8; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb new file mode 100644 index 000000000..2e04cce51 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb @@ -0,0 +1,6 @@ +package body Ada.Numerics.Aux is + procedure Dummy is + begin + null; + end Dummy; +end Ada.Numerics.Aux; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads new file mode 100644 index 000000000..772e0bdf7 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads @@ -0,0 +1,8 @@ +package Ada.Numerics.Aux is + pragma Pure; + pragma Elaborate_Body; + + procedure Dummy; + + Not_Pi : constant := 123456; +end Ada.Numerics.Aux; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/main.adb b/testsuite/tests/361-overriden-runtime-specs/src/main.adb new file mode 100644 index 000000000..77d8b9b10 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/main.adb @@ -0,0 +1,7 @@ +with Ada.Numerics.Aux; +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line (Integer'Image (Ada.Numerics.Aux.Not_Pi)); +end Main; diff --git a/testsuite/tests/361-overriden-runtime-specs/test.opt b/testsuite/tests/361-overriden-runtime-specs/test.opt new file mode 100644 index 000000000..ecdddeecc --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Compilation can't handle overloaded unit diff --git a/testsuite/tests/361-overriden-runtime-specs/test.py b/testsuite/tests/361-overriden-runtime-specs/test.py new file mode 100644 index 000000000..a565a2d01 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/test.py @@ -0,0 +1,44 @@ +""" +This test checks that we have no warning when instrumenting a project +that redefines some runtime files, here a-numaux.ad[sb] +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +wd = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=["../src"]) + +build_and_run( + gprsw=GPRswitches( + root_project=gpr, + ), + mains=["main"], + covlevel="stmt", + extra_gprbuild_args=["-gnatg"], + extra_coverage_args=[], +) + +# Ensure `gnatcov instrument` did not confuse runtime files +# (Do not run this check on bin-traces) +if thistest.options.trace_mode != "bin": + thistest.fail_if_not_equal( + "Expected empty instrumentation output, but a warning/error was found", + "", + contents_of("instrument.log"), + ) + +# Ensure the overridden runtime file was used +# On embedded targets, a source trace file will be dumped after the expected +# output. That's why we use a regex. +thistest.fail_if_no_match( + "If the right a-numaux.ads is used, it will print 123456", + r"^ 123456\n(== GNATcoverage source trace file ==.*== End ==\n)?", + contents_of("main_output.txt"), +) + +thistest.result() diff --git a/testsuite/tests/385-same_pkg_different_files/foo.ads b/testsuite/tests/385-same_pkg_different_files/foo.ads new file mode 100644 index 000000000..088c56c23 --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/foo.ads @@ -0,0 +1,8 @@ +package Pkg is + + -- Extra feature to ensure the file is not instrumented or compiled: we use + -- an expression function, which is Ada2012. + + function Bar (X : Integer) return Integer is (if X > 0 then X else X); + +end Pkg; diff --git a/testsuite/tests/385-same_pkg_different_files/main.adb b/testsuite/tests/385-same_pkg_different_files/main.adb new file mode 100644 index 000000000..c44a7c435 --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + I : constant Integer := Pkg.Ident (2); +begin + null; +end Main; diff --git a/testsuite/tests/385-same_pkg_different_files/pkg.adb b/testsuite/tests/385-same_pkg_different_files/pkg.adb new file mode 100644 index 000000000..7a73f74bb --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Ident (X : Integer) return Integer is + begin + return X; + end Ident; + +end Pkg; diff --git a/testsuite/tests/385-same_pkg_different_files/pkg.ads b/testsuite/tests/385-same_pkg_different_files/pkg.ads new file mode 100644 index 000000000..9ff0e430a --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Ident (X : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/385-same_pkg_different_files/test.opt b/testsuite/tests/385-same_pkg_different_files/test.opt new file mode 100644 index 000000000..40a7e7cb0 --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/test.opt @@ -0,0 +1 @@ +!src-traces DEAD diff --git a/testsuite/tests/385-same_pkg_different_files/test.py b/testsuite/tests/385-same_pkg_different_files/test.py new file mode 100644 index 000000000..8a66b469e --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/test.py @@ -0,0 +1,30 @@ +""" +foo.ads declares the same package as pkg.ads but with a different interface. It +is not used and probably an error in the clients' code, but it does not disturb +non-instrumented builds, so it shall not disturb instrumented builds either. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +gpr = gprfor( + mains=["main.adb"], + srcdirs=[".."], +) + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + tolerate_instrument_messages=r"warning: unit name \"PKG\" does not match" + " source name.*", +) + +thistest.result() diff --git a/testsuite/tests/393-casing_crash/test.opt b/testsuite/tests/393-casing_crash/test.opt new file mode 100644 index 000000000..04e8015f3 --- /dev/null +++ b/testsuite/tests/393-casing_crash/test.opt @@ -0,0 +1,2 @@ +!windows-host DEAD Test requires conditions only available on Windows, see #393 +all XFAIL Difference in config between prod and development setup, see #393 diff --git a/testsuite/tests/393-casing_crash/test.py b/testsuite/tests/393-casing_crash/test.py new file mode 100644 index 000000000..1d8f17931 --- /dev/null +++ b/testsuite/tests/393-casing_crash/test.py @@ -0,0 +1,73 @@ +""" +Check that gnatcov does not crash during elaboration when it fails to find +itself in PATH. + +This requires a fairly specific setup for both path lookup to work in the +terminal, but not from gnatcov. So far we have managed to do it by +- Being on a Windows system +- Having the gnatcov executable being in a case-sensitive directory +- Modifying the gnatcov.exe filename to change the case of the executable + suffix +- Invoking gnatcov without the executable suffix. + +This test aims to re-create these conditions, and thus removes some stuff from +the environment to make sure we have a the right conditions. +""" + +import os + +from e3.os.fs import which +from e3.fs import mkdir, cp + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import run_and_log + + +tmp = Wdir("tmp_") + +# Create an empty directory in which we'll change the case sensitivity and +# butcher the gnatcov exec. +gnatcov_install = os.path.abspath("fake_gnatcov_bin") +mkdir(gnatcov_install) + +# Enable file sensitivity for the install dir. This needs to be done while the +# directory is empty. +run_and_log( + ["fsutil.exe", "file", "setCaseSensitiveInfo", gnatcov_install, "enable"] +) + +# Copy the gnatcov.exe program and change its executable suffix casing +cp(which("gnatcov.exe"), os.path.join(gnatcov_install, "gnatcov.EXE")) + +# Run gnatcov without anything on the environment to make sure we don't pick up +# the correctly installed gnatcov, not the GNATCOV_PREFIX env var which would +# bypass the path lookup check. We also go through a cmd indirection to avoid +# the path lookup that takes place in e3.os.process.Run. +# +# We also need gnatcov to be invoked without the exe prefix here as the os +# search should work, but the command name for gnatcov will still not have +# the exe suffix. +crash_log = "xcov.log" +p = run_and_log( + ["cmd", "/c", "gnatcov"], + env={"PATH": gnatcov_install}, + output=crash_log, + ignore_environ=True, +) + +thistest.fail_if( + p.status == 0, + comment="gnatcov did not exit with a failure status", +) + +thistest.fail_if_not_equal( + what="Unexpected error message from gnatcov", + expected="Could not locate the invoked gnatcov command: ." + " If gnatcov is installed on a case sensitive filesystem or directory," + " ensure the casing as the executable filename is used when invoking the" + " program.", + actual=contents_of(crash_log).strip(), +) + +thistest.result() diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/main.adb b/testsuite/tests/414-sid-cons-static-cond-diff/main.adb new file mode 100644 index 000000000..a93975682 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/main.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; +with Prelude; + +procedure Main is +begin + Prelude; + if Pkg.B then + Put_Line ("B is True"); + else + Put_Line ("B is False"); + end if; +end Main; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads new file mode 100644 index 000000000..08a184067 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads @@ -0,0 +1,3 @@ +package Pkg is + B : constant Boolean := False; +end Pkg; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads new file mode 100644 index 000000000..a0a811c22 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads @@ -0,0 +1,3 @@ +package Pkg is + B : constant Boolean := True; +end Pkg; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb b/testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb new file mode 100644 index 000000000..4e1b6c3e8 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Prelude is +begin + Put_Line ("This"); + Put_Line ("is"); + Put_Line ("the"); + Put_Line ("prelude"); +end Prelude; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/test.opt b/testsuite/tests/414-sid-cons-static-cond-diff/test.opt new file mode 100644 index 000000000..40a7e7cb0 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/test.opt @@ -0,0 +1 @@ +!src-traces DEAD diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/test.py b/testsuite/tests/414-sid-cons-static-cond-diff/test.py new file mode 100644 index 000000000..7a4fd76d8 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/test.py @@ -0,0 +1,77 @@ +""" +Regression test: ensure that "gnatcov coverage" can load alternative SIDs for +the same unit (here: Main) when it contains a SCO condition that has different +static evaluations in both SIDs. +""" + +from e3.fs import cp, mkdir + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +# Create a project with two alternative sources for one unit (Pkg) depending on +# a GPR external. +gpr = gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra=""" + type Pkg_Version_Type is ("v1", "v2"); + Pkg_Version : Pkg_Version_Type := external("PKG_VERSION"); + package Naming is + for Spec ("Pkg") use "pkg__" & Pkg_Version & ".ads"; + end Naming; + """, +) + +# Create subdirectories to group the SID and trace files for "gnatcov coverage" +# to load. +mkdir("sids") +mkdir("traces") + +# In order to reproduce the crash, it was necessary to first load a SID with N +# SCO statements (here: prelude.sid, which is the same regardless of the +# selected Pkg variant), and then load the two SIDs (here: for the Main unit) +# that contain the SCO condition with different static evaluations ("if Pkg.B" +# in main.adb). Consolidation code used to use the condition SCO index from the +# SID to load (likely 2 here, SCO 1 being the statement call to Prelude) to +# wrongly subscript gnatcov's interned SCO table (SCO 2 being the second +# Put_Line statement call in prelude.adb). +sids = ["obj/prelude.sid"] +traces = [] +for v in ["v1", "v2"]: + cov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr, xvars=[("PKG_VERSION", v)]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + ) + + # Keep a side copy of the trace file and the SID for main.adb + trace_copy = f"traces/main-{v}.srctrace" + cp(cov_args[-1], trace_copy) + traces.append(trace_copy) + + sid_copy = f"sids/main-{v}.sid" + cp("obj/main.sid", sid_copy) + sids.append(sid_copy) + +sid_args = [f"--sid={f}" for f in sids] +xcov( + ["coverage", "-cstmt", "-axcov", "--output-dir=xcov", *sid_args, *traces], + out="coverage.log", +) +check_xcov_reports( + "xcov", + { + "prelude.adb.xcov": {"+": {5, 6, 7, 8}}, + "main.adb.xcov": {"+": {8, 9, 12}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkg.adb b/testsuite/tests/431-origin-prj-stub/code/src/pkg.adb new file mode 100644 index 000000000..9086121d4 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkg.adb @@ -0,0 +1,14 @@ +with Pkh; + +package body Pkg is + + function Foo (X : Integer) return Integer is + begin + if Pkh.Bar (X) = 0 then + return 0; + else + return 1; + end if; + end Foo; + +end Pkg; diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkg.ads b/testsuite/tests/431-origin-prj-stub/code/src/pkg.ads new file mode 100644 index 000000000..a608851f6 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Foo (X : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkh.adb b/testsuite/tests/431-origin-prj-stub/code/src/pkh.adb new file mode 100644 index 000000000..a7e9936fc --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkh.adb @@ -0,0 +1,8 @@ +package body Pkh is + + function Bar (X : Integer) return Integer is + begin + return X; + end Bar; + +end Pkh; diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkh.ads b/testsuite/tests/431-origin-prj-stub/code/src/pkh.ads new file mode 100644 index 000000000..6bb9c9d2d --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkh.ads @@ -0,0 +1,5 @@ +package Pkh is + + function Bar (X : Integer) return Integer; + +end Pkh; diff --git a/testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb b/testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb new file mode 100644 index 000000000..51f8cd772 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb @@ -0,0 +1,8 @@ +package body Pkh is + + function Bar (X : Integer) return Integer is + begin + return 0; + end Bar; + +end Pkh; diff --git a/testsuite/tests/431-origin-prj-stub/code/stubs.gpr b/testsuite/tests/431-origin-prj-stub/code/stubs.gpr new file mode 100644 index 000000000..582519d56 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/stubs.gpr @@ -0,0 +1,13 @@ +project Stubs extends "user.gpr" is + + for Object_Dir use "obj_stubs"; + for Source_Dirs use ("stub_src"); + + package Coverage is + + -- Pkh is stubbed, do not compute coverage over it. + + for Excluded_Units use ("Pkh"); + end Coverage; + +end stubs; diff --git a/testsuite/tests/431-origin-prj-stub/code/user.gpr b/testsuite/tests/431-origin-prj-stub/code/user.gpr new file mode 100644 index 000000000..c3971542c --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/user.gpr @@ -0,0 +1,11 @@ +project User is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + + package Coverage is + for Switches ("*") use ("--level=stmt+decision"); + for Switches ("coverage") use ("--annotate=xcov", "--output-dir=xcov"); + end Coverage; + +end User; diff --git a/testsuite/tests/431-origin-prj-stub/test.py b/testsuite/tests/431-origin-prj-stub/test.py new file mode 100644 index 000000000..e857a0e6a --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/test.py @@ -0,0 +1,54 @@ +""" +Ensure that gnatcov loads switches from the project designated by the +Origin_Project attribute, and not from any extending project. This is required +for the gnattest-gnatcov integration to work properly, as gnattest +systematically generates an extending project of the user project when stubbing +is enabled. + +The sources in the code and test directories are made to mimic the structure of +the harnesses generated by gnattest +""" + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Copy the test material in the temp dir +cp("../test", ".", recursive=True) +cp("../code", ".", recursive=True) + +# Generate a project for the test driver, "withing" the stub project and +# referencing the user project through the Origin_Project attribute +test_prj = gprfor( + mains=["pkg-test.adb"], + prjid="test", + srcdirs="test", + deps=["code/stubs.gpr"], + extra='for Origin_Project use "code/user.gpr";', +) + +# No level or annotation format provided, everything should be loaded from +# the Origin_Project (user.gpr). +build_run_and_coverage( + gprsw=GPRswitches(root_project=test_prj), + covlevel=None, + extra_coverage_args=[], + mains=["pkg-test"], +) + +check_xcov_reports( + "xcov", + { + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"!": {7}, "+": {8}, "-": {10}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/431-origin-prj-stub/test/pkg-test.adb b/testsuite/tests/431-origin-prj-stub/test/pkg-test.adb new file mode 100644 index 000000000..5948221fe --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/test/pkg-test.adb @@ -0,0 +1,9 @@ +with Support; + +procedure Pkg.Test is +begin + -- We are using the stub version of Pkh, which always returns 0, so expect + -- Pkg to return 0. + + Support.Assert (Pkg.Foo (3) = 0); +end Pkg.Test; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py new file mode 100644 index 000000000..cbabc7195 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py @@ -0,0 +1,99 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + IfStmtCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +# This test replicates the "simple-decision" test but uses an if statement +# instead of an if expression, in order to be runnable with 5.04a1 + +COV_LEVEL = "stmt+decision" + +ckb = IfStmtCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Create two checkpoints with different coverage levels +st = ckb.new(PT.ST) +sf = ckb.new(PT.SF) +dt = ckb.new(PT.DT) + +################# +# TEST CASE 1.1 # +################# +# Ensure that making a report from a static checkpoint only does not +# report any violation. +tc_runner.run_test_case( + "Test Case 1.1", [sf], ckb.EXPECT_EMPTY_STMT_NOT_COVERED +) + +################# +# TEST CASE 1.2 # +################# +# Ensure that consolidating twice the same static decision does not +# report any violation. +tc_runner.run_test_case( + "Test Case 1.2", [sf, sf], ckb.EXPECT_EMPTY_STMT_NOT_COVERED +) + +############### +# TEST CASE 2 # +############### +# Ensure that making a report from a dynamic checkpoint reports a +# decision violation. +tc_runner.run_test_case("Test Case 2", [dt], ckb.EXPECT_VIOLATION_STMT_COVERED) + +############### +# TEST CASE 3 # +############### +# Ensure that making a consolidated report from both static checkpoints +# does not raise any violation +tc_runner.run_test_case("Test Case 3", [sf, st], ckb.EXPECT_EMPTY_STMT_COVERED) + +################# +# TEST CASE 4.1 # +################# +# Ensure that making a consolidated report from the true static checkpoint +# and the dynamic one (which evaluates to True) raises a decision violation +tc_runner.run_test_case( + "Test Case 4.1", [st, dt], ckb.EXPECT_VIOLATION_STMT_COVERED +) + +################# +# TEST CASE 4.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case( + "Test Case 4.2", [dt, st], ckb.EXPECT_VIOLATION_STMT_COVERED +) + +################# +# TEST CASE 5.1 # +################# +# Ensure that making a consolidated report from the false static checkpoint +# and the dynamic one (which evaluates to True) covers the decision +tc_runner.run_test_case( + "Test Case 5.1", [sf, dt], ckb.EXPECT_EMPTY_STMT_COVERED +) + +################# +# TEST CASE 5.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case( + "Test Case 5.2", [dt, sf], ckb.EXPECT_EMPTY_STMT_COVERED +) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr new file mode 100644 index 000000000..a15a858df --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr @@ -0,0 +1,35 @@ +project Greet is + for Source_Dirs use ("src-greet"); + for Object_Dir use "obj"; + + type Decision_Type is + ("static_true", "static_false", "dynamic_true", "dynamic_false"); + + Val1_Impl : Decision_Type := + external ("DEC1", "static_true"); + Val2_Impl : Decision_Type := + external ("DEC2", "static_true"); + + package Naming is + case Val1_Impl is + when "static_true" => + for Spec ("Pkg1") use "pkg1__st.ads"; + when "static_false" => + for Spec ("Pkg1") use "pkg1__sf.ads"; + when "dynamic_true" => + for Spec ("Pkg1") use "pkg1__dt.ads"; + when "dynamic_false" => + for Spec ("Pkg1") use "pkg1__df.ads"; + end case; + case Val2_Impl is + when "static_true" => + for Spec ("Pkg2") use "pkg2__st.ads"; + when "static_false" => + for Spec ("Pkg2") use "pkg2__sf.ads"; + when "dynamic_true" => + for Spec ("Pkg2") use "pkg2__dt.ads"; + when "dynamic_false" => + for Spec ("Pkg2") use "pkg2__df.ads"; + end case; + end Naming; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb new file mode 100644 index 000000000..31993887f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb @@ -0,0 +1,6 @@ +with Greet; + +procedure Main is +begin + Greet.Say_Hi; +end Main; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb new file mode 100644 index 000000000..710021cf5 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; +with Ada.Text_IO; +with Pkg1; +with Pkg2; + +package body Greet is + procedure Say_Hi is + begin + Ada.Text_IO.Put_Line + ("Pkg.Val: " & + (if Pkg1.Val or else Pkg2.Val then "True" else "False")); + end Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads new file mode 100644 index 000000000..5a336e804 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads @@ -0,0 +1,3 @@ +package Greet is + procedure Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__df.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__df.ads new file mode 100644 index 000000000..c0cecf51a --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__df.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg1 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := not Difficult_True (30); + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__dt.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__dt.ads new file mode 100644 index 000000000..99ee44ed9 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__dt.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg1 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := Difficult_True (30); + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__sf.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__sf.ads new file mode 100644 index 000000000..88ee3b7d0 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__sf.ads @@ -0,0 +1,5 @@ +package Pkg1 is + + Val : constant Boolean := False; + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__st.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__st.ads new file mode 100644 index 000000000..82fa4f3bb --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__st.ads @@ -0,0 +1,5 @@ +package Pkg1 is + + Val : constant Boolean := True; + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__df.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__df.ads new file mode 100644 index 000000000..f5044a218 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__df.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg2 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := not Difficult_True (30); + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__dt.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__dt.ads new file mode 100644 index 000000000..c9bbc335e --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__dt.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg2 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := Difficult_True (30); + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__sf.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__sf.ads new file mode 100644 index 000000000..d11820acb --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__sf.ads @@ -0,0 +1,5 @@ +package Pkg2 is + + Val : constant Boolean := False; + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__st.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__st.ads new file mode 100644 index 000000000..56f4e3083 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__st.ads @@ -0,0 +1,5 @@ +package Pkg2 is + + Val : constant Boolean := True; + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr new file mode 100644 index 000000000..aadd50e3f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr @@ -0,0 +1,23 @@ +project Greet is + for Source_Dirs use ("src-greet"); + for Object_Dir use "obj"; + + type Decision_Type is + ("static_true", "static_false", "dynamic_true", "dynamic_false"); + + Val_Impl : Decision_Type := + external ("DECISION_TYPE", "static_true"); + + package Naming is + case Val_Impl is + when "static_true" => + for Spec ("Pkg") use "pkg__st.ads"; + when "static_false" => + for Spec ("Pkg") use "pkg__sf.ads"; + when "dynamic_true" => + for Spec ("Pkg") use "pkg__dt.ads"; + when "dynamic_false" => + for Spec ("Pkg") use "pkg__df.ads"; + end case; + end Naming; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb new file mode 100644 index 000000000..31993887f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb @@ -0,0 +1,6 @@ +with Greet; + +procedure Main is +begin + Greet.Say_Hi; +end Main; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb new file mode 100644 index 000000000..2bebe1cb4 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb @@ -0,0 +1,6 @@ +package body Dynamic is + function Difficult_True (X : Integer) return Boolean is + begin + return True; + end Difficult_True; +end Dynamic; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads new file mode 100644 index 000000000..b4fa4889d --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads @@ -0,0 +1,3 @@ +package Dynamic is + function Difficult_True (X : Integer) return Boolean; +end Dynamic; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb new file mode 100644 index 000000000..b865f1244 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; +with Ada.Text_IO; +with Pkg; + +package body Greet is + procedure Say_Hi is + begin + if Pkg.Val then + Ada.Text_IO.Put_Line ("Pkg.Val: True"); + end if; + end Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads new file mode 100644 index 000000000..5a336e804 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads @@ -0,0 +1,3 @@ +package Greet is + procedure Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.adb new file mode 100644 index 000000000..f87b2c204 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Difficult_True (X : Integer) return Boolean is + begin + if X mod 10 = 0 then + return (3 * X - 10) mod 10 = 0; + else + return False; + end if; + end Difficult_True; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.ads new file mode 100644 index 000000000..6afbf605a --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.ads @@ -0,0 +1,7 @@ +package Pkg is + + function Difficult_True (X : Integer) return Boolean; + + Val : Boolean := not Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__dt.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__dt.ads new file mode 100644 index 000000000..6b79aebc8 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__dt.ads @@ -0,0 +1,6 @@ +with Dynamic; +package Pkg is + + Val : Boolean := Dynamic.Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__sf.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__sf.ads new file mode 100644 index 000000000..4fa6bc049 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__sf.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := False; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__st.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__st.ads new file mode 100644 index 000000000..600efd95c --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__st.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := True; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr new file mode 100644 index 000000000..aadd50e3f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr @@ -0,0 +1,23 @@ +project Greet is + for Source_Dirs use ("src-greet"); + for Object_Dir use "obj"; + + type Decision_Type is + ("static_true", "static_false", "dynamic_true", "dynamic_false"); + + Val_Impl : Decision_Type := + external ("DECISION_TYPE", "static_true"); + + package Naming is + case Val_Impl is + when "static_true" => + for Spec ("Pkg") use "pkg__st.ads"; + when "static_false" => + for Spec ("Pkg") use "pkg__sf.ads"; + when "dynamic_true" => + for Spec ("Pkg") use "pkg__dt.ads"; + when "dynamic_false" => + for Spec ("Pkg") use "pkg__df.ads"; + end case; + end Naming; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb new file mode 100644 index 000000000..31993887f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb @@ -0,0 +1,6 @@ +with Greet; + +procedure Main is +begin + Greet.Say_Hi; +end Main; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb new file mode 100644 index 000000000..2223f6ad2 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; +with Ada.Text_IO; +with Pkg; + +package body Greet is + procedure Say_Hi is + begin + Ada.Text_IO.Put_Line + ("Pkg.Val: " & (if Pkg.Val then "True" else "False")); + end Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads new file mode 100644 index 000000000..5a336e804 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads @@ -0,0 +1,3 @@ +package Greet is + procedure Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__df.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__df.ads new file mode 100644 index 000000000..7c903fe06 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__df.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := not Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__dt.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__dt.ads new file mode 100644 index 000000000..ef5024163 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__dt.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__sf.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__sf.ads new file mode 100644 index 000000000..4fa6bc049 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__sf.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := False; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__st.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__st.ads new file mode 100644 index 000000000..600efd95c --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__st.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := True; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py b/testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py new file mode 100644 index 000000000..d63d775c3 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py @@ -0,0 +1,178 @@ +from enum import Enum +import os +import os.path +import shutil + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +class PkgType(Enum): + """ + This enum describes the possible values with which we can replace a + condition in a file. + Either the condition is static (known at compile-time), or dynamic. + Each variant is available with True and False for exhaustive tests. + """ + + ST = "static_true" + SF = "static_false" + DT = "dynamic_true" + DF = "dynamic_false" + + def __str__(self): + return self.value + + +class CheckpointBuilder: + """ + This class factorizes the code for producing checkpoints from a function + with a decision whose staticness may be set depending on the test needs. + Sub-classes implement the specific cases and are attached to a specific + project that lives in a src-* folder next to this file. + """ + + _SRC_DIR = None + _MAIN = "main" + + EXPECT_EMPTY = {} + EXPECT_VIOLATION = {} + + def __init__(self, cov_level): + self.cov_level = cov_level + + # Instantiate the right source directory + self._copy_src_dir() + + def _copy_src_dir(self): + """ + Copy the test-case's directory (which is proper to the checkpoint + class) into the test's current dir + """ + src_src = self._SRC_DIR + src_dst = os.path.abspath("src") + if os.path.exists(src_dst): + shutil.rmtree(src_dst) + full_src_src = os.path.abspath(os.path.join(__file__, "..", src_src)) + shutil.copytree(full_src_src, src_dst) + + def make_checkpoint(self, name, xvars, deps=None): + """ + Function in charge of compiling the project with a given combination + of PkgTypes for each condition, and creating a checkpoint from the + program execution. + """ + gpr_obj_dir = "obj" + + prj_file = gprfor( + mains=[f"{self._MAIN}.adb"], + prjid=name, + srcdirs=os.path.join("src"), + objdir=gpr_obj_dir, + deps=[os.path.join("src", "greet.gpr")] + (deps or []), + ) + + ckpt = f"test_{name}.ckpt" + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=prj_file, + units=["greet"], + xvars=xvars, + ), + covlevel=self.cov_level, + mains=[self._MAIN], + gpr_obj_dir=gpr_obj_dir, + extra_instr_args=["-v"], + extra_coverage_args=[ + "-v", + "--units=greet", + f"--save-checkpoint={ckpt}", + ], + ) + return ckpt + + +class SimpleConditionCheckpointBuilder(CheckpointBuilder): + _SRC_DIR = "src-simple" + + EXPECT_EMPTY = {"greet.adb.xcov": {}, "greet.ads.xcov": {}} + EXPECT_VIOLATION = {"greet.adb.xcov": {"!": {9}}, "greet.ads.xcov": {}} + + def new(self, dec_type): + return self.make_checkpoint( + str(dec_type), xvars=[("DECISION_TYPE", dec_type)] + ) + + +class IfStmtCheckpointBuilder(CheckpointBuilder): + _SRC_DIR = "src-if-stmt" + + EXPECT_EMPTY_STMT_COVERED = {"greet.adb.xcov": {}, "greet.ads.xcov": {}} + EXPECT_EMPTY_STMT_NOT_COVERED = { + "greet.adb.xcov": {"-": {9}}, + "greet.ads.xcov": {}, + } + EXPECT_VIOLATION_STMT_COVERED = { + "greet.adb.xcov": {"!": {8}}, + "greet.ads.xcov": {}, + } + EXPECT_VIOLATION_STMT_NOT_COVERED = { + "greet.adb.xcov": {"!": {8}, "-": {9}}, + "greet.ads.xcov": {}, + } + + def new(self, dec_type): + return self.make_checkpoint( + str(dec_type), xvars=[("DECISION_TYPE", dec_type)] + ) + + +class DoubleConditionCheckpointBuilder(CheckpointBuilder): + _SRC_DIR = "src-double" + + EXPECT_EMPTY = {"greet.adb.xcov": {}, "greet.ads.xcov": {}} + EXPECT_VIOLATION = {"greet.adb.xcov": {"!": {11}}, "greet.ads.xcov": {}} + + def new(self, type1, type2): + name = f"{type1}_{type2}" + return self.make_checkpoint( + name, xvars=[("DEC1", type1), ("DEC2", type2)] + ) + + +class TestCaseRunner: + """ + This class eases the verification of checkpoint consolidation results + through the xcov report + """ + + def __init__(self, cov_level): + self.base_cov_args = [ + "coverage", + "--annotate=xcov", + f"--level={cov_level}", + ] + + def run_test_case( + self, name: str, checkpoints, expected_report, verbose=True + ): + thistest.log(f"Test Case {name}") + slug_name = name.lower().replace(" ", "_") + + output_dir = f"testcase-{slug_name}" + + args = self.base_cov_args.copy() + args += [f"--output-dir={output_dir}"] + + if verbose: + args += ["-v"] + + # Add checkpoints + args += [item for ckpt in checkpoints for item in ["-C", ckpt]] + + xcov(args, f"{slug_name}.log") + + check_xcov_reports(output_dir, expected_report) diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py new file mode 100644 index 000000000..ee8c0878e --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py @@ -0,0 +1,150 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + DoubleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +COV_LEVEL = "stmt+decision" + +ckb = DoubleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Checkpoint naming follows the convention: +# _ + +# Fully static +st_st = ckb.new(PT.ST, PT.ST) # decision is true +st_sf = ckb.new(PT.ST, PT.SF) # decision is true +sf_st = ckb.new(PT.SF, PT.ST) # decision is true +sf_sf = ckb.new(PT.SF, PT.SF) # decision is false +# Fully dynamic +dt_dt = ckb.new(PT.DT, PT.DT) # decision is true +dt_df = ckb.new(PT.DT, PT.DF) # decision is true +df_dt = ckb.new(PT.DF, PT.DT) # decision is true +df_df = ckb.new(PT.DF, PT.DF) # decision is false +# Partly static +dt_sf = ckb.new(PT.DT, PT.SF) # decision is false + +############# +# Test case # +############# +# Fully static decisions alone never raise violations +tc_runner.run_test_case("simple-static-1", [st_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-2", [st_sf], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-3", [sf_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-4", [sf_sf], ckb.EXPECT_EMPTY) + +############# +# Test case # +############# +# Dynamic decisions alone will raise violations +tc_runner.run_test_case("simple-dynamic-1", [dt_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-2", [dt_df], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-3", [df_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-4", [df_df], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Partly static non-covering checkpoint raises a violation +tc_runner.run_test_case("simple_partly_static", [dt_sf], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Ensure consolidating twice the same non-covering static decision evaluation +# does not raise a violation +tc_runner.run_test_case( + "OK_duplicate_static", [sf_sf, sf_sf], ckb.EXPECT_EMPTY +) + +############# +# Test case # +############# +# Consolidating several different static checkpoints that don't cover the +# decision raise a violation +tc_runner.run_test_case("KO_static", [sf_st, st_sf], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Consolidating several different static checkpoints that don't cover the +# decision pass +tc_runner.run_test_case("OK_static", [sf_sf, sf_st], ckb.EXPECT_EMPTY) + +############# +# Test case # +############# +# Consolidating static and dynamic checkpoints that cover the decision +# raises no violation +tc_runner.run_test_case( + "OK_dynamic_static-1", [dt_df, sf_sf], ckb.EXPECT_EMPTY +) +tc_runner.run_test_case( + "OK_dynamic_static-2", [sf_sf, dt_dt], ckb.EXPECT_EMPTY +) + +############# +# Test case # +############# +# Consolidating static and dynamic checkpoints that don't cover the decision +# raises a violation +tc_runner.run_test_case( + "KO_dynamic_static-1", [dt_df, st_sf], ckb.EXPECT_VIOLATION +) +tc_runner.run_test_case( + "KO_dynamic_static-2", [st_sf, dt_df], ckb.EXPECT_VIOLATION +) + +############# +# Test case # +############# +# Consolidating partly static and static checkpoints +# OK +tc_runner.run_test_case( + "OK_partly_static_static-1", [dt_sf, sf_sf], ckb.EXPECT_EMPTY +) +tc_runner.run_test_case( + "OK_partly_static_static-2", [sf_sf, dt_sf], ckb.EXPECT_EMPTY +) +# KO +tc_runner.run_test_case( + "KO_partly_static_static-1", [dt_sf, st_sf], ckb.EXPECT_VIOLATION +) +tc_runner.run_test_case( + "KO_partly_static_static-2", [st_sf, dt_sf], ckb.EXPECT_VIOLATION +) + +############# +# Test case # +############# +# Consolidating partly static and dynamic checkpoints +# OK +tc_runner.run_test_case( + "OK_partly_static_dynamic-1", [dt_sf, df_df], ckb.EXPECT_EMPTY +) +tc_runner.run_test_case( + "OK_partly_static_dynamic-2", [df_df, dt_sf], ckb.EXPECT_EMPTY +) +# KO +tc_runner.run_test_case( + "KO_partly_static_dynamic-1", [dt_sf, dt_df], ckb.EXPECT_VIOLATION +) +tc_runner.run_test_case( + "KO_partly_static_dynamic-2", [dt_df, dt_sf], ckb.EXPECT_VIOLATION +) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py new file mode 100644 index 000000000..5aad2ff3a --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py @@ -0,0 +1,164 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + DoubleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +COV_LEVEL = "stmt+mcdc" + +ckb = DoubleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Checkpoint naming follows the convention: +# _ + +# Fully static +st_st = ckb.new(PT.ST, PT.ST) # decision is true +st_sf = ckb.new(PT.ST, PT.SF) # decision is true +sf_st = ckb.new(PT.SF, PT.ST) # decision is true +sf_sf = ckb.new(PT.SF, PT.SF) # decision is false +# Fully dynamic +dt_dt = ckb.new(PT.DT, PT.DT) # decision is true +dt_df = ckb.new(PT.DT, PT.DF) # decision is true +df_dt = ckb.new(PT.DF, PT.DT) # decision is true +df_df = ckb.new(PT.DF, PT.DF) # decision is false +# Partly static +dt_sf = ckb.new(PT.DT, PT.SF) # decision is false + +############# +# Test case # +############# +# Fully static decisions alone never raise violations +tc_runner.run_test_case("simple-static-1", [st_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-2", [st_sf], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-3", [sf_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-4", [sf_sf], ckb.EXPECT_EMPTY) + +############# +# Test case # +############# +# Dynamic decisions alone will raise violations +tc_runner.run_test_case("simple-dynamic-1", [dt_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-2", [dt_df], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-3", [df_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-4", [df_df], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Ensure consolidating twice the same non-covering static decision evaluation +# does not raise a violation +tc_runner.run_test_case( + "OK_duplicate_static", + [sf_sf, sf_sf], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +# Covers the decision with static checkpoints only +tc_runner.run_test_case( + "OK_static", + [sf_sf, sf_st, st_sf], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +# MCDC will raise a violation if several different static evaluations are +# merged and don't cover the decision +tc_runner.run_test_case( + "KO_static", + [sf_sf, sf_st], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_dynamic", + [df_df, dt_df, df_dt], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +# Ensure 'df_df' and 'dt_df' are not enough to cover the decision with MCDC +tc_runner.run_test_case( + "KO_dynamic", + [df_df, dt_df], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_2_dynamic_then_static", + [df_df, dt_df, sf_st], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "KO_2_dynamic_then_static", + [df_df, dt_df, st_sf], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_2_dynamic_then_partly_static", + [df_df, df_dt, dt_sf], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "KO_2_dynamic_then_partly_static", + [df_df, dt_df, dt_sf], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_2_static_then_dynamic", + [sf_sf, st_sf, df_dt], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "KO_2_static_then_dynamic", + [sf_sf, st_sf, dt_df], + ckb.EXPECT_VIOLATION, +) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt new file mode 100644 index 000000000..b2af095c2 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD feature is not supported in binary traces diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py new file mode 100644 index 000000000..742a1df83 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py @@ -0,0 +1,57 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + DoubleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +COV_LEVEL = "stmt+mcdc" + +ckb = DoubleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Fully static +st_st = ckb.new(PT.ST, PT.ST) # decision is true +sf_sf = ckb.new(PT.SF, PT.SF) # decision is false + +############# +# Test case # +############# +# Ensure that when consolidating static `true || true` and `false || false` +# will raise a violation on the second condition but not on the first one +report_file = "report.txt" +args = [ + "coverage", + "--annotate=report", + "-o", + f"{report_file}", + f"--level={COV_LEVEL}", + "-C", + f"{st_st}", + "-C", + f"{sf_sf}", +] +xcov(args, "output.log") + +with open(report_file, "r") as file: + content = file.read() + +# Fail if the first condition is not covered +thistest.fail_if(content.find("greet.adb:11:16: condition") != -1) +# Fail if the second condition is covered +thistest.fail_if(content.find("greet.adb:11:33: condition") == -1) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py new file mode 100644 index 000000000..d3d085917 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py @@ -0,0 +1,85 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + SimpleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + + +COV_LEVEL = "stmt+decision" + +ckb = SimpleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Create two checkpoints with different coverage levels +st = ckb.new(PT.ST) +sf = ckb.new(PT.SF) +dt = ckb.new(PT.DT) + +################# +# TEST CASE 1.1 # +################# +# Ensure that making a report from a static checkpoint only does not +# report any violation. +tc_runner.run_test_case("Test Case 1.1", [sf], ckb.EXPECT_EMPTY) + +################# +# TEST CASE 1.2 # +################# +# Ensure that consolidating twice the same static decision does not +# report any violation. +tc_runner.run_test_case("Test Case 1.2", [sf, sf], ckb.EXPECT_EMPTY) + +############### +# TEST CASE 2 # +############### +# Ensure that making a report from a dynamic checkpoint reports a +# decision violation. +tc_runner.run_test_case("Test Case 2", [dt], ckb.EXPECT_VIOLATION) + +############### +# TEST CASE 3 # +############### +# Ensure that making a consolidated report from both static checkpoints +# does not raise any violation +tc_runner.run_test_case("Test Case 3", [sf, st], ckb.EXPECT_EMPTY) + +################# +# TEST CASE 4.1 # +################# +# Ensure that making a consolidated report from the true static checkpoint +# and the dynamic one (which evaluates to True) raises a decision violation +tc_runner.run_test_case("Test Case 4.1", [st, dt], ckb.EXPECT_VIOLATION) + +################# +# TEST CASE 4.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case("Test Case 4.2", [dt, st], ckb.EXPECT_VIOLATION) + +################# +# TEST CASE 5.1 # +################# +# Ensure that making a consolidated report from the false static checkpoint +# and the dynamic one (which evaluates to True) covers the decision +tc_runner.run_test_case("Test Case 5.1", [sf, dt], ckb.EXPECT_EMPTY) + +################# +# TEST CASE 5.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case("Test Case 5.2", [dt, sf], ckb.EXPECT_EMPTY) + +thistest.result() diff --git a/testsuite/tests/86-subproj_lang/src_root/main.adb b/testsuite/tests/86-subproj_lang/src_root/main.adb new file mode 100644 index 000000000..f70f97420 --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_root/main.adb @@ -0,0 +1,7 @@ +with Procedure_Under_Test; use Procedure_Under_Test; + +procedure Main is +begin + Test (Control => 1, In_A => 1, In_B => 2); + Test (Control => -11, In_A => 1, In_B => 2); +end Main; diff --git a/testsuite/tests/86-subproj_lang/src_sub/calculations.c b/testsuite/tests/86-subproj_lang/src_sub/calculations.c new file mode 100644 index 000000000..b9b039b8a --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/calculations.c @@ -0,0 +1,24 @@ +#include "calculations.h" + +// simple function performing some basic math operations +// which allows a division by 0 +int +calculations_problematic (int a, int b) +{ + int temp = 0; + temp = a * b; + temp = temp + a / b; + return temp; +} + +// same as previous function but prohibits the division +// by zero +int +calculations (int a, int b) +{ + int temp = 0; + temp = a * b; + if (b != 0) + temp = temp + a / b; + return temp; +} diff --git a/testsuite/tests/86-subproj_lang/src_sub/calculations.h b/testsuite/tests/86-subproj_lang/src_sub/calculations.h new file mode 100644 index 000000000..fe6f07dff --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/calculations.h @@ -0,0 +1,3 @@ +int calculations (int a, int b); + +int calculations_problematic (int a, int b); diff --git a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb new file mode 100644 index 000000000..0621c07be --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb @@ -0,0 +1,23 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Procedure_Under_Test is + + procedure Test + (Control : Integer; + In_A : Integer; + In_B : Integer) + is + Result : Integer := 0; + begin + + if Control < 0 then + Result := Calculations_Problematic (In_A, In_B); + else + Result := Calculations (In_A, In_B); + end if; + + Put_Line (Integer'Image (Result)); + + end Test; + +end Procedure_Under_Test; diff --git a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads new file mode 100644 index 000000000..5595de1a6 --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads @@ -0,0 +1,20 @@ +package Procedure_Under_Test is + + function Calculations (A : Integer; B : Integer) return Integer; + pragma Import + (Convention => C, + Entity => Calculations, + External_Name => "calculations"); + + function Calculations_Problematic (A : Integer; B : Integer) return Integer; + pragma Import + (Convention => C, + Entity => Calculations_Problematic, + External_Name => "calculations_problematic"); + + procedure Test + (Control : Integer; + In_A : Integer; + In_B : Integer); + +end Procedure_Under_Test; diff --git a/testsuite/tests/86-subproj_lang/test.py b/testsuite/tests/86-subproj_lang/test.py new file mode 100644 index 000000000..64fee7469 --- /dev/null +++ b/testsuite/tests/86-subproj_lang/test.py @@ -0,0 +1,47 @@ +""" +Test that sources of another language not present in the root project are still +considered as sources of interest. This was not the case with the first version +of the parallelized instrumentation. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Sub has both Ada and C as languages, whereas Root only declares Ada sources. +# Gnatcov should nevertheless instrument C sources in Sub, as long as the +# instrumentation languages are not explicitly restricted. +prj_sub = gprfor( + prjid="sub", + srcdirs=["../src_sub"], + langs=["Ada", "C"], + mains=None, +) +prj_root = gprfor( + prjid="root", + srcdirs=["../src_root"], + langs=["Ada"], + mains=["main.adb"], + deps=["sub.gpr"], +) + +# Build and produce a coverage report for the test project. Only compute +# coverage for the C unit as this is the one that may not be instrumented. +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj_root, units=["calculations.c"]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", {"calculations.c.xcov": {"+": {8, 9, 10, 11, 19, 20, 21, 22, 23}}} +) + +thistest.result() diff --git a/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c new file mode 100644 index 000000000..0e161b489 --- /dev/null +++ b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c @@ -0,0 +1,7 @@ +#include "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h" + +int +ident (int x) +{ + return x; +} diff --git a/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h new file mode 100644 index 000000000..bfb193971 --- /dev/null +++ b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h @@ -0,0 +1,6 @@ +#ifndef __OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT__ +#define __OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT__ + +int ident (int x); + +#endif diff --git a/testsuite/tests/92-long_slugs/main.c b/testsuite/tests/92-long_slugs/main.c new file mode 100644 index 000000000..c0a951db2 --- /dev/null +++ b/testsuite/tests/92-long_slugs/main.c @@ -0,0 +1,7 @@ +#include "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h" + +int +main () +{ + return ident (0); +} diff --git a/testsuite/tests/92-long_slugs/test.opt b/testsuite/tests/92-long_slugs/test.opt new file mode 100644 index 000000000..f9701e94a --- /dev/null +++ b/testsuite/tests/92-long_slugs/test.opt @@ -0,0 +1 @@ +bin-traces DEAD test specific to instrumentation diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py new file mode 100644 index 000000000..3501e0a8b --- /dev/null +++ b/testsuite/tests/92-long_slugs/test.py @@ -0,0 +1,72 @@ +""" +Check that gnatcov-generated units have reasonably short filenames. +Gnatcov used to generate slugs that could take up to three characters to +represent a single one for the original unit name, thus generating overly long +unit names. +""" + +from SCOV.minicheck import ( + build_run_and_coverage, + check_xcov_reports, + xcov_instrument, +) +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +prj_switches = GPRswitches(gprfor(srcdirs=[".."], mains=["main.c"])) + +# First, check that using the legacy slugs produces paths that exceed the path +# limit. + +log = "slug_instr.log" +p = xcov_instrument( + gprsw=prj_switches, + covlevel="stmt", + extra_args=["--full-slugs"], + register_failure=False, + out=log, +) +thistest.fail_if(p.status == 0) + +# The error message for exceeding the path limit isn't the same on Windows +# and on linux. + +thistest.fail_if_no_match( + what="Missing or unexpected error message", + regexp=( + ( + r".*/gnatcov\.exe: Could not create the buffer unit for " + ".*overly_long_capitalized_c_unit_that_should_not_triple_in_size" + '_to_avoid_path_name_limit.c: invalid path name "gcvrt_b_z.*' + ) + if "windows" in thistest.env.host.platform + else r".*/gnatcov: cannot open .*/tests" + r"/92-long_slugs/tmp_/obj/gen-gnatcov-instr/gcvrt_b_z.*\.c" + ), + actual=contents_of(log).replace("\\", "/"), +) + +# Now check that the buffer units with hashes in their names work ok +build_run_and_coverage( + gprsw=prj_switches, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +unit_name = ( + "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE" + "_TO_AVOID_PATH_NAME_LIMIT" +) + +# We normalize the case of files on Windows, as such the report files won't +# have the same case as the original filename. + +check_xcov_reports( + "obj", {"main.c.xcov": {"+": {6}}, f"{unit_name}.c.xcov": {"+": {6}}} +) + +thistest.result() diff --git a/testsuite/tests/97-quant_expr_in_decl/src/pkg.adb b/testsuite/tests/97-quant_expr_in_decl/src/pkg.adb new file mode 100644 index 000000000..39342ff6c --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/pkg.adb @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package body Pkg is + + -------------- + -- All_True -- + -------------- + + function All_True (Arr : My_Arr) return Boolean is + Res : constant Boolean := (for all Elt of Arr => Elt); -- # decl + begin + return Res; -- # ret + end All_True; + + --------------- + -- Some_True -- + --------------- + + function Some_True (Arr : My_Arr) return Boolean is + Res : constant Boolean := (for some Elt of Arr => Elt); -- # decl + begin + return Res; -- # ret + end Some_True; + +end Pkg; diff --git a/testsuite/tests/97-quant_expr_in_decl/src/pkg.ads b/testsuite/tests/97-quant_expr_in_decl/src/pkg.ads new file mode 100644 index 000000000..c22a6f4d8 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/pkg.ads @@ -0,0 +1,9 @@ +package Pkg is + + type My_Arr is Array (Positive range <>) of Boolean; + + function All_True (Arr : My_Arr) return Boolean; + + function Some_True (Arr : My_Arr) return Boolean; + +end Pkg; diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb new file mode 100644 index 000000000..3b4c9adb9 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb @@ -0,0 +1,12 @@ +with Support; use Support; +with Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /decl/ l- ## s- +-- /ret/ l- ## s- diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_f.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_f.adb new file mode 100644 index 000000000..59ec55857 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_f.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Pkg; + +procedure Test_F is + All_F : Pkg.My_Arr := (False, False, False); +begin + Assert (not Pkg.All_True (All_F)); + Assert (not Pkg.Some_True (All_F)); +end Test_F; + +--# pkg.adb +-- +-- /decl/ l! ## dT- +-- /ret/ l+ ## 0 +-- +-- Decision coverage with bin traces is imprecise on simple expressions +-- +-- %opts: --trace-mode=bin +-- =/decl/ l! ## d! diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_t.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_t.adb new file mode 100644 index 000000000..6428f0cdd --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_t.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Pkg; + +procedure Test_T is + All_T : Pkg.My_Arr := (True, True, True); +begin + Assert (Pkg.All_True (All_T)); + Assert (Pkg.Some_True (All_T)); +end Test_T; + +--# pkg.adb +-- +-- /decl/ l! ## dF- +-- /ret/ l+ ## 0 +-- +-- Decision coverage with bin traces is imprecise on simple expressions +-- +-- %opts: --trace-mode=bin +-- =/decl/ l! ## d! diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb new file mode 100644 index 000000000..2ab906b6b --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb @@ -0,0 +1,17 @@ +with Support; use Support; +with Pkg; + +procedure Test_TF is + All_T : Pkg.My_Arr := (True, True, True); + All_F : Pkg.My_Arr := (False, False, False); +begin + Assert (Pkg.All_True (All_T)); + Assert (Pkg.Some_True (All_T)); + Assert (not Pkg.All_True (All_F)); + Assert (not Pkg.Some_True (All_F)); +end Test_TF; + +--# pkg.adb +-- +-- /decl/ l+ ## 0 +-- /ret/ l+ ## 0 diff --git a/testsuite/tests/97-quant_expr_in_decl/test.opt b/testsuite/tests/97-quant_expr_in_decl/test.opt new file mode 100644 index 000000000..bbf61ccd4 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 diff --git a/testsuite/tests/97-quant_expr_in_decl/test.py b/testsuite/tests/97-quant_expr_in_decl/test.py new file mode 100644 index 000000000..851fc0e58 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/test.py @@ -0,0 +1,12 @@ +""" +Check that quantified expressions are correctly instrumented in object +declaration initialization expressions. This used not to be the case. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/98-quant_expr_nested/src/pkg.ads b/testsuite/tests/98-quant_expr_nested/src/pkg.ads new file mode 100644 index 000000000..1e4b5f3cc --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/pkg.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pkg is + + type My_Arr is array (Positive range <>) of Integer; + + function All_Positive + (Arr_Main, Arr_Backup : My_Arr; Use_Backup : Boolean) return Boolean is + (for all Element of -- # stmt + My_Arr'(if Use_Backup then Arr_Backup else Arr_Main) => -- # if_expr + Element >= 0); -- # predicate + +end Pkg; diff --git a/testsuite/tests/98-quant_expr_nested/src/test_0.adb b/testsuite/tests/98-quant_expr_nested/src/test_0.adb new file mode 100644 index 000000000..b6590435f --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_0.adb @@ -0,0 +1,14 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.ads +-- +-- /stmt/ l- ## s- +-- /if_expr/ l- ## 0 +-- /predicate/ l- ## 0 diff --git a/testsuite/tests/98-quant_expr_nested/src/test_f_f.adb b/testsuite/tests/98-quant_expr_nested/src/test_f_f.adb new file mode 100644 index 000000000..853bc290e --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_f_f.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_F_F is + Arr_Main : My_Arr := (1 .. 10 => -18); + Arr_Backup : My_Arr := (1 .. 4 => 4); +begin + Assert (not All_Positive (Arr_Main, Arr_Backup, False)); +end Test_F_F; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dT- +-- /predicate/ l! ## dT- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_f_t.adb b/testsuite/tests/98-quant_expr_nested/src/test_f_t.adb new file mode 100644 index 000000000..ab84edee4 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_f_t.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_F_T is + Arr_Main : My_Arr := (1 .. 10 => 18); + Arr_Backup : My_Arr := (1 .. 4 => -4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, False)); +end Test_F_T; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dT- +-- /predicate/ l! ## dF- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_full.adb b/testsuite/tests/98-quant_expr_nested/src/test_full.adb new file mode 100644 index 000000000..b18774c0d --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_full.adb @@ -0,0 +1,17 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Full is + Arr_Main : My_Arr := (1 .. 10 => -18); + Arr_Backup : My_Arr := (1 .. 4 => 4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, True)); + Assert (not All_Positive (Arr_Main, Arr_Backup, False)); +end Test_Full; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l+ ## 0 +-- /predicate/ l+ ## 0 diff --git a/testsuite/tests/98-quant_expr_nested/src/test_t_f.adb b/testsuite/tests/98-quant_expr_nested/src/test_t_f.adb new file mode 100644 index 000000000..e288bec71 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_t_f.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_T_F is + Arr_Main : My_Arr := (1 .. 10 => 18); + Arr_Backup : My_Arr := (1 .. 4 => -4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, False)); +end Test_T_F; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dT- +-- /predicate/ l! ## dF- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_t_t.adb b/testsuite/tests/98-quant_expr_nested/src/test_t_t.adb new file mode 100644 index 000000000..704b9946e --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_t_t.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_T_T is + Arr_Main : My_Arr := (1 .. 10 => -18); + Arr_Backup : My_Arr := (1 .. 4 => 4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, True)); +end Test_T_T; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dF- +-- /predicate/ l! ## dF- diff --git a/testsuite/tests/98-quant_expr_nested/test.opt b/testsuite/tests/98-quant_expr_nested/test.opt new file mode 100644 index 000000000..2f812c360 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/test.opt @@ -0,0 +1,3 @@ +5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 +7.1.2 DEAD Ada 2012 support weak on 7.1.2 +bin-traces XFAIL Requires compiler change, will be fixed by next stable bump diff --git a/testsuite/tests/98-quant_expr_nested/test.py b/testsuite/tests/98-quant_expr_nested/test.py new file mode 100644 index 000000000..7b05164ca --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/test.py @@ -0,0 +1,15 @@ +""" +Check that decisions nested in a quantified expression but not in the predicate +are correctly instrumented. These used to be silently ignored by gnatcov. + +The naming convention for the test drivers is as follows: +test__.adb +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb new file mode 100644 index 000000000..1eaf550c5 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb @@ -0,0 +1,12 @@ +package body Counters is + + procedure Dec (C : Counter_Access) is + begin + C.Value := C.Value - 1; + end; + + function Zerop (C : Counter_Access) return Boolean is + begin + return C.Value = 0; + end; +end; diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads new file mode 100644 index 000000000..357824dad --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads @@ -0,0 +1,9 @@ +package Counters is + type Counter is record + Value : Integer; + end record; + type Counter_Access is access all Counter; + + procedure Dec (C : Counter_Access); + function Zerop (C : Counter_Access) return Boolean; +end; diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb new file mode 100644 index 000000000..4fb0bd303 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb @@ -0,0 +1,10 @@ +with Counters; use Counters; + +procedure Docount is + C : aliased Counter := (Value => 5); + Cref : Counter_Access := C'Unchecked_Access; +begin + while not Zerop (Cref) loop -- # eval + Dec (Cref); + end loop; +end; diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb new file mode 100644 index 000000000..4db4f2f70 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb @@ -0,0 +1,10 @@ +with Support, Docount; use Support; + +procedure Test_Docount is +begin + Docount; + Assert (True); +end; + +--# docount.adb +-- /check/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb new file mode 100644 index 000000000..f86f16813 --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb @@ -0,0 +1,20 @@ +package body Add is + type Uint_64 is mod 2 ** 64; + + function "+" (Left : Time; Right : Time_Span) return Stamp is + begin + if Right >= 0 -- # tover0 + and then Uint_64 (Time'Last) - Uint_64 (Left) >= Uint_64 (Right) -- # tover1 + then + return (Valid => True, -- # retplus + Value => Time (Uint_64 (Left) + Uint_64 (Right))); -- # retplus + + elsif Right < 0 and then Left >= Time (abs (Right)) then -- # tunder + return (Valid => True, -- # retmin + Value => Time (Uint_64 (Left) - Uint_64 (abs (Right)))); -- # retmin + + else + return (Valid => False, Value => 0); -- # fault + end if; + end "+"; +end; diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads new file mode 100644 index 000000000..adebe469d --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads @@ -0,0 +1,14 @@ +package Add is + type Time is mod 2 ** 64; + for Time'Size use 64; + + type Time_Span is range -2 ** 63 .. 2 ** 63 - 1; + for Time_Span'Size use 64; + + type Stamp is record + Valid : Boolean; + Value : Time; + end record; + + function "+" (Left : Time; Right : Time_Span) return Stamp; +end Add; diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb new file mode 100644 index 000000000..817e7f4eb --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb @@ -0,0 +1,16 @@ +with Support, Add; use Support, Add; + +procedure Test_Add is +begin + Assert (Time (123) + Time_Span (123) = (True, Time (246))); + Assert (Time (124) + Time_Span (-123) = (True, Time (1))); + Assert (Time (123) + Time_Span (-124) = (False, Time (0))); +end; + +--# add.adb +-- /tover0/ l+ ## 0 +-- /tover1/ l+ ## 0 +-- /retplus/ l+ ## 0 +-- /tunder/ l+ ## 0 +-- /retmin/ l+ ## 0 +-- /fault/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py b/testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb new file mode 100644 index 000000000..92b52b761 --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb @@ -0,0 +1,24 @@ + +package body Plop is + + function Identity (V : Value) return Value; + + function Steps_To_LT (X, LB : Value; Max : Step) return Step is + V : Value := X; + N : Step := 0; + begin + loop + exit when abs(V) < LB or else N >= Max; -- # eval + V := Identity (V) - 1.0; -- # body + N := N + 1; -- # body + end loop; + return N; + end; + + function Identity (V : Value) return Value is + Latch : Value := V; + pragma Volatile (Latch); + begin + return Latch; + end; +end; diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads new file mode 100644 index 000000000..963981bb2 --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads @@ -0,0 +1,5 @@ +package Plop is + type Step is new Long_Integer; + type Value is new Long_Long_Float; + function Steps_To_LT (X, LB : Value; Max : Step) return Step; +end; diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb new file mode 100644 index 000000000..d3be0803e --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb @@ -0,0 +1,8 @@ +with Support, Plop; use Support, Plop; +procedure Test_TF is +begin + Assert (Steps_To_LT (X => 5.0, LB => 1.0, Max => 10) = 5); +end; + +--# plop.adb +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py new file mode 100644 index 000000000..3b5a7182b --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py @@ -0,0 +1,17 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest +from SUITE.control import env + + +# Customer had specific extra options on ppc. We haven't been able to trigger +# a failure on this sample case anyway +if "power" in env.target.triplet: + target_options = "-mcpu=750 -mbig-endian -meabi -msdata=none -memb" +else: + target_options = "" + +TestCase( + extracargs="-fdata-sections -ffunction-sections " + target_options +).run() + +thistest.result() diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb new file mode 100644 index 000000000..cfa9f4eeb --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb @@ -0,0 +1,89 @@ +with Support; use Support; + +package body Expr is + + procedure As_RHS (A, B : Boolean) is + begin + GB := A and then B; -- # eval + end; + + procedure As_CASE (A, B : Boolean) is + begin + case A and then B is -- # eval + when True => GX := GX + 1; -- # true + when False => GX := GX - 1; -- # false + end case; + end; + + procedure Set_GB (Value : Boolean) is + begin + GB := Value; + end; + + procedure As_ACTUAL (A, B : Boolean) is + begin + Set_GB (A and then B); -- # eval + end; + + function As_RETURN (A, B : Boolean) return Boolean is + begin + return A and then B; -- # eval + end; + + procedure As_DECLINIT (A, B : Boolean) is + X : Boolean := A and then B; -- # eval + pragma Volatile (X); + begin + GB := X; + end; + + type My_Bool (Value : Boolean) is null record; + + procedure As_DISCINIT (A, B : Boolean) is + X : My_Bool (Value => A and then B); -- # eval + pragma Volatile (X); + begin + GB := X.Value; + end; + + type My_Block is array (1 .. 1) of Boolean; + + procedure As_AGGREGATE (A, B : Boolean) is + X : My_Block := (others => A and then B); -- # eval + pragma Volatile (X); + begin + GB := X(X'First); + end; + + pragma Check_Policy (Precondition, On); + pragma Check_Policy (Postcondition, On); + + procedure As_BODYPRECOND (A, B : Boolean) is + pragma Precondition (A and then B); -- # freestanding-expr + begin + GX := GX + 1; + end; + + procedure As_BODYPOSTCOND (A, B : Boolean) is + pragma Postcondition (A and then B); -- # freestanding-expr + begin + GX := GX + 1; + end; + + procedure As_SPECPRECOND (A, B : Boolean) is + begin + GX := GX + 1; + end; + + procedure As_SPECPOSTCOND (A, B : Boolean) is + begin + GX := GX + 1; + end; + + procedure As_DEBUG_ASSERT (A, B : Boolean) is + pragma Debug_Policy (Check); + begin + pragma Debug (Assert (A and then B)); -- # eval + GX := GX + 1; + end; +end; diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads new file mode 100644 index 000000000..8a8457e90 --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads @@ -0,0 +1,31 @@ +package Expr is + + GX : Integer := 0; + pragma Volatile (GX); + + GB : Boolean; + pragma Volatile (GB); + + procedure As_RHS (A, B : Boolean); + procedure As_ACTUAL (A, B : Boolean); + procedure As_CASE (A, B : Boolean); + procedure As_AGGREGATE (A, B : Boolean); + procedure As_DECLINIT (A, B : Boolean); + procedure As_DISCINIT (A, B : Boolean); + + function As_RETURN (A, B : Boolean) return Boolean; + + procedure As_BODYPRECOND (A, B : Boolean); + procedure As_BODYPOSTCOND (A, B : Boolean); + + pragma Check_Policy (Precondition, On); + pragma Check_Policy (Postcondition, On); + + procedure As_SPECPRECOND (A, B : Boolean); + pragma Precondition (A and then B); -- # freestanding-expr + + procedure As_SPECPOSTCOND (A, B : Boolean); + pragma Postcondition (A and then B); -- # freestanding-expr + + procedure As_DEBUG_ASSERT (A, B : Boolean); +end; diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb new file mode 100644 index 000000000..98b2d3277 --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb @@ -0,0 +1,29 @@ +with Support, Expr; use Support; + +procedure Test_T is +begin + Expr.As_RHS (A => True, B => True); + Expr.As_ACTUAL (A => True, B => True); + Expr.As_CASE (A => True, B => True); + Expr.As_AGGREGATE (A => True, B => True); + Expr.As_DECLINIT (A => True, B => True); + Expr.As_DISCINIT (A => True, B => True); + + Expr.GB := Expr.As_RETURN (A => True, B => True); + + Expr.As_BODYPRECOND (A => True, B => True); + Expr.As_BODYPOSTCOND (A => True, B => True); + Expr.As_SPECPRECOND (A => True, B => True); + Expr.As_SPECPOSTCOND (A => True, B => True); + + Expr.As_DEBUG_ASSERT (A => True, B => True); +end; + +--# expr.adb +-- /eval/ l+ ## 0 +-- /freestanding-expr/ l. ## 0 +-- /true/ l+ ## 0 +-- /false/ l- ## s- + +--# expr.ads +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/test.py b/testsuite/tests/Ada/decision/MA07-028-expr-context/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb new file mode 100644 index 000000000..f80f1e9ed --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Dump (E : Enum) is + Img : constant String := Pkg.Enum_Images (E).all; -- # decl + begin + if Img /= "" then -- # cond + Put_Line ("Image: " & Img); -- # then + end if; + end Dump; + +end Pkg; diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads new file mode 100644 index 000000000..2059a1e32 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads @@ -0,0 +1,15 @@ +package Pkg is + + type Enum is (A, B, C); + + Enum_Image_A : aliased constant String := "A"; + Enum_Image_B : aliased constant String := "B"; + Enum_Image_C : aliased constant String := ""; + Enum_Images : constant array (Enum) of access constant String := + (Enum_Image_A'Access, + Enum_Image_B'Access, + Enum_Image_C'Access); + + procedure Dump (E : Enum); + +end Pkg; diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb new file mode 100644 index 000000000..63dd51cd0 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_F is +begin + Pkg.Dump (Pkg.C); +end Test_F; + +--# pkg.adb +-- /decl/ l+ ## 0 +-- /cond/ l! ## dT- +-- /then/ l- ## s- diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb new file mode 100644 index 000000000..badf807f5 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_No is +begin + Put_Line (Pkg.Enum_Images (Pkg.A).all); +end Test_No; + +--# pkg.adb +-- /decl/ l- ## s- +-- /cond/ l- ## s- +-- /then/ l- ## s- diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb new file mode 100644 index 000000000..1010f3276 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_T is +begin + Pkg.Dump (Pkg.A); +end Test_T; + +--# pkg.adb +-- /decl/ l+ ## 0 +-- /cond/ l! ## dF- +-- /then/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb new file mode 100644 index 000000000..24a17446a --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_TF is +begin + Pkg.Dump (Pkg.A); + Pkg.Dump (Pkg.C); +end Test_TF; + +--# pkg.adb +-- /decl/ l+ ## 0 +-- /cond/ l+ ## 0 +-- /then/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb new file mode 100644 index 000000000..d7ae1f640 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; + +procedure Test_Values_FT is + I1 : Int; +begin + -- Cheat to force the first precond operand False + I1 := (Set => True, Val => 5); + Set (I1, 2, Reset_OK => True); +end; + +--# values.adb +-- /pre/ l! ## dF- +-- /set/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb new file mode 100644 index 000000000..263d8dfce --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb @@ -0,0 +1,11 @@ +with Support, Values; use Support, Values; + +procedure Test_Values_TF is + I1 : Int; +begin + Set (I1, 2, Reset_OK => False); +end; + +--# values.adb +-- /pre/ l! ## dF- +-- /set/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb new file mode 100644 index 000000000..1f1c7d1bb --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb @@ -0,0 +1,11 @@ +with Support, Values; use Support, Values; + +procedure Test_Values_TT is + I1 : Int; +begin + Set (I1, 2, Reset_OK => True); +end; + +--# values.adb +-- /pre/ l! ## dF- +-- /set/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb new file mode 100644 index 000000000..cd7a431f0 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb @@ -0,0 +1,8 @@ +pragma Check_Policy (Precondition, On); + +package body Values is + procedure Set (V : in out Int; Val : Integer; Reset_OK : Boolean) is + begin + V := (Set => True, Val => Val); -- # set + end; +end; diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads new file mode 100644 index 000000000..c0972f0f5 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads @@ -0,0 +1,10 @@ +package Values is + + type Int is record + Val : Integer := 0; + Set : Boolean := False; + end record; + + procedure Set (V : in out Int; Val : Integer; Reset_Ok : Boolean); + pragma Precondition ((not V.Set) or else Reset_Ok); +end; diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py b/testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb new file mode 100644 index 000000000..ce6095b15 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb @@ -0,0 +1,26 @@ + +package body Actuators is + + type Update_Policy is (Fast, Safe); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy); + pragma Inline (Increment); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy) is + begin + if Policy = Safe and then A.Value + Value > A.Safety then -- # check + return; -- # punt + else + A.Value := A.Value + Value; -- # update + end if; + end; + + procedure Fast_Increment + (A : in out Actuator; Value : Integer) is + begin + Increment (A, Value, Policy => Fast); -- # call + end; + +end; diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads new file mode 100644 index 000000000..bf3eb3449 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads @@ -0,0 +1,19 @@ +package Actuators is + + -- A very basic Actuator abstraction + + type Actuator is limited record + + Value : Integer; + -- Current output level + + Safety : Integer; + -- Value threshold beyond which output might + -- cause hardware damage + + end record; + pragma Volatile (Actuator); + + procedure Fast_Increment + (A : in out Actuator; Value : Integer); +end; diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb new file mode 100644 index 000000000..6fd63f2b7 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb @@ -0,0 +1,15 @@ +with Actuators, Support; use Actuators, Support; + +procedure Test_Fast is + + A : Actuator := (Value => 0, Safety => 2); +begin + Fast_Increment (A, 5); + Assert (A.Value = 5); +end; + +--# actuators.adb +-- /check/ l! ## dT- +-- /punt/ l- ## s- +-- /update/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt new file mode 100644 index 000000000..e7d6fd986 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1 XFAIL open question on inlining + constant folding diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb new file mode 100644 index 000000000..8f088c971 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb @@ -0,0 +1,20 @@ +pragma Short_Circuit_And_Or; + +package body Expr is + + function Bool_And (A, B : Boolean) return Boolean is + begin + return A and B; -- # lone-and + end; + + function Bool_Or (A, B : Boolean) return Boolean is + begin + return A or B; -- # lone-or + end; + + function Bool_And_Or (A, B, C : Boolean) return Boolean is + begin + return (A and B) or C; -- # and-or + end; + +end; diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads new file mode 100644 index 000000000..ea27d7e88 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads @@ -0,0 +1,5 @@ +package Expr is + function Bool_And (A, B : Boolean) return Boolean; + function Bool_Or (A, B : Boolean) return Boolean; + function Bool_And_Or (A, B, C : Boolean) return Boolean; +end; diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb new file mode 100644 index 000000000..36caee17f --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb @@ -0,0 +1,22 @@ +with Expr, Assert; use Expr; + +-- For all the expression evals, arrange to demonstrate independant +-- influence of A only. Expect condition independance not demonstrated +-- diagnostics on other conditions. + +procedure Test_A is +begin + Assert (Bool_And (True, True) = True); + Assert (Bool_and (False, True) = False); + + Assert (Bool_Or (False, False) = False); + Assert (Bool_or (True, False) = True); + + Assert (Bool_And_Or (False, True, False) = False); + Assert (Bool_And_Or (True, True, False) = True); +end; + +--# expr.adb +-- /lone-and/ l! ## c!:"B" +-- /lone-or/ l! ## c!:"B" +-- /and-or/ l! ## c!:"B", c!:"C" diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt new file mode 100644 index 000000000..9d8f75303 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD Implemented in the 7.4.0 compiler branch +7.2.2 DEAD Implemented in the 7.4.0 compiler branch +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb new file mode 100644 index 000000000..307833ddb --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb @@ -0,0 +1,14 @@ +package body Orelse is + + procedure Eval_Or_Else (A, B : Boolean; E : out Boolean) is + begin + E := A or else B; -- # evaluate + end; + + function Or_Else (A, B : Boolean) return Boolean is + Value : Boolean; + begin + Eval_Or_Else (A, B, Value); -- # returnValue + return Value; -- # returnValue + end; +end; diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads new file mode 100644 index 000000000..de7a3b89f --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads @@ -0,0 +1,3 @@ +package Orelse is + function Or_Else (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb b/testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb new file mode 100644 index 000000000..038a3ded7 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb @@ -0,0 +1,13 @@ +with Support, Orelse; use Support, Orelse; + +procedure Test_OrElse_A is +begin + Assert (Or_Else (True, False) = True); + Assert (Or_Else (False, False) = False); +end; + +--# orelse.adb +-- /evaluate/ l! ## c!:"B" +-- /decisionTrue/ l+ ## 0 +-- /decisionFalse/ l+ ## 0 +-- /returnValue/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/test.py b/testsuite/tests/Ada/mcdc/OrElse-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb new file mode 100644 index 000000000..6d6ac08c3 --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb @@ -0,0 +1,10 @@ +function In_Range (X , Min, Max : Integer) return Boolean is +begin + if X < Min then -- # XcmpMin + return False; -- # XoutMin + elsif X > Max then -- # XcmpMax + return False; -- # XoutMax + else + return True; -- # Xin + end if; +end; diff --git a/testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali new file mode 100644 index 000000000..c4a4597b5 --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali @@ -0,0 +1,19 @@ +V "GNAT Lib v6.4" +A -O1 +A -fpreserve-control-flow +A -fverbose-asm +A -mregnames +A -g +P +R nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + +U in_range%b in_range.adb 0993fb61 NE OO SU + +D in_range.adb 20100310172111 0993fb61 +D system.ads 20100303101734 23e63bde +X 1 in_range.adb +1V10*In_Range{boolean} 1b10 1>20 1>24 1>29 10t4 +1i20 X{integer} 3r7 5r10 +1i24 Min{integer} 3r11 +1i29 Max{integer} 5r14 + diff --git a/testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb b/testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb new file mode 100644 index 000000000..2b79671bf --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb @@ -0,0 +1,16 @@ +with In_Range, Support; use Support; + +-- Exercize X > max only. Verify that the < min exit and the in-range case +-- are reported uncovered. + +procedure Test_In_Range_GTmax is +begin + Assert (not In_Range (4, 2, 3)); +end; + +--# in_range.adb +-- /XcmpMin/ l+ ## 0 +-- /XcmpMax/ l+ ## 0 +-- /XoutMax/ l+ ## 0 +-- /Xin/ l- ## s- +-- /XoutMin/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/CmpMin/test.py b/testsuite/tests/Ada/stmt/CmpMin/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb new file mode 100644 index 000000000..339fbb0ae --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb @@ -0,0 +1,20 @@ +package body Flips is + + Ob, T : Boolean := True; + pragma Volatile (T); + + procedure Flip (B : in out Boolean) is + begin + B := not B; -- # doflip + end; + + procedure Flip_If (P : Boolean) is + KB : constant Boolean := T; + B : Boolean := KB; + begin + if P then + Flip (B); -- # doflip + Ob := B; -- # doflip + end if; + end; +end; diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads new file mode 100644 index 000000000..2ca76cba8 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads @@ -0,0 +1,4 @@ +package Flips is + procedure Flip (B : in out Boolean); + procedure Flip_If (P : Boolean); +end; diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali new file mode 100644 index 000000000..35aea58b0 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali @@ -0,0 +1,27 @@ +V "GNAT Lib v6.4" +A -O1 +A -fpreserve-control-flow +A -g +A -mregnames +P +R nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + +U flips%b flips.adb ef4d54cb NE OO PK + +U flips%s flips.ads 81d0dffd EE NE OO PK + +D flips.ads 20100311144045 81d0dffd +D flips.adb 20100311150436 6e9d8b36 +D system.ads 20071215102046 2b00703b +X 1 flips.ads +1K9*Flips 4e4 2|1b14 20t4 +2U14*Flip 2=20 2|6b14 9t7 +2b20 B{boolean} 2|6b20 8m7 8r16 +3U14*Flip_If 3>23 2|11b14 19t7 +3b23 P{boolean} 2|11b23 15r10 +X 2 flips.adb +3b4 Ob{boolean} 17m10 +3b8 T{boolean} 4r21 12r32 +12b7 KB{boolean} 13r22 +13b7 B{boolean} 16m10 16r19 17r16 + diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb b/testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb new file mode 100644 index 000000000..fcf9ad8f7 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb @@ -0,0 +1,9 @@ +with Support, Flips; use Support, Flips; + +procedure Test_Flip_0 is +begin + Flip_If (False); +end; + +--# flips.adb +-- /doflip/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/test.py b/testsuite/tests/Ada/stmt/DeclChain-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb new file mode 100644 index 000000000..b726597d0 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb @@ -0,0 +1,30 @@ +package body Pkg is + + task body T is + begin + null; -- # stmt + end T; + + protected body P is + end P; + + procedure Run is + task ST; -- # stmt + task body ST is + begin + null; -- # stmt + end ST; + + protected SP is -- # stmt + end SP; + + protected body SP is + end SP; + + T_Instance : T; -- # stmt + P_Instance : P; -- # stmt + begin + null; -- # stmt + end Run; + +end Pkg; diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads new file mode 100644 index 000000000..8de9a1aa9 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads @@ -0,0 +1,10 @@ +package Pkg is + + task type T; + + protected type P is + end P; + + procedure Run; + +end Pkg; diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb new file mode 100644 index 000000000..d6179b3ca --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb @@ -0,0 +1,10 @@ +with Pkg; + +procedure Test_Full is +begin + Pkg.Run; +end Test_Full; + +--# pkg.ads +--# pkg.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb new file mode 100644 index 000000000..58edb8b5b --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb @@ -0,0 +1,10 @@ +with Pkg; + +procedure Test_No is +begin + null; +end Test_No; + +--# pkg.ads +--# pkg.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/test.opt b/testsuite/tests/Ada/stmt/IncompleteTask/test.opt new file mode 100644 index 000000000..91bc868e9 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test requires tasking +RTS_RAVENSCAR DEAD Test requires tasking hierarchy diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/test.py b/testsuite/tests/Ada/stmt/IncompleteTask/test.py new file mode 100644 index 000000000..81870abe6 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/test.py @@ -0,0 +1,11 @@ +""" +Regression test for a crash in "gnatcov instrument" when processing incomplete +task type declarations. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb new file mode 100644 index 000000000..6ab874a10 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb @@ -0,0 +1,13 @@ +package body Flips is + + procedure Flip (X : in out integer) is + begin + X := - X; -- # flipx + end; + + procedure Flip (B : in out Boolean) is + begin + B := not B; -- # flipb + end; + +end; diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads new file mode 100644 index 000000000..35c7efbbb --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads @@ -0,0 +1,4 @@ +package Flips is + procedure Flip (X : in out integer); + procedure Flip (B : in out Boolean); +end; diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb new file mode 100644 index 000000000..221db5c52 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb @@ -0,0 +1,16 @@ +with Flips, Support; use Flips, Support; + +procedure Test_Flips is + B : Boolean := True; + X : Integer := 5; +begin + Flip (B); + Assert (B = False); + + Flip (X); + Assert (X = -5); +end; + +--# flips.adb +-- /flipb/ l+ ## 0 +-- /flipx/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb new file mode 100644 index 000000000..08436bca6 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb @@ -0,0 +1,8 @@ +function Id (X : Integer) return Integer is + X_Value : Integer; -- # decl +begin + X_Value := X; -- # Call + goto Done; -- # Call +<> + return X_Value; -- # Call +end; diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali new file mode 100644 index 000000000..09565ae7b --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali @@ -0,0 +1,18 @@ +V "GNAT Lib v6.4" +A -O1 +A -fpreserve-control-flow +A -gnatp +A -g +P +R nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + +U id%b id.adb ecec289f NE OO SU + +D id.adb 20100316135548 ecec289f +D system.ads 20100316073307 23e63bde +X 1 id.adb +1V10*Id{integer} 1b10 1>14 8t4 +1i14 X{integer} 4r15 +2i4 X_Value{integer} 4m4 7r12 +6L3 Done 5r9 + diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb new file mode 100644 index 000000000..84507e48a --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb @@ -0,0 +1,10 @@ +with Id, Support; use Support; + +procedure Test_Id0 is +begin + Assert (True); +end; + +--# id.adb +-- /Call/ l- ## s- +-- /decl/ ~l- ## ~s- diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb new file mode 100644 index 000000000..ed48ce070 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb @@ -0,0 +1,8 @@ +procedure Inc_By (N : Natural; X : in out Integer) is + Ninc : Natural := 0; -- # decl +begin -- # + while Ninc /= N loop -- # incLoop + X := X + 1; -- # incX + Ninc := Ninc + 1; -- # incX + end loop; +end; -- # diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb new file mode 100644 index 000000000..8ac4d76b4 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb @@ -0,0 +1,11 @@ +package body Ops is + + procedure Probe (N : Natural) is + Nprobes : Natural := 0; -- # decl + begin + while Nprobes /= N loop -- # loop + Latch := IOreg; -- # probe + Nprobes := Nprobes + 1; -- # probe + end loop; + end; +end; diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads new file mode 100644 index 000000000..f8a055364 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads @@ -0,0 +1,8 @@ +package Ops is + + Latch, IOreg : Integer; + pragma Volatile (IOreg); + pragma Volatile (Latch); + + procedure Probe (N : Natural); +end; diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt new file mode 100644 index 000000000..8c23b2d3d --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt @@ -0,0 +1 @@ +ALL XFAIL -O1 vs trivial loops J316-020 diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb new file mode 100644 index 000000000..01f274991 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb @@ -0,0 +1,12 @@ +with Inc_By, Support; use Support; + +procedure Test_Inc is + X : Integer := 12; +begin + Inc_By (15, X); + Assert (X = 27); +end; + +--# inc_by.adb +-- /decl/ ~l+ ## 0 +-- /incLoop|incX/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb new file mode 100644 index 000000000..f55ec204e --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb @@ -0,0 +1,10 @@ +with Inc_By, Support; use Support; + +procedure Test_Inc_0 is +begin + Assert (True); +end; + +--# inc_by.adb +-- /decl/ ~l- ## ~s- +-- /incLoop|incX/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb new file mode 100644 index 000000000..ef7609bdd --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb @@ -0,0 +1,10 @@ +with Ops, Support; use Ops, Support; + +procedure Test_Ops_0 is +begin + Assert (True); +end; + +--# ops.adb +-- /decl/ ~l- ## ~s- +-- /loop|probe/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb new file mode 100644 index 000000000..0184bd34c --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb @@ -0,0 +1,17 @@ +package body Plop is + pragma Unsuppress (All_Checks); + + function F (I : My_Int) return My_Int is + Res : My_Int := I; + begin + begin + Res := Res * I; -- # mult + Res := Res / 2; -- # div + exception + when Constraint_Error => + return -1; -- # handle + end; + + return Res; -- # retval + end; +end; diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads new file mode 100644 index 000000000..dac1596e2 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads @@ -0,0 +1,4 @@ +package Plop is + type My_Int is range -100 .. 100; + function F (I : My_Int) return My_Int; +end; diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb new file mode 100644 index 000000000..feddddde9 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb @@ -0,0 +1,12 @@ +with Plop, Support; use Plop, Support; + +procedure Test_CE is +begin + Assert (F (50) = -1); +end; + +--# plop.adb +-- /mult/ l+ ## 0 +-- /div/ l- ## s- +-- /retval/ l- ## s- +-- /handle/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt new file mode 100644 index 000000000..cfb29ed49 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt @@ -0,0 +1,2 @@ +RTS_RAVENSCAR,powerpc,7.0.3 SKIP !zfp sjlj eh issue fixed post 7.0, K316-021 +block DEAD Exception breaking the control flow diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb new file mode 100644 index 000000000..0b51e6c68 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb @@ -0,0 +1,27 @@ +with Support; + +package body Actuators is + + type Update_Policy is (Fast, Safe); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy); + pragma Inline (Increment); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy) is + begin + if Policy = Safe and then A.Value + Value > A.Safety then -- # check + return; -- # punt + else + A.Value := A.Value + Value; -- # update + end if; + end; + + procedure Fast_Increment + (A : in out Actuator; Value : Integer) is + begin + Increment (A, Value, Policy => Fast); -- # call + end; + +end; diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads new file mode 100644 index 000000000..bf3eb3449 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads @@ -0,0 +1,19 @@ +package Actuators is + + -- A very basic Actuator abstraction + + type Actuator is limited record + + Value : Integer; + -- Current output level + + Safety : Integer; + -- Value threshold beyond which output might + -- cause hardware damage + + end record; + pragma Volatile (Actuator); + + procedure Fast_Increment + (A : in out Actuator; Value : Integer); +end; diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb new file mode 100644 index 000000000..3fd6b8089 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb @@ -0,0 +1,15 @@ +with Actuators, Support; use Actuators, Support; + +procedure Test_Fast is + + A : Actuator := (Value => 0, Safety => 2); +begin + Fast_Increment (A, 5); + Assert (A.Value = 5); +end; + +--# actuators.adb +-- /check/ l+ ## 0 +-- /punt/ l- ## s- +-- /update/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt new file mode 100644 index 000000000..e7d6fd986 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1 XFAIL open question on inlining + constant folding diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr new file mode 100644 index 000000000..aa467bb3c --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr @@ -0,0 +1,7 @@ +library project mylib is + for source_dirs use ("."); + for object_dir use "obj"; + for library_name use project'name; + for library_dir use "lib"; + for library_interface use ("ops", "ops.values"); +end mylib; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb new file mode 100644 index 000000000..acab1997b --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb @@ -0,0 +1,6 @@ +package body Ops.Values is + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads new file mode 100644 index 000000000..d8f0f476f --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads @@ -0,0 +1,3 @@ +package Ops.Values is + procedure Inc (X : in out Integer); +end; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads new file mode 100644 index 000000000..10cdb9b3c --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads @@ -0,0 +1,9 @@ +-- Unit with only dummy statements, not generating code. Make sure +-- these aren't ignored by gnatcov and would get a violation if the +-- unit is perceived by gnatcov as absent from the test-closure. +-- +-- pragma Pure; would be a bad choice, for example. + +package Ops is + X : Integer; -- # decl +end; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb new file mode 100644 index 000000000..09d6fd202 --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb @@ -0,0 +1,24 @@ +with Support, Ops.Values; use Support, Ops.Values; + +procedure Test_Inc is + + -- The library initialization procedure isn't called automatically in some + -- configurations so we call it explicitly from here. Calling it multiple + -- times is not a problem, so we're fine in configurations where it is + -- called automatically before reaching here. + + procedure Mylib_Init; + pragma Import (C, Mylib_Init, "mylibinit"); + + K : Integer := 12; + pragma Volatile (K); +begin + Mylib_Init; + Inc (K); +end; + +--# ../mylib/ops.ads +-- /decl/ l. ## 0 + +--# ../mylib/ops-values.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt new file mode 100644 index 000000000..7da54125d --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt @@ -0,0 +1,2 @@ +bareboard SKIP Static auto-initialized libraries are not supported in BB +src-traces XFAIL S916-064: src-traces and Library_Interface project attributes diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py new file mode 100644 index 000000000..912978ddc --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py @@ -0,0 +1,16 @@ +import os.path + +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches + + +libdep = os.path.abspath("mylib/mylib.gpr") +TestCase().run( + covcontrol=CovControl( + deps=[libdep], + gprsw=GPRswitches(root_project="gen.gpr", units=["ops", "ops.values"]), + ) +) +thistest.result() diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb b/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb new file mode 100644 index 000000000..334e844b3 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_F is + + LA : Array_Type := + (1 => (X => 2, Count => 0)); +begin + Process (LA, Bump => False); + Assert (LA(1).Count = 0); + Assert (LA(1).X = 4); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## dT- +-- /true/ l- ## s- diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb b/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb new file mode 100644 index 000000000..92233825c --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_T is + + LA : Array_Type := + (1 => (X => 2, Count => 0)); +begin + Process (LA, Bump => True); + Assert (LA(1).Count = 1); + Assert (LA(1).X = 4); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/values.adb b/testsuite/tests/Ada2012/decision/ForOf/src/values.adb new file mode 100644 index 000000000..1bb006534 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/values.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package body Values is + + procedure Process (A : in out Array_Type; Bump : Boolean) is + begin + for E of A loop -- # stmt + E.X := E.X * 2; -- # stmt + if Bump then -- # eval + E.Count := E.Count + 1; -- # true + end if; + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/values.ads b/testsuite/tests/Ada2012/decision/ForOf/src/values.ads new file mode 100644 index 000000000..b1015405b --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/values.ads @@ -0,0 +1,12 @@ + +package Values is + + type Object is tagged record + X : Integer; + Count : Natural; + end record; + + type Array_Type is array (Natural range <>) of Object; + + procedure Process (A : in out Array_Type; Bump : Boolean); +end; diff --git a/testsuite/tests/Ada2012/decision/ForOf/test.py b/testsuite/tests/Ada2012/decision/ForOf/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/extra.opt b/testsuite/tests/Ada2012/extra.opt new file mode 100644 index 000000000..e1aeef0d6 --- /dev/null +++ b/testsuite/tests/Ada2012/extra.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD support for Ada2012 constructs not in 7.0.3 +7.1.2 DEAD support for Ada2012 constructs weak in 7.1.2 +7.2.2 DEAD support for Ada2012 constructs weak in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb new file mode 100644 index 000000000..fe704d7ef --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb @@ -0,0 +1,7 @@ +package body Multiop is + + procedure Set (I : in out Int; V : Integer) is + begin + I.Value := V; + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads new file mode 100644 index 000000000..d0cbb89c4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads @@ -0,0 +1,19 @@ +pragma Ada_2012; +pragma Assertion_Policy (Type_Invariant => Check); + +-- exercise a multi-operand invariant (complex expr) + +package Multiop is + + type Int (LB, UB : Integer) is private; + + procedure Set (I : in out Int; V : Integer); + +private + + type Int (LB, UB : Integer) is record + Value : Integer := LB; + end record with + Type_Invariant => (Int.Value >= Int.LB and then Int.Value <= Int.UB); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb new file mode 100644 index 000000000..77eb7a1e4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb @@ -0,0 +1,13 @@ +with Multiop; use Multiop; +with Silent_Last_Chance; + +procedure Test_Multiop_F is + O : Int (LB => 1, UB => 5); +begin + Set (O, V => 45); +exception + when others => null; +end; + +--# multiop.ads +-- /eval/ l! ## c!:"Int.Value >= Int.LB" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb new file mode 100644 index 000000000..5198b6514 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb @@ -0,0 +1,10 @@ +with Multiop; use Multiop; + +procedure Test_Multiop_T is + O : Int (LB => 1, UB => 5); +begin + Set (O, V => 3); +end; + +--# multiop.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst new file mode 100644 index 000000000..94b8e4b47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst @@ -0,0 +1,4 @@ +Exercise a mono-operand type_invariant aspect + +Check that no dc violation is raised for an invariant always satisfied, as +mono-operand expressions are never decisions in this context. diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb new file mode 100644 index 000000000..6ac7ee000 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb @@ -0,0 +1,8 @@ +package body SingleOp is + + procedure Set (I : in out Int; V : Integer) is + begin + I.Value := V; + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads new file mode 100644 index 000000000..6cd1ff056 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads @@ -0,0 +1,19 @@ +pragma Ada_2012; +pragma Assertion_Policy (Invariant => Check); + +-- exercise a mono-operand invariant (simple expr) + +package SingleOp is + + type Int (UB : Integer) is private; + + procedure Set (I : in out Int; V : Integer); + +private + + type Int (UB : Integer) is record + Value : Integer := UB; + end record with + Invariant => (Int.Value <= Int.UB); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb new file mode 100644 index 000000000..5f05ec763 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb @@ -0,0 +1,10 @@ +with Singleop; use Singleop; + +procedure Test_Singleop_T is + O : Int (UB => 5); +begin + Set (O, V => 3); +end; + +--# singleop.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst new file mode 100644 index 000000000..fd7cde47a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst @@ -0,0 +1,4 @@ +Invariant aspects shall be treated as Postconditions checked +after every operation on an object of the type. + +Only complex expressions are considered as decisions, for mcdc. diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb new file mode 100644 index 000000000..5fe656d47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb @@ -0,0 +1,12 @@ +with Values; + +-- Don't even call in. Decision never evaluated and all stmts uncovered. + +procedure Test_0 is +begin + null; +end; + +--# values.adb +-- /eval/ l- ## d- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb new file mode 100644 index 000000000..ba6ccc0fd --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb @@ -0,0 +1,16 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_A is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => -7, Valid => True); + C : Int := (Value => 12, Valid => True); +begin + Filter (A, C); -- T T + Filter (B, C); -- F T +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## c!:"B.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb new file mode 100644 index 000000000..035b58174 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb @@ -0,0 +1,16 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_B is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => -7, Valid => True); + C : Int := (Value => 12, Valid => True); +begin + Filter (A, C); -- T T + Filter (A, B); -- T F +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## c!:"A.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb new file mode 100644 index 000000000..01c7737a4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => -7, Valid => True); +begin + Filter (A, B); +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb new file mode 100644 index 000000000..a43b281ce --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb @@ -0,0 +1,11 @@ +with Support, Values; use Support, Values; + +procedure Test_T is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => 7, Valid => True); +begin + Filter (A, B); +end; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb new file mode 100644 index 000000000..9bdf01b38 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Check); + +package body Values is + + procedure validate (A, B : in out Int) + with Post => (A.Valid and then B.Valid) -- # eval + is + begin + A.Valid := A.Value > 0; -- # stmt + B.Valid := B.Value > 0; -- # stmt + end; + + procedure Filter (A, B : in out Int) is + begin + Validate (A, B); -- # stmt + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads new file mode 100644 index 000000000..902b200e3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads @@ -0,0 +1,11 @@ + +package Values is + + type Int is record + Value : Integer; + Valid : Boolean; + end record; + + procedure Filter (A, B : in out Int); + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb new file mode 100644 index 000000000..5fe656d47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb @@ -0,0 +1,12 @@ +with Values; + +-- Don't even call in. Decision never evaluated and all stmts uncovered. + +procedure Test_0 is +begin + null; +end; + +--# values.adb +-- /eval/ l- ## d- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb new file mode 100644 index 000000000..6b97ca8e2 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + X : Integer; +begin + X := Plus (5, -8); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb new file mode 100644 index 000000000..ad001f639 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Plus (5, 8) = 13); +end; + +--# values.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb new file mode 100644 index 000000000..d4775815a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb @@ -0,0 +1,7 @@ +package body Values is + + function Plus (A, B : Integer) return Integer is + begin + return A + B; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads new file mode 100644 index 000000000..bfcc9d6c0 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Check); + +package Values is + + function Plus (A, B : Integer) return Integer + with Post => (Plus'Result > 0); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb new file mode 100644 index 000000000..ebb7f7adc --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_A is + X : Integer; +begin + Assert + (Plus ((Value => 5, Valid => True), + (Value => 7, Valid => True)) = 12 + ); + X := Plus ((Value => 5, Valid => True), (Value => -7, Valid => False)); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## c!:"A.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb new file mode 100644 index 000000000..3b85d4e41 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_B is + X : Integer; +begin + Assert + (Plus ((Value => 5, Valid => True), + (Value => 7, Valid => True)) = 12 + ); + X := Plus ((Value => 5, Valid => False), (Value => -7, Valid => True)); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## c!:"B.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb new file mode 100644 index 000000000..08648eaac --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + X : Integer; +begin + X := Plus ((Value => 5, Valid => True), (Value => -7, Valid => False)); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb new file mode 100644 index 000000000..0748bb64f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert + (Plus ((Value => 5, Valid => True), + (Value => 7, Valid => True)) = 12 + ); +end; + +--# values.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb new file mode 100644 index 000000000..27873f776 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb @@ -0,0 +1,8 @@ +package body Values is + + function Plus (A, B : Int) return Integer is + begin + return A.Value + B.Value; + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads new file mode 100644 index 000000000..888ec633e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; +pragma Assertion_Policy (Pre => Check); + +package Values is + + type Int is record + Value : Integer; + Valid : Boolean; + end record; + + function Plus (A, B : Int) return Integer + with Pre => (A.Valid and then B.Valid); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb new file mode 100644 index 000000000..5fe656d47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb @@ -0,0 +1,12 @@ +with Values; + +-- Don't even call in. Decision never evaluated and all stmts uncovered. + +procedure Test_0 is +begin + null; +end; + +--# values.adb +-- /eval/ l- ## d- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb new file mode 100644 index 000000000..5da5317df --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + X : Integer; +begin + X := Plus (5, -8); +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb new file mode 100644 index 000000000..aaa1accba --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Plus (5, 8) = 13); +end; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb new file mode 100644 index 000000000..7cc5e9f28 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Check); + +package body Values is + + function CheckedPlus (A, B : Integer) return Integer + with Post => (CheckedPlus'Result > 0) -- # eval + is + begin + return A + B; -- # stmt + end; + + function Plus (A, B : Integer) return Integer is + begin + return CheckedPlus (A, B); -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads new file mode 100644 index 000000000..3cc9787ad --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads @@ -0,0 +1,5 @@ +package Values is + + function Plus (A, B : Integer) return Integer; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb new file mode 100644 index 000000000..a7d57b19f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb @@ -0,0 +1,21 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_A is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>), + 2 => (A => False, B => True, Expr => <>) + ); + +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## c!:"E.B" diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb new file mode 100644 index 000000000..a5732b005 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_AB is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>), + 2 => (A => True, B => False, Expr => <>), + 3 => (A => False, B => True, Expr => <>) + ); + +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb new file mode 100644 index 000000000..56fa7924a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb @@ -0,0 +1,21 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_B is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>), + 2 => (A => True, B => False, Expr => <>) + ); + +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## c!:"E.A" diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb new file mode 100644 index 000000000..201945e4f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_F is + + LA : Array_Type := + (1 => (A => True, B => False, Expr => <>)); +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## eT- diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb new file mode 100644 index 000000000..e5becda2e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_T is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>)); +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb new file mode 100644 index 000000000..3d403a9e2 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Values is + + procedure Process (A : in out Array_Type) is + begin + for E of A loop -- # stmt + E.Expr := E.A and then E.B; -- # eval + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads new file mode 100644 index 000000000..16faf5901 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads @@ -0,0 +1,11 @@ + +package Values is + + type Object is tagged record + A, B, Expr : Boolean; + end record; + + type Array_Type is array (Natural range <>) of Object; + + procedure Process (A : in out Array_Type); +end; diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/test.py b/testsuite/tests/Ada2012/mcdc/ForOf/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads new file mode 100644 index 000000000..50fd3d7ef --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Expr is + -- if-expressions as outer expression operands in expression context. + + -- one outer and-then expr-decision with two operands: "if a" + "if b" + -- plus two inner decisions: "A" and "B" controlling the if values. + + function Filter (A, Valat, Valaf, B, Valbt, Valbf : Boolean) return Boolean is + ((if A then Valat else Valaf) and then (if B then Valbt else Valbf)); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb new file mode 100644 index 000000000..e1e07ea97 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A_Opa is +begin + -- A op1 B op2 Outer + -- F T F T T + -- T F F T F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => True, Valat => False, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"B", c!:"if B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"B", c!:"if B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb new file mode 100644 index 000000000..b53a2bc2e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A_T is +begin + -- A op1 B op2 Outer + -- F T T T T + -- T T T T T + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => True, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => True) = True); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## eF-:"if A", d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## eF-:"if A", dF-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb new file mode 100644 index 000000000..47c1d4ab3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb @@ -0,0 +1,17 @@ +with Expr, Support; use Expr, Support; + +procedure Test_AB_T is +begin + -- A op1 B op2 Outer + -- F T T T T + -- T T F T T + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => True, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); +end; + +--# expr.ads +-- /eval/ l! ## eF-:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb new file mode 100644 index 000000000..7c6e9e5b7 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_B_Opa is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F T T F F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => False, Valat => False, Valaf => True, + B => True, Valbt => False, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", c!:"if A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", c!:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb new file mode 100644 index 000000000..f236569a8 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opa is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F F F T F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => False, Valat => True, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d!:"B", c!:"if B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", dT-:"B", c!:"if B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb new file mode 100644 index 000000000..f446ad79f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb @@ -0,0 +1,21 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opb is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F T F F F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d!:"B", c!:"if A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", dT-:"B", c!:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb new file mode 100644 index 000000000..ff0d7d7e2 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb @@ -0,0 +1,18 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opb0 is +begin + -- A op1 B op2 Outer + -- F F X X F + + Assert (Filter (A => False, Valat => False, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d-:"B", eT-:"if A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", d-:"B", eT-:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb new file mode 100644 index 000000000..08c15c9ea --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb @@ -0,0 +1,26 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opfull is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F F F T F + -- F T F F F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => False, Valat => True, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", dT-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb new file mode 100644 index 000000000..591afd41d --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb @@ -0,0 +1,15 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (A => False, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => False) = True); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## eF-:"if A", d!:"A", d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## eF-:"if A", dT-:"A", dF-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads new file mode 100644 index 000000000..b83662a26 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Expr is + X : Boolean := True; -- arbitrary value for operand not evaluated + + function Filter (A, B : Boolean; Valt : Boolean) return Boolean is + ((if A then Valt elsif B then Valt else not Valt)); -- # eval + + -- The controlling expressions are mono-operand here, and we + -- have no dominated statement to disambiguate True from False + -- on partial coverage. +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb new file mode 100644 index 000000000..80265282e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb @@ -0,0 +1,15 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A is +begin + Assert (Filter (A => True, B => X, Valt => True) = True); + Assert (Filter (A => False, B => True, Valt => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dF-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb new file mode 100644 index 000000000..645ada9cb --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb @@ -0,0 +1,15 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A_T is +begin + Assert (Filter (A => True, B => X, Valt => True) = True); + Assert (Filter (A => True, B => X, Valt => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"if A", d-:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dF-:"if A", d-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb new file mode 100644 index 000000000..83b5be57c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb @@ -0,0 +1,11 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (A => True, B => X, Valt => True) = True); + Assert (Filter (A => False, B => True, Valt => True) = True); + Assert (Filter (A => False, B => False, Valt => False) = True); +end; + +--# expr.ads +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads new file mode 100644 index 000000000..2f8001d55 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Expr is + type Opkind is (Op_And, Op_Or); + + -- Simple controlling expression, complex value expressions, + -- as expression function + + function Eval (Op : Opkind; A, B : Boolean) return Boolean is + (if (Op = Op_And) -- # if-opand + then (A and then B) -- # then-and + else (A or else B) -- # else-or + ); +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb new file mode 100644 index 000000000..4578c532c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Eval (Op_And, True, True) = True); +end; + +--# expr.ads +-- /then-and/ l! ## eF- +-- /else-or/ l! ## e- +-- +--%opts: --trace-mode=bin +-- /if-opand/ l! ## d! +-- +--%opts: --trace-mode=src +-- /if-opand/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads new file mode 100644 index 000000000..5427f0a1b --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Expr is + + -- Simple controlling expression, simple value expressions, + -- as expression function. + + function Filter (A, B : Integer) return Boolean is + (if (A > 0) -- # ctl-apos + then B > A -- # then-bgt + else B < A -- # else-agt + ); + +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb new file mode 100644 index 000000000..1a5a9739f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (5, 8) = True); -- A > 0 +end; + +--# expr.ads +-- /then-bgt/ l+ ## 0 +-- /else-agt/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /ctl-apos/ l! ## d! +-- +--%opts: --trace-mode=src +-- /ctl-apos/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb new file mode 100644 index 000000000..a01d95c79 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Disable); + +function Plus (A, B : Integer) return Integer + with Post => (if (A > 0) then (B > 0) else (B <= 0)) -- # eval +is +begin + return A + B; -- # stmt +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb new file mode 100644 index 000000000..eb28bd557 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb @@ -0,0 +1,10 @@ +with Plus; + +procedure Test_0 is +begin + null; +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb new file mode 100644 index 000000000..6be12cd0a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb @@ -0,0 +1,10 @@ +with Plus, Support; use Support; + +procedure Test_F is +begin + Assert (Plus (5, -3) = 2); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb new file mode 100644 index 000000000..c6303940a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb @@ -0,0 +1,10 @@ +with Plus, Support; use Support; + +procedure Test_T is +begin + Assert (Plus (5, 6) = 11); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb new file mode 100644 index 000000000..19dee5902 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; +pragma Assertion_Policy (Pre => Disable); + +function Plus (A, B : Integer) return Integer + with Pre => (if (A > 0) then (B > 0) else (B <= 0)) -- # eval +is +begin + return A + B; -- # stmt +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb new file mode 100644 index 000000000..eb28bd557 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb @@ -0,0 +1,10 @@ +with Plus; + +procedure Test_0 is +begin + null; +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb new file mode 100644 index 000000000..6be12cd0a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb @@ -0,0 +1,10 @@ +with Plus, Support; use Support; + +procedure Test_F is +begin + Assert (Plus (5, -3) = 2); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb new file mode 100644 index 000000000..c6303940a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb @@ -0,0 +1,10 @@ +with Plus, Support; use Support; + +procedure Test_T is +begin + Assert (Plus (5, 6) = 11); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb new file mode 100644 index 000000000..a264ed7d6 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; +package body Expr is + function Eval (Op : Opkind; A, B : Boolean) return Boolean is + begin + -- Simple controlling expression, complex value expressions + + return (if (Op = Op_And) -- # if-opand + then (A and then B) -- # then-and + else (A or else B) -- # else-or + ); + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads new file mode 100644 index 000000000..8cf3a00d4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads @@ -0,0 +1,5 @@ +package Expr is + type Opkind is (Op_And, Op_Or); + + function Eval (Op : Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb new file mode 100644 index 000000000..b8de074f0 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Eval (Op_And, True, True) = True); +end; + +--# expr.adb +-- /then-and/ l! ## eF- +-- /else-or/ l! ## e- +-- +--%opts: --trace-mode=bin +-- /if-opand/ l! ## d! +-- +--%opts: --trace-mode=src +-- /if-opand/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb new file mode 100644 index 000000000..a9860e784 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Expr is + + function Filter (A, B : Integer) return Boolean is + begin + return (if (A > 0) -- # ctl-apos + then B > A -- # then-bgt + else B < A -- # else-agt + ); + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads new file mode 100644 index 000000000..3fd35bd0c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Expr is + + -- Simple controlling expression, simple value expressions, + -- as expression function. + + function Filter (A, B : Integer) return Boolean; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb new file mode 100644 index 000000000..9b6f5303a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (5, 8) = True); -- A > 0 +end; + +--# expr.adb +-- /then-bgt/ l+ ## 0 +-- /else-agt/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /ctl-apos/ l! ## d! +-- +--%opts: --trace-mode=src +-- /ctl-apos/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb new file mode 100644 index 000000000..a2abf3451 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package body Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer is + begin + if Pos then -- # test + Pos := X > 0 and then Y > 0; -- # eval + end if; + return X + Y; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads new file mode 100644 index 000000000..4753272d7 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads @@ -0,0 +1,5 @@ +pragma Ada_2012; + +package Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer; +end; diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb new file mode 100644 index 000000000..75b3b8e23 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_F is + Pos : Boolean := True; +begin + Assert (Plus (5, -6, Pos) = -1); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l! ## dF- +-- /eval/ l! ## eT- diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb new file mode 100644 index 000000000..4e26f3ba1 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_T is + Pos : Boolean := True; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = True); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l! ## dF- +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb new file mode 100644 index 000000000..89ca2bcc1 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Neval is + Pos : Boolean := False; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l! ## dT- +-- /eval/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/InOut/test.py b/testsuite/tests/Ada2012/mcdc/InOut/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb new file mode 100644 index 000000000..3ec44f99f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_F is +begin + Assert (not Even_Odd (2, 8)); + Assert (not Even_Odd (1, 7)); +end; + +--# values.ads +-- /eval/ l! ## eT- diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb new file mode 100644 index 000000000..356448465 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Even_Odd (4, 7)); + Assert (Even_Odd (2, 1)); +end; + +--# values.ads +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb new file mode 100644 index 000000000..4919f6750 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_X is +begin + Assert (Even_Odd (4, 7)); + Assert (not Even_Odd (1, 1)); +end; + +--# values.ads +-- /eval/ l! ## c!:"Y" diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb new file mode 100644 index 000000000..ab9c6cb39 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_Y is +begin + Assert (Even_Odd (4, 7)); + Assert (not Even_Odd (2, 8)); +end; + +--# values.ads +-- /eval/ l! ## c!:"X" diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads b/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads new file mode 100644 index 000000000..ef9b24b60 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package Values is + + type My_Int is new Integer range 1 .. 8; + + function Even_Odd (X, Y : My_Int) return Boolean is + (X in 2 | 4 | 6 | 8 and then Y in 1 | 3 | 5 | 7); -- # eval +end; diff --git a/testsuite/tests/Ada2012/mcdc/Membership/test.py b/testsuite/tests/Ada2012/mcdc/Membership/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb new file mode 100644 index 000000000..460ec57af --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_A is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (All_Pos (Positives, Positives)); + Assert (not All_Pos (Negatives, Positives)); +end Test_A; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for all E", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for all E", dF-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb new file mode 100644 index 000000000..4848a065e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_B is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (All_Pos (Positives, Positives)); + Assert (not All_Pos (Positives, Negatives)); +end Test_B; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for all K", d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for all K", dF-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb new file mode 100644 index 000000000..46fd8495a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support, Values; + +procedure Test_T is + S1 : Sequence := (1, 4, 12, 15, 20); + S2 : Sequence := (1, 15, 13); +begin + Assert (All_Pos (S1, S2)); +end Test_T; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## eF-, d!:"S1(K) > 0", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## eF-, dF-:"S1(K) > 0", dF-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb new file mode 100644 index 000000000..0dde12bf9 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package body Values is + + function All_Pos (S1, S2: Sequence) return Boolean is + begin + -- Assertions are not (yet) supposed to be processed by gnatcov, + -- but this kind of construct can make the instrumenter fail + -- (see U526-032) so this assertion is here only to test the + -- instrumenter robustness for the moment. + -- Coverage results are irrelevant for the time being. + + pragma Assert (for all K in Value_Seq'Range => Value_Seq (K) > 0); + + return (for all K in S1'Range => S1(K) > 0) and then (for all E of S2 => E > 0); -- # eval + end All_Pos; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads new file mode 100644 index 000000000..6e5f14570 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads @@ -0,0 +1,7 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function All_Pos (S1, S2: Sequence) return Boolean; + + Value_Seq : Sequence := (1, 2, 3, 4); +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb new file mode 100644 index 000000000..4a010beff --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_A is +begin + Assert (All_Pos_Some_Neg ((1, 5, 3), (1, 9, -1, 12))); + Assert (not All_Pos_Some_Neg ((1, -5, 3), (1, 9, -1, 12))); +end Test_A; + +--# values.adb +-- /eval/ l! ## c!:"for some E" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb new file mode 100644 index 000000000..203e56e95 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; + +procedure Test_B is +begin + Assert (All_Pos_Some_Neg ((1, 5, 3), (1, 9, -1, 12))); + Assert (not All_Pos_Some_Neg ((1, 12, 3), (1, 9))); +end Test_B; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for all K", d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for all K", dF-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb new file mode 100644 index 000000000..f22d83060 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (All_Pos_Some_Neg ((1, 5, 3), (1, 9, -1, 12))); +end Test_T; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## eF-, d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## eF-, dF-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb new file mode 100644 index 000000000..d0748ea56 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function All_Pos_Some_neg (S1, S2: Sequence) return Boolean is + begin + return (for all K in S1'Range => S1(K) > 0) and then (for some E of S2 => E < 0); -- # eval + end; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads new file mode 100644 index 000000000..58f31a0ad --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function All_Pos_Some_Neg (S1, S2: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb new file mode 100644 index 000000000..60a0744d4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_A is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (not Some_Pos (Negatives, Negatives)); + Assert (Some_Pos (Positives, Negatives)); +end Test_A; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for some E", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for some E", dT-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb new file mode 100644 index 000000000..9ba69f718 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_B is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (not Some_Pos (Negatives, Negatives)); + Assert (Some_Pos (Negatives, Positives)); +end Test_B; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for some K", d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for some K", dT-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb new file mode 100644 index 000000000..d6abcb9ed --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Some_Pos ((-1, -2), (3, -8))); +end Test_T; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## eF-, d!:"S1(K) > 0", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## eF-, dT-:"S1(K) > 0", dF-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb new file mode 100644 index 000000000..7c3d2213c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function Some_Pos (S1, S2: Sequence) return Boolean is + begin + return (for some K in S1'Range => S1(K) > 0) or else (for some E of S2 => E > 0); -- # eval + end; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads new file mode 100644 index 000000000..e312fee2e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function Some_Pos (S1, S2: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb new file mode 100644 index 000000000..41d6ec0d8 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_A is +begin + Assert (All_Pos_And_Even ((2, 8))); + Assert (not All_Pos_And_Even ((28, 8, -14))); +end Test_A; + +--# values.adb +-- /eval/ l! ## c!:"X mod 2" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb new file mode 100644 index 000000000..b278b95f0 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_B is +begin + Assert (All_Pos_And_Even ((2, 8))); + Assert (not All_Pos_And_Even ((28, 8, 7))); +end Test_B; + +--# values.adb +-- /eval/ l! ## c!:"X > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb new file mode 100644 index 000000000..ecb6c87ae --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (All_Pos_And_Even ((2, 12, 28))); +end Test_T; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb new file mode 100644 index 000000000..f128ad9d9 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function All_Pos_And_Even (S1: Sequence) return Boolean is + begin + return (for all X of S1 => X > 0 and then X mod 2 = 0); -- # eval + end All_Pos_And_Even; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads new file mode 100644 index 000000000..ead7740bf --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function All_Pos_And_Even (S1: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb new file mode 100644 index 000000000..e83261122 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_A is +begin + Assert (not Some_Pos_Or_Even ((-1, -3, -7))); + Assert (Some_Pos_Or_Even ((-1, 5))); +end; + +--# values.adb +-- /eval/ l! ## c!:"S1(K) mod 2" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb new file mode 100644 index 000000000..d1176ebff --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_B is +begin + Assert (not Some_Pos_Or_Even ((-1, -3, -7))); + Assert (Some_Pos_Or_Even ((-1, -8))); +end Test_B; + +--# values.adb +-- /eval/ l! ## c!:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb new file mode 100644 index 000000000..5a6380b23 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Some_Pos_Or_Even ((2, 12, 28))); +end Test_T; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb new file mode 100644 index 000000000..f60ee3108 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function Some_Pos_Or_Even (S1: Sequence) return Boolean is + begin + return (for some K in S1'Range => S1(K) > 0 or else S1(K) mod 2 = 0); -- # eval + end Some_Pos_Or_Even; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads new file mode 100644 index 000000000..87af86b8e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads @@ -0,0 +1,4 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + function Some_Pos_Or_Even (S1: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb new file mode 100644 index 000000000..45421d8ce --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb @@ -0,0 +1,80 @@ +with Support; use Support; + +package body FUAND is + + function To_String (C : Coord) return String is + begin + return (1 .. 1 => Character'Val (48 - C)); + end; + + function Line (O : Object) return String is + begin + return To_String (O.X); + end; + + function Col (O : Object) return String is + begin + return To_String (O.Y); + end; + + -- + + type Red_Circle is new Object with null record; + + function Shape (O : Red_Circle) return String; + function Color (O : Red_Circle) return String; + + function Shape (O : Red_Circle) return String is + begin + return "circle"; + end; + + function Color (O : Red_Circle) return String is + begin + return "red"; + end; + + -- + + type Blue_Square is new Object with null record; + + function Shape (O : Blue_Square) return String; + function Color (O : Blue_Square) return String; + + function Shape (O : Blue_Square) return String is + begin + return "square"; + end; + + function Color (O : Blue_Square) return String is + begin + return "blue"; + end; + + -- + + procedure TEST_A is + A : Red_Circle := (X => 1, Y => 2); + B : Blue_Square := (X => 1, Y => 2); + begin + Assert (Fight (A, B)); -- T T + Assert (not Fight (A, A)); -- F T + end; + + procedure TEST_B is + A : Red_Circle := (X => 1, Y => 2); + B : Blue_Square := (X => 1, Y => 2); + C : Blue_Square := (X => 1, Y => 3); + begin + Assert (Fight (A, B)); -- T T + Assert (not Fight (A, C)); -- T F + end; + + procedure TEST_T is + A : Red_Circle := (X => 1, Y => 2); + B : Blue_Square := (X => 1, Y => 2); + begin + Assert (Fight (A, B)); + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads new file mode 100644 index 000000000..9ff0bee3f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads @@ -0,0 +1,23 @@ +pragma Ada_2012; + +package FUAND is + + type Coord is range 0 .. 9; + type Object is abstract tagged record + X, Y : Coord; + end record; + + function Shape (O : Object) return String is abstract; + function Color (O : Object) return String is abstract; + + function Line (O : Object) return String; + function Col (O : Object) return String; + + function Fight (A, B : Object'Class) return Boolean is + ((Color(A) & "-" & Shape(A)) /= (Color(B) & "-" & Shape(B)) and then (Line(A) & Col(A)) = (Line(B) & Col(B))); -- # eval + + procedure Test_A; + procedure Test_B; + procedure Test_T; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb new file mode 100644 index 000000000..3d087228c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb @@ -0,0 +1,14 @@ +with Fuand; + +procedure Test_FUAND_A is +begin + Fuand.Test_A; +end; + +--# fuand.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## c!:"Line(A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## c!:"(Line(A" diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb new file mode 100644 index 000000000..81c49b4cf --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb @@ -0,0 +1,14 @@ +with Fuand; + +procedure Test_FUAND_B is +begin + Fuand.Test_B; +end; + +--# fuand.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## c!:"Color(A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## c!:"(Color(A" diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb new file mode 100644 index 000000000..1d9bf96c3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb @@ -0,0 +1,9 @@ +with Fuand; + +procedure Test_FUAND_T is +begin + Fuand.Test_T; +end; + +--# fuand.ads +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb new file mode 100644 index 000000000..8ab828d99 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; + +package body Pkg.Simple is + + ------------- + -- Is_Null -- + ------------- + + function Is_Null (Self : Simple_Object) return Boolean is + begin + return False; + end Is_Null; + + --------------- + -- Get_Model -- + --------------- + + function Get_Model (Self : Simple_Object) return Model'Class is + Result : constant Model := (Not_Null => True); + begin + return Result; + end Get_Model; + +end Pkg.Simple; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads new file mode 100644 index 000000000..92ec2fa7c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Pkg.Simple is + type Simple_Object is new Object with private; + Singleton : constant Simple_Object; + function Is_Null (Self : Simple_Object) return Boolean; + function Get_Model (Self : Simple_Object) return Model'Class; +private + type Simple_Object is new Object with null record; + Singleton : constant Simple_Object := (null record); +end Pkg.Simple; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb new file mode 100644 index 000000000..e72ce33f3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb @@ -0,0 +1,22 @@ +package body Pkg is + + ----------- + -- Clone -- + ----------- + + function Clone (Self : Object'Class) return Object'Class + is + begin + return Self; -- # clone + end Clone; + + ------------- + -- Is_Null -- + ------------- + + function Is_Null (Self : Model'Class) return Boolean is + begin + return not Self.Not_Null; -- # is-null + end Is_Null; + +end Pkg; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads new file mode 100644 index 000000000..a3c451c58 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads @@ -0,0 +1,23 @@ +pragma Ada_2012; + +package Pkg is + + type Model is tagged private; + type Object is interface; + + function Is_Null (Self : Object) return Boolean is abstract; + function Clone (Self : Object'Class) return Object'Class with + Post => not Clone'Result.Get_Model.Is_Null; + function Get_Model (Self : Object) return Model'Class is abstract; + function Get_Id (Self : Object'Class) return Natural is + (if Self.Is_Null or else Self.Clone.Is_Null -- # get-id-cond + then 0 -- # get-id-then + else 1); -- # get-id-else + + function Is_Null (Self : Model'Class) return Boolean; + +private + type Model is tagged record + Not_Null : Boolean; + end record; +end Pkg; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb new file mode 100644 index 000000000..8d3a64c06 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb @@ -0,0 +1,21 @@ +with Pkg.Simple; use Pkg.Simple; + +procedure Test_No is +begin + if Singleton.Is_Null then + raise Program_Error; + end if; + + if Singleton.Get_Model.Is_Null then + raise Program_Error; + end if; +end Test_No; + +--# pkg.ads +-- /get-id-cond/ l- ## s- +-- /get-id-then/ l- ## 0 +-- /get-id-else/ l- ## 0 + +--# pkg.adb +-- /clone/ l- ## s- +-- /is-null/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt new file mode 100644 index 000000000..1f8985273 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test relies on advanced use of tagged types +RTS_LIGHT_TASKING DEAD Requires language features not available in the runtime diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads new file mode 100644 index 000000000..a1325e258 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Expr is + function F (A, B, C : Boolean) return Boolean is + ((A and then B) or else C); -- # eval +end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb new file mode 100644 index 000000000..b2a762343 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb @@ -0,0 +1,10 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Expr_A is +begin + Assert (F (False, True, False) = False); + Assert (F (True, True, False) = True); +end; + +--# expr.ads +-- /eval/ l! ## c!:"B",c!:"C" diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb new file mode 100644 index 000000000..5447fb4c3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb @@ -0,0 +1,10 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Expr_F is +begin + Assert (F (True, False, False) = False); + Assert (F (False, True, False) = False); +end; + +--# expr.ads +-- /eval/ l! ## eT- diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb new file mode 100644 index 000000000..caac52984 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb @@ -0,0 +1,11 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Expr_T is +begin + Assert (F (True, True, False) = True); + Assert (F (False, True, True) = True); + Assert (F (True, False, True) = True); +end; + +--# expr.ads +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/status.txt b/testsuite/tests/Ada2012/status.txt new file mode 100644 index 000000000..9cd74fee8 --- /dev/null +++ b/testsuite/tests/Ada2012/status.txt @@ -0,0 +1,114 @@ +Ada2012 specific items +====================== + +----------- +Pre aspects +----------- + +No code when deactivated. +Few tests otherwise. + +Pre aspect is considered as a control flow context, so applies to dc & single +op expressions as well. Is this what we want ? We don't do that for pragmas. + +----------- +Post aspects +------------ + +Tool processing-wise, current status is same as Pre. + +Turning a Post False is tough in real life though, so ... + +*Background discussion* + + * keep as regular decision for mcdc ? + + * claim nothing of interest at all ? + + * in-between: "contract" expression, always same value, + but operand variations required ? + +---------------------- +Type_Invariant aspects +---------------------- + +Invariant expressions considered as decisions but are not processed +correctly. Additional complexity is the lack of debug info in invariant +checking subprograms (N212-009) + +Needs definition work prior to implementation. + +---------------- +For E of +---------------- + +Works fine, as a regular for statement SC'wise. Few tests. + +---------- +X in 1|2|7 +---------- + +Works fine, considered as single operand (condition). Few tests. + +*Background discussion* + +Should this be seen as a implicit nested decision with three tests ? +Would complicate matters a lot and why not wonder the same about X < 0 ? + +-------------- +Expr functions +-------------- + +Work fine. Few tests. + +-------------- +If expressions +-------------- + +In deactivated Pre or Post, no code => no violation ever. Few tests. + +As of now, + +* the IF is seen as a control flow context + => controlling expression is decision even if simple. + +* THEN/ELSE are not seen as control flow context and + expressions treated as decisions if complex, for mcdc + +* inaccurate results on degraded origins for ctl expr (N227-030) + +*Background discussion* + +How do we want to deal with the functional programming aspects of Ada2012 ? +(N214-014) + +Introduce "expression" coverage, where subexpressions of if or case +expressions need to be evaluated at least once ? + + +------------------ +subtype predicates +------------------ + +To be evaluated. + +------------------ +in out to function +------------------ + +Works fine. Few tests checking that things "work" with stmts assignining +to In Out of function, stmt & mcdc. + +---------------- +Case expressions +---------------- + +To be evaluated. + +---------------------- +Quantified Expressions +---------------------- + +Work fine. ForAll and ForSome are both considered as conditions. +Complex expressions nested in the for-all/for-some predicate are +seen as decisions. diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb new file mode 100644 index 000000000..a6b3329ba --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb @@ -0,0 +1,14 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb new file mode 100644 index 000000000..13810fd28 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (others => (X => 5)); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E.X = 6); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb new file mode 100644 index 000000000..77d90022f --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb @@ -0,0 +1,14 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.GSA := (others => (X => 4)); + + Global.Do_Loop; + Assert (Global.GSA (1).X = 5); + Assert (Global.GSA (3).X = 5); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads new file mode 100644 index 000000000..228198706 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads @@ -0,0 +1,6 @@ +package Values.Global is + + GSA : Array_Type; + + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb new file mode 100644 index 000000000..84bf26181 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb @@ -0,0 +1,8 @@ +package body Values is + + procedure Touch (E : in out Object) is + begin + E.X := E.X + 1; + end; + +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads new file mode 100644 index 000000000..e1c95fc5c --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads @@ -0,0 +1,12 @@ + +package Values is + + type Object is tagged record + X : Integer; + end record; + + type Array_Type is array (1 .. 8) of Object; + + procedure Touch (E : in out Object); + +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb new file mode 100644 index 000000000..a6b3329ba --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb @@ -0,0 +1,14 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb new file mode 100644 index 000000000..62b5cd71b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (others => 1); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E = 2); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb new file mode 100644 index 000000000..4d63cb5da --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb @@ -0,0 +1,13 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.GSA := (1 .. 2 => 1, 3 .. 4 => 2); + Global.Do_Loop; + Assert (Global.GSA (2) = 2); + Assert (Global.GSA (4) = 4); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads new file mode 100644 index 000000000..097418586 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads @@ -0,0 +1,5 @@ + +package Values.Global is + GSA : Array_Type; + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb new file mode 100644 index 000000000..859ef8749 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb @@ -0,0 +1,6 @@ +package body Values is + procedure Touch (E : in out Num) is + begin + E := E * 2; + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads new file mode 100644 index 000000000..30c047deb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads @@ -0,0 +1,10 @@ + +package Values is + type Num is mod 2**8; + for Num'Size use 8; + + type Array_Type is array (1 .. 4) of Num; + pragma Pack (Array_Type); + + procedure Touch (E : in out Num); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb new file mode 100644 index 000000000..a6b3329ba --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb @@ -0,0 +1,14 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb new file mode 100644 index 000000000..1052ce376 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (others => 5); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E = 10); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb new file mode 100644 index 000000000..b21b00a41 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb @@ -0,0 +1,14 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.GSA := (1, 2, 3, 4, 5, 6, 7, 8); + + Global.Do_Loop; + Assert (Global.GSA (3) = 6); + Assert (Global.GSA (6) = 12); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads new file mode 100644 index 000000000..097418586 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads @@ -0,0 +1,5 @@ + +package Values.Global is + GSA : Array_Type; + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb new file mode 100644 index 000000000..799aa7ad6 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb @@ -0,0 +1,6 @@ +package body Values is + procedure Touch (E : in out Integer) is + begin + E := E * 2; + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads new file mode 100644 index 000000000..dec7883bf --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Array_Type is array (1 .. 8) of Integer; + + procedure Touch (E : in out Integer); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb new file mode 100644 index 000000000..a6b3329ba --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb @@ -0,0 +1,14 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb new file mode 100644 index 000000000..c9b734197 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (1 .. 12 => 5); + pragma Volatile (LA); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E = 10); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb new file mode 100644 index 000000000..5321d43ad --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb @@ -0,0 +1,11 @@ +with Values.Arg, Support; use Values, Support; + +procedure Test_Values_EMPTY is + LA : Array_Type (1 .. 0); +begin + Arg.Do_Loop_Over (LA); +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb new file mode 100644 index 000000000..e9f32129b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb @@ -0,0 +1,12 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.Do_Loop; + Assert (Global.GSA (3) = 2); + Assert (Global.GSA (6) = 4); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads new file mode 100644 index 000000000..eb2d3cf71 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads @@ -0,0 +1,5 @@ + +package Values.Global is + GSA : Array_Type := (1 .. 4 => 1, 5 .. 8 => 2); + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb new file mode 100644 index 000000000..799aa7ad6 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb @@ -0,0 +1,6 @@ +package body Values is + procedure Touch (E : in out Integer) is + begin + E := E * 2; + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads new file mode 100644 index 000000000..0a9672070 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Array_Type is array (Natural range <>) of Integer; + + procedure Touch (E : in out Integer); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb new file mode 100644 index 000000000..570b6c6da --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Values.ARG is + + procedure Do_Loop_Over (A : in out Array_Type) is + begin + for E of A loop -- # stmt + Touch (E); -- # loop_op + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads new file mode 100644 index 000000000..54924ee93 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads @@ -0,0 +1,4 @@ + +package Values.Arg is + procedure Do_Loop_Over (A : in out Array_Type); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb b/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb new file mode 100644 index 000000000..e0c003e8d --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Values.Global is + + procedure Do_Loop is + begin + for E of GSA loop -- # stmt + Touch (E); -- # loop_op + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/expr.adb b/testsuite/tests/Ada2012/stmt/InOut/src/expr.adb new file mode 100644 index 000000000..a2abf3451 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/expr.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package body Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer is + begin + if Pos then -- # test + Pos := X > 0 and then Y > 0; -- # eval + end if; + return X + Y; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/expr.ads b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ads new file mode 100644 index 000000000..4753272d7 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ads @@ -0,0 +1,5 @@ +pragma Ada_2012; + +package Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer; +end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/expr.ali b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ali new file mode 100644 index 000000000..c07658cc1 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ali @@ -0,0 +1,22 @@ +V "GNAT Lib v7.3" +A -mtune=generic +A -march=x86-64 +P ZX + +RN +RV NO_IMPLEMENTATION_PRAGMAS + +U expr%b expr.adb 9afba2dd NE OO PK + +U expr%s expr.ads a0cd5364 EE NE OO PK + +D expr.ads 20140214111047 a0cd5364 +D expr.adb 20140214111226 3a36f1b9 +D system.ads 20120706154652 90249111 +X 1 expr.ads +3K9*Expr 5e4 2|3b14 11t4 +4V13*Plus{integer} 4>19 4>22 4=35 2|4b13 10t7 +4i19 X{integer} 2|4b19 7r17 9r14 +4i22 Y{integer} 2|4b22 7r32 9r18 +4b35 Pos{boolean} 2|4b35 6r10 7m10 + diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb new file mode 100644 index 000000000..84e948c53 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_F is + Pos : Boolean := True; +begin + Assert (Plus (5, -6, Pos) = -1); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l+ ## 0 +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb new file mode 100644 index 000000000..9eb84a894 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_T is + Pos : Boolean := True; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = True); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l+ ## 0 +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb new file mode 100644 index 000000000..085633770 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Neval is + Pos : Boolean := False; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l+ ## 0 +-- /eval/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/InOut/test.py b/testsuite/tests/Ada2012/stmt/InOut/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb new file mode 100644 index 000000000..3e37d82cb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased R; -- # npc decl + begin + PR4 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads new file mode 100644 index 000000000..59232baad --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR4 (X : access R'Class) is null; -- # npb + + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb new file mode 100644 index 000000000..3bcdd3feb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased constant R := (null record); -- # npc decl + begin + PR5 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads new file mode 100644 index 000000000..52256bb2b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR5 (X : access constant R'Class) is null; -- # npb + + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb new file mode 100644 index 000000000..fd95d6af6 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased constant Integer := 1; -- # npc decl + begin + P4 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads new file mode 100644 index 000000000..34bf52b6c --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P4 (X : access constant Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb new file mode 100644 index 000000000..7c18d8e2e --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package body Pak is + + function Callback (S : access String) return Natural + is (S.all'Length); -- # npp + + procedure Call is + begin + P2 (Callback'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads new file mode 100644 index 000000000..f854906f1 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + procedure P2 + (X : access function (S : access String) return Natural) + is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb new file mode 100644 index 000000000..297735871 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased Integer; -- # npc decl + begin + P2 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads new file mode 100644 index 000000000..dfebd4298 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P2 (X : access Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb new file mode 100644 index 000000000..e0aee321e --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb @@ -0,0 +1,10 @@ +package body Pak is + + procedure Callback is null; -- # npp + + procedure Call is + begin + P2 (Callback'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads new file mode 100644 index 000000000..b0c9d9454 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P2 (X : access procedure) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb new file mode 100644 index 000000000..df8954e8b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb @@ -0,0 +1,11 @@ +package body Pak is + + procedure PPR2 (X : access PR) is null; -- # npb + + procedure Call is + X : aliased PR; -- # npc decl + begin + PPR2 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads new file mode 100644 index 000000000..58ad97f92 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Pak is + type R is abstract tagged limited null record; + type PR is new R with private; + procedure PPR2 (X : access PR); + + procedure Call; + +private + type PR is new R with null record; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb new file mode 100644 index 000000000..e75f02451 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased PR; -- # npc decl + begin + PPR1 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads new file mode 100644 index 000000000..ac550a515 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pak is + type R is abstract tagged limited null record; + type PR is new R with private; + procedure PPR1 (X : access PR); + + procedure Call; + +private + type PR is new R with null record; + procedure PPR1 (X : access PR) is null; -- # npb +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb new file mode 100644 index 000000000..75c660547 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased PR; -- # npc decl + begin + PPR0 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads new file mode 100644 index 000000000..f8a278a9c --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Pak is + type R is abstract tagged limited null record; + type PR is new R with private; + procedure PPR0 (X : access PR) is null; -- # npb + + procedure Call; + +private + type PR is new R with null record; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb new file mode 100644 index 000000000..e0762f1e4 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased R; -- # npc decl + begin + PR2 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads new file mode 100644 index 000000000..7cfe43bf7 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR2 (X : access R) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb new file mode 100644 index 000000000..f99ffc3bb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : R; -- # npc decl + begin + PR1 (X); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads new file mode 100644 index 000000000..577432a34 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR1 (X : R'Class) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb new file mode 100644 index 000000000..2dc9c754e --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb @@ -0,0 +1,8 @@ +package body Pak is + + procedure Call is + begin + P1 (4); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads new file mode 100644 index 000000000..0d9b467c2 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P1 (X : Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb new file mode 100644 index 000000000..e93aa2b62 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb @@ -0,0 +1,8 @@ +package body Pak is + + procedure Call is + begin + P0; -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads new file mode 100644 index 000000000..eef128b87 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P0 is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb new file mode 100644 index 000000000..315f900ef --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased Integer; -- # npc decl + begin + P3 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads new file mode 100644 index 000000000..2a3eabcdc --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P3 (X : not null access Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb new file mode 100644 index 000000000..db9b4d188 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased R; -- # npc decl + begin + PR3 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads new file mode 100644 index 000000000..c74d94855 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR3 (X : not null access R) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb new file mode 100644 index 000000000..185923d48 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : R; -- # npc decl + begin + PR0 (X); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads new file mode 100644 index 000000000..95facf357 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR0 (X : R) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb new file mode 100644 index 000000000..b0251fdfe --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb @@ -0,0 +1,18 @@ +with Pak; +procedure Test_Pak_Call is +begin + Pak.Call; +end Test_Pak_Call; + +--# pak.ads +-- /npc/ l+ ## 0 +-- /npp/ l- ## s- +-- /npb/ l+ ## 0 + +--# pak.adb +-- /npc/ l+ ## 0 +-- /npp/ l- ## s- +-- /npb/ l+ ## 0 +-- +--%opts: --trace-mode=bin %cargs:-O1 +-- =/npp/ l. ## 0 diff --git a/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb new file mode 100644 index 000000000..e2cb3a4ae --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb @@ -0,0 +1,18 @@ +with Pak; +procedure Test_Pak_No is +begin + null; +end Test_Pak_No; + +--# pak.ads +-- /npc/ l- ## s- +-- /npp/ l- ## s- +-- /npb/ l- ## s- + +--# pak.adb +-- /npc/ l- ## s- +-- /npp/ l- ## s- +-- /npb/ l- ## s- +-- +--%opts: --trace-mode=bin %cargs:-O1 +-- =/npp/ l. ## 0 diff --git a/testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads b/testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads new file mode 100644 index 000000000..735168bd2 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads @@ -0,0 +1,4 @@ +pragma Ada_2012; +package Expr is + function Plus (X, Y : Integer) return Integer is (X + Y); -- # stmt +end; diff --git a/testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb b/testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb new file mode 100644 index 000000000..662071ae5 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb @@ -0,0 +1,9 @@ +with Support, expr; use Support, Expr; + +procedure Test_0 is +begin + null; +end; + +--# expr.ads +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/Xfunctions/test.py b/testsuite/tests/Ada2012/stmt/Xfunctions/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/Xfunctions/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb new file mode 100644 index 000000000..dd9bfedd8 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +package body Pkg is + + function Absolute (Input : Int_Arr) return Int_Arr is + begin + if Input = [] then -- # empty_aggr_guard + return []; -- # empty_aggr_st + elsif Input'Length = 1 then -- # single_elt_guard + return -- # single_elt_st + [(declare Elt : Integer renames Input (Input'First); -- # single_elt_st + begin (if Elt > 0 then Elt else -Elt))]; -- # single_elt_dc + else + return [for Idx in Input'Range => -- # multi_elt_st + (declare Elt : Integer renames Input (Idx) ; -- # multi_elt_st + begin (if Elt > 0 then Elt else -Elt))]; -- # multi_elt_dc + end if; + end Absolute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads new file mode 100644 index 000000000..17b7dc446 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + type Int_Arr is array (Positive range <>) of Integer; + + function Absolute (Input : Int_Arr) return Int_Arr; + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb new file mode 100644 index 000000000..092bf29fb --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l- ## s- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb new file mode 100644 index 000000000..f9720cad3 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Empty is +begin + Assert (Absolute ([]) = []); +end Test_Empty; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dF- +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb new file mode 100644 index 000000000..4fb707887 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb @@ -0,0 +1,23 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Full is +begin + Assert (Absolute ([]) = []); + Assert (Absolute ([9]) = [9]); + Assert (Absolute ([-8]) = [8]); + Assert (Absolute ([-3, 2]) = [3, 2]); +end Test_Full; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l+ ## 0 +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l+ ## 0 +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc/ l+ ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb new file mode 100644 index 000000000..d775bd38e --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Multi is +begin + Assert (Absolute ([9, 4]) = [9, 4]); +end Test_Multi; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dT- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb new file mode 100644 index 000000000..ab3aade30 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Single is +begin + Assert (Absolute ([9]) = [9]); +end Test_Single; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dF- +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc/ l! ## dF- +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/tc.rst b/testsuite/tests/Ada2022/aggregates/arrays/tc.rst new file mode 100644 index 000000000..83cdb6db6 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/tc.rst @@ -0,0 +1,17 @@ +** DC for decisions nested in generalized array aggregates ** + +Check proper handling and decision coverage computing for decisions nested in +generalized array aggregates. Pkg implements a function presenting three forms +of generalized array aggregates, i.e. a positional empty aggregate, a single +element positional aggregate and a iterated component association aggregate. + +The test drivers are articulated as follows: + - Test_0 ensures only statement violations are reported when the + function is not called, + - Test_Empty ensures that decision coverage can be computed on a decision + containing an empty generalized array aggregate, + - Test_Single ensures that decisions nested within a single element positional + aggregate are correctly processed, + - Test_Multi ensures that decisions nested within iterated component + associations in a generalized array aggregate are properly processed. + - Test_Full ensures all the above can be covered simultaneously. diff --git a/testsuite/tests/Ada2022/aggregates/arrays/test.py b/testsuite/tests/Ada2022/aggregates/arrays/test.py new file mode 100644 index 000000000..10fe9c9a3 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/test.py @@ -0,0 +1,12 @@ +""" +Test correct support for generalized array aggregates, including iterated +component associations. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/check.adb b/testsuite/tests/Ada2022/aggregates/containers/src/check.adb new file mode 100644 index 000000000..149c78d62 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/check.adb @@ -0,0 +1,19 @@ +pragma Ada_2022; + +with Ada.Containers; use Ada.Containers; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Check (Input : Int_Set) is + use Int_Maps; + Res : constant Int_Map := Overly_Complex_Identity_Build (Input); +begin + Assert (Input.Length = Res.Length); + Assert ((for all Val of Input => + (declare Cur : constant Cursor := Res.Find (Val); + begin Has_Element (Cur) + and then Key (Cur) = Val + and then Element (Cur) = Val))); +end Check; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb new file mode 100644 index 000000000..dd2a70682 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb @@ -0,0 +1,27 @@ +pragma Ada_2022; + +with Ada.Containers; use Ada.Containers; + +package body Pkg is + + function Overly_Complex_Identity_Build (Input : Int_Set) return Int_Map is + use Int_Sets; + use Int_Maps; + begin + if Input = [] then -- # empty_aggr_guard + return []; -- # empty_aggr_st + elsif Input.Length = 1 then -- # single_elt_guard + declare + Elt : constant Integer := Input.First_Element; -- # single_elt_st + begin + return [(if Elt > 0 then Elt else Elt) => -- # single_elt_dc1 + (if Elt > 0 then Elt else Elt)]; -- # single_elt_dc2 + end; + else + return [for Elt of Input use -- # multi_elt_st + (if Elt > 0 then Elt else Elt) => -- # multi_elt_dc1 + (if Elt > 0 then Elt else Elt)]; -- # multi_elt_dc2 + end if; + end Overly_Complex_Identity_Build; + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads new file mode 100644 index 000000000..76532bfe6 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads @@ -0,0 +1,17 @@ +with Ada.Containers.Ordered_Maps; +with Ada.Containers.Ordered_Sets; + +package Pkg is + + package Int_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Integer, Element_Type => Integer); + subtype Int_Map is Int_Maps.Map; + + package Int_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Integer); + subtype Int_Set is Int_Sets.Set; + + function Overly_Complex_Identity_Build (Input : Int_Set) return Int_Map; + -- Build an identity map for the elements of Input + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb new file mode 100644 index 000000000..25b1472ad --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; +with Check; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l- ## s- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc1/ l- ## s- +-- /single_elt_dc2/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc1/ l- ## 0 +-- /multi_elt_dc2/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb new file mode 100644 index 000000000..37b96acfd --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Empty is + use Int_Sets; +begin + Check ([]); +end Test_Empty; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dF- +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc1/ l- ## s- +-- /single_elt_dc2/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc1/ l- ## 0 +-- /multi_elt_dc2/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb new file mode 100644 index 000000000..1b412544f --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb @@ -0,0 +1,25 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Full is + use Int_Sets; +begin + Check ([]); + Check ([9]); + Check ([-8]); + Check ([-3, 2]); +end Test_Full; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l+ ## 0 +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l+ ## 0 +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc1/ l+ ## 0 +-- /single_elt_dc2/ l+ ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc1/ l+ ## 0 +-- /multi_elt_dc2/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb new file mode 100644 index 000000000..51bc3837f --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Multi is + use Int_Sets; +begin + Check ([-3, 9]); +end Test_Multi; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dT- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc1/ l- ## s- +-- /single_elt_dc2/ l- ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc1/ l+ ## 0 +-- /multi_elt_dc2/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb new file mode 100644 index 000000000..d281efa3e --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Single is + use Int_Sets; +begin + Check ([9]); +end Test_Single; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dF- +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc1/ l! ## dF- +-- /single_elt_dc2/ l! ## dF- +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc1/ l- ## 0 +-- /multi_elt_dc2/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/tc.rst b/testsuite/tests/Ada2022/aggregates/containers/tc.rst new file mode 100644 index 000000000..8b904c6cc --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/tc.rst @@ -0,0 +1,17 @@ +** DC for decisions nested in container aggregates ** + +Check proper handling and decision coverage computing for decisions nested in +container aggregates. Pkg implements a function presenting three forms of +container aggregates, i.e. a positional empty aggregate, a single element +positional aggregate and a iterated component association aggregate. + +The test drivers are articulated as follows: + - Test_0 ensures only statement violations are reported when the + function is not called, + - Test_Empty ensures that decision coverage can be computed on a decision + containing an empty container aggregate, + - Test_Single ensures that decisions nested within a single element positional + aggregate are correctly processed, + - Test_Multi ensures that decisions nested within iterated component + associations in a container aggregate are properly processed. + - Test_Full ensures all the above can be covered simultaneously. diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt new file mode 100644 index 000000000..34e52284f --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -0,0 +1 @@ +!native DEAD Test instantiates containers diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.py b/testsuite/tests/Ada2022/aggregates/containers/test.py new file mode 100644 index 000000000..54724f7a9 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/test.py @@ -0,0 +1,12 @@ +""" +Test correct handling and instrumentation of container aggregates, and +decisions nested within. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/extra.opt b/testsuite/tests/Ada2022/declare_expr/extra.opt new file mode 100644 index 000000000..77e633e36 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/extra.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD tests propagate exceptions +RTS_LIGHT_TASKING DEAD Test propagates exceptions diff --git a/testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb b/testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb new file mode 100644 index 000000000..5ef26c5a5 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb @@ -0,0 +1,15 @@ +pragma Ada_2022; + +package body Pkg is + + function Compute (A, B, C, D , Stop : Boolean) return Boolean is + (declare -- # ret_stmt + AB_AT : constant Boolean := A and then B; -- # at + CD_OE : constant Boolean := C or else D; -- # oe + Did_Stop : constant Boolean := -- # stop_stmt + (if Stop then raise Dummy_Error else Stop); -- # raise_expr + F : Boolean renames B; -- # rename + begin -- # begin + AB_AT or else CD_OE); -- # eval + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py b/testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py new file mode 100644 index 000000000..6cfe237bb --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of declare expressions, +within an expression function. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb new file mode 100644 index 000000000..3c130fec7 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +package body Pkg is + + function Compute (A, B, C, D , Stop : Boolean) return Boolean is + Res : Boolean := A; -- # before + begin + if (declare -- # if_stmt + AB_AT : constant Boolean := A and then B; -- # at + CD_OE : constant Boolean := C or else D; -- # oe + Did_Stop : constant Boolean := -- # stop_stmt + (if Stop then raise Dummy_Error else Stop); -- # raise_expr + F : Boolean renames B; -- # rename + begin -- # begin + AB_AT or else CD_OE) -- # eval + then + Res := True; -- # after_expr + end if; + return Res; -- # after_expr + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb new file mode 100644 index 000000000..8a61d5869 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb @@ -0,0 +1,35 @@ +with Support; +with Pkg; + +procedure Test_Pkg_R is + Res : Boolean; +begin + Res := Pkg.Compute + (A => False, + B => False, + C => False, + D => False, + Stop => True); + Support.Assert (False); +exception + when Pkg.Dummy_Error => + null; +end Test_Pkg_R; + +-- These test expectations are specialized for this particular test, as the +-- enclosing statement for the declare contains a decision and thus different +-- expectations are required. + +--# pkg.adb +-- +-- /before/ l+ ## 0 +-- /if_stmt/ l! ## d- +-- /declare/ l! ## 0 +-- /at/ l! ## eT- +-- /oe/ l! ## eT- +-- /stop_stmt/ l! ## 0 +-- /raise_expr/ l! ## dF- +-- /rename/ l! ## s- +-- /begin/ l! ## 0 +-- /eval/ l! ## e- +-- /after/ l- ## s- diff --git a/testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py new file mode 100644 index 000000000..0841a6a9a --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of declare expressions, +within an if statement, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb b/testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb new file mode 100644 index 000000000..4e11e02ec --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Pkg is + + function Compute (A, B, C, D , Stop : Boolean) return Boolean is + begin + return -- # ret_stmt + (declare -- # declare + AB_AT : constant Boolean := A and then B; -- # at + CD_OE : constant Boolean := C or else D; -- # oe + Did_Stop : constant Boolean := -- # stop_stmt + (if Stop then raise Dummy_Error else Stop); -- # raise_expr + F : Boolean renames B; -- # rename + begin -- # begin + AB_AT or else CD_OE); -- # eval + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/in_ret/test.py b/testsuite/tests/Ada2022/declare_expr/in_ret/test.py new file mode 100644 index 000000000..4965f0a21 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_ret/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of declare expressions, in a +simple statement. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/src/pkg.ads b/testsuite/tests/Ada2022/declare_expr/src/pkg.ads new file mode 100644 index 000000000..dba1e78c0 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + Dummy_Error : Exception; + + function Compute (A, B, C, D, Stop : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb new file mode 100644 index 000000000..6261ee04c --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb @@ -0,0 +1,22 @@ +with Support; +with Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /before/ l- ## s- +-- /ret_stmt/ l- ## s- +-- /if_stmt/ l- ## s- +-- /declare/ l- ## 0 +-- /at/ l- ## s- +-- /oe/ l- ## s- +-- /stop_stmt/ l- ## s- +-- /raise_expr/ l- ## 0 +-- /rename/ l- ## s- +-- /begin/ l- ## 0 +-- /eval/ l- ## 0 +-- /after/ l- ## s- diff --git a/testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb new file mode 100644 index 000000000..f195643de --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb @@ -0,0 +1,50 @@ +with Support; +with Pkg; + +procedure Test_Pkg_F is + Res : Boolean; +begin + Res := Pkg.Compute + (A => True, + B => False, + C => False, + D => False, + Stop => False); + Res := Pkg.Compute + (A => True, + B => True, + C => True, + D => False, + Stop => False); + Res := Pkg.Compute + (A => False, + B => True, + C => False, + D => True, + Stop => False); + Res := Pkg.Compute + (A => False, + B => False, + C => False, + D => False, + Stop => True); + Support.Assert (False); +exception + when Pkg.Dummy_Error => + null; +end Test_Pkg_F; + +--# pkg.adb +-- +-- /before/ l+ ## 0 +-- /ret_stmt/ l+ ## 0 +-- /if_stmt/ l+ ## 0 +-- /declare/ l+ ## 0 +-- /at/ l+ ## 0 +-- /oe/ l+ ## 0 +-- /stop_stmt/ l+ ## 0 +-- /raise_expr/ l+ ## 0 +-- /rename/ l+ ## 0 +-- /begin/ l+ ## 0 +-- /eval/ l+ ## 0 +-- /after/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb new file mode 100644 index 000000000..b192d052e --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb @@ -0,0 +1,36 @@ +with Support; +with Pkg; + +procedure Test_Pkg_R is + Res : Boolean; +begin + Res := Pkg.Compute + (A => False, + B => False, + C => False, + D => False, + Stop => True); + Support.Assert (False); +exception + when Pkg.Dummy_Error => + null; +end Test_Pkg_R; + +-- These test expectations are not applicable for the "in_if_stmt" test, as in +-- this test the enclosing statement for the declare contains a decision and +-- thus require different expectations. + +--# pkg.adb +-- +-- /before/ l+ ## 0 +-- /ret_stmt/ l+ ## 0 +-- /if_stmt/ l! ## d- +-- /declare/ l+ ## 0 +-- /at/ l! ## eT- +-- /oe/ l! ## eT- +-- /stop_stmt/ l+ ## 0 +-- /raise_expr/ l! ## dF- +-- /rename/ l! ## s- +-- /begin/ l+ ## 0 +-- /eval/ l! ## e- +-- /after/ l- ## s- diff --git a/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb new file mode 100644 index 000000000..6acf27889 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +package body Pkg is + + -------------------------- + -- Copy_With_Abs_Update -- + -------------------------- + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite + is + Elem : integer renames -- # st + Input (if Item = First then 1 else 2); -- # comp_expr + begin + return -- # st + [(if Use_Cache then Cached_Comp else Input) with delta -- # base_expr_first + (if Item = First then 1 else 2) => -- # comp_expr + (if Elem >= 0 then Elem else -Elem)]; -- # value_expr_first + end Copy_With_Abs_Update; +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads new file mode 100644 index 000000000..c149b8ec6 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads @@ -0,0 +1,40 @@ +pragma Ada_2012; + +package Pkg is + + type Item_Type is (First, Last); + + type Composite is private; + + Cached_Comp : constant Composite; + + function Make (First, Last : Integer) return Composite; + + function Eq (Comp : Composite; First, Last : Integer) return Boolean; + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite; + -- Return a copy of Input or Cached_Comp depending on the value of + -- Use_Cache, with either the "First" or "Last" component being updated to + -- its absolute value. +private + type Composite is array (1 .. 2) of Integer; + + Cached_Comp : constant Composite := (0, 0); + + ---------- + -- Make -- + ---------- + + function Make (First, Last : Integer) return Composite is ((First, Last)); + + -------- + -- Eq -- + -------- + + function Eq (Comp : Composite; First, Last : Integer) return Boolean is + (Comp (1) = First and then Comp (2) = Last); + +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/array/test.py b/testsuite/tests/Ada2022/delta_aggr/array/test.py new file mode 100644 index 000000000..8a18bd4d2 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/array/test.py @@ -0,0 +1,11 @@ +""" +Test the correct handling and instrumentation of array delta aggregates +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb new file mode 100644 index 000000000..570270d4e --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb @@ -0,0 +1,30 @@ +pragma Ada_2022; + +package body Pkg is + + -------------------------- + -- Copy_With_Abs_Update -- + -------------------------- + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite + is + Elem : constant integer := -- # st + (if Item = First then Input.First else Input.Last); -- # comp_expr + begin + -- We can't dynamically condition which component is used in a record + -- delta aggregate, so in order to emulate the behavior we need to + -- resort to two separate aggregates. This duplicates some decisions, + -- only one will be covered by the driver meant to exercise the + -- specific part of the aggregate. + + return -- # st + ((if Item = First -- # comp_expr + then ((if Use_Cache then Cached_Comp else Input) with delta -- # base_expr_first + First => (if Elem >= 0 then Elem else -Elem)) -- # value_expr_first + else ((if Use_Cache then Cached_Comp else Input) with delta -- # base_expr_last + Last => (if Elem >= 0 then Elem else -Elem)))); -- # value_expr_last + end Copy_With_Abs_Update; +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads new file mode 100644 index 000000000..38b60f16a --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads @@ -0,0 +1,43 @@ +pragma Ada_2012; + +package Pkg is + + type Item_Type is (First, Last); + + type Composite is private; + + Cached_Comp : constant Composite; + + function Make (First, Last : Integer) return Composite; + + function Eq (Comp : Composite; First, Last : Integer) return Boolean; + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite; + -- Return a copy of Input or Cached_Comp depending on the value of + -- Use_Cache, with either the "First" or "Last" component being updated to + -- its absolute value. +private + type Composite is record + First : Integer; + Last : Integer; + end record; + + Cached_Comp : constant Composite := (0, 0); + + ---------- + -- Make -- + ---------- + + function Make (First, Last : Integer) return Composite is ((First, Last)); + + -------- + -- Eq -- + -------- + + function Eq (Comp : Composite; First, Last : Integer) return Boolean is + (Comp.First = First and then Comp.Last = Last); + +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/record/test.py b/testsuite/tests/Ada2022/delta_aggr/record/test.py new file mode 100644 index 000000000..461f85bfb --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/record/test.py @@ -0,0 +1,11 @@ +""" +Test the correct handling and instrumentation of record delta aggregates +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb new file mode 100644 index 000000000..4d2bbca3c --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb @@ -0,0 +1,13 @@ +with Pkg; use Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /st/ l- ## s- +-- /base_expr/ l- ## 0 +-- /comp_expr/ l- ## 0 +-- /value_expr/ l- ## 0 diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb new file mode 100644 index 000000000..4781ded38 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Base is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, True), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); +end Test_Pkg_Base; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr_last/ l! ## d- +-- /base_expr_first/ l+ ## 0 +-- /comp_expr/ l! ## dF- +-- /value_expr_last/ l! ## d- +-- /value_expr_first/ l! ## dF- diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb new file mode 100644 index 000000000..d99fd7fd0 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb @@ -0,0 +1,17 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Comp is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, False), 0, 0)); +end Test_Pkg_Comp; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr/ l! ## dT- +-- /comp_expr/ l+ ## 0 +-- /value_expr/ l! ## dF- diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb new file mode 100644 index 000000000..9efe82a1c --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb @@ -0,0 +1,24 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Full is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, True), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, True), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, False), 0, 0)); + Comp := Make (-1, 0); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 1, 0)); + Comp := Make (0, -1); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, False), 0, 1)); + +end Test_Pkg_Full; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr/ l+ ## 0 +-- /comp_expr/ l+ ## 0 +-- /value_expr/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb new file mode 100644 index 000000000..228f1fe4e --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb @@ -0,0 +1,20 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Value is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); + Comp := Make (-1, 0); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 1, 0)); +end Test_Pkg_Value; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr_last/ l! ## d- +-- /base_expr_first/ l! ## dT- +-- /comp_expr/ l! ## dF- +-- /value_expr_last/ l! ## d- +-- /value_expr_first/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/delta_aggr/tc_set.rst b/testsuite/tests/Ada2022/delta_aggr/tc_set.rst new file mode 100644 index 000000000..ededabf8b --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/tc_set.rst @@ -0,0 +1,18 @@ +DC on various decisions nested in delta aggregates +================================================== + +Exercise decision coverage on decisions nested within both array and record +delta aggregates. Check for correct handling of nested decisions within the +base expression, in the index expression as well as in the component value +expression. The tests are organized such that each test exercises all three +possible decisions in a delta aggregate for the construct corresponding to the +test directory name. + +The Test_Pkg_0 driver tests ensures only SC violations are reported when the +code in the unit of interest is not executed, Test_Pkg_Base verifies proper DC +of decisions present in the base expression of the delta aggregate, +Test_Pkg_Comp ensures proper DC computation for decisions nested in the +component index expression of the delta aggregate, Test_Pkg_Value ensures that +decisions within the component value expression are properly processed, and +Test_Pkg_Full demonstrates decision coverage being exercised for all three +possible nested decisions at the same time. diff --git a/testsuite/tests/Ada2022/extra.opt b/testsuite/tests/Ada2022/extra.opt new file mode 100644 index 000000000..087421040 --- /dev/null +++ b/testsuite/tests/Ada2022/extra.opt @@ -0,0 +1,3 @@ +7.1.2 DEAD Ada 2022 not supported on old toolchains +5.04a1 DEAD Ada 2022 not supported on old toolchains +bin-traces DEAD Ada 2022 not supported on bin traces diff --git a/testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb b/testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb new file mode 100644 index 000000000..65b5b3492 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Pkg is + + function Non_Zero_Mult (Arr : Arr_T) return Integer is + Res : Integer := 1; -- # other_stmt + Filtered_Arr : Arr_T := -- # other_stmt + [for Element of Arr -- # other_cont + when Element < 0 or else Element > 0 -- # filter + => Element]; -- # other_cont + begin + for Element of Filtered_Arr loop -- # other_stmt + Res := Res * Element; -- # loop_body + end loop; + return Res; -- # other_stmt + end Non_Zero_Mult; + +end Pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/array_aggr/test.py b/testsuite/tests/Ada2022/iter_filter/array_aggr/test.py new file mode 100644 index 000000000..ede968ea4 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/array_aggr/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within an array aggregate. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb b/testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb new file mode 100644 index 000000000..ad2f2fcf8 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb @@ -0,0 +1,24 @@ +pragma Ada_2022; + +with Ada.Containers.Ordered_Sets; + +package body Pkg is + + package Int_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Integer); + subtype Set is Int_Sets.Set; + + function Non_Zero_Mult (Arr : Arr_T) return Integer is + Res : Integer := 1; -- # other_stmt + Filtered_Set : Set := -- # other_stmt + [for Element of Arr -- # other_cont + when Element < 0 or else Element > 0 -- # filter + => Element]; -- # other_cont + begin + for Element of Filtered_Set loop -- # other_stmt + Res := Res * Element; -- # loop_body + end loop; + return Res; -- # other_stmt + end Non_Zero_Mult; + +end Pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt new file mode 100644 index 000000000..e1d9057fb --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD Test uses Ada.Containers, not available in that profile diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py new file mode 100644 index 000000000..ef7b2f4be --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within a container aggregate. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb b/testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb new file mode 100644 index 000000000..750c18f2c --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb @@ -0,0 +1,16 @@ +pragma Ada_2022; + +package body Pkg is + + function Non_Zero_Mult (Arr : Arr_T) return Integer is + Res : Integer := 1; -- # other_stmt + begin + for Element of Arr -- # other_stmt + when Element < 0 or else Element > 0 -- # filter + loop + Res := Res * Element; -- # loop_body + end loop; + return Res; -- # other_stmt + end Non_Zero_Mult; + +end Pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/for_loop/test.py b/testsuite/tests/Ada2022/iter_filter/for_loop/test.py new file mode 100644 index 000000000..3a5aca4a9 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/for_loop/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within a for-loop specification. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads new file mode 100644 index 000000000..24e0eb21e --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package Foo is + + type Arr_T is array (Positive range <>) of Integer; + + function All_Naturals_Are_Non_Zero (Arr : Arr_T) return Boolean is + (for all Element of Arr -- # stmt + when Element >= 0 -- # filter + => Element /= 0); -- # pred + +end Foo; diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb new file mode 100644 index 000000000..3dce55cf0 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb @@ -0,0 +1,13 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_0 is +begin + null; +end Test_0; + +--# foo.ads +-- +-- /stmt/ l- ## s- +-- /filter/ l- ## 0 +-- /pred/ l- ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb new file mode 100644 index 000000000..22ad3b942 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb @@ -0,0 +1,16 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_F_X is + Arr : constant Arr_T := (-1, -2, -3); +begin + -- A for all with no element passing the filter is True + + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_F_X; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l! ## dT- +-- /pred/ l! ## d- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb new file mode 100644 index 000000000..e93155c0f --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_Full is + Arr : constant Arr_T := (1, -2, 3, 0, 9); +begin + Assert (not All_Naturals_Are_Non_Zero (Arr)); +end Test_Full; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /pred/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb new file mode 100644 index 000000000..ee975106b --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_T_T is + Arr : constant Arr_T := (1, 2, 3); +begin + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_T_T; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l! ## dF- +-- /pred/ l! ## dF- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb new file mode 100644 index 000000000..0a8421722 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_TF_F is + Arr : constant Arr_T := (-1, -2, 0); +begin + Assert (not All_Naturals_Are_Non_Zero (Arr)); +end Test_TF_F; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /pred/ l! ## dT- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb new file mode 100644 index 000000000..34ca27a5c --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_TF_T is + Arr : constant Arr_T := (1, -2, 3); +begin + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_TF_T; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /pred/ l! ## dF- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb new file mode 100644 index 000000000..f8b0fcc06 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb @@ -0,0 +1,16 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_X_X is + Arr : constant Arr_T := (1 .. 0 => 0); +begin + -- A for all with not elements is True + + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_X_X; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l! ## d- +-- /pred/ l! ## d- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/test.py b/testsuite/tests/Ada2022/iter_filter/quant_expr/test.py new file mode 100644 index 000000000..c8f8356e4 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/test.py @@ -0,0 +1,15 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within a quantified expression. + +The naming convention of the test drivers is +test__.adb +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/src/pkg.ads b/testsuite/tests/Ada2022/iter_filter/src/pkg.ads new file mode 100644 index 000000000..0d336a916 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/pkg.ads @@ -0,0 +1,8 @@ +package pkg is + + type Arr_T is array (Positive range <>) of Integer; + + function Non_Zero_Mult (Arr : Arr_T) return Integer; + -- Returns the product of all the non-zero elements in Arr + +end pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb new file mode 100644 index 000000000..111b8ad78 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb @@ -0,0 +1,15 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /filter/ l- ## 0 +-- /loop_body/ l- ## s- +-- /other_stmt/ l- ## s- +-- /other_cont/ l- ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb new file mode 100644 index 000000000..131699ab9 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_P is + Input_Arr : Arr_T := (1 => 1); +begin + Assert (Non_Zero_Mult (Input_Arr) = 1); +end Test_Pkg_P; + +--# pkg.adb +-- +-- /filter/ l! ## dF- +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb new file mode 100644 index 000000000..e6557535b --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_Z is + Input_Arr : Arr_T := (1 => 0); +begin + Assert (Non_Zero_Mult (Input_Arr) = 1); +end Test_Pkg_Z; + +--# pkg.adb +-- +-- /filter/ l! ## dT- +-- /loop_body/ l- ## s- +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb new file mode 100644 index 000000000..b1994c2fe --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_ZN is + Input_Arr : Arr_T := (0, -1); +begin + Assert (Non_Zero_Mult (Input_Arr) = -1); +end Test_Pkg_ZN; + +--# pkg.adb +-- +-- /filter/ l! ## c!:"Element > 0" +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb new file mode 100644 index 000000000..440f47d7c --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_ZP is + Input_Arr : Arr_T := (0, 1); +begin + Assert (Non_Zero_Mult (Input_Arr) = 1); +end Test_Pkg_ZP; + +--# pkg.adb +-- +-- /filter/ l! ## c!:"Element < 0" +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb new file mode 100644 index 000000000..573029470 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_ZPN is + Input_Arr : Arr_T := (0, 1, -1); +begin + Assert (Non_Zero_Mult (Input_Arr) = -1); +end Test_Pkg_ZPN; + +--# pkg.adb +-- +-- /filter/ l+ ## 0 +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb new file mode 100644 index 000000000..349ad50c9 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb @@ -0,0 +1,9 @@ +pragma Ada_2022; + +procedure Foo (B, C : Boolean) is + A : Boolean := B; -- # stmt +begin + A := @; -- # stmt + A := (if @ then @ else @) ; -- # dec + A := (if @ or else C then @ else @); -- # mcdc +end Foo; diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb new file mode 100644 index 000000000..1ce9b62c3 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb @@ -0,0 +1,10 @@ +procedure Test_0 is +begin + null; +end Test_0; + +--# foo.adb +-- +-- /stmt/ l- ## s- +-- /dec/ l- ## s- +-- /mcdc/ l- ## s- diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb new file mode 100644 index 000000000..887345df1 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb @@ -0,0 +1,14 @@ +with Foo; + +procedure Test_Full is +begin + Foo (False, False); + Foo (True, False); + Foo (False, True); +end Test_Full; + +--# foo.adb +-- +-- /stmt/ l+ ## 0 +-- /dec/ l+ ## 0 +-- /mcdc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb new file mode 100644 index 000000000..293f6fea6 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb @@ -0,0 +1,13 @@ +with Foo; + +procedure Test_Part is +begin + Foo (False, False); + Foo (True, False); +end Test_Part; + +--# foo.adb +-- +-- /stmt/ l+ ## 0 +-- /dec/ l+ ## 0 +-- /mcdc/ l! ## c! diff --git a/testsuite/tests/Ada2022/lhs-shortcut/test.py b/testsuite/tests/Ada2022/lhs-shortcut/test.py new file mode 100644 index 000000000..81234afa2 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/test.py @@ -0,0 +1,17 @@ +""" +Test correct support for @, the LHS reference shortcut: + - It is correctly instrumented when it is in an expression operand of an + initialization statement, without control flow. + - It is correctly instrumented when featured as the decision of an if + expression. + - It is correctly instrumented when featured as a boolean operand of an if + expression. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/extra.opt b/testsuite/tests/Ada2022/raise_expr/extra.opt new file mode 100644 index 000000000..e414c7dda --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/extra.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Tests propagate exceptions +RTS_LIGHT_TASKING DEAD Tests propagate exceptions diff --git a/testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb b/testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb new file mode 100644 index 000000000..98fe3f0aa --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package body Pkg is + + -- Note: the lone parenthesis is used here to dissociate the statement from + -- the decision in the coverage reports. It is not a formatting glitch. + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean is + ( -- # stmt + (not Do_Raise or else raise Custom_Error) and then A); -- # expr :o/e: + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py b/testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py new file mode 100644 index 000000000..bce78cfc0 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of raise expressions, +within a return statement, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb new file mode 100644 index 000000000..54f79c1c6 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb @@ -0,0 +1,16 @@ +pragma Ada_2022; + +package body Pkg is + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean is + begin + if -- # stmt + (not Do_Raise or else raise Custom_Error) and then A -- # expr :o/d: + then + return True; -- # ret_true + else + return False; -- # ret_false + end if; + end Identity; + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py new file mode 100644 index 000000000..aa836cd69 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of raise expressions, +within an expression function, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb new file mode 100644 index 000000000..e7111ceaa --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Pkg is + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean is + begin + return -- # stmt + (not Do_Raise or else raise Custom_Error) and then A; -- # expr :o/e: + end Identity; + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py new file mode 100644 index 000000000..bce78cfc0 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of raise expressions, +within a return statement, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/src/pkg.ads b/testsuite/tests/Ada2022/raise_expr/src/pkg.ads new file mode 100644 index 000000000..c82a842a3 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/pkg.ads @@ -0,0 +1,9 @@ +package Pkg is + + Custom_Error : Exception; + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean; + -- Returns the value of A if Do_Raise is False, raises Custom_Error + -- otherwise. + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb new file mode 100644 index 000000000..523a532f7 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb @@ -0,0 +1,14 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /stmt/ l- ## s- +-- /expr/ l- ## 0 +-- /ret/ l- ## s- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb new file mode 100644 index 000000000..cb7f9a361 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb @@ -0,0 +1,15 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_F is +begin + Support.Assert (not Identity (A => False, Do_Raise => False)); +end Test_Pkg_F; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## oT- +-- /ret_false/ l+ ## 0 +-- /ret_true/ l- ## s- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb new file mode 100644 index 000000000..4fedea6ba --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb @@ -0,0 +1,18 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_Raise is +begin + Support.Assert (Identity (A => True, Do_Raise => True)); +exception + when Custom_Error => + null; +end Test_Pkg_Raise; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## o- +-- /ret_false/ l- ## s- +-- /ret_true/ l- ## s- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb new file mode 100644 index 000000000..aa006f7a9 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb @@ -0,0 +1,15 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_T is +begin + Support.Assert (Identity (A => True, Do_Raise => False)); +end Test_Pkg_T; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## oF- +-- /ret_false/ l- ## s- +-- /ret_true/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb new file mode 100644 index 000000000..838d01cbe --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_TF is +begin + Support.Assert (Identity (A => True, Do_Raise => False)); + Support.Assert (not Identity (A => False, Do_Raise => False)); +end Test_Pkg_TF; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## c!:"Do_Raise", c!:"raise Custom_Error" +-- /ret_false/ l+ ## 0 +-- /ret_true/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb new file mode 100644 index 000000000..14a17643d --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb @@ -0,0 +1,25 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_TFR is +begin + Support.Assert (Identity (A => True, Do_Raise => False)); + Support.Assert (not Identity (A => False, Do_Raise => False)); + Support.Assert (not Identity (A => True, Do_Raise => True)); +exception + when Custom_Error => + null; +end Test_Pkg_TFR; + +-- This specific test shows that, despite having a T/F pair for Do_Raise, the +-- raise expression evaluation prevents the last evaluation of the decision +-- from completing and thus we can't find a pair to show the independent +-- influence of Do_Raise. + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## c!:"Do_Raise", c!:"raise Custom_Error" +-- /ret_false/ l+ ## 0 +-- /ret_true/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb new file mode 100644 index 000000000..086f373fd --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb @@ -0,0 +1,25 @@ +pragma Ada_2022; + +package body Pkg is + + ------------- + -- Compute -- + ------------- + + function Compute (Inp : Arr_T; Op : Op_T) return Integer is + function Reducer (Accum : Integer; Value : Integer) return Integer; + + ------------- + -- Reducer -- + ------------- + + function Reducer (Accum : Integer; Value : Integer) return Integer is + (if Op = Sum -- # reducer_main + then Accum + Value -- # reducer_cont + else Integer'Max (Accum, Value)); -- # reducer_cont + begin + return Inp'Reduce -- # reduce_st + (Reducer, (if Op = Sum then 0 else Integer'First)); -- # reduce_dc + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads new file mode 100644 index 000000000..09c18584c --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads @@ -0,0 +1,11 @@ +package Pkg is + + type Arr_T is array (Positive range <>) of Integer; + + type Op_T is (Sum, Max); + + function Compute (Inp : Arr_T; Op : Op_T) return Integer; + -- Compute either the sum or the maximum of the Element in Inp based on the + -- value of Op. + +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb new file mode 100644 index 000000000..5d61a4327 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb @@ -0,0 +1,13 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_st/ l- ## s- +-- /reduce_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb new file mode 100644 index 000000000..cffc279da --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1 .. 0 => 0); +begin + Assert (Compute (Inp, Sum) = 0); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb new file mode 100644 index 000000000..5925f3eb5 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Full is + Inp : Arr_T := [for I in 1 .. 3 => I]; +begin + Assert (Compute (Inp, Sum) / 2 = Compute (Inp, Max)); +end Test_Full; + +--# pkg.adb +-- +-- /reducer_main/ l+ ## 0 +-- /reducer_cont/ l+ ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb new file mode 100644 index 000000000..06711a1d0 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Max is + Inp : Arr_T := (1, 3, 2, 5, 4); +begin + Assert (Compute (Inp, Max) = 5); +end Test_Max; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dT- +-- /reducer_cont/ l+ ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l! ## dT- diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb new file mode 100644 index 000000000..029665404 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Sum is + Inp : Arr_T := (1, 3, 2, 5, 4); +begin + Assert (Compute (Inp, Sum) = 15); +end Test_Sum; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dF- +-- /reducer_cont/ l+ ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/test.py b/testsuite/tests/Ada2022/reduce_attr/shorthand/test.py new file mode 100644 index 000000000..ae9947b1d --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/test.py @@ -0,0 +1,12 @@ +""" +Check that gnatcov correctly processes sources containing reduce attributes, in +their shorthand form (no value sequence), and that nested decisions in the +initial value are correctly instrumented. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb new file mode 100644 index 000000000..5c45d1d54 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb @@ -0,0 +1,27 @@ +pragma Ada_2022; + +package body Pkg is + + ------------- + -- Compute -- + ------------- + + function Compute (Inp : Arr_T; Op : Op_T) return Integer is + function Reducer (Accum : Integer; Value : Integer) return Integer; + + ------------- + -- Reducer -- + ------------- + + function Reducer (Accum : Integer; Value : Integer) return Integer is + (if Op = Sum -- # reducer_main + then Accum + Value -- # reducer_cont + else Accum * Value); -- # reducer_cont + begin + return [for Elt of Inp -- # reduce_stmt + when Elt /= 0 => -- # filter + (if Op = Sum then Elt else abs Elt)]'Reduce -- # map + (Reducer, (if Op = Sum then 0 else 1)); -- # reduce_dc + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads new file mode 100644 index 000000000..3f839aa2b --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads @@ -0,0 +1,11 @@ +package Pkg is + + type Arr_T is array (Positive range <>) of Integer; + + type Op_T is (Sum, Abs_Mult); + + function Compute (Inp : Arr_T; Op : Op_T) return Integer; + -- If Op is Sum, return the sum of the elements in Inp. otherwise, if Op + -- is Abs_Mult, return the product of the absolute value of the non-zero + -- elements in Inp. +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb new file mode 100644 index 000000000..cd52a87b5 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb @@ -0,0 +1,15 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_stmt/ l- ## s- +-- /filter/ l- ## 0 +-- /map/ l- ## 0 +-- /reduce_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb new file mode 100644 index 000000000..4d31520cb --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1 .. 0 => 0); +begin + Assert (Compute (Inp, Sum) = 0); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l! ## d- +-- /map/ l! ## d- +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb new file mode 100644 index 000000000..d78f6a7c3 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Full is + Inp : Arr_T := (1, 2, 0, 3); +begin + Assert (Compute (Inp, Sum) = Compute (Inp, Abs_Mult)); +end Test_Full; + +--# pkg.adb +-- +-- /reducer_main/ l+ ## 0 +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /map/ l+ ## 0 +-- /reduce_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb new file mode 100644 index 000000000..f22a70b4c --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Mult is + Inp : Arr_T := (1, 2, 3); +begin + Assert (Compute (Inp, Abs_Mult) = 6); +end Test_Mult; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dT- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l! ## dF- +-- /map/ l! ## dT- +-- /reduce_dc/ l! ## dT- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb new file mode 100644 index 000000000..3c55f7256 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Mult_Z is + Inp : Arr_T := (1, 2, 0, 3); +begin + Assert (Compute (Inp, Abs_Mult) = 6); +end Test_Mult_Z; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dT- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /map/ l! ## dT- +-- /reduce_dc/ l! ## dT- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb new file mode 100644 index 000000000..4e1cb1568 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Sum is + Inp : Arr_T := (1, 2, 3); +begin + Assert (Compute (Inp, Sum) = 6); +end Test_Sum; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dF- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l! ## dF- +-- /map/ l! ## dF- +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb new file mode 100644 index 000000000..08ae83054 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Sum_Z is + Inp : Arr_T := (1, 2, 0, 3); +begin + Assert (Compute (Inp, Sum) = 6); +end Test_Sum_Z; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dF- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /map/ l! ## dF- +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/test.py b/testsuite/tests/Ada2022/reduce_attr/value_seq/test.py new file mode 100644 index 000000000..4d9959a5c --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/test.py @@ -0,0 +1,12 @@ +""" +Test checking that gnatcov correctly processes sources containing reduce +attributes, with a value sequence prefix, and that decisions withing the value +sequence are correctly instrumented. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb new file mode 100644 index 000000000..bc92010dc --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb @@ -0,0 +1,6 @@ +pragma Ada_2022; + +function Gen_Ident (X : T) return T is +begin + return X; -- # ret +end Gen_Ident; diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads new file mode 100644 index 000000000..76228558a --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads @@ -0,0 +1,5 @@ +pragma Ada_2022; + +generic + type T is private or use Boolean; +function Gen_Ident (X : T) return T; diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads new file mode 100644 index 000000000..cf33136bb --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2022; + +with Gen_Ident; + +package Pkg is + + function Default_Ident is new Gen_Ident; + +end Pkg; diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb new file mode 100644 index 000000000..0999e03e0 --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb @@ -0,0 +1,12 @@ +with Pkg; + +procedure Test_Pkg is +begin + if Pkg.Default_Ident (False) then + raise Program_Error; + end if; +end Test_Pkg; + +--# gen_ident.adb +-- +-- /ret/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py new file mode 100644 index 000000000..9d8b420e5 --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py @@ -0,0 +1,12 @@ +""" +Sanity test to ensure gnatcov does not crash when instrumenting code +containing a default subtype mark for a generic formal type. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads b/testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads new file mode 100644 index 000000000..8f670e8a9 --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads @@ -0,0 +1,8 @@ +pragma Ada_2022; + +package Pkg is + + function Foo (X : Integer; Y : Boolean with Unreferenced) return Integer is + (X); -- # expr + +end Pkg; diff --git a/testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb b/testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb new file mode 100644 index 000000000..a72492aec --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb @@ -0,0 +1,12 @@ +with Pkg; + +procedure Test_Pkg is +begin + if Pkg.Foo (1, True) /= 1 then + raise Program_Error; + end if; +end Test_Pkg; + +--# pkg.ads +-- +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/sanity/param_aspects/test.py b/testsuite/tests/Ada2022/sanity/param_aspects/test.py new file mode 100644 index 000000000..0310ec10c --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/param_aspects/test.py @@ -0,0 +1,15 @@ +""" +Sanity test checking that there are no crashes in gnatcov when processing +sources containing aspects attached to subprograms formal parameters. + +As the only aspect that can be attached to a formal subprogram parameter +supported by GNAT is Unreferenced, which accepts no argument, we currently +have no way of testing a hypothetical instrumentation of this kind of aspect. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/static_expr_func/src/test_1.adb b/testsuite/tests/Ada2022/static_expr_func/src/test_1.adb new file mode 100644 index 000000000..df667356e --- /dev/null +++ b/testsuite/tests/Ada2022/static_expr_func/src/test_1.adb @@ -0,0 +1,12 @@ +pragma Ada_2022; + +procedure Test_1 is + function Foo return Integer is (42) with Static; -- # expr +begin + null; -- # stmt +end Test_1; + +--# test_1.adb +-- +-- /expr/ l. ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/static_expr_func/test.py b/testsuite/tests/Ada2022/static_expr_func/test.py new file mode 100644 index 000000000..c7bdc091a --- /dev/null +++ b/testsuite/tests/Ada2022/static_expr_func/test.py @@ -0,0 +1,11 @@ +""" +Test checking that gnatcov correctly instruments static expression functions +(annotated with the static aspect). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb new file mode 100644 index 000000000..a07193e09 --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb @@ -0,0 +1,34 @@ +pragma Ada_2022; + +package body Pkg is + + ------------ + -- Do_Sum -- + ------------ + + function Do_Sum (N_Values : Positive) return Natural + is + Arr : array (1 .. N_Values) of Positive range 1 .. Positive' + (If Constrained and then Really_Constrained -- # Constrained + then 10 + else Positive'Last) := + [for I in 1 .. N_Values => I]; + Acc : Natural := 0; + begin + -- According to RM 5.5.2 5/5, the subtype indication in the generalized + -- loop iteration must *statically* match the one of the component of + -- the iterated value. We thus can't produce any non-static decisions + -- in the subtype indication. + + for Val : Positive range 1 .. Positive' + (If Constrained and then Really_Constrained -- # Constrained + then 10 + else Positive'Last) + of Arr + loop + Acc := Acc + Val; + end loop; + return Acc; + end Do_Sum; + +end Pkg; diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads new file mode 100644 index 000000000..922fbef6b --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package Pkg is + + Constrained : constant Boolean := True; + Really_Constrained : constant Boolean := False; + + function Do_Sum (N_Values : Positive) return Natural; + -- Return the sum of the values from 1 to N_Values + +end Pkg; diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb new file mode 100644 index 000000000..945008f94 --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Pkg is + Res : Positive; + pragma Volatile (Res); +begin + Res := Pkg.Do_Sum (10); + if Res /= 55 then + raise Program_Error; + end if; +end Test_Pkg; + +--# pkg.adb +-- /Constrained/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/test.py b/testsuite/tests/Ada2022/subtype_ind_in_iter/test.py new file mode 100644 index 000000000..533e9342b --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/test.py @@ -0,0 +1,15 @@ +""" +Test the correct handling of subtype indications in generalized loop +iterations. As the subtype indication in the loop must statically match the +type of the iterated cursor type, we can only create static decisions that are +not currently instrumented by gnatcov. This test thus only really checks that +there is no crash in the presence of this construct. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/C++/extra.opt b/testsuite/tests/C++/extra.opt new file mode 100644 index 000000000..057749df0 --- /dev/null +++ b/testsuite/tests/C++/extra.opt @@ -0,0 +1,2 @@ +!C++ DEAD Only run C++ tests if we have a supported C++ compiler +bin-traces DEAD C++ not supported with binary traces diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp new file mode 100644 index 000000000..7491a1abe --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp @@ -0,0 +1,14 @@ +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + // Basic lambda function here, a mere expression return + + auto AndExpr = [] (int aa, int bb) { // # other + return aa > 0 && bb > 0; // # eval :o/e: + }; // # lambda_other + + volatile bool b = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp new file mode 100644 index 000000000..7aeecfdb6 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp @@ -0,0 +1,23 @@ +#include + +class AndExpr +{ +public: + int + eval (bool aa, bool bb) + { + if (aa && bb) // # eval :o/d: + return true; // # true + else + return false; // # false + } +}; + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + AndExpr ().eval (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp new file mode 100644 index 000000000..567a0b345 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp @@ -0,0 +1,25 @@ +template class AndExpr +{ + bool _ev; + +public: + void + eval () + { + _ev = aa && bb; // # eval :o/e: + } +}; + +static bool a; +bool b; + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + a = aa; // # other + b = bb; // # other + AndExpr ().eval (); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp new file mode 100644 index 000000000..2b8838f86 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp @@ -0,0 +1,21 @@ +#include + +class AndExpr +{ + bool _value; + +public: + AndExpr (bool aa, bool bb) + { + _value = aa && bb; // # eval :o/e: + } +}; + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py b/testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp new file mode 100644 index 000000000..c7585e64d --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp @@ -0,0 +1,21 @@ +#include "tryme.hh" + +namespace glob +{ +bool aa, bb; +} + +void +bar (bool b = glob::aa || glob::bb) // # eval :o/e: +{ +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + glob::aa = aa; // # other + glob::bb = bb; // # other + bar (); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt new file mode 100644 index 000000000..b63692c38 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt @@ -0,0 +1 @@ +all XFAIL MCDC instrumentation of default initializers not supported diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp new file mode 100644 index 000000000..ca7d4f9b4 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp @@ -0,0 +1,34 @@ +class AndExpr +{ +public: + AndExpr (bool a, bool b); + ~AndExpr (); + +private: + bool aa, bb; +}; + +AndExpr::AndExpr (bool a, bool b) +{ + this->aa = a; // # other + this->bb = b; // # other +} + +static bool evalue; + +AndExpr::~AndExpr () +{ + if (aa && bb) // # eval :o/d: + ::evalue = true; // # true + else + ::evalue = false; // # false +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + AndExpr e (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py b/testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp new file mode 100644 index 000000000..752809650 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp @@ -0,0 +1,17 @@ +extern "C" +{ + bool + AndExpr (bool aa, bool bb) + { + return aa && bb; // # eval :o/e: + } +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + volatile bool ev = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.opt b/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.opt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py b/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp new file mode 100644 index 000000000..408a24f82 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp @@ -0,0 +1,15 @@ +template +bool +AndExpr (T aa, T bb) +{ + return aa && bb; // # eval :o/e: +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + volatile bool b = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp new file mode 100644 index 000000000..be1a4d032 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp @@ -0,0 +1,17 @@ +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + // A lambda function with a real sequence of statements here + + auto AndExpr = [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }; // # lambda_other + + volatile bool b = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp new file mode 100644 index 000000000..2488e0053 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp @@ -0,0 +1,37 @@ +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + // A lambda function in a compound statement + { + auto InCompound = [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }; // # lambda_other + volatile bool a = InCompound (aa, bb); // # other + } + + // A lambda function in a for statement + int i = 0; // # other + for (; i++ < 1;) // # other + [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }(aa, bb); // # lambda_other + + // A nested lambda + [] (int aa, int bb) { // # other + [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }(aa, bb); // # lambda_other + }(aa, bb); // # lambda_other +} diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py new file mode 100644 index 000000000..6723f353a --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py @@ -0,0 +1,11 @@ +""" +Regression / robustness test case: we use to implement spuriously source +coverage obligations inside lambda expressions. Check that we correctly +instrument lambda expressions in various contexts. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp new file mode 100644 index 000000000..b9583193a --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp @@ -0,0 +1,17 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); + tryme (/* aa */ false, /* bb */ true); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## c!:"bb" +// /true/ l+ ## 0 +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp new file mode 100644 index 000000000..601962c54 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp @@ -0,0 +1,17 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); + tryme (/* aa */ true, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## c!:"aa" +// /true/ l+ ## 0 +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp new file mode 100644 index 000000000..8ceb14f73 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp @@ -0,0 +1,18 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); + tryme (/* aa */ true, /* bb */ false); + tryme (/* aa */ false, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l+ ## 0 +// /true/ l+ ## 0 +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp new file mode 100644 index 000000000..572a53763 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp @@ -0,0 +1,19 @@ +#include + +int +main () +{ + tryme (/* aa */ false, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## oT- +// /true/ l- ## s- +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /lambda_true/ l! ## s- +// /lambda_false/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp new file mode 100644 index 000000000..08da49ef3 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp @@ -0,0 +1,24 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true, /* skip */ true); +} + +//# tryme.cpp tryme.hh +// /eval/ l- ## s- +// /true/ l- ## s- +// /false/ l- ## s- +// /other/ l- ## s- + +// All the lines of a stmt involving a lambda expr +// are noted '-' and the ones marked "other" don't +// have a nested entity of their own + +// /lambda_other/ l- ## 0c +// /lambda_true/ l- ## s- +// /lambda_false/ l- ## s- + +// /test_skip/ l! ## dF- +// /skip/ l+ ## 0 diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp new file mode 100644 index 000000000..798084759 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp @@ -0,0 +1,19 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## oT- +// /true/ l- ## s- +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /lambda_true/ l! ## s- +// /lambda_false/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp new file mode 100644 index 000000000..7e3c79980 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp @@ -0,0 +1,19 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## oF- +// /true/ l+ ## 0 +// /false/ l- ## s- +// /other/ l+ ## 0 + +// /lambda_true/ l+ ## 0 +// /lambda_false/ l! ## s- + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh b/testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh new file mode 100644 index 000000000..76a1f23c8 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh @@ -0,0 +1 @@ +extern void tryme (bool aa, bool bb, bool skip = false); diff --git a/testsuite/tests/C++/mcdc/AandB/tc_set.rst b/testsuite/tests/C++/mcdc/AandB/tc_set.rst new file mode 100644 index 000000000..317b03055 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/tc_set.rst @@ -0,0 +1,24 @@ +**Exercise mcdc on a "a && b" expression instated in a variety of contexts** + +-- + +The code to test always features a "tryme" entry point expecting +the Boolean values to use for "a" and "b", as well as a "skip" argument +to request an early return. + +Expectation anchors: + +/eval/ Line where the a && b expression is evaluated. +/true/ Regular code executed when the expr evaluates true. +/false/ Regular code executed when the expr evaluates false. +/other/ Regular code executed regardless of the expr value. + +/lambda_true/ Code executed when the expr evaluates true + as part of a lambda function. +/lambda_false/ Code executed when the expr evaluates false + as part of a lambda function. +/lambda_other/ Other lines constituting a lambda expression, + expected not to contain any stmt of their own. + +/test_skip/ Line testing the "skip" argument. +/skip/ Code executed when "skip" is true. diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh b/testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh new file mode 100644 index 000000000..57a467c98 --- /dev/null +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh @@ -0,0 +1,5 @@ +constexpr int +bar () +{ + return 0; // # ce-header +} diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp new file mode 100644 index 000000000..cf461fb6c --- /dev/null +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp @@ -0,0 +1,31 @@ +#include "pkg.hh" + +constexpr int +foo () +{ + if (true && false) // # ce-body + return 1; // # ce-body + constexpr bool a = true; // # ce-body + if constexpr (false) // # ce-body + return 1; // # ce-body + return 0; // # ce-body +} + +int +main () +{ + constexpr bool a = true || false; // # single-ce-decl + constexpr bool b = true || false, c = true || false; // # double-ce-decl + if constexpr (false) // # if-ce + return 1; // # if-rt + return 0; // # rt +} + +//# test_constexpr.cpp +// +// /ce-body/ l. ## 0 +// /single-ce-decl/ l+ ## 0 +// /double-ce-decl/ l+ ## 0 +// /if-ce/ l+ ## 0 +// /if-rt/ l- ## s- +// /rt/ l+ ## 0 diff --git a/testsuite/tests/C++/mcdc/ConstExpr/test.py b/testsuite/tests/C++/mcdc/ConstExpr/test.py new file mode 100644 index 000000000..6f496a80c --- /dev/null +++ b/testsuite/tests/C++/mcdc/ConstExpr/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(tolerate_messages=r".* cannot instrument constexpr").run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp new file mode 100644 index 000000000..dc2811cef --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp @@ -0,0 +1,13 @@ +#include "sum.hh" +#include "validate.hh" + +int +sum (std::vector ints) +{ + int result = 0; // # init + for (validate (ints); // # for-init + const int &i : ints // # for-range + ) + result += i; // # add + return result; // # return +} diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh new file mode 100644 index 000000000..1e4dd32b0 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh @@ -0,0 +1,3 @@ +#include + +extern int sum (std::vector ints); diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp new file mode 100644 index 000000000..91f13c42c --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp @@ -0,0 +1,16 @@ +#include "sum.hh" + +int +main (void) +{ + volatile bool b = false; + return b && sum ({ 0, 1 }); +} + +//# sum.cpp +// +// /init/ l- ## s- +// /for-init/ l- ## s- +// /for-range/ l- ## s- +// /add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp new file mode 100644 index 000000000..d560f4e33 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp @@ -0,0 +1,26 @@ +#include "sum.hh" + +int +main (void) +{ + int result; + + try + { + result = sum ({ 0, 1 }); + } + catch (const char *msg) + { + return 0; + } + + return 1; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-init/ l+ ## 0 +// /for-range/ l- ## s- +// /add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp new file mode 100644 index 000000000..ffd905de3 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum ({ 1, 2 }) != 3) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-return/ l- ## s- +// /if-add/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp new file mode 100644 index 000000000..38fc3101d --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp @@ -0,0 +1,11 @@ +#include "validate.hh" + +void +validate (std::vector ints) +{ + for (const int &i : ints) + { + if (i == 0) + throw "invalid null element"; + } +} diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh new file mode 100644 index 000000000..01c165241 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh @@ -0,0 +1,3 @@ +#include + +extern void validate (std::vector ints); diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/test.opt b/testsuite/tests/C++/stmt/ForRange/WithInit/test.opt new file mode 100644 index 000000000..ecaecfaa9 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/test.opt @@ -0,0 +1 @@ +bareboard DEAD Exception propagation support required diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/test.py b/testsuite/tests/C++/stmt/ForRange/WithInit/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp new file mode 100644 index 000000000..f8b695b0d --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp @@ -0,0 +1,18 @@ +#include + +int +main (void) +{ + int sum = 0; // # init + for (auto i : { 1, 2, 3 }) // # for-range + { + sum += i; // # for-body + } + return 0; +} + +//# test_for_range.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /for-body/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py new file mode 100644 index 000000000..c34f08074 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py @@ -0,0 +1,13 @@ +""" +Test that gnatcov correctly instruments a for range with an initializer as the +range expression and an initialization statement, e.g. +``` +for (int i = 0; auto j : {1, 2}){} +``` +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp new file mode 100644 index 000000000..d86b3ffd7 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp @@ -0,0 +1,14 @@ +#include "sum.hh" + +int +sum (const RangeIterable &r) +{ + int result = 0; // # init + for (int i : r) // # for-range + { + if (i == 10) // # if-cond + return 0; // # if-return + result += i; // # if-add + } + return result; // # return +} diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh new file mode 100644 index 000000000..d22ef5369 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh @@ -0,0 +1,3 @@ +#include "range_iterable.hh" + +extern int sum (const RangeIterable &r); diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp new file mode 100644 index 000000000..aa86977dd --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp @@ -0,0 +1,17 @@ +#include "sum.hh" + +int +main (void) +{ + volatile bool b = false; + return b && sum (RangeIterable (1)); +} + +//# sum.cpp +// +// /init/ l- ## s- +// /for-range/ l- ## s- +// /if-cond/ l- ## s- +// /if-return/ l- ## s- +// /if-add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp new file mode 100644 index 000000000..7ebc04713 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum (RangeIterable (10)) != 0) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-return/ l+ ## 0 +// /if-add/ l+ ## 0 +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp new file mode 100644 index 000000000..9db3c36d5 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum (RangeIterable (-1)) != 0) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l- ## s- +// /if-return/ l- ## s- +// /if-add/ l- ## s- +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp new file mode 100644 index 000000000..cf8343f01 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum (RangeIterable (2)) != 3) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-return/ l- ## s- +// /if-add/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py b/testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh b/testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh new file mode 100644 index 000000000..efd524e5b --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh @@ -0,0 +1,60 @@ +#ifndef RANGE_ITERABLE_HH +#define RANGE_ITERABLE_HH + +class RangeCursor +{ + int max; + int current; + +public: + RangeCursor (int max, int current) : max (max), current (current) {} + + int + operator* () const + { + return current; + } + + RangeCursor & + operator++ () + { + current += 1; + return *this; + } + + static inline bool + equals (const RangeCursor &lhs, const RangeCursor &rhs) + { + return lhs.current == rhs.current; + } +}; + +inline bool +operator!= (const RangeCursor &lhs, const RangeCursor &rhs) +{ + return !RangeCursor::equals (lhs, rhs); +} + +class RangeIterable +{ + int max; + +public: + RangeIterable (int max) : max (max) {} + + RangeIterable (const RangeIterable &&r) : max (r.max) {} + + RangeCursor + begin () const + { + return RangeCursor (max, 0); + } + + RangeCursor + end () const + { + return RangeCursor (max, max + 1); + } +}; + +#endif diff --git a/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp b/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp new file mode 100644 index 000000000..7fb9f95de --- /dev/null +++ b/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp @@ -0,0 +1,23 @@ +struct Foo +{ + void + bar () + { + return; // # member-fun + } +}; + +int +main (void) +{ + struct Foo foo; // # decl + foo.bar (); // # call + return 0; // # return +} + +//# test_struct.cpp +// +// /decl/ l+ ## 0 +// /member-fun/ l+ ## 0 +// /call/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/StructMemberFun/test.py b/testsuite/tests/C++/stmt/StructMemberFun/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/StructMemberFun/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp new file mode 100644 index 000000000..23718f4aa --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp @@ -0,0 +1,13 @@ +#include "count_digits.hh" + +int +count_digits (const char *str) +{ + int result = 0; // # init + while (const char c = *str++) // # while-cond + { + if ('0' <= c && c <= '9') // # if-cond + result += 1; // # if-incr + } + return result; // # return +} diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh new file mode 100644 index 000000000..38f39cf6d --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh @@ -0,0 +1 @@ +extern int count_digits (const char *str); diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp new file mode 100644 index 000000000..e8707d6ab --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp @@ -0,0 +1,16 @@ +#include "count_digits.hh" + +int +main (void) +{ + volatile bool b = false; + return b && count_digits ("hello"); +} + +//# count_digits.cpp +// +// /init/ l- ## s- +// /while-cond/ l- ## s- +// /if-cond/ l- ## s- +// /if-incr/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp new file mode 100644 index 000000000..c3165bf25 --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp @@ -0,0 +1,17 @@ +#include "count_digits.hh" + +int +main (void) +{ + if (count_digits ("") != 0) + return 1; + return 0; +} + +//# count_digits.cpp +// +// /init/ l+ ## 0 +// /while-cond/ l+ ## 0 +// /if-cond/ l- ## s- +// /if-incr/ l- ## s- +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp new file mode 100644 index 000000000..8d9caedf3 --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp @@ -0,0 +1,17 @@ +#include "count_digits.hh" + +int +main (void) +{ + if (count_digits ("aa00") != 2) + return 1; + return 0; +} + +//# count_digits.cpp +// +// /init/ l+ ## 0 +// /while-cond/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-incr/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp new file mode 100644 index 000000000..0cc3f3448 --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp @@ -0,0 +1,17 @@ +#include "count_digits.hh" + +int +main (void) +{ + if (count_digits ("aa") != 0) + return 1; + return 0; +} + +//# count_digits.cpp +// +// /init/ l+ ## 0 +// /while-cond/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-incr/ l- ## s- +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/WhileDecl/test.py b/testsuite/tests/C++/stmt/WhileDecl/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp.c b/testsuite/tests/C/decision/CommaExpr/src/cmp.c new file mode 100644 index 000000000..dbf549e86 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp.c @@ -0,0 +1,12 @@ +#include "cmp_internal.h" + +int +less_than (int a, int b) +{ + int result; // # decl + + if (compute_less_than (&result, a, b), result) // # if-cond + return 1; // # if-then + else + return 0; // # if-else +} diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp.h b/testsuite/tests/C/decision/CommaExpr/src/cmp.h new file mode 100644 index 000000000..7f2fb7b7c --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp.h @@ -0,0 +1 @@ +extern int less_than (int a, int b); diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c new file mode 100644 index 000000000..512c79a1b --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c @@ -0,0 +1,5 @@ +void +compute_less_than (int *result, int a, int b) +{ + *result = a < b; +} diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h new file mode 100644 index 000000000..91b3e6dc5 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h @@ -0,0 +1 @@ +extern void compute_less_than (int *result, int a, int b); diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_0.c b/testsuite/tests/C/decision/CommaExpr/src/test_0.c new file mode 100644 index 000000000..7ba70d919 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_0.c @@ -0,0 +1,15 @@ +#include "cmp.h" + +int +main (void) +{ + volatile int b = 0; + return b && less_than (1, 2); +} + +//# cmp.c +// +// /decl/ l- ## s- +// /if-cond/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_f.c b/testsuite/tests/C/decision/CommaExpr/src/test_f.c new file mode 100644 index 000000000..5a7532ac4 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_f.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dT- +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_t.c b/testsuite/tests/C/decision/CommaExpr/src/test_t.c new file mode 100644 index 000000000..6323605d1 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_t.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (1, 2)) + { + return 0; + } + else + { + return 1; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dF- +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_tf.c b/testsuite/tests/C/decision/CommaExpr/src/test_tf.c new file mode 100644 index 000000000..1cd4b58b3 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_tf.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (!less_than (1, 2) || less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/decision/CommaExpr/test.py b/testsuite/tests/C/decision/CommaExpr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c new file mode 100644 index 000000000..dc326136b --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c @@ -0,0 +1,8 @@ +char +aligned (int x, int y, int factor) +{ + if (!(x & (factor - 1)) && !(y && (factor - 1))) // # decision + return 1; // # stmt-true + else + return 0; // # stmt-false +} diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads new file mode 100644 index 000000000..bb85736e1 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads @@ -0,0 +1,4 @@ +package Misc is + function Aligned (X, Y, Factor : Integer) return Boolean; + pragma Import (C, Aligned, "aligned"); +end; diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb new file mode 100644 index 000000000..f9cc9fba8 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb @@ -0,0 +1,11 @@ +with Misc, Support; use Misc, Support; + +procedure Test_Aligned_False is +begin + Assert (not Aligned (1, 0, 0)); +end; + +--# aligned.c +-- /decision/ l! ## dT- +-- /stmt-true/ l- ## s- +-- /stmt-false/ l+ ## 0 diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb new file mode 100644 index 000000000..3567b0330 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb @@ -0,0 +1,11 @@ +with Misc, Support; use Misc, Support; + +procedure Test_Aligned_True is +begin + Assert (Aligned (0, 0, 0)); +end; + +--# aligned.c +-- /decision/ l! ## dF- +-- /stmt-true/ l+ ## 0 +-- /stmt-false/ l- ## s- diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt new file mode 100644 index 000000000..32bb8756f --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt @@ -0,0 +1 @@ +7.2.2 DEAD requires compiler change from 2014-10, not in 7.2.2 diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/extra.opt b/testsuite/tests/C/extra.opt new file mode 100644 index 000000000..0182653a4 --- /dev/null +++ b/testsuite/tests/C/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp.c b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.c new file mode 100644 index 000000000..dbf549e86 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.c @@ -0,0 +1,12 @@ +#include "cmp_internal.h" + +int +less_than (int a, int b) +{ + int result; // # decl + + if (compute_less_than (&result, a, b), result) // # if-cond + return 1; // # if-then + else + return 0; // # if-else +} diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp.h b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.h new file mode 100644 index 000000000..7f2fb7b7c --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.h @@ -0,0 +1 @@ +extern int less_than (int a, int b); diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c new file mode 100644 index 000000000..512c79a1b --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c @@ -0,0 +1,5 @@ +void +compute_less_than (int *result, int a, int b) +{ + *result = a < b; +} diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h new file mode 100644 index 000000000..91b3e6dc5 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h @@ -0,0 +1 @@ +extern void compute_less_than (int *result, int a, int b); diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_0.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_0.c new file mode 100644 index 000000000..7ba70d919 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_0.c @@ -0,0 +1,15 @@ +#include "cmp.h" + +int +main (void) +{ + volatile int b = 0; + return b && less_than (1, 2); +} + +//# cmp.c +// +// /decl/ l- ## s- +// /if-cond/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_f.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_f.c new file mode 100644 index 000000000..5a7532ac4 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_f.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dT- +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_t.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_t.c new file mode 100644 index 000000000..6323605d1 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_t.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (1, 2)) + { + return 0; + } + else + { + return 1; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dF- +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c new file mode 100644 index 000000000..1cd4b58b3 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (!less_than (1, 2) || less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/mcdc/CommaExpr/test.py b/testsuite/tests/C/mcdc/CommaExpr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c new file mode 100644 index 000000000..12a105014 --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c @@ -0,0 +1,21 @@ + +int +fact (int n) +{ + if (n == 0) + { + return 1; + } + return n * fact (n - 1); +} + +int +main (void) +{ + return + /* GNATCOV_EXEMPT_ON "In statement"*/ + fact (0) == 1 + /* GNATCOV_EXEMPT_OFF)*/ + ? 0 + : 1; +} diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py new file mode 100644 index 000000000..04c8d0a7d --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py @@ -0,0 +1,37 @@ +""" +Check that gnatcov correctly rejects exemption markers intersecting SCOs. +""" + +# TODO: This may need to be moved to a Robustness chapter instead when +# proper qualification tests are written for C. + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.c"], srcdirs=[".."])), + extra_coverage_args=["--annotate=xcov"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + tolerate_instrument_messages="Exemption .* intersects", +) + +check_xcov_reports( + "obj", + {"main.c.xcov": {"+": {7, 15}, "!": {5, 17}, "-": {9}}}, +) + +thistest.fail_if_no_match( + what="Unexpected instrument output", + regexp=r"(warning: Exemption annotation at main\.c:\d+:\d+ intersects a" + r" coverage obligation \(.*\), ignoring it\n)+", + actual=contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c new file mode 100644 index 000000000..79b73498a --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c @@ -0,0 +1,35 @@ +#include "pkg.h" +#include + +#define NOT(A) !A + +// GNATCOV_EXEMPT_ON "whole function single line comment" // # exempt_at +bool // # exempt_at +andThen (bool a, bool b) // # exempt_at +{ // # exempt_at + return a && b; // # exempt_at +} // # exempt_at +// GNATCOV_EXEMPT_OFF // # exempt_at + +bool +orElse (bool a, bool b) +{ + // GNATCOV_EXEMPT_ON "if stmt" // # exempt_oe + if (a || b) // # exempt_oe_v1 + { // # exempt_oe + // GNATCOV_EXEMPT_OFF // # exempt_oe + return true; + } + else + { + return false; + } +} + +bool +negation (bool a) +{ + /* GNATCOV_EXEMPT_ON "single statement, multiline comment"*/ // # exempt_neg + return NOT (a); // # exempt_neg_v1 + /* GNATCOV_EXEMPT_OFF */ // # exempt_neg +} diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h new file mode 100644 index 000000000..419e178b8 --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h @@ -0,0 +1,12 @@ +#ifndef PKG_H +#define PKG_H + +#include + +extern bool andThen (bool a, bool b); + +extern bool orElse (bool a, bool b); + +extern bool negation (bool a); + +#endif diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c new file mode 100644 index 000000000..10627e6ab --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c @@ -0,0 +1,20 @@ +#include "pkg.h" + +int +main (void) +{ + volatile bool x = orElse (false, true); + x = orElse (false, false); + x = andThen (true, true); + x = andThen (true, false); + x = andThen (false, false); + return 0; +} + +//# pkg.c +// +// /exempt_at/ l# ## x0 +// /exempt_oe/ l* ## x+ +// /exempt_oe_v1/ l= ## Xc! +// /exempt_neg/ l* ## x+ +// /exempt_neg_v1/ l= ## Xs- diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py b/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py new file mode 100644 index 000000000..0fee72b52 --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py @@ -0,0 +1,9 @@ +""" +Test proper support for exemptions in comments for C. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/extra.opt b/testsuite/tests/C/mcdc/Exemptions/extra.opt new file mode 100644 index 000000000..25d72a22d --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD exemptions not supported in bin traces for C diff --git a/testsuite/tests/C/mcdc/Macros/pkg.h b/testsuite/tests/C/mcdc/Macros/pkg.h new file mode 100644 index 000000000..89015692e --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/pkg.h @@ -0,0 +1 @@ +#define PRINT_HW_PKG printf ("Hello world!\n"); diff --git a/testsuite/tests/C/mcdc/Macros/test.opt b/testsuite/tests/C/mcdc/Macros/test.opt new file mode 100644 index 000000000..b9f5a8268 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD check SCO annotations emitted by the instrumenter +RTS_ZFP DEAD Uses printf, not available in light runtimes +!linux DEAD Check built-in macros, defined differently for each OS diff --git a/testsuite/tests/C/mcdc/Macros/test.py b/testsuite/tests/C/mcdc/Macros/test.py new file mode 100644 index 000000000..f119350f3 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test.py @@ -0,0 +1,37 @@ +""" +Check that we have the right annotations for SCOs that come from macro +expansion. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + +# For simplicity, avoid commas in these arguments to avoid issues with the +# argument separator for --c-opts. +macro_args = [ + '-DCMDLINE_MACRO_STMT=printf ("Command-line macro");', + "-DCMDLINE_MACRO_DECL(x)=int x;", + "-DCMDLINE_MACRO_NO_VALUE(x)x", +] +copts_args = "--c-opts=" + ",".join(macro_args) +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test_macros.c"]) + ), + covlevel="stmt+mcdc", + mains=["test_macros"], + extra_instr_args=[copts_args], + extra_coverage_args=["--annotate=xcov+"], +) + +thistest.fail_if_diff( + os.path.join("..", "test_macros.c.xcov.expected"), + os.path.join("obj", "test_macros.c.xcov"), +) +thistest.result() diff --git a/testsuite/tests/C/mcdc/Macros/test_macros.c b/testsuite/tests/C/mcdc/Macros/test_macros.c new file mode 100644 index 000000000..9ad700592 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test_macros.c @@ -0,0 +1,47 @@ +#include "pkg.h" +#include + +#define PRINT_HW printf ("Hello world!\n"); +#define PRINT printf +#define HW "Hello world!\n" +#define PRINT_HW_PRINT_HW \ + PRINT_HW; \ + PRINT_HW +#define WRAPPER_PRINT_HW PRINT_HW +#define ID(x) x +#define AND(x, y) ID (x) && y +#define WRAP_AND(x, y) AND (x, y) +#define WRAP_CMDLINE_MACRO_STMT CMDLINE_MACRO_STMT + +void +macro_stmts () +{ + PRINT_HW_PKG; + PRINT_HW; + WRAPPER_PRINT_HW; + PRINT ("Hello world!\n"); + PRINT (HW); + PRINT_HW_PRINT_HW; + WRAP_CMDLINE_MACRO_STMT; + CMDLINE_MACRO_STMT; + CMDLINE_MACRO_DECL (a); + CMDLINE_MACRO_NO_VALUE (int b =); + // Test that coverage obligations coming from built-in macros are reported + // correctly. + __linux + 1; +} + +void +macro_decision_violations (int a, int b) +{ + if (WRAP_AND (ID (a), b)) + PRINT_HW; +} + +int +main () +{ + macro_decision_violations (1, 0); + macro_decision_violations (1, 1); + return 0; +} diff --git a/testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected b/testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected new file mode 100644 index 000000000..e95147f31 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected @@ -0,0 +1,99 @@ +25% of 16 lines covered +29% statement coverage (5 out of 17) +100% decision coverage (1 out of 1) +50% MC/DC coverage (1 out of 2) + +Coverage level: stmt+mcdc + 1 .: #include "pkg.h" + 2 .: #include + 3 .: + 4 .: #define PRINT_HW printf ("Hello world!\n"); + 5 .: #define PRINT printf + 6 .: #define HW "Hello world!\n" + 7 .: #define PRINT_HW_PRINT_HW \ + 8 .: PRINT_HW; \ + 9 .: PRINT_HW + 10 .: #define WRAPPER_PRINT_HW PRINT_HW + 11 .: #define ID(x) x + 12 .: #define AND(x, y) ID (x) && y + 13 .: #define WRAP_AND(x, y) AND (x, y) + 14 .: #define WRAP_CMDLINE_MACRO_STMT CMDLINE_MACRO_STMT + 15 .: + 16 .: void + 17 .: macro_stmts () + 18 .: { + 19 -: PRINT_HW_PKG; +statement "printf ("..." at 19:3 not executed + note: in definition of macro PRINT_HW_PKG at location pkg.h:1:22 + note: from expansion of macro PRINT_HW_PKG at location test_macros.c:19:3 + 20 -: PRINT_HW; +statement "printf ("..." at 20:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:20:3 + 21 -: WRAPPER_PRINT_HW; +statement "printf ("..." at 21:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:10:26 + note: from expansion of macro WRAPPER_PRINT_HW at location test_macros.c:21:3 + 22 -: PRINT ("Hello world!\n"); +statement "printf ("..." at 22:3 not executed + note: in definition of macro PRINT at location test_macros.c:5:15 + note: from expansion of macro PRINT at location test_macros.c:22:3 + 23 -: PRINT (HW); +statement "printf ("..." at 23:3 not executed + note: in definition of macro PRINT at location test_macros.c:5:15 + note: from expansion of macro PRINT at location test_macros.c:23:3 + 24 -: PRINT_HW_PRINT_HW; +statement "printf ("..." at 24:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:8:3 + note: from expansion of macro PRINT_HW_PRINT_HW at location test_macros.c:24:3 +statement "printf ("..." at 24:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:9:3 + note: from expansion of macro PRINT_HW_PRINT_HW at location test_macros.c:24:3 + 25 -: WRAP_CMDLINE_MACRO_STMT; +statement "printf ("..." at 25:3 not executed + note: in definition of macro CMDLINE_MACRO_STMT at location + note: from expansion of macro CMDLINE_MACRO_STMT at location test_macros.c:14:33 + note: from expansion of macro WRAP_CMDLINE_MACRO_STMT at location test_macros.c:25:3 + 26 -: CMDLINE_MACRO_STMT; +statement "printf ("..." at 26:3 not executed + note: in definition of macro CMDLINE_MACRO_STMT at location + note: from expansion of macro CMDLINE_MACRO_STMT at location test_macros.c:26:3 + 27 -: CMDLINE_MACRO_DECL (a); +statement "int a;" at 27:3 not executed + note: in definition of macro CMDLINE_MACRO_DECL at location + note: from expansion of macro CMDLINE_MACRO_DECL at location test_macros.c:27:3 + 28 -: CMDLINE_MACRO_NO_VALUE (int b =); +statement "int b = 1..." at 28:3 not executed + note: in definition of macro CMDLINE_MACRO_NO_VALUE at location + note: from expansion of macro CMDLINE_MACRO_NO_VALUE at location test_macros.c:28:3 + 29 .: // Test that coverage obligations coming from built-in macros are reported + 30 .: // correctly. + 31 -: __linux + 1; +statement "1 + 1" at 31:3 not executed + note: in definition of macro __linux at location + note: from expansion of macro __linux at location test_macros.c:31:3 + 32 .: } + 33 .: + 34 .: void + 35 .: macro_decision_violations (int a, int b) + 36 .: { + 37 !: if (WRAP_AND (ID (a), b)) +condition "a" at 37:7 has no independent influence pair, MC/DC not achieved + note: in definition of macro ID at location test_macros.c:11:15 + note: from expansion of macro ID at location test_macros.c:12:19 + note: from expansion of macro AND at location test_macros.c:13:24 + note: from expansion of macro WRAP_AND at location test_macros.c:37:7 + note: from expansion of macro ID at location test_macros.c:37:17 + 38 +: PRINT_HW; + 39 .: } + 40 .: + 41 .: int + 42 .: main () + 43 .: { + 44 +: macro_decision_violations (1, 0); + 45 +: macro_decision_violations (1, 1); + 46 +: return 0; + 47 .: } diff --git a/testsuite/tests/C/mcdc/include-current-dir/pkg.c b/testsuite/tests/C/mcdc/include-current-dir/pkg.c new file mode 100644 index 000000000..f939f7693 --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/pkg.c @@ -0,0 +1,5 @@ +int +foo (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/C/mcdc/include-current-dir/pkg.h b/testsuite/tests/C/mcdc/include-current-dir/pkg.h new file mode 100644 index 000000000..7c8a5c82e --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/pkg.h @@ -0,0 +1,9 @@ +extern int foo (int a, int b); + +static int +bar (int a, int b) +{ + if (a || b) + return 1; + return 0; +} diff --git a/testsuite/tests/C/mcdc/include-current-dir/test.c b/testsuite/tests/C/mcdc/include-current-dir/test.c new file mode 100644 index 000000000..8fa741fed --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/test.c @@ -0,0 +1,10 @@ +#include "pkg.h" + +int +main () +{ + bar (0, 1); + bar (0, 0); + int a = foo (0, 1); + return 0; +} diff --git a/testsuite/tests/C/mcdc/include-current-dir/test.py b/testsuite/tests/C/mcdc/include-current-dir/test.py new file mode 100644 index 000000000..aa34848b1 --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/test.py @@ -0,0 +1,39 @@ +""" +This test checks that coverage obligations in a header files are processed. It +also checks that running gnatcov instrument when the source files are in the +current directory works. gnatcov instrument used to ignore source files because +the sloc of nodes returned by libclang in that case is relative (./pkg.h +instead of /pkg.h). +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest, gprfor + + +wd = Wdir("tmp_") +for src in ("pkg.h", "pkg.c", "test.c"): + cp(os.path.join("..", src), src) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=["."], mains=["test.c"])), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], +) + +check_xcov_reports( + "xcov", + { + "pkg.h.xcov": {"+": {7, 8}, "!": {6}}, + "pkg.c.xcov": {"!": {4}}, + "test.c.xcov": {"+": {6, 7, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/C/mcdc/misc/src/aligned.c b/testsuite/tests/C/mcdc/misc/src/aligned.c new file mode 100644 index 000000000..4cff388f7 --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/src/aligned.c @@ -0,0 +1,6 @@ + +char +aligned (int x, int y, int factor) +{ + return !(x & (factor - 1)) && !(y & (factor - 1)); // # eval +} diff --git a/testsuite/tests/C/mcdc/misc/src/misc.ads b/testsuite/tests/C/mcdc/misc/src/misc.ads new file mode 100644 index 000000000..566eefc05 --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/src/misc.ads @@ -0,0 +1,5 @@ +package Misc is + + function Aligned (X, Y, Factor : Integer) return Boolean; + pragma Import (C, Aligned, "aligned"); +end; diff --git a/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb b/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb new file mode 100644 index 000000000..ce655e415 --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb @@ -0,0 +1,10 @@ +with Misc, Support; use Misc, Support; + +procedure Test_Aligned_X is +begin + Assert (Aligned (16, 24, 8)); + Assert (not Aligned (7, 24, 8)); +end; + +--# aligned.c +-- /eval/ l! ## c!:"!(y" diff --git a/testsuite/tests/C/mcdc/misc/test.py b/testsuite/tests/C/mcdc/misc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/mcdc/sign-warn/src/foo.c b/testsuite/tests/C/mcdc/sign-warn/src/foo.c new file mode 100644 index 000000000..6bfe65c3b --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/src/foo.c @@ -0,0 +1,28 @@ +#include "foo.h" + +#include + +int +do_test (int *x, int *y, int *z) +{ + + // pointer equality ops in condition + if (x == NULL || y == NULL) // # ob + { + + // and in decision + if (z == NULL) // # ob + return 0; // # ob + return *z; // # ob + } + + // Relational ops in conditions + if (*x < 0 && *y < 0) // # ob + return *z; // # ob + + // Relational ops in decision + if (*y < 0) // # ob + return *y; // # ob + + return *z; // # ob +} diff --git a/testsuite/tests/C/mcdc/sign-warn/src/foo.h b/testsuite/tests/C/mcdc/sign-warn/src/foo.h new file mode 100644 index 000000000..78c3f280c --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/src/foo.h @@ -0,0 +1 @@ +int do_test (int *x, int *y, int *z); diff --git a/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c b/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c new file mode 100644 index 000000000..adfcd51a7 --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c @@ -0,0 +1,38 @@ +#include "foo.h" + +#include + +int +main () +{ + // Aiming for full coverage + int x, y, z; + + x = 1; + y = 2; + z = 3; + do_test (NULL, NULL, NULL); + do_test (NULL, NULL, &z); + do_test (&x, NULL, NULL); + do_test (&x, &y, &z); + + x = -2; + y = 1; + z = 3; + do_test (&x, &y, &z); + + x = 2; + y = -1; + z = 3; + do_test (&x, &y, &z); + + x = -2; + y = -1; + z = 3; + do_test (&x, &y, &z); + return 0; +} + +//# foo.c +// +// /ob/ l+ ## 0 diff --git a/testsuite/tests/C/mcdc/sign-warn/test.py b/testsuite/tests/C/mcdc/sign-warn/test.py new file mode 100644 index 000000000..c09b0bab9 --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/test.py @@ -0,0 +1,20 @@ +""" +Test that the introduction of witness function call in the decision expressions +does not generate warnings with -Wsign-conversion, on logical and relational +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +# Run the testcases for decision and mcdc to test all witness_* function +# variants. +# +# Enable warnings as errors to stop the test should we get any warnings, as +# otherwise the output of gprbuild is not checked. +TestCase(extracargs="-Wsign-conversion -Werror", category=CAT.decision).run() +TestCase(extracargs="-Wsign-conversion -Werror", category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/calc.c b/testsuite/tests/C/stmt/NA28-015-default-return/calc.c new file mode 100644 index 000000000..e5e14845e --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/calc.c @@ -0,0 +1,22 @@ +#include "process.h" +#include +#include + +void +usage () +{ + printf ("calc , print result of \n"); +} + +int +main (int argc, const char *argv[]) +{ + if (argc != 4) + { + usage (); + exit (1); + } + + process (argv); + return 0; +} diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/process.c b/testsuite/tests/C/stmt/NA28-015-default-return/process.c new file mode 100644 index 000000000..f9ded8bef --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/process.c @@ -0,0 +1,28 @@ +#include "process.h" +#include +#include +#include + +void +process (const char *argv[]) +{ + int x = atoi (argv[1]), y = atoi (argv[2]); + char opcode = argv[3][0]; + + int result; + + switch (opcode) + { + case '*': + result = x * y; // # mult + break; // # mult + case '+': + result = x + y; // # plus + break; // # plus + default: + printf ("unsupported opcode %c\n", opcode); // # unsupp + return; // # unsupp + } + + printf ("%d %c %d = %d\n", x, opcode, y, result); // # result +} diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/process.h b/testsuite/tests/C/stmt/NA28-015-default-return/process.h new file mode 100644 index 000000000..940dfaa0f --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/process.h @@ -0,0 +1,6 @@ +#ifndef __PROCESS_H__ +#define __PROCESS_H__ + +extern void process (const char *argv[]); + +#endif diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/test.opt b/testsuite/tests/C/stmt/NA28-015-default-return/test.opt new file mode 100644 index 000000000..cbce755aa --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/test.opt @@ -0,0 +1,2 @@ +!x86-linux,!x86_64-linux DEAD test relies on passing command line arguments +RTS_ZFP DEAD test relies on bin-file dump channel diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/test.py b/testsuite/tests/C/stmt/NA28-015-default-return/test.py new file mode 100644 index 000000000..33999dcbd --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/test.py @@ -0,0 +1,90 @@ +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import xcov, thistest +from SUITE.tutils import gprfor, srctracename_for, tracename_for + +import re + +Wdir("tmp_") + +# Point here is to exercise consolidation over distinct executions of the same +# program with different command line arguments. The SCOV circuitry isn't +# really suited for this so we're doing a rough approximation manually. + +# This also exercises a specific sequence of C constructs, with an explicit +# return in the default alternative of a switch case. + + +def run_trace_with_args(prefix, exec_args): + build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["calc.c"]) + ), + covlevel="stmt", + mains=["calc"], + extra_coverage_args=[], + extra_run_args=["-o", f"{prefix}.trace"], + extra_instr_args=[ + f"--dump-filename-prefix={prefix}", + "--dump-filename-simple", + ], + register_failure=False, + exec_args=exec_args, + ) + + +def trycov(cases, xnocov): + """ + Consolidate the set of traces whose basenames are provided in CASES. Check + that we have '-' notes on lines designated by exprs in XNOCOV, and only + there. + """ + + fun_tracename = ( + srctracename_for + if thistest.options.trace_mode == "src" + else tracename_for + ) + + xcov( + "coverage --level=stmt --annotate=xcov" + " -P gen.gpr %s" % " ".join(fun_tracename(c) for c in cases) + ) + + def check_mark_on(line): + m = re.search(string=line, pattern=r"^ *\d+ (?P.):") + if not m: + return + + note = m.group("note") + + m = re.search(string=line, pattern="// # (?P.*)") + mark = m.group("mark") if m else None + + thistest.fail_if( + mark in xnocov and note != "-", + "missing expected '-' note on line:\n%s" % line, + ) + + thistest.fail_if( + note == "-" and mark not in xnocov, + "unexpected '-' note on line:\n %s" % line, + ) + + print("checking cases=%s" % str(cases)) + with open("obj/process.c.xcov", "r") as f: + for line in f: + check_mark_on(line=line.strip()) + + +run_trace_with_args("plus", ["2", "3", "+"]) +run_trace_with_args("mult", ["4", "5", "*"]) +run_trace_with_args("unsupp", ["4", "5", "#"]) + +trycov(cases=["mult", "plus"], xnocov=["unsupp"]) +trycov(cases=["plus"], xnocov=["mult", "unsupp"]) +trycov(cases=["mult"], xnocov=["plus", "unsupp"]) +trycov(cases=["mult", "plus", "unsupp"], xnocov=[]) + +thistest.result() diff --git a/testsuite/tests/Disassemblers/arm_be/symbolization.baseline b/testsuite/tests/Disassemblers/arm_be/symbolization.baseline new file mode 100644 index 000000000..cf9afd167 --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_be/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: e0 80 00 00 add r0, r0, r0 +00000004 -: ea ff ff ff b 0x8 +00000008 -: e1 a0 f0 0e mov pc, lr +: +0000000c -: e3 a0 00 01 mov r0, #1 +00000010 -: eb ff ff fa bl 0x0 diff --git a/testsuite/tests/Disassemblers/arm_be/symbolization.s b/testsuite/tests/Disassemblers/arm_be/symbolization.s new file mode 100644 index 000000000..963e7de0c --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_be/symbolization.s @@ -0,0 +1,16 @@ + .text + .align 0 + + .type f, %function +f: + add r0, r0, r0 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + mov r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/arm_le/symbolization.baseline b/testsuite/tests/Disassemblers/arm_le/symbolization.baseline new file mode 100644 index 000000000..905c3f196 --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_le/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: 00 00 80 e0 add r0, r0, r0 +00000004 -: ff ff ff ea b 0x8 +00000008 -: 0e f0 a0 e1 mov pc, lr +: +0000000c -: 01 00 a0 e3 mov r0, #1 +00000010 -: fa ff ff eb bl 0x0 diff --git a/testsuite/tests/Disassemblers/arm_le/symbolization.s b/testsuite/tests/Disassemblers/arm_le/symbolization.s new file mode 100644 index 000000000..963e7de0c --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_le/symbolization.s @@ -0,0 +1,16 @@ + .text + .align 0 + + .type f, %function +f: + add r0, r0, r0 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + mov r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/disaconv.py b/testsuite/tests/Disassemblers/disaconv.py new file mode 100644 index 000000000..7e48d3b47 --- /dev/null +++ b/testsuite/tests/Disassemblers/disaconv.py @@ -0,0 +1,80 @@ +#! /usr/bin/env python + +import argparse +import re +import sys + + +# Command-line parsing + +parser = argparse.ArgumentParser( + description=( + "Convert a objdump/gnatcov disassembly dump to a simple format" + ) +) +parser.add_argument( + "-o", + "--output", + type=argparse.FileType("w"), + default=sys.stdout, + dest="output", +) +parser.add_argument( + "input", + type=argparse.FileType("r"), + nargs="?", + default=sys.stdin, +) + + +# Internal data structures + + +def section(match): + return "Section" + + +def insn(match): + addr = int(match.group("addr"), 16) + return "Insn: {:08x}".format(addr) + + +# Input matching + +# These are the pattern generated by objdump: +OBJDUMP_SECTION = re.compile("^Disassembly of section (?P.+):$") +OBJDUMP_INSN = re.compile( + "^ *(?P[0-9a-f]+):\t[ 0-9a-f]+\t" "(?P[^ ]*)" +) + +# And those ones are generated by gnatcov disassemble: +GNATCOV_SECTION = re.compile("^Section") +GNATCOV_INSN = re.compile( + "(?P[0-9a-f]+) -: (?: [0-9a-f]{2})+ {3,}" "(?P[^ ]+)" +) + + +# Matching table: associate a pattern with an action. + +MATCHING_TABLE = ( + (OBJDUMP_SECTION, section), + (OBJDUMP_INSN, insn), + (GNATCOV_SECTION, section), + (GNATCOV_INSN, insn), +) + + +def disaconv(fin, fout): + # For each line in the input file, try to find a matching pattern and write + # the result of the associated action to the output file. + for line in fin: + for pattern, action in MATCHING_TABLE: + m = pattern.match(line) + if m: + fout.write(action(m)) + fout.write("\n") + + +if __name__ == "__main__": + args = parser.parse_args() + disaconv(args.input, args.output) diff --git a/testsuite/tests/Disassemblers/leon/symbolization.baseline b/testsuite/tests/Disassemblers/leon/symbolization.baseline new file mode 100644 index 000000000..2d06cef3f --- /dev/null +++ b/testsuite/tests/Disassemblers/leon/symbolization.baseline @@ -0,0 +1,10 @@ +Section .text: 00000000-0000001b +: +00000000 -: 9d e3 bf a0 save %sp, -96, %sp +00000004 -: 80 00 00 00 add %g0, %g0, %g0 +00000008 -: 10 80 00 01 b 0xc +0000000c -: 81 e8 00 00 restore +00000010 -: 81 c3 e0 08 retl +: +00000014 -: b0 10 00 00 mov %g0, %i0 +00000018 -: 06 bf ff fa bl 0x0 diff --git a/testsuite/tests/Disassemblers/leon/symbolization.s b/testsuite/tests/Disassemblers/leon/symbolization.s new file mode 100644 index 000000000..a5d7af26a --- /dev/null +++ b/testsuite/tests/Disassemblers/leon/symbolization.s @@ -0,0 +1,17 @@ + .text + + .type f, %function +f: + save %sp, -96, %sp + add %g0, %g0, %g0 + b local +local: + restore + jmp %o7+8 + .size f, .-f + + .type foo, %function +foo: + mov %g0, %i0 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/lmp/symbolization.baseline b/testsuite/tests/Disassemblers/lmp/symbolization.baseline new file mode 100644 index 000000000..d840f9462 --- /dev/null +++ b/testsuite/tests/Disassemblers/lmp/symbolization.baseline @@ -0,0 +1,12 @@ +Section .text: 00000000-00000023 +: +00000000 -: 86 00 00 04 add.l r0,r0,r0 +00000004 -: ff 80 00 04 bra tr,r0,r0 +00000008 -: 00 00 00 00 nop +0000000c -: 7f 95 00 04 bra tr,r21,r0 +00000010 -: 00 00 00 00 nop +: +00000014 -: 84 aa 00 00 moviu r10,0x0000 +00000018 -: 84 aa 00 00 moviu r10,0x0000 +0000001c -: 7f 8a 54 04 bra tr,r10,r21 +00000020 -: 00 00 00 00 nop diff --git a/testsuite/tests/Disassemblers/lmp/symbolization.s b/testsuite/tests/Disassemblers/lmp/symbolization.s new file mode 100644 index 000000000..00d74dbb0 --- /dev/null +++ b/testsuite/tests/Disassemblers/lmp/symbolization.s @@ -0,0 +1,19 @@ + .text + + .type f, %function +f: + add.l r0,r0,r0 + bra tr,r0,r0 + nop +local: + bra tr,r21,r0 + nop + .size f, .-f + + .type foo, %function +foo: + moviu r10,%u f + moviu r10,%l f + bra tr,r10,r21 + nop + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/ppc_be/symbolization.baseline b/testsuite/tests/Disassemblers/ppc_be/symbolization.baseline new file mode 100644 index 000000000..6b1ef110e --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_be/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: 48 00 00 08 b 0x8 +00000004 -: 60 00 00 00 nop +00000008 -: 4e 80 00 20 blr +: +0000000c -: 4b ff ff f5 bl 0x0 +00000010 -: 60 00 00 00 nop diff --git a/testsuite/tests/Disassemblers/ppc_be/symbolization.s b/testsuite/tests/Disassemblers/ppc_be/symbolization.s new file mode 100644 index 000000000..7f65f2c54 --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_be/symbolization.s @@ -0,0 +1,15 @@ + .text + + .type f, %function +f: + b local + nop +local: + blr + .size f, .-f + + .type foo, %function +foo: + bl f + nop + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/ppc_le/symbolization.baseline b/testsuite/tests/Disassemblers/ppc_le/symbolization.baseline new file mode 100644 index 000000000..707bea161 --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_le/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: 08 00 00 48 b 0x8 +00000004 -: 00 00 00 60 nop +00000008 -: 20 00 80 4e blr +: +0000000c -: f5 ff ff 4b bl 0x0 +00000010 -: 00 00 00 60 nop diff --git a/testsuite/tests/Disassemblers/ppc_le/symbolization.s b/testsuite/tests/Disassemblers/ppc_le/symbolization.s new file mode 100644 index 000000000..7f65f2c54 --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_le/symbolization.s @@ -0,0 +1,15 @@ + .text + + .type f, %function +f: + b local + nop +local: + blr + .size f, .-f + + .type foo, %function +foo: + bl f + nop + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/test.py b/testsuite/tests/Disassemblers/test.py new file mode 100644 index 000000000..b12b12503 --- /dev/null +++ b/testsuite/tests/Disassemblers/test.py @@ -0,0 +1,126 @@ +""" +Test the integration of libopcodes in gnatcov's disassembling machinery. + +gnatcov delegates object code disassembling to binutils's libopcodes, so it +makes no sense here to test for all possible instructions. What we rather check +is whether the integration of libopcodes in gnatcov works as expected. + +To do so, we compare the output of `gnatcov disassemble` against baselines for +assembly files corresponding to the current target architecture, in both +endianity when applicable. Testcase should demonstrate that generally +libopcodes is properly used, and that symbolization works as expected. +""" + +from collections import OrderedDict +import os.path + +from e3.diff import diff + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +# Mapping: architecture discriminant -> tests directory. If one discriminant +# is a key for this mapping, the associated directory names are used to get +# testcases. + + +class Testcase(object): + def __init__(self, test_dir, discriminant, cargs=(), asm_spec=""): + self.test_dir = test_dir + self.discriminant = discriminant + self.cargs = cargs + self.asm_spec = asm_spec + + self.spec_file = None + + def prepare(self): + if self.asm_spec: + self.spec_file = os.path.abspath("{}.spec".format(self.test_dir)) + with open(self.spec_file, "w") as f: + f.write("*asm:\n") + f.write("+ {}\n".format(self.asm_spec)) + + self.cargs = list(self.cargs) + [ + "-specs={}".format(self.spec_file) + ] + + +testcases = OrderedDict() + +for tc in ( + # Avoid running this on Windows platforms as the assembler will fail + # processing the test material, there. + Testcase("x86", "x86-linux"), + Testcase("x86_64", "x86_64-linux"), + Testcase("lmp", "visium-elf", ["-mcpu=gr6"]), + # Use GCC's spec files, in particular the "asm" rule to force the + # assemblers' endianity. This short-circuits the -m{little,big}-endian flag + # we get from the testuite-wide project configuration file. + Testcase("arm_le", "arm", ["-mcpu=cortex-r4f"], "-EL"), + Testcase("arm_be", "arm", ["-mcpu=cortex-r4f"], "-EB"), + Testcase("thumb_le", "arm", ["-mthumb"], "-EL"), + Testcase("thumb_be", "arm", ["-mthumb"], "-EB"), + Testcase("ppc_be", "ppc-elf", ["-mbig-endian"]), + Testcase("ppc_le", "ppc-elf", ["-mlittle-endian"]), + Testcase("leon", "leon3-elf"), +): + testcases[tc.test_dir] = tc + + +def with_ext(name, ext): + """Return the given name suffixed by an extension.""" + return "{}{}{}".format(name, os.path.extsep, ext) + + +def is_asm(filename): + """Return if the given filename is an assembly source.""" + return os.path.splitext(filename)[-1] == ".s" + + +tmp = Wdir("tmp_") + +# Run tests in each test directory that matches architecture discriminants. +for test_dir, tc in testcases.items(): + if tc.discriminant not in thistest.options.tags: + continue + tc.prepare() + + path = os.path.join(tmp.homedir, test_dir) + tmp_sub = Wdir(test_dir) + + testcases = sorted(filter(is_asm, os.listdir(path))) + + # Prepare object file from assembly sources. + project = gprfor(testcases, srcdirs=path, main_cargs=tc.cargs) + gprbuild(project, gargs=["-c"]) + + # And then iterate on each testcase to run it. + for testcase in testcases: + compile_unit = os.path.splitext(testcase)[0] + objfile = os.path.join("obj", with_ext(compile_unit, "o")) + + baseline = os.path.join(path, with_ext(compile_unit, "baseline")) + disa_gnatcov = with_ext(compile_unit, "disassembly") + + # Disassemble it using gnatcov. + xcov(["disassemble", objfile], out=disa_gnatcov) + + # And finally compare it to the baseline. + disaconv_diff = diff(baseline, disa_gnatcov) + thistest.log( + "Comparing the disassembly of {}/{}...".format(test_dir, testcase) + ) + if disaconv_diff: + thistest.log(disaconv_diff) + else: + thistest.log("No difference") + thistest.fail_if( + disaconv_diff, + "{}/{}: disassemblies are not the same".format(test_dir, testcase), + ) + + tmp_sub.to_homedir() + +thistest.result() diff --git a/testsuite/tests/Disassemblers/thumb_be/symbolization.baseline b/testsuite/tests/Disassemblers/thumb_be/symbolization.baseline new file mode 100644 index 000000000..df9701cc1 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_be/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-0000000b +: +00000000 -: 30 03 adds r0, #3 +00000002 -: e7 ff b.n 0x4 +00000004 -: 46 f7 mov pc, lr +: +00000006 -: 20 01 movs r0, #1 +00000008 -: f7 ff ff fa bl 0x0 diff --git a/testsuite/tests/Disassemblers/thumb_be/symbolization.s b/testsuite/tests/Disassemblers/thumb_be/symbolization.s new file mode 100644 index 000000000..ff0dad4a9 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_be/symbolization.s @@ -0,0 +1,19 @@ + .text + .arch armv4t + .syntax unified + .thumb + .align 0 + + .type f, %function +f: + adds r0, #3 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + movs r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/thumb_le/symbolization.baseline b/testsuite/tests/Disassemblers/thumb_le/symbolization.baseline new file mode 100644 index 000000000..884766d65 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_le/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-0000000b +: +00000000 -: 03 30 adds r0, #3 +00000002 -: ff e7 b.n 0x4 +00000004 -: f7 46 mov pc, lr +: +00000006 -: 01 20 movs r0, #1 +00000008 -: ff f7 fa ff bl 0x0 diff --git a/testsuite/tests/Disassemblers/thumb_le/symbolization.s b/testsuite/tests/Disassemblers/thumb_le/symbolization.s new file mode 100644 index 000000000..ff0dad4a9 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_le/symbolization.s @@ -0,0 +1,19 @@ + .text + .arch armv4t + .syntax unified + .thumb + .align 0 + + .type f, %function +f: + adds r0, #3 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + movs r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/x86/symbolization.baseline b/testsuite/tests/Disassemblers/x86/symbolization.baseline new file mode 100644 index 000000000..12a8393d7 --- /dev/null +++ b/testsuite/tests/Disassemblers/x86/symbolization.baseline @@ -0,0 +1,10 @@ +Section .text: 00000000-00000011 +: +00000000 -: 83 c0 02 add $0x2,%eax +00000003 -: eb 01 jmp 0x6 +00000005 -: 90 nop +00000006 -: c3 ret +: +00000007 -: b8 01 00 00 00 mov $0x1,%eax +0000000c -: e8 ef ff ff ff call 0x0 +00000011 -: c3 ret diff --git a/testsuite/tests/Disassemblers/x86/symbolization.s b/testsuite/tests/Disassemblers/x86/symbolization.s new file mode 100644 index 000000000..b595b820b --- /dev/null +++ b/testsuite/tests/Disassemblers/x86/symbolization.s @@ -0,0 +1,17 @@ + .text + + .type f, %function +f: + add $2, %eax + jmp local + nop +local: + ret + .size f, .-f + + .type foo, %function +foo: + mov $1, %eax + call f + ret + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/x86_64/symbolization.baseline b/testsuite/tests/Disassemblers/x86_64/symbolization.baseline new file mode 100644 index 000000000..bb4ea5a2f --- /dev/null +++ b/testsuite/tests/Disassemblers/x86_64/symbolization.baseline @@ -0,0 +1,10 @@ +Section .text: 0000000000000000-0000000000000011 +: +0000000000000000 -: 83 c0 02 add $0x2,%eax +0000000000000003 -: eb 01 jmp 0x6 +0000000000000005 -: 90 nop +0000000000000006 -: c3 ret +: +0000000000000007 -: b8 01 00 00 00 mov $0x1,%eax +000000000000000c -: e8 ef ff ff ff call 0x0 +0000000000000011 -: c3 ret diff --git a/testsuite/tests/Disassemblers/x86_64/symbolization.s b/testsuite/tests/Disassemblers/x86_64/symbolization.s new file mode 100644 index 000000000..b595b820b --- /dev/null +++ b/testsuite/tests/Disassemblers/x86_64/symbolization.s @@ -0,0 +1,17 @@ + .text + + .type f, %function +f: + add $2, %eax + jmp local + nop +local: + ret + .size f, .-f + + .type foo, %function +foo: + mov $1, %eax + call f + ret + .size foo, .-foo diff --git a/testsuite/tests/FullRuntime/Barrier/src/buffer.adb b/testsuite/tests/FullRuntime/Barrier/src/buffer.adb new file mode 100644 index 000000000..94d929115 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/buffer.adb @@ -0,0 +1,31 @@ +with GNAT.IO; use GNAT.IO; + +package body Buffer is + + protected body Buffer is + + entry Push (V : Integer; Tell : Boolean) + when not Has_Value -- # push_guard + is + begin + if Tell then -- # push_test_tell + Put_Line ("push " & Integer'Image (V)); -- # push_tell + end if; + Value := V; -- # push_do + Has_Value := True; -- # push_do + end Push; + + entry Pop (V : out Integer; Tell : Boolean) + when Has_Value -- # pop_guard + is + begin + if Tell then -- # pop_test_tell + Put_Line ("pop " & Integer'Image (V)); -- # pop_tell + end if; + V := Value; -- # pop_do + Has_Value := False; -- # pop_do + end Pop; + + end Buffer; + +end Buffer; diff --git a/testsuite/tests/FullRuntime/Barrier/src/buffer.ads b/testsuite/tests/FullRuntime/Barrier/src/buffer.ads new file mode 100644 index 000000000..ab1d4edc6 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/buffer.ads @@ -0,0 +1,18 @@ +package Buffer is + + protected type Buffer is + + -- Synchronisation buffer for two threads. + + entry Push (V : Integer; Tell : Boolean); + -- Hang until the buffer is free and fill it with V + + entry Pop (V : out Integer; Tell : Boolean); + -- Hang until the buffer is filled, set V and make the buffer empty + + private + Value : Integer; -- # component_decl + Has_Value : Boolean := False; -- # component_decl + end; + +end Buffer; diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb new file mode 100644 index 000000000..c5826104d --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb @@ -0,0 +1,38 @@ +with Buffer; + +procedure Test_Pop is + Buf : Buffer.Buffer; + V : Integer; +begin + select + Buf.Pop (V, False); + else + null; + end select; +end Test_Pop; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l- ## s- +-- =/push_test_tell/ l- ## s- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l- ## s- +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/push_guard/ l- ## d- +-- =/push_do/ l- ## s- +-- =/push_test_tell/ l- ## s- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l! ## dT- +-- =/pop_do/ l- ## s- +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb new file mode 100644 index 000000000..7e0248e85 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb @@ -0,0 +1,45 @@ +with Buffer; + +procedure Test_Pop_Push_Pop is + Buf : Buffer.Buffer; + V : Integer; +begin + select + Buf.Pop (V, False); + else + null; + end select; + V := 1; + Buf.Push (V, True); + V := 2; + Buf.Pop (V, False); + if V /= 1 then + raise Program_Error; + end if; +end Test_Pop_Push_Pop; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l+ ## 0 +-- =/push_tell/ l+ ## 0 +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/push_guard/ l! ## dF- +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l! ## dF- +-- =/push_tell/ l+ ## 0 +-- =/pop_guard/ l+ ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l! ## dT- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_push.adb b/testsuite/tests/FullRuntime/Barrier/src/test_push.adb new file mode 100644 index 000000000..59959554d --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_push.adb @@ -0,0 +1,32 @@ +with Buffer; + +procedure Test_Push is + Buf : Buffer.Buffer; +begin + Buf.Push (1, False); +end Test_Push; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l+ ## 0 +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l- ## s- +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/push_guard/ l! ## dF- +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l! ## dT- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l- ## d- +-- =/pop_do/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb new file mode 100644 index 000000000..b2b6f40d2 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb @@ -0,0 +1,45 @@ +with Buffer; + +procedure Test_Push_Push_Pop is + Buf : Buffer.Buffer; + V : Integer; +begin + V := 1; + Buf.Push (V, False); + select + Buf.Push (V, False); + else + null; + end select; + V := 2; + Buf.Pop (V, True); + if V /= 1 then + raise Program_Error; + end if; +end Test_Push_Push_Pop; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l+ ## 0 +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l+ ## 0 +-- =/pop_test_tell/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/push_guard/ l+ ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l! ## dT- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l! ## dF- +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l+ ## 0 +-- =/pop_test_tell/ l! ## dF- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/test.opt b/testsuite/tests/FullRuntime/Barrier/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/Barrier/test.py b/testsuite/tests/FullRuntime/Barrier/test.py new file mode 100644 index 000000000..5541cb162 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in (CAT.stmt, CAT.decision): + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb new file mode 100644 index 000000000..6eb5a9f71 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb @@ -0,0 +1,55 @@ +with Ada.Real_Time; use Ada.Real_Time; +with Ada.Text_IO; use Ada.Text_IO; + +package body Ops is + + task type Opmaster is + entry Start (O : Opkind); + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Start (O : Opkind) do -- # compute + Op := O; -- # compute + end Start; + + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + + end; + or + delay To_Duration (Minutes (1)); + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Seconds (1); -- # compute + Put_Line ("T.Compute timed out"); -- # sometimes-timeout + end select; + + T.Start (Op); -- # compute + + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Minutes (1); + Put_Line ("T.Compute timed out"); -- # never-timeout + end select; + + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb new file mode 100644 index 000000000..049a9f393 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb @@ -0,0 +1,55 @@ +with Ada.Real_Time; use Ada.Real_Time; +with Ada.Text_IO; use Ada.Text_IO; + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Start (O : Opkind); + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Start (O : Opkind) do -- # compute + Op := O; -- # compute + end Start; + + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + + end; + or + delay To_Duration (Minutes (1)); + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Seconds (1); -- # compute + Put_Line ("T.Compute timed out"); -- # sometimes-timeout + end select; + + T.Start (Op); -- # compute + + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Minutes (1); + Put_Line ("T.Compute timed out"); -- # never-timeout + end select; + + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb new file mode 100644 index 000000000..e4f98a001 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb @@ -0,0 +1,40 @@ + +package body Ops is + + task type Opmaster is + entry Stop; + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Stop; -- # kill + else + + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb new file mode 100644 index 000000000..388320369 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb @@ -0,0 +1,39 @@ +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Stop; + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Stop; -- # kill + else + + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb new file mode 100644 index 000000000..5efebbe67 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb @@ -0,0 +1,34 @@ + +package body Ops is + + task type Opmaster is + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb new file mode 100644 index 000000000..2afa64c07 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb @@ -0,0 +1,34 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb new file mode 100644 index 000000000..3ca416bfc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb @@ -0,0 +1,38 @@ + +package body Ops is + + task type Opmaster (Op : Opkind) is + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + loop + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + or + terminate; + end select; + end loop; + end; + + + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + T_And : Opmaster (Op_And); + T_Or : Opmaster (Op_Or); + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T_And.Compute (A, B, Result); -- # do_and + when Op_Or => T_Or.Compute (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb new file mode 100644 index 000000000..98ba96163 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb @@ -0,0 +1,38 @@ +with Ada.Real_Time; use Ada.Real_Time; + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster (Op : Opkind) is + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + loop + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + or + terminate; + end select; + end loop; + end; + + T_And : Opmaster (Op_And); + T_Or : Opmaster (Op_Or); + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T_And.Compute (A, B, Result); -- # do_and + when Op_Or => T_Or.Compute (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb new file mode 100644 index 000000000..6013c8d85 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb @@ -0,0 +1,44 @@ + +package body Ops is + + task type Opmaster is + entry Push_Opkind (O : Opkind); + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Push_Opkind (O : Opkind) do -- # compute + Op := O; -- # compute + end Push_Opkind; + + select -- # compute + when Op = Op_And => + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + when Op = Op_Or => + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + T.Push_Opkind (Op); -- # compute + + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb new file mode 100644 index 000000000..1bf8daf90 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb @@ -0,0 +1,44 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Push_Opkind (O : Opkind); + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Push_Opkind (O : Opkind) do -- # compute + Op := O; -- # compute + end Push_Opkind; + + select -- # compute + when Op = Op_And => + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + when Op = Op_Or => + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + T.Push_Opkind (Op); -- # compute + + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb new file mode 100644 index 000000000..4b8a793f0 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb @@ -0,0 +1,29 @@ + +package body Ops is + + task type Opmaster is + entry Compute (Op : Opkind; A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + accept Compute + (Op : Opkind; A, B : Boolean; Result : out Boolean) + do + case Op is + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + T.Compute (Op, A, B, Result); -- # compute + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb new file mode 100644 index 000000000..845780d63 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb @@ -0,0 +1,27 @@ +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task T is + entry Compute (Op : Opkind; A, B : Boolean; Result : out Boolean); + end; + + task body T is + begin + accept Compute + (Op : Opkind; A, B : Boolean; Result : out Boolean) + do + case Op is + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + end; + + Result : Boolean; + begin + T.Compute (Op, A, B, Result); -- # compute + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads b/testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads new file mode 100644 index 000000000..cbbc1b55b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads @@ -0,0 +1,4 @@ +package Ops is + type Opkind is (Op_And, Op_Or); + function Compute (Op : Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb b/testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb new file mode 100644 index 000000000..7c764a7c1 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb @@ -0,0 +1,15 @@ +with Support, Ops; use Support, Ops; + +procedure Test_0 is +begin + Assert (True); +end; + + +--# ops.adb +-- /do_and/ l- ## s- +-- /do_or/ l- ## s- +-- /compute/ l- ## s- +-- /kill/ l- ## s- +-- /sometimes-timeout/ l- ## s- +-- /never-timeout/ l- ## s- diff --git a/testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb b/testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb new file mode 100644 index 000000000..2b264422e --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb @@ -0,0 +1,15 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_And_TT is +begin + Assert (Ops.Compute (Op_And, True, True) = True); +end; + + +--# ops.adb +-- /do_and/ l+ ## 0 +-- /do_or/ l- ## s- +-- /compute/ l+ ## 0 +-- /kill/ l- ## s- +-- /sometimes-timeout/ l+ ## 0 +-- /never-timeout/ l- ## s- diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb new file mode 100644 index 000000000..c49c2310b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb @@ -0,0 +1,56 @@ + +package body Ops is + + protected type Opmaster is + entry Take_And; + entry Take_Or; + procedure Release; + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + Free : Boolean := True; -- # decl + Count : Natural := 0; -- # decl + end Opmaster; + + protected body Opmaster is + entry Take_And when Op = Op_And or else Count = 0 is + begin + Count := Count + 1; -- # do_and + Op := Op_And; -- # do_and + end Take_And; + + entry Take_Or when Op = Op_Or or else Count = 0 is + begin + Count := Count + 1; -- # do_or + Op := Op_Or; -- # do_or + end Take_Or; + + procedure Release is + begin + Count := Count - 1; -- # compute + end Release; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + PO : Opmaster; -- # compute + Result : Boolean; + begin + case Op is -- # compute + when Op_And => PO.Take_And; -- # do_and + when Op_Or => PO.Take_Or; -- # do_or + end case; + PO.Compute (A, B, Result); -- # compute + PO.Release; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb new file mode 100644 index 000000000..d2479cf52 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb @@ -0,0 +1,57 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + protected type Opmaster is + entry Take_And; + entry Take_Or; + procedure Release; + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + Free : Boolean := True; -- # decl + Count : Natural := 0; -- # decl + end Opmaster; + + protected body Opmaster is + entry Take_And when Op = Op_And or else Count = 0 is + begin + Count := Count + 1; -- # do_and + Op := Op_And; -- # do_and + end Take_And; + + entry Take_Or when Op = Op_Or or else Count = 0 is + begin + Count := Count + 1; -- # do_or + Op := Op_Or; -- # do_or + end Take_Or; + + procedure Release is + begin + Count := Count - 1; -- # compute + end Release; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + PO : Opmaster; -- # compute + Result : Boolean; + begin + case Op is -- # compute + when Op_And => PO.Take_And; -- # do_and + when Op_Or => PO.Take_Or; -- # do_or + end case; + PO.Compute (A, B, Result); -- # compute + PO.Release; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb new file mode 100644 index 000000000..dadb5df12 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb @@ -0,0 +1,36 @@ + +package body Ops is + + protected type Opmaster is + procedure Set_Op (O : Opkind); + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + end Opmaster; + + protected body Opmaster is + procedure Set_Op (O : Opkind) is + begin + Op := O; -- # compute + end Set_Op; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + PO : Opmaster; + Result : Boolean; + begin + PO.Set_Op (Op); -- # compute + PO.Compute (A, B, Result); -- # compute + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb new file mode 100644 index 000000000..f6136a21b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb @@ -0,0 +1,37 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + protected type Opmaster is + procedure Set_Op (O : Opkind); + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + end Opmaster; + + protected body Opmaster is + procedure Set_Op (O : Opkind) is + begin + Op := O; -- # compute + end Set_Op; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + PO : Opmaster; + Result : Boolean; + begin + PO.Set_Op (Op); -- # compute + PO.Compute (A, B, Result); -- # compute + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads new file mode 100644 index 000000000..cbbc1b55b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads @@ -0,0 +1,4 @@ +package Ops is + type Opkind is (Op_And, Op_Or); + function Compute (Op : Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb new file mode 100644 index 000000000..a684509e3 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb @@ -0,0 +1,13 @@ +with Support, Ops; use Support, Ops; + +procedure Test_0 is +begin + Assert (True); +end; + + +--# ops.adb +-- /do_and/ l- ## s- +-- /do_or/ l- ## s- +-- /compute/ l- ## s- +-- /decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb new file mode 100644 index 000000000..ab7f704af --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb @@ -0,0 +1,13 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_And_TT is +begin + Assert (Ops.Compute (Op_And, True, True) = True); +end; + + +--# ops.adb +-- /do_and/ l+ ## 0 +-- /do_or/ l- ## s- +-- /compute/ l+ ## 0 +-- /decl/ l+ ## 0 diff --git a/testsuite/tests/HA16-013_cleanups/src/assert.adb b/testsuite/tests/HA16-013_cleanups/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/p1.adb b/testsuite/tests/HA16-013_cleanups/src/p1.adb new file mode 100644 index 000000000..5c5de3729 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/p1.adb @@ -0,0 +1,8 @@ +with Vars; +procedure P1 is + S : string (1 .. Vars.N); + pragma Volatile (S); +begin + Vars.Raise_PE; -- # call_raise + Vars.Post_Raise; -- # post_raise +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/p2.adb b/testsuite/tests/HA16-013_cleanups/src/p2.adb new file mode 100644 index 000000000..d4476b909 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/p2.adb @@ -0,0 +1,11 @@ +with Vars; +procedure P2 is +begin + declare + S : string (1 .. Vars.N); + pragma Volatile (S); + begin + Vars.Raise_PE; -- # call_raise + Vars.Post_Raise; -- # post_raise + end; +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb b/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb new file mode 100644 index 000000000..ed582d1c8 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb @@ -0,0 +1,23 @@ +with Vars, P1, P2, Assert; + +procedure Test_Blobs is +begin + begin + P1; + Assert (Vars.N_Post_Raise = 0); + exception + when Program_Error => null; + end; + + begin + P2; + Assert (Vars.N_Post_Raise = 0); + exception + when Program_Error => null; + end; + +end; + +--# p1.adb p2.adb vars.adb +-- /call_raise/ l+ ## 0 +-- /post_raise/ l- ## s- diff --git a/testsuite/tests/HA16-013_cleanups/src/vars.adb b/testsuite/tests/HA16-013_cleanups/src/vars.adb new file mode 100644 index 000000000..3256dc1f6 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/vars.adb @@ -0,0 +1,11 @@ +package body Vars is + procedure Raise_PE is + begin + raise Program_Error; -- # call_raise + end; + + procedure Post_Raise is + begin + N_Post_Raise := N_Post_Raise + 1; -- # post_raise + end; +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/vars.ads b/testsuite/tests/HA16-013_cleanups/src/vars.ads new file mode 100644 index 000000000..3e41e958b --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/vars.ads @@ -0,0 +1,9 @@ +package Vars is + + N : Integer := 12; -- to be used for VLA sizing + + procedure Raise_PE; + + procedure Post_Raise; + N_Post_Raise : Integer := 0; +end; diff --git a/testsuite/tests/HA16-013_cleanups/test.opt b/testsuite/tests/HA16-013_cleanups/test.opt new file mode 100644 index 000000000..6ee8973ff --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test on exception propagation cleanups, zfp-irrelevant +RTS_LIGHT_TASKING DEAD test on exception propagation cleanups, light-tasking irrelevant +block DEAD Exception breaking the control flow diff --git a/testsuite/tests/HA16-013_cleanups/test.py b/testsuite/tests/HA16-013_cleanups/test.py new file mode 100644 index 000000000..3a558099a --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(category=None).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt new file mode 100644 index 000000000..878ab70b6 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt @@ -0,0 +1 @@ +CARGS_O1 DEAD already testing with both -O0 and -O1 diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py new file mode 100644 index 000000000..939a5bcbb --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py @@ -0,0 +1,29 @@ +""" +Check that gnatcov tries and fails to consolidate two "f" symbols, both with +debug information and from the same compilation unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# Test expectations +test_drivers = { + "test_1": {"not.c": ["-g", "-O0"]}, + "test_2": {"not.c": ["-g", "-O1"]}, +} +coverage_expectations = { + # The two not.c:f() are compiled with different levels of optimization. In + # object coverage, gnatcov is supposed to fail: there is no coverage + # expectation. + "f": {"-": 0, "!": 0, "+": 0}, +} + +tc = TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../src"] +) +thistest.fail_if( + tc.run(register_failure=False), + '"gnatcov coverage" was supposed to fail, but it did not', +) +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py new file mode 100644 index 000000000..775f7d866 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py @@ -0,0 +1,28 @@ +""" +Check that "f" symbols, both with debug information but from different +compilation units, are not consolidated. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# Test expectations. All compile units have debug symbols. +switches = ["-O0", "-g"] +test_drivers = { + "test_1": {"not.c": switches, "fact.c": switches}, + "test_2": {"not.c": switches, "fact.c": switches}, +} +coverage_expectations = { + # - In test_1, not.c:f() is partially covered + # - In test_2, fact.c:f() is fully covered + # + # There is no consolidation, so there will be one partially covered + # routine and one fully covered one. + "f": {"-": 0, "!": 1, "+": 1}, +} + +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c new file mode 100644 index 000000000..6043eafd3 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c @@ -0,0 +1,8 @@ +#include "fact.h" + +int +main (void) +{ + compute_fact (2); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py new file mode 100644 index 000000000..127c55748 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py @@ -0,0 +1,22 @@ +""" +Check that "f" symbols, both with debug information and from the same +compilation unit, are consolidated. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + +switches = ["-O0", "-g"] + +# Test expectations +test_drivers = {"test_1": {"not.c": switches}, "test_2": {"not.c": switches}} +coverage_expectations = { + # Both not.c:f() are partially covered (each one covers a complementary + # part), so there is one fully covered routine after consolidation. + "f": {"-": 0, "!": 0, "+": 1}, +} + +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt new file mode 100644 index 000000000..5a7a8f08f --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt @@ -0,0 +1 @@ +Test the requirement: consolidates two symbols if and only if they have the same compilation unit. diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py new file mode 100644 index 000000000..06ecb1609 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py @@ -0,0 +1,36 @@ +""" +Check that "f" symbols, one with (in "test_1.c") and the other without debug +information (in "test_2.c") are not consolidated whereas they are in the same +compile unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = { + "test_1": {"not.c": ["-g", "-O0"]}, + "test_2": {"not.c": ["-g", "-O0"]}, + "test_3": {"not.c": ["-g0", "-O0"]}, +} +# Here, the "not.c" compile unit has debug info except in one test driver (the +# last one). + +coverage_expectations = { + # - In test_1, not.c:f() is half-covered + # - The other half is covered in test_2 + # - Some part is covered in test_3 + # + # test_1 and test_2 are consolidated, so there must be one f() that is + # fully covered. One other is partially covered for test_3 that do not + # consolidate. + "f": {"-": 0, "!": 1, "+": 1}, +} + +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py new file mode 100644 index 000000000..09cea09d3 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py @@ -0,0 +1,29 @@ +""" +Check that "f" symbols, one with (in "test_1.c") and the other without debug +information (in "test_2.c") are not consolidated whereas they are in the same +compile unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = { + "test_1": {"not.c": ["-g0", "-O0"]}, + "test_2": {"not.c": ["-g", "-O0"]}, +} +# Here, the "not.c" compile unit has debug info only in one test driver. + +coverage_expectations = { + # Both not.c:f() are partially covered (each one covers a complementary + # part, so they would be fully covered if consolidated). + "f": {"-": 0, "!": 2, "+": 0}, +} + +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py new file mode 100644 index 000000000..8b5c1a17b --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py @@ -0,0 +1,29 @@ +""" +Check that "f" symbols, both without debug information, in "test_1.c" and +"test_2.c" are not consolidated (they are not in the same compile unit, +anyway). +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = { + "test_1": {"not.c": ["-g0", "-O0"]}, + "test_2": {"fact.c": ["-g0", "-O0"]}, +} +# Here, no compile unit has specific compilation flag: no one has debug info. + +coverage_expectations = { + # not.c:f() is fully covered + # fact.c:f() is partially covered + "f": {"-": 0, "!": 1, "+": 1}, +} + +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c new file mode 100644 index 000000000..8ec4a4109 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c @@ -0,0 +1,9 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c new file mode 100644 index 000000000..c4963c184 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "fact.h" + +int +main (void) +{ + compute_fact (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py new file mode 100644 index 000000000..b3cae45e4 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py @@ -0,0 +1,28 @@ +""" +Check that "f" symbols, both without debug information, in "test_1.c" and +"test_2.c" are not consolidated whereas they are in the same compile unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = { + "test_1": {"not.c": ["-g0", "-O0"]}, + "test_2": {"not.c": ["-g0", "-O0"]}, +} +# Here, no compile unit has debug info. + +coverage_expectations = { + # Both not.c:f() are partially covered (each one covers a complementary + # part, so they would be fully covered if consolidated). + "f": {"-": 0, "!": 2, "+": 0}, +} + +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt new file mode 100644 index 000000000..410189baf --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt @@ -0,0 +1 @@ +Test the requirement: if a symbol has no compilation unit, never consolidate it. diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt b/testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt new file mode 100644 index 000000000..d419f4d90 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt @@ -0,0 +1,13 @@ +drivers=test_12|test_13 + +--# fact.c +-- /fact-partial/ l+ ## 0 +-- /fact-full/ l+ ## 0 + +--# not.c +-- /not-all/ l+ ## 0 +-- /not-false/ l+ ## 0 +-- /not-true/ l- ## s- + +--# double.c +-- /double-partial/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c new file mode 100644 index 000000000..94f852ada --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c @@ -0,0 +1,19 @@ +#include "fact.h" +#include "not.h" + +int +main (void) +{ + compute_fact (2); + compute_not (0); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l+ ## 0 + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c new file mode 100644 index 000000000..2f5883337 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c @@ -0,0 +1,17 @@ +#include "double.h" +#include "fact.h" + +int +main (void) +{ + compute_fact (0); + compute_double (0); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l- ## s- + +//# double.c +// /double-partial/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list new file mode 100644 index 000000000..7173224ec --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list @@ -0,0 +1 @@ +test_1-obj/not.gli diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt new file mode 100644 index 000000000..28d2879e2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt @@ -0,0 +1,2 @@ +CARGS_O1 DEAD already testing with both -O0 and -O1 +src-traces DEAD test for binary traces diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py new file mode 100644 index 000000000..459438a66 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py @@ -0,0 +1,38 @@ +""" +Check that gnatcov tries and fails to consolidate in source coverage two "f" +symbols, both with debug information and from the same compilation unit, but +compiled with different options. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest +from SUITE.cutils import Wdir + + +test_drivers = {"test_1": {"not.c": ["-O0"]}, "test_2": {"not.c": ["-O1"]}} +coverage_expectations = { + # There is no object coverage expectation. This entry is to add "f" to the + # routines to consolidate. + "f": None, +} + +# SCOs are the same for each project: not.gli +wd = Wdir("tmp_") +with open("scos.list", "w") as f: + for sco_f in ["not.gli"]: + f.write("test_1-obj/{}\n".format(sco_f)) +wd.to_homedir() + +tc = TestCase( + test_drivers, + coverage_expectations, + extra_sourcedirs=["../../../src"], + level="stmt", + annotate="xcov", + extra_xcov_args=["--scos=@scos.list"], +) +thistest.fail_if( + tc.run(register_failure=False), + '"gnatcov coverage" was supposed to fail, but it did not', +) +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt new file mode 100644 index 000000000..022f07853 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt @@ -0,0 +1,7 @@ +drivers=test_1|test_2 + +--# sum.c +-- /sum-all/ l+ ## 0 +-- /sum-add/ l+ ## 0 +-- /sum-sub/ l+ ## 0 +-- /sum-none/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c new file mode 100644 index 000000000..46211a0b3 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c @@ -0,0 +1,15 @@ +#include "sum.h" + +int +main (void) +{ + int array[4] = { 1, 2, 3, 4 }; + compute_sum (array, 4, SUM_ADD); + return 0; +} + +//# sum.c +// /sum-all/ l+ ## 0 +// /sum-add/ l+ ## 0 +// /sum-sub/ l- ## s- +// /sum-none/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c new file mode 100644 index 000000000..34f83a4db --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c @@ -0,0 +1,15 @@ +#include "sum.h" + +int +main (void) +{ + int array[4] = { 1, 2, 3, 4 }; + compute_sum (array, 4, SUM_SUB); + return 0; +} + +//# sum.c +// /sum-all/ l+ ## 0 +// /sum-add/ l- ## s- +// /sum-sub/ l+ ## 0 +// /sum-none/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py new file mode 100644 index 000000000..4b0979927 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(extracargs="-ffunction-sections", category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c new file mode 100644 index 000000000..97460f972 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c @@ -0,0 +1,21 @@ +#include "fact.h" +#include "not.h" + +int +main (void) +{ + compute_fact (0); + compute_fact (2); + compute_not (0); + compute_not (1); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l+ ## 0 + +//# not.c +// /not-all/ l+ ## 0 +// /not-true/ l+ ## 0 +// /not-false/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c new file mode 100644 index 000000000..761181c21 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c @@ -0,0 +1,26 @@ +#include "fact.h" +#include "not.h" + +int cov = 0; + +int +main (void) +{ + /* Never call "run*", but reference then anyway so that they are included by + the linker (gnatcov will not cover them otherwise). */ + if (cov) + { + compute_fact (0); + compute_not (0); + } + return 0; +} + +//# fact.c +// /fact-partial/ l- ## s- +// /fact-full/ l- ## s- + +//# not.c +// /not-all/ l- ## s- +// /not-true/ l- ## s- +// /not-false/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c new file mode 100644 index 000000000..7b3629595 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c @@ -0,0 +1,19 @@ +#include "fact.h" +#include "not.h" + +int +main (void) +{ + compute_fact (0); + compute_not (0); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l- ## s- + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt new file mode 100644 index 000000000..d53ece098 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt @@ -0,0 +1,10 @@ +drivers=test_1|test_2 + +--# not.c +-- /not-all/ l+ ## 0 +-- /not-false/ l+ ## 0 +-- /not-true/ l- ## s- + +--# fact.c +-- /fact-partial/ l+ ## 0 +-- /fact-full/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c new file mode 100644 index 000000000..695d20bf5 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c @@ -0,0 +1,13 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c new file mode 100644 index 000000000..54bd12dac --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c @@ -0,0 +1,12 @@ +#include "fact.h" + +int +main (void) +{ + compute_fact (2); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt new file mode 100644 index 000000000..f3a30cfdf --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt @@ -0,0 +1,6 @@ +drivers=test_1|test_2 + +--# not.c +-- /not-all/ l+ ## 0 +-- /not-false/ l+ ## 0 +-- /not-true/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c new file mode 100644 index 000000000..695d20bf5 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c @@ -0,0 +1,13 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c new file mode 100644 index 000000000..ff3c92326 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c @@ -0,0 +1,13 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l- ## s- +// /not-true/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/extra.opt b/testsuite/tests/HomonymSymbols/extra.opt new file mode 100644 index 000000000..4ad105b5d --- /dev/null +++ b/testsuite/tests/HomonymSymbols/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD C specific tests for which 7.0.3 misses proper SCO support +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/HomonymSymbols/src/double.c b/testsuite/tests/HomonymSymbols/src/double.c new file mode 100644 index 000000000..fead82d16 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/double.c @@ -0,0 +1,13 @@ +#include "double.h" + +static int +f (int n) +{ + return 2 * n; // # double-partial +} + +int +compute_double (int n) +{ + return f (n); // # double-partial +} diff --git a/testsuite/tests/HomonymSymbols/src/double.h b/testsuite/tests/HomonymSymbols/src/double.h new file mode 100644 index 000000000..9ad39f0b6 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/double.h @@ -0,0 +1,6 @@ +#ifndef DOUBLE_H +#define DOUBLE_H + +int compute_double (int n); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/fact.c b/testsuite/tests/HomonymSymbols/src/fact.c new file mode 100644 index 000000000..8a9a0bc1b --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/fact.c @@ -0,0 +1,16 @@ +#include "fact.h" + +static int +f (int n) +{ + if (n <= 1) // # fact-partial + return 1; // # fact-partial + else + return n * f (n - 1); // # fact-full +} + +int +compute_fact (int n) +{ + return f (n); // # fact-partial +} diff --git a/testsuite/tests/HomonymSymbols/src/fact.h b/testsuite/tests/HomonymSymbols/src/fact.h new file mode 100644 index 000000000..503d565a9 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/fact.h @@ -0,0 +1,6 @@ +#ifndef FACT_H +#define FACT_H + +int compute_fact (int n); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/not.c b/testsuite/tests/HomonymSymbols/src/not.c new file mode 100644 index 000000000..dac4eea81 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/not.c @@ -0,0 +1,20 @@ +#include "not.h" +#include "support.h" + +/* -O1 removes this "f" function if it is static. */ +int +f (int b) +{ + /* -O1 inlines the call to "f" from "compute_not" without the following call + to "identity". Inlining yields unexpected results in object coverage. */ + if (!identity (b)) // # not-all + return 1; // # not-false + else + return 0; // # not-true +} + +int +compute_not (int b) +{ + return f (b); // # not-all +} diff --git a/testsuite/tests/HomonymSymbols/src/not.h b/testsuite/tests/HomonymSymbols/src/not.h new file mode 100644 index 000000000..d2d644515 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/not.h @@ -0,0 +1,6 @@ +#ifndef NOT_H +#define NOT_H + +int compute_not (int b); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/sum.c b/testsuite/tests/HomonymSymbols/src/sum.c new file mode 100644 index 000000000..b44b438bb --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/sum.c @@ -0,0 +1,42 @@ +#include "sum.h" + +int +sum_add (int *array, unsigned size) +{ + int result = 0; // # sum-add + unsigned i = 0; // # sum-add + + while (i < size) // # sum-add + { + result += array[i]; // # sum-add + ++i; // # sum-add + } + + return result; // # sum-add +} + +int +sum_sub (int *array, unsigned size) +{ + int result = 0; // # sum-sub + unsigned i = 0; // # sum-sub + + while (i < size) // # sum-sub + { + result -= array[i]; // # sum-sub + ++i; // # sum-sub + } + + return result; // # sum-sub +} + +int +compute_sum (int *array, unsigned size, int mode) +{ + if (mode == SUM_ADD) // # sum-all + return sum_add (array, size); // # sum-add + else if (mode == SUM_SUB) // # sum-sub + return sum_sub (array, size); // # sum-sub + else + return 0; // # sum-none +} diff --git a/testsuite/tests/HomonymSymbols/src/sum.h b/testsuite/tests/HomonymSymbols/src/sum.h new file mode 100644 index 000000000..dff60f1d7 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/sum.h @@ -0,0 +1,9 @@ +#ifndef SUM_H +#define SUM_H + +#define SUM_ADD 1 +#define SUM_SUB 2 + +int compute_sum (int *array, unsigned size, int mode); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/support.h b/testsuite/tests/HomonymSymbols/src/support.h new file mode 100644 index 000000000..6b0c268fc --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/support.h @@ -0,0 +1,6 @@ +#ifndef SUPPORT_H +#define SUPPORT_H + +extern int identity (int n); /* from libsupport. */ + +#endif diff --git a/testsuite/tests/I401-009/src/engines.adb b/testsuite/tests/I401-009/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/I401-009/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/I401-009/src/engines.ads b/testsuite/tests/I401-009/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/I401-009/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/I401-009/src/test_engines.adb b/testsuite/tests/I401-009/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/I401-009/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/I401-009/test.opt b/testsuite/tests/I401-009/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I401-009/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I401-009/test.py b/testsuite/tests/I401-009/test.py new file mode 100644 index 000000000..e62a28f4f --- /dev/null +++ b/testsuite/tests/I401-009/test.py @@ -0,0 +1,33 @@ +""" +We run a partial test of the simple 'engines' example and expect the analyzer +to report only partial coverage of the relevant subprogram return statement. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +gprbuild(gprfor(["test_engines.adb"], srcdirs="../src")) + +xrun(exepath_to("test_engines")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + tracename_for("test_engines"), + ] +) + +thistest.fail_if(not match(r" \!:.*return.*Stable_P", "engines.adb.xcov")) +thistest.result() diff --git a/testsuite/tests/I427-029/src/assert.adb b/testsuite/tests/I427-029/src/assert.adb new file mode 100644 index 000000000..075669142 --- /dev/null +++ b/testsuite/tests/I427-029/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (X : Boolean) is +begin + if not X then + raise Program_Error; + end if; +end Assert; diff --git a/testsuite/tests/I427-029/src/engines.adb b/testsuite/tests/I427-029/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/I427-029/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/I427-029/src/engines.ads b/testsuite/tests/I427-029/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/I427-029/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/I427-029/src/test_engines_mm.adb b/testsuite/tests/I427-029/src/test_engines_mm.adb new file mode 100644 index 000000000..3d1303e2a --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_mm.adb @@ -0,0 +1,11 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_MM is + E : Engine; +begin + -- MM case: Both values set to stability threshold Minus one + + E.P := Stable_P - 1; + E.T := Stable_T - 1; + Assert (Stable (E)); +end; diff --git a/testsuite/tests/I427-029/src/test_engines_mp.adb b/testsuite/tests/I427-029/src/test_engines_mp.adb new file mode 100644 index 000000000..6c6f50445 --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_mp.adb @@ -0,0 +1,9 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_MP is + E : Engine; +begin + E.P := Stable_P - 1; + E.T := Stable_T + 1; + Assert (not Stable (E)); +end; diff --git a/testsuite/tests/I427-029/src/test_engines_pm.adb b/testsuite/tests/I427-029/src/test_engines_pm.adb new file mode 100644 index 000000000..c2964b30a --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_pm.adb @@ -0,0 +1,9 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_PM is + E : Engine; +begin + E.P := Stable_P + 1; + E.T := Stable_T - 1; + Assert (not Stable (E)); +end; diff --git a/testsuite/tests/I427-029/src/test_engines_pp.adb b/testsuite/tests/I427-029/src/test_engines_pp.adb new file mode 100644 index 000000000..34176836f --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_pp.adb @@ -0,0 +1,11 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_PP is + E : Engine; +begin + -- PP case: Both values set to stability threshold Plus one + + E.P := Stable_P + 1; + E.T := Stable_T + 1; + Assert (not Stable (E)); +end; diff --git a/testsuite/tests/I427-029/test.opt b/testsuite/tests/I427-029/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I427-029/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I427-029/test.py b/testsuite/tests/I427-029/test.py new file mode 100644 index 000000000..021b5f14b --- /dev/null +++ b/testsuite/tests/I427-029/test.py @@ -0,0 +1,139 @@ +""" +Perform a bunch of xcov related operations to validate the basic toolset +functionalities. +""" + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + maybe_valgrind, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +# Context information, basic command line interface checks +print("maybe_valgrind prepends ... " + str(maybe_valgrind([]))) +xcov(["--version"]) +xcov(["--help"]) + +# Core functions checks over the Engines example + +# We will first work on a set of operations around the "engines" simple +# example, with different executables to exercise various combinations of +# value/thresold relationships on pressure and temperature. +# +# Each variant sets the engine P/T parameters to the P/T stability threshold +# plus or minus one and checks that the Stable function returns the expected +# value. Doing so, it exercises a subset of the possible path combinations +# through the function return boolean expression. +# +# We name each variant with a couple of letters, one per Pressure/Temperature +# parameter, each either P or M to denote whether the parameter is set to the +# threshold Plus or Minus one. +variants = ["mm", "mp", "pm", "pp"] + + +# The sources are named accordingly (e.g. test_engines_mm.adb), and we we play +# with a number of related outputs (test_engines_mm executable, .trace file +# out of qemu, etc.). We Define a class to help handle such variants: + + +class Vtest: + def __init__(self, basename, variant): + self.basename = basename + self.variant = variant + + def filename(self, suffix=""): + """ + Return the name to use for a file related to this variant, suffixed + with SUFFIX. + """ + return self.basename + "_" + self.variant + suffix + + def tag(self): + """Return a trace tag to associate with this test variant.""" + return "%s, %s variant" % (self.basename, self.variant) + + +# Build all the executable variants from a single multi-mains project file +gprbuild( + gprfor( + [Vtest("test_engines", v).filename(".adb") for v in variants], + srcdirs="../src", + ) +) + +# First, a number of tests over individual variants: +for variant in variants: + vt = Vtest("test_engines", variant) + + # Xrun & stick a dedicated tag into the trace output + xrun([exepath_to(vt.filename()), "--tag=" + vt.tag()]) + + # Compute branch coverage for this variant & check that there's only + # partial coverage of the return expression + xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + vt.filename(tracename_for("")), + ] + ) + thistest.fail_if( + not match(r" \!:.*return.*Stable_P", "engines.adb.xcov"), + "single input, expected partial coverage over return expr", + ) + + # Verify that we can dump the trace and find the tag in the dump output + xcov( + ["dump-trace", tracename_for(vt.filename())], vt.filename(".tracedump") + ) + thistest.fail_if( + not match( + "Tag.*(User_Tag).*\nLen.*\nData.*%s" % vt.tag(), + vt.filename(".tracedump"), + ), + "single input, expected user tag from --dump-trace", + ) + +# Now, check that we can combine the trace results from all the variants +# and obtain full branch coverage of the return boolean expression. Build +# a consolidation routine list for this purpose. +with open("list.stable", "w") as rl: + rl.write(target_info().to_platform_specific_symbol("engines__stable\n")) + +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + "--routines=@list.stable", + ] + + [tracename_for(Vtest("test_engines", v).filename()) for v in variants] +) +thistest.fail_if( + not match(r" \+:.*return.*Stable_P", "engines.adb.xcov"), + "combined inputs, expected full branch coverage over return expr", +) + +# Check that we can produce html without crashing as well ... +xcov( + [ + "coverage", + "--level=branch", + "--annotate=html+", + "--routines=@list.stable", + ] + + [Vtest("test_engines", v).filename(tracename_for("")) for v in variants] +) + +thistest.result() diff --git a/testsuite/tests/I505-018/src/services.adb b/testsuite/tests/I505-018/src/services.adb new file mode 100644 index 000000000..0acdb2f69 --- /dev/null +++ b/testsuite/tests/I505-018/src/services.adb @@ -0,0 +1,14 @@ +package body Services is + + Counter : Integer; + + procedure To_Be_Called is + begin + Counter := Counter + 1; + end; + + procedure Not_To_Be_Called is + begin + raise Program_Error; + end; +end; diff --git a/testsuite/tests/I505-018/src/services.ads b/testsuite/tests/I505-018/src/services.ads new file mode 100644 index 000000000..0f80506e4 --- /dev/null +++ b/testsuite/tests/I505-018/src/services.ads @@ -0,0 +1,7 @@ +-- This unit is to be compiled with -ffunction-sections and must expose at +-- least to entry points to exercise the targetted internal circuits. + +package Services is + procedure To_Be_Called; + procedure Not_To_Be_Called; +end; diff --git a/testsuite/tests/I505-018/src/test_services.adb b/testsuite/tests/I505-018/src/test_services.adb new file mode 100644 index 000000000..9654c4b4c --- /dev/null +++ b/testsuite/tests/I505-018/src/test_services.adb @@ -0,0 +1,6 @@ +with Services; + +procedure Test_Services is +begin + Services.To_Be_Called; +end; diff --git a/testsuite/tests/I505-018/test.py b/testsuite/tests/I505-018/test.py new file mode 100644 index 000000000..7b6a8f19b --- /dev/null +++ b/testsuite/tests/I505-018/test.py @@ -0,0 +1,34 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir("tmp_") + +# Check that "gnatcov coverage" produces reports for units exposing more than +# one entry point when compiled with -ffunction-sections. +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_services.adb"], + srcdirs="../src", + compiler_extra='for Default_Switches ("Ada")' + ' use ("-ffunction-sections");', + ) + ), + covlevel="stmt", + mains=["test_services"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/services", "obj/test_services"], +) + +# Use match to both verify that expected reports are there and +# that coverage results are as we expect as well, while we're at it. +thistest.fail_if( + not match("100% of [1-9] lines covered", "test_services.adb.xcov") +) +thistest.fail_if(not match("-:.*raise Program_Error;", "services.adb.xcov")) + +thistest.result() diff --git a/testsuite/tests/I511-019-response-files/src/bar.adb b/testsuite/tests/I511-019-response-files/src/bar.adb new file mode 100644 index 000000000..121dc18fc --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/bar.adb @@ -0,0 +1,11 @@ +package body Bar is + procedure Proc1 is + begin + null; + end; + + procedure Proc2 is + begin + null; + end; +end; diff --git a/testsuite/tests/I511-019-response-files/src/bar.ads b/testsuite/tests/I511-019-response-files/src/bar.ads new file mode 100644 index 000000000..86dcb8e3f --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/bar.ads @@ -0,0 +1,5 @@ + +package Bar is + procedure Proc1; + procedure Proc2; +end; diff --git a/testsuite/tests/I511-019-response-files/src/foo.adb b/testsuite/tests/I511-019-response-files/src/foo.adb new file mode 100644 index 000000000..a71566ccb --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/foo.adb @@ -0,0 +1,5 @@ + +procedure Foo is +begin + null; +end; diff --git a/testsuite/tests/I511-019-response-files/src/test_foobar.adb b/testsuite/tests/I511-019-response-files/src/test_foobar.adb new file mode 100644 index 000000000..0b05245d3 --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/test_foobar.adb @@ -0,0 +1,13 @@ +with Foo; with Bar; + +procedure Test_Foobar is +begin + Foo; + Bar.Proc1; + Bar.Proc2; + + -- This test is designed for command line checks, + -- not to be run + + raise Program_Error; +end; diff --git a/testsuite/tests/I511-019-response-files/test.opt b/testsuite/tests/I511-019-response-files/test.opt new file mode 100644 index 000000000..b553eb717 --- /dev/null +++ b/testsuite/tests/I511-019-response-files/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disp-routines, specific to binary trace mode diff --git a/testsuite/tests/I511-019-response-files/test.py b/testsuite/tests/I511-019-response-files/test.py new file mode 100644 index 000000000..9671e8b66 --- /dev/null +++ b/testsuite/tests/I511-019-response-files/test.py @@ -0,0 +1,37 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, set_from +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir("tmp_") + +# Build a dummy project, to generate objects that we will query with +# disp-routines via an explicit list or a response file, to compare +# the results. +gprbuild(gprfor(["test_foobar.adb"], srcdirs="../src")) +objects = ["obj/foo.o", "obj/bar.o"] + +# Get disp-routines output from explicit command line arguments +xcov(args=["disp-routines"] + objects, out="explicit.out") + +# Build response file with same list of objects, and get disp-routines +# output from this +with open("foobar.list", "w") as f: + f.write("\n".join(objects) + "\n") + +xcov(args=["disp-routines", "@foobar.list"], out="response.out") + +# Check that both outputs are the same and non-empty, with at least one +# of the bits we expect there. Do not rely on symbols ordering: it is not +# specified. +response = set_from("response.out") +explicit = set_from("explicit.out") +thistest.fail_if( + explicit != response, + "expect disp-routines output identical from args or response file", +) +thistest.fail_if( + not any("bar" in symbol for symbol in explicit), + 'expect "bar" in disp-routines output', +) +thistest.result() diff --git a/testsuite/tests/I512-020/ppcstart.elf b/testsuite/tests/I512-020/ppcstart.elf new file mode 100644 index 000000000..e2fe1ebbb Binary files /dev/null and b/testsuite/tests/I512-020/ppcstart.elf differ diff --git a/testsuite/tests/I512-020/test.opt b/testsuite/tests/I512-020/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/I512-020/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/I512-020/test.py b/testsuite/tests/I512-020/test.py new file mode 100644 index 000000000..68a2c5eac --- /dev/null +++ b/testsuite/tests/I512-020/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SUITE.tutils import xcov + + +xcov(["disp-routines", "ppcstart.elf"]) +thistest.result() diff --git a/testsuite/tests/I519-015/func.list b/testsuite/tests/I519-015/func.list new file mode 100644 index 000000000..4dd3d11bf --- /dev/null +++ b/testsuite/tests/I519-015/func.list @@ -0,0 +1 @@ +_ada_min diff --git a/testsuite/tests/I519-015/min.adb b/testsuite/tests/I519-015/min.adb new file mode 100644 index 000000000..3457a01e0 --- /dev/null +++ b/testsuite/tests/I519-015/min.adb @@ -0,0 +1,11 @@ +function Min (X, Y : Float) return Float is + M : Float; +begin + -- Compare X and Y + if Y < X then + M := Y; + else + M := X; + end if; + return M; +end Min; diff --git a/testsuite/tests/I519-015/min.ads b/testsuite/tests/I519-015/min.ads new file mode 100644 index 000000000..77645339d --- /dev/null +++ b/testsuite/tests/I519-015/min.ads @@ -0,0 +1,2 @@ +function Min (X, Y : in Float) return Float; +-- pragma Import (Ada, Min); diff --git a/testsuite/tests/I519-015/test.opt b/testsuite/tests/I519-015/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I519-015/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I519-015/test.py b/testsuite/tests/I519-015/test.py new file mode 100644 index 000000000..47d4e554b --- /dev/null +++ b/testsuite/tests/I519-015/test.py @@ -0,0 +1,74 @@ +""" +This test performs a bunch of xcov related operations to validate the basic +toolset functionalities. +""" + +import re + +from SUITE.context import thistest +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) +from SUITE.cutils import Wdir, contents_of, match + + +Wdir("tmp_") + +# Context information, basic command line interface checks +gprbuild( + gprfor( + mains=["test_min.adb", "test_min1.adb", "test_min2.adb"], srcdirs=".." + ), + gargs=["-O1"], +) + +xrun(exepath_to("test_min")) + +# Check that the test exercising both sides of the 'if' stmt +# get full coverage +xcov( + "coverage --level=branch --annotate=asm " + tracename_for("test_min"), + out="test_min.out", +) + +thistest.fail_if( + not match(r"_ada_min \+:.*", "test_min.out"), "full coverage expected" +) + +# Seek partial branch coverage for the first test exercising only one side of +# the 'if' stmt. Remember what we found. +xrun(exepath_to("test_min1")) +xcov( + "coverage -c branch -a asm --routines=_ada_min " + + tracename_for("test_min1"), + out="test_min1.out", +) + +m = re.search("(>|v): .* (bclr|bge|blt|bnl)", contents_of("test_min1.out")) + +thistest.fail_if(not m, "couldn't find expected partially covered branch") + +dir1 = m.group(1) +insn1 = m.group(2) + +# Seek the other partial branch coverage for the second test exercising only +# the other side of the 'if' stmt. +alt_sign = {">": "v", "v": ">"} + +xrun(exepath_to("test_min2")) +xcov( + "coverage --level=branch --annotate=asm --routines=@../func.list " + + tracename_for("test_min2"), + out="test_min2.out", +) +thistest.fail_if( + not match(alt_sign[dir1] + ": .* " + insn1, "test_min2.out"), + "couldn't find alternate branch coverage", +) + +thistest.result() diff --git a/testsuite/tests/I519-015/test_min.adb b/testsuite/tests/I519-015/test_min.adb new file mode 100644 index 000000000..cf684bc88 --- /dev/null +++ b/testsuite/tests/I519-015/test_min.adb @@ -0,0 +1,12 @@ +with Min; + +procedure Test_Min is + V : Float; +begin + V := 1.5; + V := Min (V, 0.5); + V := Min (V, 2.0); + if V /= 0.5 then + raise Program_Error; + end if; +end Test_Min; diff --git a/testsuite/tests/I519-015/test_min1.adb b/testsuite/tests/I519-015/test_min1.adb new file mode 100644 index 000000000..3115ac9ac --- /dev/null +++ b/testsuite/tests/I519-015/test_min1.adb @@ -0,0 +1,11 @@ +with Min; + +procedure Test_Min1 is + V : Float; +begin + V := 1.5; + V := Min (V, 0.5); + if V /= 0.5 then + raise Program_Error; + end if; +end Test_Min1; diff --git a/testsuite/tests/I519-015/test_min2.adb b/testsuite/tests/I519-015/test_min2.adb new file mode 100644 index 000000000..c4c72c989 --- /dev/null +++ b/testsuite/tests/I519-015/test_min2.adb @@ -0,0 +1,11 @@ +with Min; + +procedure Test_Min2 is + V : Float; +begin + V := 1.5; + V := Min (V, 2.5); + if V /= 1.5 then + raise Program_Error; + end if; +end Test_Min2; diff --git a/testsuite/tests/I519-030/src/kops.adb b/testsuite/tests/I519-030/src/kops.adb new file mode 100644 index 000000000..fdc3374c2 --- /dev/null +++ b/testsuite/tests/I519-030/src/kops.adb @@ -0,0 +1,7 @@ + +package body Kops is + procedure Inc (X : in out Integer) is + begin + X := X + K; + end Inc; +end; diff --git a/testsuite/tests/I519-030/src/kops.ads b/testsuite/tests/I519-030/src/kops.ads new file mode 100644 index 000000000..b97d2afbe --- /dev/null +++ b/testsuite/tests/I519-030/src/kops.ads @@ -0,0 +1,7 @@ + +generic + K : Integer; +package Kops is + procedure Inc (X : in out Integer); + pragma Inline (Inc); +end; diff --git a/testsuite/tests/I519-030/src/ops4.ads b/testsuite/tests/I519-030/src/ops4.ads new file mode 100644 index 000000000..1d4738d2d --- /dev/null +++ b/testsuite/tests/I519-030/src/ops4.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops4 is new Kops (K => 4); diff --git a/testsuite/tests/I519-030/src/ops8.ads b/testsuite/tests/I519-030/src/ops8.ads new file mode 100644 index 000000000..d69b950a1 --- /dev/null +++ b/testsuite/tests/I519-030/src/ops8.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops8 is new Kops (K => 8); diff --git a/testsuite/tests/I519-030/src/test_kops.adb b/testsuite/tests/I519-030/src/test_kops.adb new file mode 100644 index 000000000..0b479da84 --- /dev/null +++ b/testsuite/tests/I519-030/src/test_kops.adb @@ -0,0 +1,11 @@ +with Ops4, Ops8, Vars; + +procedure Test_Kops is + Vx : Integer := Vars.X; +begin + Ops4.Inc (Vx); + Vars.Assert_Eq (Vx, 16); + + Ops8.Inc (Vx); + Vars.Assert_Eq (Vx, 24); +end; diff --git a/testsuite/tests/I519-030/src/vars.adb b/testsuite/tests/I519-030/src/vars.adb new file mode 100644 index 000000000..b36792c78 --- /dev/null +++ b/testsuite/tests/I519-030/src/vars.adb @@ -0,0 +1,8 @@ +package body Vars is + procedure Assert_Eq (Value, Expected : Integer) is + begin + if Value /= Expected then + raise Program_Error; + end if; + end; +end; diff --git a/testsuite/tests/I519-030/src/vars.ads b/testsuite/tests/I519-030/src/vars.ads new file mode 100644 index 000000000..06a24b27f --- /dev/null +++ b/testsuite/tests/I519-030/src/vars.ads @@ -0,0 +1,6 @@ +package Vars is + X : Integer := 12; + pragma Volatile (X); + + procedure Assert_Eq (Value, Expected : Integer); +end; diff --git a/testsuite/tests/I519-030/test.opt b/testsuite/tests/I519-030/test.opt new file mode 100644 index 000000000..45c00da6b --- /dev/null +++ b/testsuite/tests/I519-030/test.opt @@ -0,0 +1,5 @@ +-- This is an -O1 specific test. No need to noise the runs we do for +-- qualification tests at other levels. This test is also specific to object +-- coverage, so applicable only to binary traces. +bin-traces,CARGS_O1 +ALL DEAD diff --git a/testsuite/tests/I519-030/test.py b/testsuite/tests/I519-030/test.py new file mode 100644 index 000000000..d97b289a2 --- /dev/null +++ b/testsuite/tests/I519-030/test.py @@ -0,0 +1,112 @@ +""" +Check object coverage results in presence of inlining, with a single trivial +public routine called once from another unit. +""" + +import re + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +# We expect the routine machine code to appear in two places: in the +# associated unit object and at the unique call site. We expect both to be +# attached to the routine source and only the latter to be exercised. +# +# With generics involved, similar expectations with multiple versions of the +# object code all attached to the unique generic source. +_target_info = target_info() + +# Build with inlining activated. Don't force unreferenced symbols away. +gprbuild( + project=gprfor(["test_kops.adb"], srcdirs="../src"), + extracargs=["-O1", "-gnatn", "-save-temps"], +) + +# Run, then check results. +xrun(exepath_to("test_kops")) + +instances = ["ops4", "ops8"] + +# We expect all the source level calls to have been inlined, hence the base +# object code alone never to be called +xcov( + ["disp-routines"] + ["obj/" + i + ".o" for i in instances], out="kops.list" +) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov+", + "--routines=@kops.list", + tracename_for("test_kops"), + ] +) +thistest.fail_if( + not match(r"-:.*X := X \+ K", "kops.adb.xcov"), + "expect body of inlined not to be covered", +) + +# And full object code coverage should report partial coverage only +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + tracename_for("test_kops"), + ] +) +thistest.fail_if(not match(r"!:.*X := X \+ K", "kops.adb.xcov")) + +# Besides, attached to the generic source, we expect distinct object code +# sequences from the testing code (all covered, but we don't check for that). +# We request asm inserts for this purpose, and can't be sure about the exact +# layout of lines so have '.' match newlines as well. +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov+", + tracename_for("test_kops"), + ] +) + +symbol = _target_info.to_platform_specific_symbol("_ada_test_kops") +thistest.fail_if( + not match( + "procedure Inc" + + ".*" + + "<{}.*".format(symbol) * len(instances) + + "end Inc", + "kops.adb.xcov", + flags=re.DOTALL, + ), + "expect body of inlined attached to inlined source", +) + +# Likewise, we expect one object code sequence for each generic instance (all +# uncovered, but we don't check for that). There's no guarantee on the order +# in which the instances object code will show up, so iterate on searches. +for i in instances: + symbol = _target_info.to_platform_specific_symbol(i) + thistest.fail_if( + not match( + "procedure Inc" + ".*" + "<" + symbol + "__inc" + ".*" + "end Inc", + "kops.adb.xcov", + flags=re.DOTALL, + ), + "expect %s inlined machine code attached to inlined source" % symbol, + ) + +thistest.result() diff --git a/testsuite/tests/I522-010/src/volp.adb b/testsuite/tests/I522-010/src/volp.adb new file mode 100644 index 000000000..e94334282 --- /dev/null +++ b/testsuite/tests/I522-010/src/volp.adb @@ -0,0 +1,8 @@ +procedure Volp is + X : Integer := 10; + pragma Volatile (X); +begin + if X /= 10 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I522-010/test.opt b/testsuite/tests/I522-010/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/I522-010/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/I522-010/test.py b/testsuite/tests/I522-010/test.py new file mode 100644 index 000000000..bafb57d7f --- /dev/null +++ b/testsuite/tests/I522-010/test.py @@ -0,0 +1,17 @@ +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + + +Wdir("tmp_") + +extralargs = ",--entry=volp" if target_info().partiallinks else "" +gprbuild( + project=gprfor(["volp.adb"], srcdirs="../src"), + extracargs="-ffunction-sections", + largs="-Wl,--gc-sections" + extralargs, +) +xrun(exepath_to("volp")) + +thistest.result() diff --git a/testsuite/tests/I715-012/src/monitor.adb b/testsuite/tests/I715-012/src/monitor.adb new file mode 100644 index 000000000..efc5cd47b --- /dev/null +++ b/testsuite/tests/I715-012/src/monitor.adb @@ -0,0 +1,6 @@ +package body Monitor is + procedure Touch is + begin + N_Ops := N_Ops + 1; + end; +end; diff --git a/testsuite/tests/I715-012/src/monitor.ads b/testsuite/tests/I715-012/src/monitor.ads new file mode 100644 index 000000000..d387b410e --- /dev/null +++ b/testsuite/tests/I715-012/src/monitor.ads @@ -0,0 +1,5 @@ +package Monitor is + N_Ops : Integer := 0; + + procedure Touch; +end; diff --git a/testsuite/tests/I715-012/src/p.adb b/testsuite/tests/I715-012/src/p.adb new file mode 100644 index 000000000..06a6afc10 --- /dev/null +++ b/testsuite/tests/I715-012/src/p.adb @@ -0,0 +1,6 @@ +with Pack; + +procedure P is +begin + Pack.Func; +end P; diff --git a/testsuite/tests/I715-012/src/pack.adb b/testsuite/tests/I715-012/src/pack.adb new file mode 100644 index 000000000..fd4e4de60 --- /dev/null +++ b/testsuite/tests/I715-012/src/pack.adb @@ -0,0 +1,10 @@ +with Monitor; + +package body Pack is + + procedure Func is + begin + Monitor.Touch; + end Func; + +end Pack; diff --git a/testsuite/tests/I715-012/src/pack.ads b/testsuite/tests/I715-012/src/pack.ads new file mode 100644 index 000000000..fdf6d56b0 --- /dev/null +++ b/testsuite/tests/I715-012/src/pack.ads @@ -0,0 +1,5 @@ +package Pack is + + procedure Func; + +end Pack; diff --git a/testsuite/tests/I715-012/test.opt b/testsuite/tests/I715-012/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I715-012/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I715-012/test.py b/testsuite/tests/I715-012/test.py new file mode 100644 index 000000000..9522bb668 --- /dev/null +++ b/testsuite/tests/I715-012/test.py @@ -0,0 +1,43 @@ +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_tmp +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + platform_specific_symbols, + tracename_for, + xcov, + xrun, +) + + +wd = Wdir("tmp_") +gprbuild(project=gprfor(srcdirs=["../src"], mains=["p.adb"])) +symfile = list_to_tmp(platform_specific_symbols(["pack__func"])) + +xrun(exepath_to("p")) +xcov( + [ + "coverage", + "--level=branch", + "--routines=@" + symfile, + "--annotate=xcov+", + tracename_for("p"), + ] +) + +# This test should check that xcov does not generate null report files +# for sources that are not considered in the coverage operation. +# Here, only pack.adb.xcov should be generated, as the routine list +# contains only pack__func, fully defined in pack.adb. +thistest.fail_if( + not os.path.exists("pack.adb.xcov") + or os.path.exists("text_io.adb.xcov") + or os.path.exists("monitor.ads.xcov") + or os.path.exists("monitor.adb.xcov") + or os.path.exists("p.adb.xcov") +) + +thistest.result() diff --git a/testsuite/tests/I716-009/func.list b/testsuite/tests/I716-009/func.list new file mode 100644 index 000000000..1bd8f61d2 --- /dev/null +++ b/testsuite/tests/I716-009/func.list @@ -0,0 +1 @@ +min diff --git a/testsuite/tests/I716-009/min.ads b/testsuite/tests/I716-009/min.ads new file mode 100644 index 000000000..03da5c0a8 --- /dev/null +++ b/testsuite/tests/I716-009/min.ads @@ -0,0 +1,2 @@ +function Min (X, Y : in Integer) return Integer; +pragma Import (Ada, Min); diff --git a/testsuite/tests/I716-009/min_asm.s b/testsuite/tests/I716-009/min_asm.s new file mode 100644 index 000000000..a18ba3195 --- /dev/null +++ b/testsuite/tests/I716-009/min_asm.s @@ -0,0 +1,17 @@ + .file "min.adb" + .gnu_attribute 4, 1 + .gnu_attribute 8, 1 + .section ".text" + .align 2 + .globl min + .type min, @function +min: + mr 0,3 + mr 3,4 +# cmpw 7,4,0 +# blelr 7 + cmpw 7,0,4 + bgtlr 7 + mr 3,0 + blr + .size min, .-min diff --git a/testsuite/tests/I716-009/test.opt b/testsuite/tests/I716-009/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I716-009/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I716-009/test.py b/testsuite/tests/I716-009/test.py new file mode 100644 index 000000000..275054c5b --- /dev/null +++ b/testsuite/tests/I716-009/test.py @@ -0,0 +1,43 @@ +""" +This test performs a bunch of xcov related operations to validate the basic +toolset functionalities. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + maybe_valgrind, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +# Context information, basic command line interface checks +print("maybe_valgrind prepends ...", maybe_valgrind([])) + +gprbuild( + project=gprfor( + mains=["test_min.adb"], langs=["Ada", "Asm"], srcdirs=[".."] + ) +) +xrun(exepath_to("test_min")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_min"), + ], + "test_min.out", +) +thistest.fail_if( + not match(r"min \+:.*", "test_min.out"), "full coverage expected" +) + +thistest.result() diff --git a/testsuite/tests/I716-009/test_min.adb b/testsuite/tests/I716-009/test_min.adb new file mode 100644 index 000000000..4efd8abed --- /dev/null +++ b/testsuite/tests/I716-009/test_min.adb @@ -0,0 +1,12 @@ +with Min; + +procedure Test_Min is + V : Integer; +begin + V := 3; + V := Min (V, 4); + V := Min (V, 1); + if V /= 1 then + raise Program_Error; + end if; +end Test_Min; diff --git a/testsuite/tests/I716-021/src/p.adb b/testsuite/tests/I716-021/src/p.adb new file mode 100644 index 000000000..86ea6ebc8 --- /dev/null +++ b/testsuite/tests/I716-021/src/p.adb @@ -0,0 +1,11 @@ +package body P is + function Head_Of (B : Block_T) return System.Address is + Blength : constant Integer := B'Last - B'First + 1; + Baddr : System.Address := System.Null_Address; + begin + if Blength > 0 then + Baddr := B(B'First)'Address; + end if; + return Baddr; + end; +end; diff --git a/testsuite/tests/I716-021/src/p.ads b/testsuite/tests/I716-021/src/p.ads new file mode 100644 index 000000000..4c2be74ca --- /dev/null +++ b/testsuite/tests/I716-021/src/p.ads @@ -0,0 +1,8 @@ +with System; + +package P is + subtype Index_T is Integer range 0 .. 255; + type Block_T is array (Integer range <>) of Integer; + + function Head_Of (B : Block_T) return System.Address; +end; diff --git a/testsuite/tests/I716-021/src/test_p.adb b/testsuite/tests/I716-021/src/test_p.adb new file mode 100644 index 000000000..5dc06f8be --- /dev/null +++ b/testsuite/tests/I716-021/src/test_p.adb @@ -0,0 +1,19 @@ +with System, P; use P; + +procedure Test_P is + My_Block : Block_T (1 ..2) := (1, 2); + My_Empty_Block : Block_T (2 .. 1); + + Addr : System.Address; + use type System.Address; +begin + Addr := Head_Of (My_Block); + if Addr /= My_Block (My_Block'First)'Address then + raise Program_Error; + end if; + + Addr := Head_Of (My_Empty_Block); + if Addr /= System.Null_Address then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I716-021/test.opt b/testsuite/tests/I716-021/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I716-021/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I716-021/test.py b/testsuite/tests/I716-021/test.py new file mode 100644 index 000000000..b863ae35d --- /dev/null +++ b/testsuite/tests/I716-021/test.py @@ -0,0 +1,26 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +gprbuild(project=gprfor(["test_p.adb"], srcdirs="../src")) +xrun(exepath_to("test_p")) +xcov( + ["coverage", "--level=branch", "--annotate=xcov+", tracename_for("test_p")] +) + +# We expect the test to exercise the single branch in p.head_of +# both ways, and that this branch is associated with the "if" statement +# there, something like +# +# 6 +: if Blength > 0 then +thistest.fail_if(not match(r"[0-9]+ \+:.*if .* then", "p.adb.xcov")) +thistest.result() diff --git a/testsuite/tests/I717-018/explore.list b/testsuite/tests/I717-018/explore.list new file mode 100644 index 000000000..4d6021ab5 --- /dev/null +++ b/testsuite/tests/I717-018/explore.list @@ -0,0 +1 @@ +robots__robot_control_inport diff --git a/testsuite/tests/I717-018/src/actors.adb b/testsuite/tests/I717-018/src/actors.adb new file mode 100644 index 000000000..ec41c8261 --- /dev/null +++ b/testsuite/tests/I717-018/src/actors.adb @@ -0,0 +1,38 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Actors is + + ---------- + -- Live -- + ---------- + function Live (A : Actor'Class) return Boolean is + begin + return A.Live; + end Live; + + ---------- + -- Kill -- + ---------- + procedure Kill (A : in out Actor'Class) is + begin + A.Live := False; + end Kill; + +end Actors; diff --git a/testsuite/tests/I717-018/src/actors.ads b/testsuite/tests/I717-018/src/actors.ads new file mode 100644 index 000000000..dbcbc22a5 --- /dev/null +++ b/testsuite/tests/I717-018/src/actors.ads @@ -0,0 +1,42 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the root Actor abstraction for the Explore example, +-- meant to be used for active entities in the system, such as the robot +-- or the control station. +-- +-- This is useful to allow associations of arbitrary entities to other +-- software components, for instance to support port/actor ownership. + +package Actors is + type Actor is abstract tagged private; + type Actor_Ref is access all Actor'Class; + + procedure Kill (A : in out Actor'Class); + -- Called when something bad happened to/in A and it is + -- not to be relied upon any more. + + function Live (A : Actor'Class) return Boolean; + -- True until A is killed + +private + type Actor is abstract tagged record + Live : Boolean := True; + end record; +end Actors; diff --git a/testsuite/tests/I717-018/src/controls.ads b/testsuite/tests/I717-018/src/controls.ads new file mode 100644 index 000000000..1c768f6d1 --- /dev/null +++ b/testsuite/tests/I717-018/src/controls.ads @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the Robot command/control enumerals and the associated +-- Link abstraction for the Explore example. + +with Links; + +package Controls is + + -- Possible Robot Operational modes + + type Robot_Opmode is + (Cautious, -- The Robot won't execute potentially damaging commands + Dumb -- The Robot executes all the commands it receives + ); + + -- Commands the robot understands on its "robot control" input port. + + type Robot_Command is + (Nop, -- Do nothing + Opmode, -- Switch to new operational mode + Step_Forward, -- Step forward + Rotate_Right, -- Rotate 90 deg, counterclockwise + Rotate_Left, -- Rotate 90 deg, clockwise + Probe -- Probe field one step ahead and report + ); + + type Robot_Control is record + Code : Robot_Command; + Value : Integer; -- Possible argument associated with command CODE. + end record; + + package Robot_Control_Links is new Links (Data_Type => Robot_Control); +end Controls; diff --git a/testsuite/tests/I717-018/src/explore.adb b/testsuite/tests/I717-018/src/explore.adb new file mode 100644 index 000000000..c8ecdbd78 --- /dev/null +++ b/testsuite/tests/I717-018/src/explore.adb @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This is the main unit for the Explore example, a sample application used +-- to introduce/illustrate a number of concepts in the Xcov documentation. +-- +-- This example features a fake robot exploring a field, controled through +-- communication channels by a inhabited control station off the field. See +-- the Overview dummy spec for a functional and organisational overview, +-- separated out to allow inclusion into the documentation. + +with Overview, Actors, Robots, Stations, Controls, Geomaps; +use Overview, Actors, Robots, Stations, Controls, Geomaps; + +with Robots_Devices.Dummy; + +------------- +-- Explore -- +------------- + +-- This is the main subprogram for this example. It instanciates the +-- actors, the communication links, and schedules the actors runs in a +-- simple cyclic fashion. +-- +-- The field and the robot disposition are implicitly created by the +-- Robot fake radar and locator devices, which both let it evaluate its +-- current situation. + +procedure Explore is + + -- Instanciate the Robot and Station actors + + R : Robot_Access := new Robot; + S : Station_Access := new Station; + +begin + Init (R, Robots_Devices.Dummy.Get_Hardware); + Init (S); + + -- Instantiate the Station/Robot communication Links and attach them + -- to their dedicated ports on both sides. + + declare + SR_Control_Link : Robot_Control_Links.IOlink_Access + := new Robot_Control_Links.IOlink; + SR_Situation_Link : Situation_Links.IOlink_Access + := new Situation_Links.IOlink; + begin + Robot_Control_Links.Connect + (Robot_Control_Outport (S.all), Robot_Control_Inport (R.all), + SR_Control_Link); + Situation_Links.Connect + (Robot_Situation_Outport (R.all), Robot_Situation_Inport (S.all), + SR_Situation_Link); + end; + + -- Then run just one cycle + + Run (S); + Run (R); + +end Explore; diff --git a/testsuite/tests/I717-018/src/geomaps.adb b/testsuite/tests/I717-018/src/geomaps.adb new file mode 100644 index 000000000..5fdc43345 --- /dev/null +++ b/testsuite/tests/I717-018/src/geomaps.adb @@ -0,0 +1,72 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with GNAT.IO; use GNAT.IO; + +package body Geomaps is + + -- Characters to printout for each possible kind of field Square, + -- and to represent an actor heading to a specific direction. + + Square_Image : array (Square) of Character + := (Ground => ' ', Block => '#', Water => '~', Unknown => '?'); + + Situ_Image : array (Direction) of Character + := (North => '^', West => '<', East => '>', South => 'v'); + + ---------- + -- Dump -- + ---------- + + procedure Dump (Map : Geomap; Situ : Situation) is + begin + New_Line; + for Y in Map'Range (Sqy) loop + for X in Map'Range (Sqx) loop + if Situ.Pos = (X, Y) then + Put (Situ_Image (Situ.Dir)); + else + Put (Square_Image (Map (X, Y))); + end if; + end loop; + New_Line; + end loop; + end Dump; + + ------------------ + -- Pos_Ahead_Of -- + ------------------ + + function Pos_Ahead_Of (Situ : Situation) return Position is + subtype Move_XYrange is Integer range -1 .. +1; + + type Move is record + Dx, Dy : Move_XYrange; + end record; + + XYmoves : constant array (Direction) of Move + := (West => (Dx => -1, Dy => 0), East => (Dx => +1, Dy => 0), + South => (Dx => 0, Dy => +1), North => (Dx => 0, Dy => -1)); + + XYmove : Move renames XYmoves (Situ.Dir); + begin + return (X => Situ.Pos.X + XYmove.Dx, Y => Situ.Pos.Y + XYmove.Dy); + end Pos_Ahead_Of; + +end Geomaps; diff --git a/testsuite/tests/I717-018/src/geomaps.ads b/testsuite/tests/I717-018/src/geomaps.ads new file mode 100644 index 000000000..ba229457a --- /dev/null +++ b/testsuite/tests/I717-018/src/geomaps.ads @@ -0,0 +1,76 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes very basic Geographical Map abstractions for the +-- field in the Explore example. + +-- The field is very simply abstracted as a two dimensions array of +-- squares, each with an (x, y) position relative to (1, 1) for the +-- north-west corner. + +with Links; + +package Geomaps is + + ------------------------------ + -- Directions and Positions -- + ------------------------------ + + type Direction is (West, North, East, South); + + subtype XYrange is Integer range 1 .. 5; + type Position is record + X, Y : XYrange; + end record; + + ---------------- + -- Situations -- + ---------------- + + -- A Situation on the field encompasses an actor position, the + -- direction it is heading at and the kind of Square one step ahead + -- in this direction. + + type Square is (Ground, Block, Water, Unknown); + + type Situation is record + Pos : Position; + Dir : Direction; + Sqa : Square; + end record; + + function Pos_Ahead_Of (Situ : Situation) return Position; + -- Position of the square ahead the position in SITU, looking into + -- the direction held there as well. + + package Situation_Links is new Links (Data_Type => Situation); + + ----------------------------------------- + -- The field map representation per se -- + ----------------------------------------- + + type Geomap is array (XYrange'Range, XYrange'Range) of Square; + Sqx : constant := 1; + Sqy : constant := 2; + + procedure Dump (Map : Geomap; Situ : Situation); + -- Printout field MAP to standard output, and represent a robot + -- situation SITU on top. + +end Geomaps; diff --git a/testsuite/tests/I717-018/src/links.adb b/testsuite/tests/I717-018/src/links.adb new file mode 100644 index 000000000..4d36d895f --- /dev/null +++ b/testsuite/tests/I717-018/src/links.adb @@ -0,0 +1,100 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Links is + + ----------------------- + -- IOport operations -- + ----------------------- + + function Create_IOport + (Capacity : Natural; Owner : Actor_Ref) return IOport_Access + is + Ret : IOport_Access := new IOport (Capacity); + begin + Ret.Owner := Owner; + return Ret; + end Create_IOport; + + procedure On_Push + (Port : IOport_Access; Callback : Callback_Access) is + begin + Port.Push_Callback := Callback; + end On_Push; + + procedure Push (Item : Data_Type; Port : IOport_Access) is + begin + Push (Item, Port.Data); + if Port.Push_Callback /= null then + Port.Push_Callback.all (Port); + end if; + end Push; + + procedure Pop (Item : out Data_Type; Port : IOport_Access) is + begin + Pop (Item, Port.Data); + end Pop; + + function Full (Port : IOport_Access) return Boolean is + begin + return Full (Port.Data); + end Full; + + function Empty (Port : IOport_Access) return Boolean is + begin + return Empty (Port.Data); + end Empty; + + function Owner (Port : IOport_Access) return Actor_Ref is + begin + return Port.Owner; + end Owner; + + ------------------------ + -- IOlinks operations -- + ------------------------ + + procedure Flush (Port : IOport_Access); + -- Flush all the data available from Port through the Link to which it + -- is connected. This is called when data is pushed into Port after it + -- has been Connected (linked) to another one. + + procedure Flush (Port : IOport_Access) is + Link : IOlink_Access := Port.Link; + Data : Data_Type; + begin + while not Empty (Link.Outp) loop + Pop (Data, Link.Outp); + Push (Data, Link.Inp); + end loop; + end Flush; + + procedure Connect + (Outp, Inp : IOport_Access; Link : IOlink_Access) is + begin + Inp.Link := Link; + Outp.Link := Link; + + Link.Inp := Inp; + Link.Outp := Outp; + + On_Push (Outp, Flush'Access); + end Connect; + +end Links; diff --git a/testsuite/tests/I717-018/src/links.ads b/testsuite/tests/I717-018/src/links.ads new file mode 100644 index 000000000..2f40dfb5c --- /dev/null +++ b/testsuite/tests/I717-018/src/links.ads @@ -0,0 +1,124 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes IO Ports and Links abstractions to represent +-- interconnections between Actors. + +-- A Port is an abstract interface point into which data may be pushed +-- or out of which data may be popped, possibly buffered up to a specified +-- Capacity. A Link is an abstract communication channel which connects an +-- output Port to an input Port, all for a specific data type. + +-- Ports are meant to be attached to (owned by) an Actor to let it either +-- receive data (input ports) or emit data (output ports), not both. +-- +-- Links are meant to allow interconnections between actors via the ports +-- they own. The simple figure below illustrates such an interconnection +-- between +-- +-- a source actor Sa with an output port Op, and +-- a destination actor Da with an input port Ip +-- +-- +======+ +======+ +-- | Da Ip <---- Link ----< Op Sa | +-- +======+ +======+ +-- +-- Operation-wise, Links operate as data push propagators. In the example +-- above, data Pushed by Sa into Op becomes available for a Pop out of Ip +-- by Da at the other end of the Link. +-- +-- At this stage, a port may connect to at most one link and links support +-- only one to one connections. + +with Actors, Queues; +use Actors; + +generic + type Data_Type is private; +package Links is + + ------------ + -- IOport -- + ------------ + + type IOport (<>) is private; + type IOport_Access is access IOport; + + function Create_IOport + (Capacity : Natural; Owner : Actor_Ref) return IOport_Access; + -- The IO Port constructor. + + function Full (Port : IOport_Access) return Boolean; + -- Whether Port is full with respect to its Capacity. + + function Empty (Port : IOport_Access) return Boolean; + -- Whether Port is empty. + + procedure Push (Item : Data_Type; Port : IOport_Access); + -- Push Item on top into Port if it is not Full, + -- raise Program_Error and leave Port unchanged otherwise. + + procedure Pop (Item : out Data_Type; Port : IOport_Access); + -- Pop the oldest data Item out of Port if it is not Empty, + -- raise Program_Error and leave Item undefined otherwise. + + function Owner (Port : IOport_Access) return Actor_Ref; + -- Retrieve the owner of the port. + + ------------ + -- IOlink -- + ------------ + + type IOlink is private; + type IOlink_Access is access IOlink; + + procedure Connect (Outp, Inp : IOport_Access; Link : IOlink_Access); + -- Connect the output port Outp to the input port Inp via Link. Data + -- pushed into Outp is immediately popped out of it and pushed into Inp. + +private + + -- While they are intended to represent almost concrete concepts, ports + -- as we expose them much resemble queues, except for the support of a + -- callback on push. + + package Data_Queue_P is new Queues (Data_Type => Data_Type); + use Data_Queue_P; + + subtype Data_Queue is Data_Queue_P.Queue; + + type Callback_Access is access procedure (Port : IOport_Access); + + type IOport (Capacity : Natural) is record + Data : Data_Queue (Capacity => Capacity); + Push_Callback : Callback_Access; + + Owner : Actor_Ref; + Link : IOlink_Access; + end record; + + procedure On_Push (Port : IOport_Access; Callback : Callback_Access); + -- Register Callback as a subprogram to be called every time data is + -- pushed into Port. + + type IOlink is record + Inp, Outp : IOport_Access; + end record; + +end Links; diff --git a/testsuite/tests/I717-018/src/overview.ads b/testsuite/tests/I717-018/src/overview.ads new file mode 100644 index 000000000..73d47069a --- /dev/null +++ b/testsuite/tests/I717-018/src/overview.ads @@ -0,0 +1,153 @@ +------------------------------------------------------------------------------ +-- Couverture/Explore example -- +-- Copyright (C) 2008-2009, AdaCore -- +------------------------------------------------------------------------------ + +------------------------- +-- Functional overview -- +------------------------- + +-- This example implements software pieces involved in the following +-- imaginary situation: +-- +-- - A pilotless robot is set on a field to explore, where we expect to +-- find either regular ground or rock blocks. +-- +-- - An inhabited station off the field communicates with the robot to +-- control it and visualize the explored portions of the field. + +-- The robot is equipped with several devices: +-- +-- - a steering engine, able to have the robot perform a short step +-- forward or rotate 90 deg either way without advancing, +-- +-- - a front radar, able to probe the field characteristics (ground or +-- block) one step ahead, +-- +-- - a locator, able to evaluate the robot's position and orientation on +-- the field. +-- +-- The robot communicates with the station via two communication links: +-- +-- - a control link, through which the station sends commands for the +-- robot to execute (probe ahead, step forward, ...) +-- +-- - a situation link, through which the robot sends info about it's +-- current situation (position, orientation, field ahead). +-- +-- The field is modeled as a set of squares, each represented by a +-- single character to denote the square nature: +-- +-- '#' is a rock block, ' ' is regular ground, '~' is water +-- +-- '?' is a square yet unexplored +-- +-- '<', '>', '^' or 'v' is the robot heading west, east, north +-- or south, respectively. + +-- Below is a schematic illustration of the various parts involved +-- for a rectangular field delimited by rock blocks, a robot heading +-- south and an 'S' to materialize the Station: +-- +-- field view +-- ########## ?????????? +-- # # # <- control link ? # ? ?? +-- # v<==========================>S ?? R ?? +-- # ~ # situation link -> ? ? ?? +-- ########## ?????????? +-- +-- The Robot and Station active entities are both called Actors in this +-- world, and Links are attached to local Ports owned by these actors. +-- +-- The Robot runs in one of two modes: in Cautious mode, it wont execute +-- unsafe commands like stepping forward with a rock block ahead. In Dumb +-- mode it executes all the commands it receives. + +-------------------- +-- Sample session -- +-------------------- + +-- A user running the program is like sitting at the Station, able to type +-- commands for the Robot to execute and to receive feedback on the new +-- situation, from which the local view of the field is updated. Below is +-- sample session with explanatory comments in []: +-- +-- $ ./explore +-- +-- [The fake initial field is setup as a 5x5 area with blocks all around +-- and 1 in the middle, like +-- +-- ##### +-- # # +-- # # # +-- # # +-- ##### +-- +-- Robot is arbitrarily placed in the upperwest corner, heading east] +-- +-- 'C'autious mode, 'D'umb mode +-- 'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? P +-- +-- [Station asks for user input, user types "P" to probe ahead. +-- Robot answers with it's current situation: position (x=2, y=2), +-- looking east, square ahead is regular ground. +-- Station displays its current knowledge of the field]: +-- +-- ????? +-- ?> ?? +-- ????? +-- ????? +-- ????? +-- +-- [Probe command processing done, Next cycle ...] +-- +-- 'C'autious mode, 'D'umb mode +-- 'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? L +-- +-- [User asks "rotate left (counterclockwise)", station sends out +-- command followed by a Probe request. +-- Robot processes both requests and answers: position unchanged, +-- now heading north, square ahead is a block. +-- Station displays its current knowledge of the field]: +-- +-- ?#??? +-- ?^ ?? +-- ????? +-- ????? +-- ????? +-- +-- [etc until user requests 'Q'uit or crashes the robot by asking +-- it to step forward into a block, in Dumb mode] +-- + +----------------------------------- +-- General software organization -- +----------------------------------- + +-- The set of units and essential abstractions involved is sketched below - +-- units underlined, associated abstractions parenthesized). +-- +-- This set is a pretty straightforward mapping of the general concepts +-- involved, as described in the Functional Overview. Only "Queues" is a +-- pure support unit, offering the well known datastructure abstraction. +-- +-- See the package specs for extra descriptive details. +-- +-- ======= +-- Explore +-- ======= +-- +-- Geomaps (field Map, Situations + Situation_Links) +-- ======= +-- +-- Actors (Actor) Robots (Robot) Stations (Station) +-- ====== ====== ======== +-- +-- Links (IOports, IOlinks) Queues (Queue) +-- ===== ====== +-- +-- Controls (Robot_Control + Robot_Control_Links) +-- ======== + +package Overview is +end Overview; diff --git a/testsuite/tests/I717-018/src/queues.adb b/testsuite/tests/I717-018/src/queues.adb new file mode 100644 index 000000000..ad2cf4264 --- /dev/null +++ b/testsuite/tests/I717-018/src/queues.adb @@ -0,0 +1,74 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Queues is + + ------------------------- + -- Classical accessors -- + ------------------------- + + function Size (Q : Queue) return Natural; + -- The number of items available in Q + + function Size (Q : Queue) return Natural is + begin + return Q.Size; + end Size; + + function Full (Q : Queue) return Boolean is + begin + return Size (Q) = Q.Capacity; + end Full; + + function Empty (Q : Queue) return Boolean is + begin + return Size (Q) = 0; + end Empty; + + procedure Pop (Item : out Data_Type; Q : in out Queue) is + begin + if Empty (Q) then + raise Program_Error; + end if; + + Item := Q.Items (Q.Front); + if Q.Front = Q.Items'Last then + Q.Front := Q.Items'First; + else + Q.Front := Q.Front + 1; + end if; + Q.Size := Q.Size - 1; + end Pop; + + procedure Push (Item : Data_Type; Q : in out Queue) is + begin + if Full (Q) then + raise Program_Error; + end if; + + Q.Items (Q.Back) := Item; + if Q.Back = Q.Items'Last then + Q.Back := Q.Items'First; + else + Q.Back := Q.Back + 1; + end if; + Q.Size := Q.Size + 1; + end Push; + +end Queues; diff --git a/testsuite/tests/I717-018/src/queues.ads b/testsuite/tests/I717-018/src/queues.ads new file mode 100644 index 000000000..d7aa74c1a --- /dev/null +++ b/testsuite/tests/I717-018/src/queues.ads @@ -0,0 +1,49 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package offers a simple "bounded queue" data structure abstraction + +generic + type Data_Type is private; -- The elements data type +package Queues is + type Queue (Capacity : Natural) is private; + + function Full (Q : Queue) return Boolean; + -- Whether Q is full with respect to its Capacity. + + function Empty (Q : Queue) return Boolean; + -- Whether Q is empty. + + procedure Push (Item : Data_Type; Q : in out Queue); + -- Push Item at the back of queue Q if it is not Full, + -- raise Program_Error and leave Q unchanged otherwise. + + procedure Pop (Item : out Data_Type; Q : in out Queue); + -- Pop the top element off the head of Q into Item if Q is not Empty, + -- raise Program_Error and leave Item undefined otherwise. + +private + + type Data_Array is array (Natural range <>) of Data_Type; + type Queue (Capacity : Natural) is record + Items : Data_Array (1 .. Capacity); + Size : Natural := 0; + Front, Back : Natural := 1; + end record; +end Queues; diff --git a/testsuite/tests/I717-018/src/robots.adb b/testsuite/tests/I717-018/src/robots.adb new file mode 100644 index 000000000..2556c24d5 --- /dev/null +++ b/testsuite/tests/I717-018/src/robots.adb @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Robots is + + -------------------- + -- IOports access -- + -------------------- + + function Robot_Control_Inport + (R : Robot) return Robot_Control_Links.IOport_Access is + begin + return R.Robot_Control_Inp; + end Robot_Control_Inport; + + function Robot_Situation_Outport + (R : Robot) return Situation_Links.IOport_Access is + begin + return R.Robot_Situation_Outp; + end Robot_Situation_Outport; + + ---------------------- + -- Input processing -- + ---------------------- + + use Robot_Control_Links; + + function Unsafe (Cmd : Robot_Command; Sqa : Square) return Boolean; + -- Whether execution of CMD is unsafe with the SQA square ahead + + pragma Export (Ada, Unsafe, "robots__unsafe"); + -- ??? prevent inlining + + procedure Process_Next_Control (Port : Robot_Control_Links.IOport_Access); + -- Process the next control command available from PORT + + ------------ + -- Unsafe -- + ------------ + + function Unsafe (Cmd : Robot_Command; Sqa : Square) return Boolean is + begin + -- Stepping forward into a rock block or a water pit is Unsafe + + return Cmd = Step_Forward + and then (Sqa = Block or else Sqa = Water); + end Unsafe; + + -------------------------- + -- Process_Next_Control -- + -------------------------- + + procedure Process_Next_Control + (Port : Robot_Control_Links.IOport_Access) + is + Ctrl : Robot_Control; + Robot : Robot_Access := Robot_Access (Owner (Port)); + + begin + Pop (Ctrl, Port); + + -- In Cautious mode, the robot refuses to process unsafe controls + + if Robot.Mode = Cautious + and then Unsafe (Ctrl.Code, Probe_Ahead (Robot.Hw.Rad)) + then + return; + end if; + + case Ctrl.Code is + when Nop => + return; + + when Opmode => + Robot.Mode := Robot_Opmode'Val (Ctrl.Value); + + when Step_Forward => + Step_Forward (Robot.Hw.Eng); + + when Rotate_Left => + Rotate_Left (Robot.Hw.Eng); + + when Rotate_Right => + Rotate_Right (Robot.Hw.Eng); + + when Probe => + Situation_Links.Push + (Situation' + (Pos => Get_Position (Robot.Hw.Loc), + Dir => Get_Direction (Robot.Hw.Loc), + Sqa => Probe_Ahead (Robot.Hw.Rad)), + Robot_Situation_Outport (Robot.all)); + + end case; + end Process_Next_Control; + + --------- + -- Run -- + --------- + + procedure Run (R : Robot_Access) is + Control_Port : IOport_Access := Robot_Control_Inport (R.all); + begin + while not Empty (Control_Port) loop + Process_Next_Control (Control_Port); + end loop; + end Run; + + ---------- + -- Init -- + ---------- + + procedure Init (R : Robot_Access; Hw : Robot_Hardware) is + begin + R.Robot_Situation_Outp := + Situation_Links.Create_IOport + (Capacity => 1, + Owner => Actor_Ref (R)); + R.Robot_Control_Inp := + Robot_Control_Links.Create_IOport + (Capacity => 2, + Owner => Actor_Ref (R)); + R.Hw := Hw; + end Init; + +end Robots; diff --git a/testsuite/tests/I717-018/src/robots.ads b/testsuite/tests/I717-018/src/robots.ads new file mode 100644 index 000000000..ce231350e --- /dev/null +++ b/testsuite/tests/I717-018/src/robots.ads @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the Robot abstraction of the Explore example. +-- +-- A Robot is an active entity able to execute Robot_Control commands +-- received through an input Control port. Placed on a field, the Robot is +-- able to evaluate its current Situation (location, orientation, field +-- square ahead), and send this through an output Situation port. +-- +-- A Robot operates in one of several modes, as described in the Controls +-- abstraction. + +with Actors, Geomaps, Controls, Robots_Devices; +use Actors, Geomaps, Controls, Robots_Devices; + +package Robots is + + type Robot is new Actor with private; + type Robot_Access is access all Robot; + + function Robot_Control_Inport + (R : Robot) return Robot_Control_Links.IOport_Access; + function Robot_Situation_Outport + (R : Robot) return Situation_Links.IOport_Access; + + procedure Init (R : Robot_Access; Hw : Robot_Hardware); + -- Initialize robot R using the hardware Hw - setup ports and internal + -- devices + + procedure Run (R : Robot_Access); + -- Run robot R - process pending messages on input ports + + type Robot_Opmode is (Cautious, Dumb); + +private + + type Robot is new Actor with record + Robot_Control_Inp : Robot_Control_Links.IOport_Access; + Robot_Situation_Outp : Situation_Links.IOport_Access; + + Hw : Robot_Hardware; + Mode : Robot_Opmode := Cautious; + end record; + +end Robots; diff --git a/testsuite/tests/I717-018/src/robots_devices-dummy.adb b/testsuite/tests/I717-018/src/robots_devices-dummy.adb new file mode 100644 index 000000000..c532a699d --- /dev/null +++ b/testsuite/tests/I717-018/src/robots_devices-dummy.adb @@ -0,0 +1,219 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Geomaps; use Geomaps; + +package body Robots_Devices.Dummy is + + procedure Update_Square_Ahead (Device : access Dummy_Engine); + -- Update the square ahead after an engine action + + procedure Fake_Map (Map : in out Geomap); + -- Build a fake field MAP to perform pretended probes from, with + -- block borders and a few blocks within. + + ------------------ + -- Step_Forward -- + ------------------ + + procedure Step_Forward (Device : access Dummy_Engine) is + Sq : Square; + begin + Device.Env.Situ.Pos := Pos_Ahead_Of (Device.Env.Situ); + Sq := Device.Env.Map (Device.Env.Situ.Pos.X, Device.Env.Situ.Pos.Y); + + -- If we steped on Water or into a block, we're destroyed ... + if Sq = Water or else Sq = Block then + raise Program_Error; + end if; + + Update_Square_Ahead (Device); + end Step_Forward; + + ----------------- + -- Rotate_Left -- + ----------------- + + procedure Rotate_Left (Device : access Dummy_Engine) is + begin + if Device.Env.Situ.Dir = Direction'First then + Device.Env.Situ.Dir := Direction'Last; + else + Device.Env.Situ.Dir := Direction'Pred (Device.Env.Situ.Dir); + end if; + + Update_Square_Ahead (Device); + end Rotate_Left; + + ------------------ + -- Rotate_Right -- + ------------------ + + procedure Rotate_Right (Device : access Dummy_Engine) is + begin + if Device.Env.Situ.Dir = Direction'Last then + Device.Env.Situ.Dir := Direction'First; + else + Device.Env.Situ.Dir := Direction'Succ (Device.Env.Situ.Dir); + end if; + + Update_Square_Ahead (Device); + end Rotate_Right; + + ----------------- + -- Probe_Ahead -- + ----------------- + + function Probe_Ahead (Device : access Dummy_Radar) return Square is + begin + return Device.Env.Situ.Sqa; + end Probe_Ahead; + + ------------------ + -- Get_Position -- + ------------------ + + function Get_Position (Device : access Dummy_Locator) return Position is + begin + return Device.Env.Situ.Pos; + end Get_Position; + + ------------------- + -- Get_Direction -- + ------------------- + + function Get_Direction (Device : access Dummy_Locator) return Direction is + begin + return Device.Env.Situ.Dir; + end Get_Direction; + + ------------------ + -- Get_Hardware -- + ------------------ + + function Get_Hardware return Robot_Hardware is + Hw : Robot_Hardware; + Env : Environment_Access := new Environment; + begin + -- Create the hardware set. + Hw := (Eng => new Dummy_Engine, + Rad => new Dummy_Radar, + Loc => new Dummy_Locator); + + -- All devices share the same environment. + Dummy_Engine (Hw.Eng.all).Env := Env; + Dummy_Radar (Hw.Rad.all).Env := Env; + Dummy_Locator (Hw.Loc.all).Env := Env; + + -- We now initialize the environment with a dummy map and initial + -- position + Fake_Map (Env.Map); + Env.Situ := + (Pos => (X => 2, Y => 2), + Dir => East, + Sqa => Ground); + + -- Verify that the Sqa value is correct. + Update_Square_Ahead (Dummy_Engine (Hw.Eng.all)'Access); + + return Hw; + end Get_Hardware; + + ------------------------- + -- Update_Square_Ahead -- + ------------------------- + + procedure Update_Square_Ahead (Device : access Dummy_Engine) is + Posa : Position renames Pos_Ahead_Of (Device.Env.Situ); + begin + Device.Env.Situ.Sqa := Device.Env.Map (Posa.X, Posa.Y); + end Update_Square_Ahead; + + -------------- + -- Fake_Map -- + -------------- + + procedure Fake_Map (Map : in out Geomap) is + + procedure Block_Borders_On (Map : in out Geomap); + procedure Clear_Playzone_On (Map : in out Geomap); + procedure Setup_Blocks_On (Map : in out Geomap); + + procedure Block_Borders_On (Map : in out Geomap) is + X, Y : Natural; + begin + X := Map'First (Sqx); + for Y in Map'Range (Sqy) loop + Map (X, Y) := Block; + end loop; + X := Map'Last (Sqx); + for Y in Map'Range (Sqy) loop + Map (X, Y) := Water; + end loop; + + Y := Map'First (Sqy); + for X in Map'Range (Sqx) loop + Map (X, Y) := Block; + end loop; + Y := Map'Last (Sqy); + for X in Map'Range (Sqx) loop + Map (X, Y) := Block; + end loop; + end Block_Borders_On; + + procedure Clear_Playzone_On (Map : in out Geomap) is + begin + for X in Map'First (Sqx) + 1 .. Map'Last (Sqx) - 1 loop + for Y in Map'First (Sqy) + 1 .. Map'Last (Sqy) - 1 loop + Map (X, Y) := Ground; + end loop; + end loop; + end Clear_Playzone_On; + + procedure Setup_Blocks_On (Map : in out Geomap) is + X, Y : Natural; + + -- Setup ~ 1 block per five squares in both directions + + Wx : Natural := Map'Length (Sqx); + Wy : Natural := Map'Length (Sqy); + Nx : Natural := Wx / 5; + Ny : Natural := Wy / 5; + + Stepx : Natural := Wx / (Nx + 1); + Stepy : Natural := Wy / (Ny + 1); + begin + Y := Map'First (Sqy) + Stepy; + while Y <= Map'Last (Sqy) loop + X := Map'First (Sqx) + Stepx; + while X <= Map'Last (Sqx) loop + Map (X, Y) := Block; + X := X + Stepx; + end loop; + Y := Y + Stepy; + end loop; + end Setup_Blocks_On; + + begin + Block_Borders_On (Map); + Clear_Playzone_On (Map); + Setup_Blocks_On (Map); + end Fake_Map; + +end Robots_Devices.Dummy; diff --git a/testsuite/tests/I717-018/src/robots_devices-dummy.ads b/testsuite/tests/I717-018/src/robots_devices-dummy.ads new file mode 100644 index 000000000..c375a2eb3 --- /dev/null +++ b/testsuite/tests/I717-018/src/robots_devices-dummy.ads @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- Fake implementation of robots devices, using a static Map. + +package Robots_Devices.Dummy is + + type Dummy_Engine is new Robots_Devices.Engine with private; + + procedure Step_Forward (Device : access Dummy_Engine); + -- Make the Engines step forward + + procedure Rotate_Left (Device : access Dummy_Engine); + -- Make the Engines rotate left + + procedure Rotate_Right (Device : access Dummy_Engine); + -- Make the Engines rotate right + + type Dummy_Radar is new Robots_Devices.Radar with private; + + function Probe_Ahead (Device : access Dummy_Radar) return Square; + -- Use the radar to determine what kind of square is ahead + + type Dummy_Locator is new Robots_Devices.Locator with private; + + function Get_Position (Device : access Dummy_Locator) return Position; + function Get_Direction (Device : access Dummy_Locator) return Direction; + -- Use the locator to retrieve the current position and direction. + + function Get_Hardware return Robot_Hardware; + -- Get a complete hardware set based on the above devices. + +private + + type Environment is record + Map : Geomap; + Situ : Situation; + end record; + + type Environment_Access is access Environment; + -- Shared environment for all devices. + + type Dummy_Engine is new Robots_Devices.Engine with record + Env : Environment_Access; + end record; + + type Dummy_Radar is new Robots_Devices.Radar with record + Env : Environment_Access; + end record; + + type Dummy_Locator is new Robots_Devices.Locator with record + Env : Environment_Access; + end record; + +end Robots_Devices.Dummy; diff --git a/testsuite/tests/I717-018/src/robots_devices.ads b/testsuite/tests/I717-018/src/robots_devices.ads new file mode 100644 index 000000000..1eb4d6d67 --- /dev/null +++ b/testsuite/tests/I717-018/src/robots_devices.ads @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit offers a simple device access internal API to the Robot +-- abstraction of the Explore example. +-- +-- This API abstracts the capabilities of +-- +-- - a steering engine, able to have the robot perform a short step +-- forward or rotate 90 deg either way without advancing, +-- +-- - a front radar, able to probe the field characteristics one step ahead, +-- +-- - a locator, able to evaluate the robot's position and orientation on +-- the field. + +with Controls, Geomaps; +use Controls, Geomaps; + +package Robots_Devices is + + type Engine is abstract tagged null record; + type Engine_Access is access all Engine'Class; + + procedure Step_Forward (Device : access Engine) is abstract; + -- Make the Engines step forward + + procedure Rotate_Left (Device : access Engine) is abstract; + -- Make the Engines rotate left + + procedure Rotate_Right (Device : access Engine) is abstract; + -- Make the Engines rotate right + + type Radar is abstract tagged null record; + type Radar_Access is access all Radar'Class; + + function Probe_Ahead (Device : access Radar) return Square is abstract; + -- Use the radar to determine what kind of square is ahead + + type Locator is abstract tagged null record; + type Locator_Access is access all Locator'Class; + + function Get_Position + (Device : access Locator) return Position is abstract; + function Get_Direction + (Device : access Locator) return Direction is abstract; + -- Use the locator to retrieve the current position and direction. + + type Robot_Hardware is record + Eng : Engine_Access; + Rad : Radar_Access; + Loc : Locator_Access; + end record; + +end Robots_Devices; diff --git a/testsuite/tests/I717-018/src/stacks.adb b/testsuite/tests/I717-018/src/stacks.adb new file mode 100644 index 000000000..1d4c1313d --- /dev/null +++ b/testsuite/tests/I717-018/src/stacks.adb @@ -0,0 +1,61 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Stacks is + + ------------------------- + -- Classical accessors -- + ------------------------- + + function Size (S : Stack) return Natural; + + function Size (S : Stack) return Natural is + begin + return S.Size; + end Size; + + function Full (S : Stack) return Boolean is + begin + return Size (S) = S.Capacity; + end Full; + + function Empty (S : Stack) return Boolean is + begin + return Size (S) = 0; + end Empty; + + procedure Pop (Item : out Data_Type; S : in out Stack) is + begin + if Empty (S) then + raise Program_Error; + end if; + Item := S.Items (S.Size); + S.Size := S.Size - 1; + end Pop; + + procedure Push (Item : Data_Type; S : in out Stack) is + begin + if Full (S) then + raise Program_Error; + end if; + S.Size := S.Size + 1; + S.Items (S.Size) := Item; + end Push; + +end Stacks; diff --git a/testsuite/tests/I717-018/src/stacks.ads b/testsuite/tests/I717-018/src/stacks.ads new file mode 100644 index 000000000..89f6a0dbb --- /dev/null +++ b/testsuite/tests/I717-018/src/stacks.ads @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package offers a simple "bounded stack" data structure abstraction + +generic + type Data_Type is private; -- The elements data type +package Stacks is + type Stack (Capacity : Natural) is private; + + function Full (S : Stack) return Boolean; + -- Whether S is full with respect to its Capacity. + + function Empty (S : Stack) return Boolean; + -- Whether S is empty. + + procedure Push (Item : Data_Type; S : in out Stack); + -- Push Item on top of stack S if it is not Full, + -- raise Program_Error and leave S unchanged otherwise. + + procedure Pop (Item : out Data_Type; S : in out Stack); + -- Pop the top element off stack S into Item if S is not Empty, + -- raise Program_Error and leave Item undefined otherwise. + +private + type Data_Array is array (Natural range <>) of Data_Type; + type Stack (Capacity : Natural) is record + Items : Data_Array (1 .. Capacity); + Size : Natural := 0; + -- The number of Items currently available in the stack + end record; +end Stacks; diff --git a/testsuite/tests/I717-018/src/stations.adb b/testsuite/tests/I717-018/src/stations.adb new file mode 100644 index 000000000..4b1ac9aa2 --- /dev/null +++ b/testsuite/tests/I717-018/src/stations.adb @@ -0,0 +1,162 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with GNAT.IO; use GNAT.IO; + +package body Stations is + + -------------------- + -- IOports access -- + -------------------- + + function Robot_Control_Outport + (Sta : Station) return Robot_Control_Links.IOport_Access is + begin + return Sta.Robot_Control_Outp; + end Robot_Control_Outport; + + function Robot_Situation_Inport + (Sta : Station) return Situation_Links.IOport_Access is + begin + return Sta.Robot_Situation_Inp; + end Robot_Situation_Inport; + + use Robot_Control_Links, Situation_Links; + + --------- + -- Run -- + --------- + + procedure Run (Sta : Station_Access) is + + procedure Update (Map : in out Geomap; Situ : Situation); + -- Update MAP from the info found in SITU, about the kind of square + -- probed ahead of a given position. + + procedure Update (Map : in out Geomap; Situ : Situation) is + Posa : constant Position := Pos_Ahead_Of (Situ); + begin + Map (Posa.X, Posa.Y) := Situ.Sqa; + end Update; + + procedure Process_Pending_Inputs (Sta : Station_Access); + -- Fetch and process pending Situation inputs - update and + -- dump the map of our local view of the field. + + procedure Process_Pending_Inputs (Sta : Station_Access) is + Situ : Situation; + begin + while not Empty (Robot_Situation_Inport (Sta.all)) loop + Pop (Situ, Robot_Situation_Inport (Sta.all)); + Update (Sta.Map, Situ); + Dump (Sta.Map, Situ); + end loop; + end Process_Pending_Inputs; + + function Control_For (C : Character) return Robot_Control; + -- Map user input character C to Robot_Control command, Nop if + -- the input isn't recognized. + + function Control_For + (C : Character) return Robot_Control is + begin + case C is + when 'p' | 'P' => + return (Code => Probe, Value => 0); + when 's' | 'S' => + return (Code => Step_Forward, Value => 0); + when 'l' | 'L' => + return (Code => Rotate_Left, Value => 0); + when 'r' | 'R' => + return (Code => Rotate_Right, Value => 0); + when 'c' | 'C' => + return (Code => Opmode, Value => Robot_Opmode'Pos (Cautious)); + when 'd' | 'D' => + return (Code => Opmode, Value => Robot_Opmode'Pos (Dumb)); + when others => + return (Code => Nop, Value => 0); + end case; + end Control_For; + + procedure Execute_Command (C : Character) is + Ctrl : Robot_Control := Control_For (C); + begin + + -- Push the command out to the robot, so that it executes, and + -- follow with a probe request so that a situation update gets + -- sent if this is not just what we asked. + + Push (Ctrl, Robot_Control_Outport (Sta.all)); + if Ctrl.Code /= Probe then + Push (Control_For ('P'), Robot_Control_Outport (Sta.all)); + end if; + + -- In case the Robot reacts instantly ... + + Process_Pending_Inputs (Sta); + end; + + begin + + -- In case something came in since last time ... + + Process_Pending_Inputs (Sta); + + -- Get the next command from the terminal line and map it to an + -- internal control code. + + Put_Line ("'C'autious mode, 'D'umb mode"); + Put ("'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? "); + + -- Dummy version here, for compilation and basic run check in + -- batch mode. + + end Run; + + ---------- + -- Init -- + ---------- + + procedure Init (Sta : Station_Access) is + + procedure All_Unknown (Map : in out Geomap); + -- Fill all the squares in MAP as Unknown + + procedure All_Unknown (Map : in out Geomap) is + begin + for X in Map'Range (Sqx) loop + for Y in Map'Range (Sqy) loop + Map (X, Y) := Unknown; + end loop; + end loop; + end All_Unknown; + + begin + Sta.Robot_Control_Outp := + Robot_Control_Links.Create_IOport + (Capacity => 2, + Owner => Actor_Ref (Sta)); + Sta.Robot_Situation_Inp := + Situation_Links.Create_IOport + (Capacity => 1, + Owner => Actor_Ref (Sta)); + All_Unknown (Sta.Map); + end Init; + +end Stations; diff --git a/testsuite/tests/I717-018/src/stations.ads b/testsuite/tests/I717-018/src/stations.ads new file mode 100644 index 000000000..39e800830 --- /dev/null +++ b/testsuite/tests/I717-018/src/stations.ads @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the Control Station abstraction of the Explore +-- example. The station gets user input about the next robot order to +-- transmit, sends them over the control link, receives the situation +-- report over the situation link and maintains a local view of the field +-- as it gets explored. + +with Actors, Controls, Geomaps; use Actors, Controls, Geomaps; + +package Stations is + + type Station is new Actor with private; + type Station_Access is access all Station; + + function Robot_Control_Outport + (Sta : Station) return Robot_Control_Links.IOport_Access; + function Robot_Situation_Inport + (Sta : Station) return Situation_Links.IOport_Access; + + procedure Init (Sta : Station_Access); + -- Initialize station STA - setup ports and local field view + + procedure Run (Sta : Station_Access); + -- Run a single command processing cycle on station STA + +private + type Station is new Actor with record + Robot_Control_Outp : Robot_Control_Links.IOport_Access; + Robot_Situation_Inp : Situation_Links.IOport_Access; + + Map : Geomap; + end record; +end Stations; diff --git a/testsuite/tests/I717-018/test.opt b/testsuite/tests/I717-018/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I717-018/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I717-018/test.py b/testsuite/tests/I717-018/test.py new file mode 100644 index 000000000..1b484bf45 --- /dev/null +++ b/testsuite/tests/I717-018/test.py @@ -0,0 +1,50 @@ +""" +This test checks that a line with empty instruction range at the beginning of a +function is not associated to the function that precedes it in the text +segment. +""" + +import re + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +gprbuild(project=gprfor(["explore.adb"], srcdirs="../src")) + +xrun(exepath_to("explore")) + +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov+", + "--routines={}".format( + target_info().to_platform_specific_symbol( + "robots__robot_control_inport" + ) + ), + tracename_for("explore"), + ] +) + +thistest.fail_if( + not match( + r"\.: function Robot_Situation_Outport", + "robots.adb.xcov", + flags=re.DOTALL, + ), + "expect line with empty instruction range dropped", +) + +thistest.result() diff --git a/testsuite/tests/I812-011/main.adb b/testsuite/tests/I812-011/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/I812-011/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/I812-011/test.py b/testsuite/tests/I812-011/test.py new file mode 100644 index 000000000..439d59a8b --- /dev/null +++ b/testsuite/tests/I812-011/test.py @@ -0,0 +1,67 @@ +""" +Check that --output-dir maked gnatcov produce all annotated reports in the +output directory, none in the current directory. +""" + +import os.path + +from e3.fs import mkdir + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, list_to_tmp, match +from SUITE.tutils import gprfor, xcov + + +Wdir("tmp_") + + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(["main.adb"], srcdirs="..")), + covlevel="stmt", + mains=["main"], + scos=["obj/main"], + extra_coverage_args=["--level=stmt"], +) + + +# Check that the annotated reports are produced in the expected directory +mkdir("xcovs") +mkdir("htmls") +xcov(xcov_args + ["--annotate=xcov", "--output-dir=./xcovs"]) +xcov(xcov_args + ["--annotate=html", "--output-dir=./htmls"]) +xcov_report = "main.adb.xcov" +html_report = "index.html" +thistest.fail_if( + os.path.exists("./" + xcov_report) + or os.path.exists("./" + html_report) + or not os.path.exists("./htmls/" + html_report) + or not os.path.exists("./xcovs/" + xcov_report), + "reports in the wrong output dir", +) + +# Check that a proper error message is given when the output dir is not a +# directory. +p = xcov( + xcov_args + ["--annotate=html", "--output-dir=./gen.gpr"], + out="gen.gpr.out", + register_failure=False, +) + +thistest.fail_if( + p.status == 0 + or not match(": cannot create output path ./gen.gpr: ", "gen.gpr.out"), + "no error if output dir is not a directory", +) + +# Check that gnatcov can take a list of traces using the '@' prefix with the +# various forms to pass trace files on the command line, checking the output +# report in all cases. +trace_file = xcov_args.pop() +tlist = "@" + list_to_tmp([trace_file]) +for arg in [["--trace=" + tlist], ["-T", tlist], [tlist]]: + xcov(xcov_args + ["--annotate=xcov"] + arg) + check_xcov_reports(".", {"main.adb.xcov": {"+": {3}}}) + +thistest.result() diff --git a/testsuite/tests/I914-023/src/robots.adb b/testsuite/tests/I914-023/src/robots.adb new file mode 100644 index 000000000..eb36edb33 --- /dev/null +++ b/testsuite/tests/I914-023/src/robots.adb @@ -0,0 +1,25 @@ +package body Robots is + + function Current_Mode (R : Robot) return Opmode is + begin + return R.Mode; + end; + + function Unsafe (C : Command) return Boolean is + begin + return C = Step; + end; + + procedure Run (R : in out Robot; C : Command) is + Mode : Opmode; + begin + Mode := Current_Mode (R); + if Mode = Cautious + and then Unsafe (C) + then + return; + end if; + R.Exec := R.Exec + 1; + end; + +end; diff --git a/testsuite/tests/I914-023/src/robots.ads b/testsuite/tests/I914-023/src/robots.ads new file mode 100644 index 000000000..2402ce292 --- /dev/null +++ b/testsuite/tests/I914-023/src/robots.ads @@ -0,0 +1,12 @@ + +package Robots is + type Opmode is (Cautious, Dumb); + type Command is (Nop, Rotate, Step); + + type Robot is record + Mode : Opmode := Cautious; + Exec : Integer := 0; + end record; + + procedure Run (R : in out Robot; C : Command); +end; diff --git a/testsuite/tests/I914-023/src/test_robots.adb b/testsuite/tests/I914-023/src/test_robots.adb new file mode 100644 index 000000000..957bcc2b5 --- /dev/null +++ b/testsuite/tests/I914-023/src/test_robots.adb @@ -0,0 +1,12 @@ +with Robots; use Robots; + +procedure Test_Robots is + R : Robot; +begin + Run (R, Nop); + Run (R, Rotate); + + if R.Exec /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I914-023/test.opt b/testsuite/tests/I914-023/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I914-023/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I914-023/test.py b/testsuite/tests/I914-023/test.py new file mode 100644 index 000000000..9a1a6d720 --- /dev/null +++ b/testsuite/tests/I914-023/test.py @@ -0,0 +1,55 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project = gprfor(['test_robots.adb'])) + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to("../test_robots")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_robots"), + ], + "robots.out", +) + +# Expect something like ... + +# 17 +: if Mode = Cautious +# [...] +# fffc01e8 >: 40 9e 00 20 bne- cr7,0xfffc021c +# 18 +: and then Unsafe (C) +# [...] +# fffc0204 >: 40 9e 00 20 bne- cr7,0xfffc0238 +thistest.fail_if( + not match("fff003dc v: 40 9e 00 20 bne", "robots.out"), + "expect Mode = Cautious always true", +) +thistest.fail_if( + not match("fff003f8 v: 40 9e 00 48 bne", "robots.out"), + "expect Unsafe (C) always false", +) + +thistest.result() diff --git a/testsuite/tests/I914-023/test_robots b/testsuite/tests/I914-023/test_robots new file mode 100755 index 000000000..f6709ccc9 Binary files /dev/null and b/testsuite/tests/I914-023/test_robots differ diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-bt-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-bt-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-bt-x2/src/test_cond.adb new file mode 100644 index 000000000..c3289b705 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/src/test_cond.adb @@ -0,0 +1,17 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-bt-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py b/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py new file mode 100644 index 000000000..cdfe30784 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond new file mode 100755 index 000000000..30e44d4cd Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-bt/gnu.ld b/testsuite/tests/I930-009-ppc-beq-bt/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-bt/src/cond.s b/testsuite/tests/I930-009-ppc-beq-bt/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb new file mode 100644 index 000000000..9ee2290b1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test.opt b/testsuite/tests/I930-009-ppc-beq-bt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test.py b/testsuite/tests/I930-009-ppc-beq-bt/test.py new file mode 100644 index 000000000..cdfe30784 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test_cond b/testsuite/tests/I930-009-ppc-beq-bt/test_cond new file mode 100755 index 000000000..99032e11f Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-bt/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb new file mode 100644 index 000000000..1b60d0b41 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py new file mode 100644 index 000000000..671bc61e2 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 v: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond new file mode 100755 index 000000000..05a87c49c Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-ft/gnu.ld b/testsuite/tests/I930-009-ppc-beq-ft/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-ft/src/cond.s b/testsuite/tests/I930-009-ppc-beq-ft/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb new file mode 100644 index 000000000..ce4dd93fe --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test.opt b/testsuite/tests/I930-009-ppc-beq-ft/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test.py b/testsuite/tests/I930-009-ppc-beq-ft/test.py new file mode 100644 index 000000000..671bc61e2 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 v: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test_cond b/testsuite/tests/I930-009-ppc-beq-ft/test_cond new file mode 100755 index 000000000..81cce4cb5 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-ft/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld b/testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld new file mode 100644 index 000000000..8bb68d779 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000) - 8; + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb new file mode 100644 index 000000000..9ee2290b1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py new file mode 100644 index 000000000..3e8063489 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff00ffc \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond new file mode 100755 index 000000000..7ac9b8ed5 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld b/testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld new file mode 100644 index 000000000..8bb68d779 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000) - 8; + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb new file mode 100644 index 000000000..ce4dd93fe --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py new file mode 100644 index 000000000..ec3505fb7 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff00ffc v: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond new file mode 100755 index 000000000..0286d3750 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld b/testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld new file mode 100644 index 000000000..8bb68d779 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000) - 8; + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb new file mode 100644 index 000000000..67f39c8be --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py new file mode 100644 index 000000000..7b47f8b53 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py @@ -0,0 +1,43 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project = gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr'); + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in + +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== + +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff00ffc >: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond new file mode 100755 index 000000000..5f5d0c427 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/gnu.ld b/testsuite/tests/I930-009-ppc-beq-nt/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/cond.s b/testsuite/tests/I930-009-ppc-beq-nt/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb new file mode 100644 index 000000000..598a2fdb6 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb @@ -0,0 +1,4 @@ +function Get_False return Boolean is +begin + return False; +end Get_False; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads new file mode 100644 index 000000000..94abd0fe4 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads @@ -0,0 +1 @@ +function Get_False return Boolean; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb new file mode 100644 index 000000000..e33d5ce90 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb @@ -0,0 +1,12 @@ +with Get_False; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Get_False then + if Cond (1) /= 2 then + raise Program_Error; + end if; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test.opt b/testsuite/tests/I930-009-ppc-beq-nt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test.py b/testsuite/tests/I930-009-ppc-beq-nt/test.py new file mode 100644 index 000000000..f72fdeb5e --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 -: 41 9e 00 0c beq", "cond.out"), + "branch should not be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test_cond b/testsuite/tests/I930-009-ppc-beq-nt/test_cond new file mode 100755 index 000000000..86a52dfc6 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-nt/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb new file mode 100644 index 000000000..d5b06cd17 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb @@ -0,0 +1,17 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py new file mode 100644 index 000000000..cdfe30784 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond new file mode 100755 index 000000000..440f7d974 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-tb/gnu.ld b/testsuite/tests/I930-009-ppc-beq-tb/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-tb/src/cond.s b/testsuite/tests/I930-009-ppc-beq-tb/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-tb/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-tb/src/test_cond.adb new file mode 100644 index 000000000..81411b26a --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-tb/test.opt b/testsuite/tests/I930-009-ppc-beq-tb/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-tb/test.py b/testsuite/tests/I930-009-ppc-beq-tb/test.py new file mode 100644 index 000000000..cdfe30784 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tb/test_cond b/testsuite/tests/I930-009-ppc-beq-tb/test_cond new file mode 100755 index 000000000..39a5c43d9 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-tb/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb new file mode 100644 index 000000000..865176e19 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py new file mode 100644 index 000000000..7d2e32576 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 >: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond new file mode 100755 index 000000000..274880312 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-tk/gnu.ld b/testsuite/tests/I930-009-ppc-beq-tk/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-tk/src/cond.s b/testsuite/tests/I930-009-ppc-beq-tk/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-tk/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-tk/src/test_cond.adb new file mode 100644 index 000000000..67f39c8be --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test.opt b/testsuite/tests/I930-009-ppc-beq-tk/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test.py b/testsuite/tests/I930-009-ppc-beq-tk/test.py new file mode 100644 index 000000000..7d2e32576 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 >: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test_cond b/testsuite/tests/I930-009-ppc-beq-tk/test_cond new file mode 100755 index 000000000..07a300e51 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beq-tk/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld b/testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s b/testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s new file mode 100644 index 000000000..c8f3e4d00 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s @@ -0,0 +1,12 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + li %r3,120 + beqlr %cr7 + # != 0 + li %r3,2 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb new file mode 100644 index 000000000..9ee2290b1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test.opt b/testsuite/tests/I930-009-ppc-beqlr-bt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test.py b/testsuite/tests/I930-009-ppc-beqlr-bt/test.py new file mode 100644 index 000000000..b63a86f2b --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01008 \\+: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond b/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond new file mode 100755 index 000000000..1a400e3b0 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/gnu.ld b/testsuite/tests/I930-009-ppc-beqlr-ft/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/src/cond.s b/testsuite/tests/I930-009-ppc-beqlr-ft/src/cond.s new file mode 100644 index 000000000..c8f3e4d00 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/src/cond.s @@ -0,0 +1,12 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + li %r3,120 + beqlr %cr7 + # != 0 + li %r3,2 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beqlr-ft/src/test_cond.adb new file mode 100644 index 000000000..ce4dd93fe --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/test.opt b/testsuite/tests/I930-009-ppc-beqlr-ft/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/test.py b/testsuite/tests/I930-009-ppc-beqlr-ft/test.py new file mode 100644 index 000000000..894e241d7 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01008 v: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond b/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond new file mode 100755 index 000000000..90cea1ca7 Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr b/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld b/testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s b/testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s new file mode 100644 index 000000000..c8f3e4d00 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s @@ -0,0 +1,12 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + li %r3,120 + beqlr %cr7 + # != 0 + li %r3,2 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb new file mode 100644 index 000000000..81411b26a --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test.opt b/testsuite/tests/I930-009-ppc-beqlr-tb/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test.py b/testsuite/tests/I930-009-ppc-beqlr-tb/test.py new file mode 100644 index 000000000..b63a86f2b --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01008 \\+: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond b/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond new file mode 100755 index 000000000..b2cce0d8c Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond.gpr b/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/gnu.ld b/testsuite/tests/I930-009-ppc-beqlr-tk/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/src/cond.s b/testsuite/tests/I930-009-ppc-beqlr-tk/src/cond.s new file mode 100644 index 000000000..c8f3e4d00 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/src/cond.s @@ -0,0 +1,12 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + li %r3,120 + beqlr %cr7 + # != 0 + li %r3,2 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beqlr-tk/src/test_cond.adb new file mode 100644 index 000000000..67f39c8be --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/test.opt b/testsuite/tests/I930-009-ppc-beqlr-tk/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/test.py b/testsuite/tests/I930-009-ppc-beqlr-tk/test.py new file mode 100644 index 000000000..ad2c410e2 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01008 >: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond b/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond new file mode 100755 index 000000000..efdb4222a Binary files /dev/null and b/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond differ diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond.gpr b/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-ft/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-ft/src/cond.s new file mode 100644 index 000000000..a401df1b6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/cond.s @@ -0,0 +1,15 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test.opt b/testsuite/tests/I930-009-sparc-be-a-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test.py b/testsuite/tests/I930-009-sparc-be-a-ft/test.py new file mode 100644 index 000000000..9344fb189 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test.py @@ -0,0 +1,48 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001404 v: 32 80 00 02 bne,a", "cond.out"), + "branch should not be taken", +) +thistest.fail_if( + not match("40001408 -: 90 10 20 02 mov", "cond.out"), + "delay slot should not be executed", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test_cond b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond new file mode 100755 index 000000000..40231af19 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s new file mode 100644 index 000000000..ba3b613aa --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s @@ -0,0 +1,17 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3064 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py new file mode 100644 index 000000000..0c069959a --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py @@ -0,0 +1,28 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild('test_cond.gpr') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc v: 32 80 00 02 bne,a", "cond.out"), + "branch should be not taken", +) +thistest.fail_if( + not match("40002000 -: 90 10 20 02 mov", "cond.out"), + "delay slot shouldn't be executed", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond new file mode 100755 index 000000000..316dfd397 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s new file mode 100644 index 000000000..ba3b613aa --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s @@ -0,0 +1,17 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3064 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py new file mode 100644 index 000000000..37436f06a --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py @@ -0,0 +1,24 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild('test_cond.gpr') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc >: 32 80 00 02 bne,a", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond new file mode 100755 index 000000000..afa57ce4d Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-nt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-nt/src/cond.s new file mode 100644 index 000000000..a401df1b6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/cond.s @@ -0,0 +1,15 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test.opt b/testsuite/tests/I930-009-sparc-be-a-nt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test.py b/testsuite/tests/I930-009-sparc-be-a-nt/test.py new file mode 100644 index 000000000..46cd96842 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test.py @@ -0,0 +1,49 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001404 v: 32 80 00 02 bne,a", "cond.out"), + "branch should not be taken", +) + +thistest.fail_if( + not match("40001408 -: 90 10 20 02 mov", "cond.out"), + "delay slot should not be executed", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test_cond b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond new file mode 100755 index 000000000..40231af19 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s new file mode 100644 index 000000000..ad8a8f5d3 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s @@ -0,0 +1,15 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test.opt b/testsuite/tests/I930-009-sparc-be-a-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test.py b/testsuite/tests/I930-009-sparc-be-a-tk/test.py new file mode 100644 index 000000000..206adb013 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test.py @@ -0,0 +1,49 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001404 >: 32 80 00 02 bne,a", "cond.out"), + "branch should be taken", +) + +thistest.fail_if( + not match("40001408 \\+: 90 10 20 02 mov", "cond.out"), + "delay slot should be executed", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test_cond b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond new file mode 100755 index 000000000..16204f37a Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/cond.c b/testsuite/tests/I930-009-sparc-be-bt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/cond.s b/testsuite/tests/I930-009-sparc-be-bt/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb new file mode 100644 index 000000000..108814c01 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb @@ -0,0 +1,13 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-bt/test.opt b/testsuite/tests/I930-009-sparc-be-bt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-bt/test.py b/testsuite/tests/I930-009-sparc-be-bt/test.py new file mode 100644 index 000000000..b3dccf739 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/test.py @@ -0,0 +1,43 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001430 \\+: 12 80 00 04 bne", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-bt/test_cond b/testsuite/tests/I930-009-sparc-be-bt/test_cond new file mode 100755 index 000000000..e85f0f050 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-bt/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-bt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-bt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/cond.c b/testsuite/tests/I930-009-sparc-be-ft/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/cond.s b/testsuite/tests/I930-009-sparc-be-ft/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-ft/test.opt b/testsuite/tests/I930-009-sparc-be-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-ft/test.py b/testsuite/tests/I930-009-sparc-be-ft/test.py new file mode 100644 index 000000000..4e745ae73 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/test.py @@ -0,0 +1,50 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. + +The test intently gets into the 'Run' function twice in Cautious mode for a +safe command. We expect, then, partial coverage for both conditions in + + procedure Run (R : in out Robot; C : Command) is + Mode : Opmode; + begin + Mode := Current_Mode (R); + if Mode = Cautious <== + and then Unsafe (C) <== + +We seek the reported status of the associated cond branch instructions +directly. +""" + +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr'); +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) + +thistest.fail_if( + not match( + re.escape( + "40001400 v: 12 80 00 04 " "bne 0x40001410 " + ), + "cond.out", + ), + "branch should be taken on fall-through", +) +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-ft/test_cond b/testsuite/tests/I930-009-sparc-be-ft/test_cond new file mode 100755 index 000000000..372c198ca Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-ft/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s new file mode 100644 index 000000000..f1178ec87 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s @@ -0,0 +1,18 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3020 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb new file mode 100644 index 000000000..108814c01 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb @@ -0,0 +1,13 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test.opt b/testsuite/tests/I930-009-sparc-be-npg-bt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test.py b/testsuite/tests/I930-009-sparc-be-npg-bt/test.py new file mode 100644 index 000000000..f673543e1 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test.py @@ -0,0 +1,23 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + +Wdir("tmp_") + +# gprbuild('test_cond.gpr') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc \\+: 12 80 00 04 bne", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond new file mode 100755 index 000000000..7378057b5 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s new file mode 100644 index 000000000..34cd5d5bf --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s @@ -0,0 +1,18 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3068 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test.opt b/testsuite/tests/I930-009-sparc-be-npg-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test.py b/testsuite/tests/I930-009-sparc-be-npg-ft/test.py new file mode 100644 index 000000000..7364f24f8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test.py @@ -0,0 +1,24 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild('test_cond.gpr') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc v: 12 80 00 04 bne", "cond.out"), + "branch should be taken fall-through", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond new file mode 100755 index 000000000..985c4a67a Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s new file mode 100644 index 000000000..34cd5d5bf --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s @@ -0,0 +1,18 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3068 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test.opt b/testsuite/tests/I930-009-sparc-be-npg-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test.py b/testsuite/tests/I930-009-sparc-be-npg-tk/test.py new file mode 100644 index 000000000..ab365f1c0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test.py @@ -0,0 +1,24 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild ('test_cond.gpr') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc \\>: 12 80 00 04 bne", "cond.out"), + "branch should be taken on both dir", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond new file mode 100755 index 000000000..26a501fa7 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/cond.c b/testsuite/tests/I930-009-sparc-be-nt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/cond.s b/testsuite/tests/I930-009-sparc-be-nt/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb new file mode 100644 index 000000000..c20d60c81 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb @@ -0,0 +1,13 @@ +with Get_False; +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Get_False then + if Cond (1) /= 2 then + raise Program_Error; + end if; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-nt/test.opt b/testsuite/tests/I930-009-sparc-be-nt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-nt/test.py b/testsuite/tests/I930-009-sparc-be-nt/test.py new file mode 100644 index 000000000..20047923f --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001444 -: 12 80 00 04 bne", "cond.out"), + "branch should not be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-nt/test_cond b/testsuite/tests/I930-009-sparc-be-nt/test_cond new file mode 100755 index 000000000..8442eff92 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-nt/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-tk/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-tk/test.opt b/testsuite/tests/I930-009-sparc-be-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-tk/test.py b/testsuite/tests/I930-009-sparc-be-tk/test.py new file mode 100644 index 000000000..b69e729c8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/test.py @@ -0,0 +1,43 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# gprbuild(project = gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr'); + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in + +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== + +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001400 >: 12 80 00 04 bne", "cond.out"), + "branch should be taken", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-tk/test_cond b/testsuite/tests/I930-009-sparc-be-tk/test_cond new file mode 100755 index 000000000..7acbe7ea9 Binary files /dev/null and b/testsuite/tests/I930-009-sparc-be-tk/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s new file mode 100644 index 000000000..fd96ab66f --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s @@ -0,0 +1,15 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + mov 2, %o0 +.LL2: + jmp %o7+8 + .size cond, .-cond + .type cond1, #function +cond1: + nop + .size cond1, .-cond1 + diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb b/testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test.opt b/testsuite/tests/I930-009-sparc-cross-boundary/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test.py b/testsuite/tests/I930-009-sparc-cross-boundary/test.py new file mode 100644 index 000000000..5f6157fbb --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test.py @@ -0,0 +1,47 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + +Wdir("tmp_") + +# gprbuild(project = gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) + +thistest.fail_if( + not match("40001400 \\+: 81 c3 e0 08 retl", "cond.out"), + "cond should be covered", +) +thistest.fail_if( + not match("40001404 \\+: 01 00 00 00 nop", "cond.out"), + "cond1 should be covered", +) + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test_cond b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond new file mode 100755 index 000000000..bc01f0acb Binary files /dev/null and b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond differ diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-019/src/kops.adb b/testsuite/tests/I930-019/src/kops.adb new file mode 100644 index 000000000..fdc3374c2 --- /dev/null +++ b/testsuite/tests/I930-019/src/kops.adb @@ -0,0 +1,7 @@ + +package body Kops is + procedure Inc (X : in out Integer) is + begin + X := X + K; + end Inc; +end; diff --git a/testsuite/tests/I930-019/src/kops.ads b/testsuite/tests/I930-019/src/kops.ads new file mode 100644 index 000000000..b97d2afbe --- /dev/null +++ b/testsuite/tests/I930-019/src/kops.ads @@ -0,0 +1,7 @@ + +generic + K : Integer; +package Kops is + procedure Inc (X : in out Integer); + pragma Inline (Inc); +end; diff --git a/testsuite/tests/I930-019/src/ops4.ads b/testsuite/tests/I930-019/src/ops4.ads new file mode 100644 index 000000000..1d4738d2d --- /dev/null +++ b/testsuite/tests/I930-019/src/ops4.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops4 is new Kops (K => 4); diff --git a/testsuite/tests/I930-019/src/ops8.ads b/testsuite/tests/I930-019/src/ops8.ads new file mode 100644 index 000000000..d69b950a1 --- /dev/null +++ b/testsuite/tests/I930-019/src/ops8.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops8 is new Kops (K => 8); diff --git a/testsuite/tests/I930-019/src/test_kops.adb b/testsuite/tests/I930-019/src/test_kops.adb new file mode 100644 index 000000000..0b479da84 --- /dev/null +++ b/testsuite/tests/I930-019/src/test_kops.adb @@ -0,0 +1,11 @@ +with Ops4, Ops8, Vars; + +procedure Test_Kops is + Vx : Integer := Vars.X; +begin + Ops4.Inc (Vx); + Vars.Assert_Eq (Vx, 16); + + Ops8.Inc (Vx); + Vars.Assert_Eq (Vx, 24); +end; diff --git a/testsuite/tests/I930-019/src/vars.adb b/testsuite/tests/I930-019/src/vars.adb new file mode 100644 index 000000000..b36792c78 --- /dev/null +++ b/testsuite/tests/I930-019/src/vars.adb @@ -0,0 +1,8 @@ +package body Vars is + procedure Assert_Eq (Value, Expected : Integer) is + begin + if Value /= Expected then + raise Program_Error; + end if; + end; +end; diff --git a/testsuite/tests/I930-019/src/vars.ads b/testsuite/tests/I930-019/src/vars.ads new file mode 100644 index 000000000..06a24b27f --- /dev/null +++ b/testsuite/tests/I930-019/src/vars.ads @@ -0,0 +1,6 @@ +package Vars is + X : Integer := 12; + pragma Volatile (X); + + procedure Assert_Eq (Value, Expected : Integer); +end; diff --git a/testsuite/tests/I930-019/test.py b/testsuite/tests/I930-019/test.py new file mode 100644 index 000000000..8ebfdd3a8 --- /dev/null +++ b/testsuite/tests/I930-019/test.py @@ -0,0 +1,35 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir("tmp_") + + +# Run, then check results. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor("test_kops.adb", srcdirs="../src")), + covlevel="stmt", + mains=["test_kops"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/kops", "obj/ops4", "obj/ops8", "obj/test_kops", "obj/vars"], +) + +thistest.fail_if( + not match(r"4 \+:", "test_kops.adb.xcov"), "test_kops.adb:4 not covered" +) +thistest.fail_if( + not match(r"6 \+:", "test_kops.adb.xcov"), "test_kops.adb:6 not covered" +) +thistest.fail_if( + not match(r"7 \+:", "test_kops.adb.xcov"), "test_kops.adb:7 not covered" +) +thistest.fail_if( + not match(r"9 \+:", "test_kops.adb.xcov"), "test_kops.adb:9 not covered" +) +thistest.fail_if( + not match(r"10 \+:", "test_kops.adb.xcov"), "test_kops.adb:10 not covered" +) +thistest.result() diff --git a/testsuite/tests/IA01-015/src/monitor.adb b/testsuite/tests/IA01-015/src/monitor.adb new file mode 100644 index 000000000..efc5cd47b --- /dev/null +++ b/testsuite/tests/IA01-015/src/monitor.adb @@ -0,0 +1,6 @@ +package body Monitor is + procedure Touch is + begin + N_Ops := N_Ops + 1; + end; +end; diff --git a/testsuite/tests/IA01-015/src/monitor.ads b/testsuite/tests/IA01-015/src/monitor.ads new file mode 100644 index 000000000..d387b410e --- /dev/null +++ b/testsuite/tests/IA01-015/src/monitor.ads @@ -0,0 +1,5 @@ +package Monitor is + N_Ops : Integer := 0; + + procedure Touch; +end; diff --git a/testsuite/tests/IA01-015/src/trymon.adb b/testsuite/tests/IA01-015/src/trymon.adb new file mode 100644 index 000000000..bc6d6a5ab --- /dev/null +++ b/testsuite/tests/IA01-015/src/trymon.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Monitor; + +procedure Trymon is +begin + Monitor.Touch; +end; diff --git a/testsuite/tests/IA01-015/test.py b/testsuite/tests/IA01-015/test.py new file mode 100644 index 000000000..1d823e4fe --- /dev/null +++ b/testsuite/tests/IA01-015/test.py @@ -0,0 +1,63 @@ +""" +We check that gnatcov can take a list of ALI/SID files using the '@' prefix or +a single input file. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_tmp +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir("tmp_") +trace_file = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["trymon.adb"]) + ), + covlevel="stmt", + mains=["trymon"], + extra_coverage_args=[], +)[-1] + +coverage_base_args = [ + "coverage", + "--level=stmt", + "--annotate=xcov", + trace_file, +] +expected_reports = { + "trymon.adb.xcov": {"+": {24}}, + "monitor.adb.xcov": {"+": {4}}, + "monitor.ads.xcov": {}, +} +# Unlike in binary trace mode, where it is no-code, instrumentation allows to +# detect that the Integer library-level variable declaration at line 2 is +# covered. +if thistest.options.trace_mode == "src": + expected_reports["monitor.ads.xcov"] = {"+": {2}} + + +def tryseq(label, scoargs): + thistest.log("== {} ==".format(label)) + xcov(coverage_base_args + scoargs) + check_xcov_reports(".", expected_reports, discard_empty=False) + + +if thistest.options.trace_mode == "src": + option = "sid" + ext = "sid" +else: + option = "scos" + ext = "ali" + +sco_files = ["obj/trymon.{}".format(ext), "obj/monitor.{}".format(ext)] +tryseq( + "one_response_file", + scoargs=["--{}".format(option), "@{}".format(list_to_tmp(sco_files))], +) +tryseq( + "multiple_files", + scoargs=["--{}={}".format(option, ali) for ali in sco_files], +) +thistest.result() diff --git a/testsuite/tests/IA06-008-override-exec/src/noop.adb b/testsuite/tests/IA06-008-override-exec/src/noop.adb new file mode 100644 index 000000000..545d3b1f6 --- /dev/null +++ b/testsuite/tests/IA06-008-override-exec/src/noop.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +procedure NOOP is + X : Integer := 1; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/IA06-008-override-exec/test.opt b/testsuite/tests/IA06-008-override-exec/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/IA06-008-override-exec/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/IA06-008-override-exec/test.py b/testsuite/tests/IA06-008-override-exec/test.py new file mode 100644 index 000000000..6ff8d8064 --- /dev/null +++ b/testsuite/tests/IA06-008-override-exec/test.py @@ -0,0 +1,61 @@ +"""Check that --exec works properly.""" + +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + unixpath_to, + xcov, + xrun, +) + + +wd = Wdir("tmp_") + +gprbuild(gprfor(srcdirs=["../src"], mains=["noop.adb"])) +xrun(unixpath_to("noop")) + +# On Windows, we cannot override an existing file during a renaming. +if os.path.exists("nop"): + os.unlink("nop") +os.rename(exepath_to("noop"), "nop") + +p = xcov( + ["coverage", "--level=branch", "--annotate=asm", tracename_for("noop")], + out="not_found.out", + register_failure=False, +) +thistest.fail_if( + p.status == 0 + or not match( + "Cannot open ELF file %s for trace file" % unixpath_to("noop"), + "not_found.out", + ), + "no error if exec not found", +) + +# We are not interested in the exact coverage status of the main symbol, so +# just look if we have some coverage indication for it as a sanity check that +# the coverage analysis request did something. Beware that "main" might be +# named after the main subprogram on VxWorks systems. +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + "--exec=nop", + tracename_for("noop"), + ], + out="noop.stdout", +) +thistest.fail_if( + not match("main|noop [+!]:", "noop.stdout"), + "--exec overrides trace file info", +) + +thistest.result() diff --git a/testsuite/tests/IA06-009-offset-from-sym/src/p.adb b/testsuite/tests/IA06-009-offset-from-sym/src/p.adb new file mode 100644 index 000000000..e5bd5de07 --- /dev/null +++ b/testsuite/tests/IA06-009-offset-from-sym/src/p.adb @@ -0,0 +1,7 @@ + +procedure P is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/IA06-009-offset-from-sym/test.opt b/testsuite/tests/IA06-009-offset-from-sym/test.opt new file mode 100644 index 000000000..141c4c88d --- /dev/null +++ b/testsuite/tests/IA06-009-offset-from-sym/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests object coverage diff --git a/testsuite/tests/IA06-009-offset-from-sym/test.py b/testsuite/tests/IA06-009-offset-from-sym/test.py new file mode 100644 index 000000000..ce79b37ad --- /dev/null +++ b/testsuite/tests/IA06-009-offset-from-sym/test.py @@ -0,0 +1,37 @@ +""" +Check that start of block addresses are offsets from the corresponding symbol, +not absolute addresses. +""" + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + +wd = Wdir("tmp_") +symbol = target_info().to_platform_specific_symbol("_ada_p") + +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +xrun(exepath_to("p")) +xcov( + [ + "coverage", + "--level=insn", + "--annotate=xcov+", + "--routines={}".format(symbol), + tracename_for("p"), + ] +) + +thistest.fail_if( + not match(r"<{}\+(00000000){{1,2}}>:".format(symbol), "p.adb.xcov"), + "offset from symbols", +) +thistest.result() diff --git a/testsuite/tests/IA09-021-unit-nosco/src/checks.adb b/testsuite/tests/IA09-021-unit-nosco/src/checks.adb new file mode 100644 index 000000000..3d4bea996 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/src/checks.adb @@ -0,0 +1,8 @@ +package body Checks is + procedure Assert (Cond : Boolean) is + begin + if not Cond then + raise Program_Error; + end if; + end; +end; diff --git a/testsuite/tests/IA09-021-unit-nosco/src/checks.ads b/testsuite/tests/IA09-021-unit-nosco/src/checks.ads new file mode 100644 index 000000000..ee6427f07 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/src/checks.ads @@ -0,0 +1,5 @@ +-- A spec with a mere suprogram declaration. No SCO at all for this file. + +package Checks is + procedure Assert (Cond : Boolean); +end; diff --git a/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb b/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb new file mode 100644 index 000000000..e35764b90 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb @@ -0,0 +1,8 @@ +with Checks; + +procedure Test_Assert is + X : Integer := 12; + pragma Volatile (X); +begin + Checks.Assert (X = 12); +end; diff --git a/testsuite/tests/IA09-021-unit-nosco/test.opt b/testsuite/tests/IA09-021-unit-nosco/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/IA09-021-unit-nosco/test.py b/testsuite/tests/IA09-021-unit-nosco/test.py new file mode 100644 index 000000000..c3688bc83 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/test.py @@ -0,0 +1,30 @@ +""" +Check that gnatcov doesn't crash while processing the ALI file for +a unit producing not a single SCO. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +gprbuild(gprfor(["test_assert.adb"], srcdirs="../src")) +xrun(exepath_to("test_assert")) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos=obj/checks.ali", + tracename_for("test_assert"), + ] +) +thistest.result() diff --git a/testsuite/tests/IA13-015-loop-body/src/for_loop.adb b/testsuite/tests/IA13-015-loop-body/src/for_loop.adb new file mode 100644 index 000000000..60618ac6d --- /dev/null +++ b/testsuite/tests/IA13-015-loop-body/src/for_loop.adb @@ -0,0 +1,14 @@ +procedure For_Loop is + X : Integer := 0; + procedure Inc_X (N : Integer) is + begin + for I in 1 .. N loop + X := X + 1; + end loop; + end; +begin + Inc_X (0); + if X /= 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/IA13-015-loop-body/test.opt b/testsuite/tests/IA13-015-loop-body/test.opt new file mode 100644 index 000000000..141c4c88d --- /dev/null +++ b/testsuite/tests/IA13-015-loop-body/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests object coverage diff --git a/testsuite/tests/IA13-015-loop-body/test.py b/testsuite/tests/IA13-015-loop-body/test.py new file mode 100644 index 000000000..5503d3a34 --- /dev/null +++ b/testsuite/tests/IA13-015-loop-body/test.py @@ -0,0 +1,23 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +gprbuild(gprfor(["for_loop.adb"], srcdirs="../src"), gargs="-O0") +xrun(exepath_to("for_loop")) +xcov("coverage --level=branch --annotate=xcov " + tracename_for("for_loop")) + +# We expect the for loop body to be uncovered +thistest.fail_if( + not match(r"[0-9]+ -:.*X := X \+ 1", "for_loop.adb.xcov"), + "expect loop body to be uncovered", +) +thistest.result() diff --git a/testsuite/tests/IA16-028-disp-routines/baseline3.txt b/testsuite/tests/IA16-028-disp-routines/baseline3.txt new file mode 100644 index 000000000..bf0ee31d5 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/baseline3.txt @@ -0,0 +1,3 @@ +_ada_p +pack__q +pack__r diff --git a/testsuite/tests/IA16-028-disp-routines/src/monitor.adb b/testsuite/tests/IA16-028-disp-routines/src/monitor.adb new file mode 100644 index 000000000..27284037c --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/monitor.adb @@ -0,0 +1,7 @@ +package body Monitor is + + procedure Touch is + begin + Nops := Nops + 1; + end; +end; diff --git a/testsuite/tests/IA16-028-disp-routines/src/monitor.ads b/testsuite/tests/IA16-028-disp-routines/src/monitor.ads new file mode 100644 index 000000000..160354c0a --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/monitor.ads @@ -0,0 +1,4 @@ +package Monitor is + procedure Touch; + Nops : Integer := 0; +end; diff --git a/testsuite/tests/IA16-028-disp-routines/src/p.adb b/testsuite/tests/IA16-028-disp-routines/src/p.adb new file mode 100644 index 000000000..764987377 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/p.adb @@ -0,0 +1,12 @@ +with Monitor; +with Pack; use Pack; + +procedure P is +begin + I := I + 1; + Q; + R; + if I > 2 then + Monitor.Touch; + end if; +end P; diff --git a/testsuite/tests/IA16-028-disp-routines/src/pack.adb b/testsuite/tests/IA16-028-disp-routines/src/pack.adb new file mode 100644 index 000000000..f05c2c2bd --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/pack.adb @@ -0,0 +1,13 @@ +package body Pack is + + procedure Q is + begin + I := I + 2; + end Q; + + procedure R is + begin + I := I + 3; + end R; + +end Pack; diff --git a/testsuite/tests/IA16-028-disp-routines/src/pack.ads b/testsuite/tests/IA16-028-disp-routines/src/pack.ads new file mode 100644 index 000000000..3d5f47dc2 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/pack.ads @@ -0,0 +1,9 @@ +package Pack is + + I : Integer := 3; + + procedure Q; + + procedure R; + +end Pack; diff --git a/testsuite/tests/IA16-028-disp-routines/test.opt b/testsuite/tests/IA16-028-disp-routines/test.opt new file mode 100644 index 000000000..b553eb717 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disp-routines, specific to binary trace mode diff --git a/testsuite/tests/IA16-028-disp-routines/test.py b/testsuite/tests/IA16-028-disp-routines/test.py new file mode 100644 index 000000000..3bb2963d8 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/test.py @@ -0,0 +1,79 @@ +import os.path +import re +from shutil import copy + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, set_from +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + platform_specific_symbols, + xcov, +) + + +Wdir("tmp_") + +# Check that --exclude/--include options are properly supported. + +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +exe = exepath_to("p") + +# Simple usage of disp-routines: + +xcov(["disp-routines", exe, "--exclude", "obj/b__p.o"], out="routines1.txt") + +r1 = contents_of("routines1.txt") + +for pattern in ("pack__q", "pack__r", "_ada_p"): + thistest.fail_if( + not re.search(pattern, r1), + "'%s' not found in disp-routines output" % pattern, + ) + + +# Check that "p.o - S" return the empty set if p.o is in S: + +xcov( + ["disp-routines", "--include", "obj/p.o", "--exclude", exe], + out="routines2.txt", +) + +thistest.fail_if( + os.path.getsize("routines2.txt") > 0, + "disp-routines -i p.o -o p.exe should return an empty set. Got:\n" + + contents_of("routines2.txt"), +) + +# Check various properties: that "S + p.o - p.o" is idempotent iff p.o is in S, +# that "p.o + b~p.o - p.o - b~p.o + p.o" do exclude b~p.o... comparing the +# output of disp-routines against a baseline (do not rely on the order of +# output symbols, it is not defined). + +copy("obj/p.o", "obj/p1.o") +copy("obj/p.o", "obj/p2.o") +copy("obj/b__p.o", "obj/b__p1.o") + +xcov( + [ + "disp-routines", + "obj/p.o", + "obj/b__p.o", + "--include", + "obj/pack.o", + "--exclude", + "obj/p1.o", + "obj/b__p1.o", + "--include", + "obj/p2.o", + ], + out="routines3.txt", +) + +baseline3 = set(platform_specific_symbols(set_from("../baseline3.txt"))) +routines3 = set_from("routines3.txt") + +thistest.fail_if(baseline3 != routines3, "Advanced usage of disp-routines") + +thistest.result() diff --git a/testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb b/testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/IA19-009-no-useless-srcs/test.py b/testsuite/tests/IA19-009-no-useless-srcs/test.py new file mode 100644 index 000000000..f3f55ded7 --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/test.py @@ -0,0 +1,33 @@ +""" +Check that "gnatcov coverage" does not produce reports for units that are not +of interest. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(["test_engines.adb"], srcdirs="../src"), + units=["engines"], + ), + covlevel="stmt", + mains=["test_engines"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/engines"], +) + +thistest.fail_if( + not os.path.exists("engines.adb.xcov") + or os.path.exists("test_engines.adb.xcov"), + "no annotated file when no sco", +) +thistest.result() diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/p.adb b/testsuite/tests/IA21-003-simple-decision-sco/src/p.adb new file mode 100644 index 000000000..a7c50d3a4 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/p.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Pack; use Pack; + +procedure Hello is +begin + Not_Fully_Covered_Stmt_Wise; +end; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb new file mode 100644 index 000000000..5675e9c71 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb @@ -0,0 +1,13 @@ + +package body Pack is + + procedure Not_Fully_Covered_Stmt_Wise is + begin + if Where then + N_True := N_True + 1; + else + N_False := N_False + 1; + end if; + end Not_Fully_Covered_Stmt_Wise; + +end Pack; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads new file mode 100644 index 000000000..eb1114116 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads @@ -0,0 +1,9 @@ +package Pack is + + N_True, N_False : Natural := 0; + + Where : Boolean := False; + + procedure Not_Fully_Covered_Stmt_Wise; + +end Pack; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.opt b/testsuite/tests/IA21-003-simple-decision-sco/test.opt new file mode 100644 index 000000000..4ac701d56 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests compiler-provided SCOs diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.py b/testsuite/tests/IA21-003-simple-decision-sco/test.py new file mode 100644 index 000000000..2dea8fd62 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.py @@ -0,0 +1,39 @@ +""" +Check that gnatcov correctly loads and interprets a simple decision SCO. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +xrun(exepath_to("p")) + +xcov(["map-routines", "--scos=obj/pack.ali"]) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=report", + "--scos=obj/pack.ali", + "-o", + "out", + tracename_for("p"), + ] +) +thistest.fail_if( + not match("pack.adb:7:.* statement not executed", "out"), + "missing expected s- diagnostic with simple decision sco", +) + +thistest.result() diff --git a/testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb b/testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb new file mode 100644 index 000000000..979a55925 --- /dev/null +++ b/testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb @@ -0,0 +1,9 @@ +pragma Warnings (Off); +procedure Nested_Same_Sloc is + A, B : Boolean; +begin + if (A and then B) = True then + null; + end if; + raise Program_Error; +end Nested_Same_Sloc; diff --git a/testsuite/tests/IA21-009-nested-scos/test.opt b/testsuite/tests/IA21-009-nested-scos/test.opt new file mode 100644 index 000000000..d05c6047b --- /dev/null +++ b/testsuite/tests/IA21-009-nested-scos/test.opt @@ -0,0 +1 @@ +src-traces DEAD Test specific to binary traces diff --git a/testsuite/tests/IA21-009-nested-scos/test.py b/testsuite/tests/IA21-009-nested-scos/test.py new file mode 100644 index 000000000..b64d2441f --- /dev/null +++ b/testsuite/tests/IA21-009-nested-scos/test.py @@ -0,0 +1,9 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir("tmp_") +gprbuild(gprfor(["nested_same_sloc.adb"], srcdirs="../src")) +xcov(["map-routines", "--scos=obj/nested_same_sloc.ali", "nested_same_sloc"]) +thistest.result() diff --git a/testsuite/tests/IA22-004-same-basename/.gitignore b/testsuite/tests/IA22-004-same-basename/.gitignore new file mode 100644 index 000000000..1861073fc --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/.gitignore @@ -0,0 +1 @@ +main.elf.trace diff --git a/testsuite/tests/IA22-004-same-basename/d1/func.c b/testsuite/tests/IA22-004-same-basename/d1/func.c new file mode 100644 index 000000000..fe91e5b7f --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/d1/func.c @@ -0,0 +1,5 @@ +int +func1 (int a) +{ + return a * 2; +} diff --git a/testsuite/tests/IA22-004-same-basename/d2/func.c b/testsuite/tests/IA22-004-same-basename/d2/func.c new file mode 100644 index 000000000..3e7b7055e --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/d2/func.c @@ -0,0 +1,5 @@ +int +func2 (int a) +{ + return a * 3; +} diff --git a/testsuite/tests/IA22-004-same-basename/main.c b/testsuite/tests/IA22-004-same-basename/main.c new file mode 100644 index 000000000..6bea78070 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/main.c @@ -0,0 +1,29 @@ +extern int func1 (int); +extern int func2 (int); +extern void putchar (int); + +void +put_digit (int a) +{ + putchar ('0' + a); +} + +void +put_str (char *s) +{ + while (*s) + putchar (*s++); +} + +int +c_main (void) +{ + put_str ("func2: "); + put_digit (func2 (1)); + putchar ('\n'); + put_str ("func1: "); + put_digit (func1 (2)); + putchar ('\n'); + + return 0; +} diff --git a/testsuite/tests/IA22-004-same-basename/main.elf b/testsuite/tests/IA22-004-same-basename/main.elf new file mode 100755 index 000000000..ccdc72926 Binary files /dev/null and b/testsuite/tests/IA22-004-same-basename/main.elf differ diff --git a/testsuite/tests/IA22-004-same-basename/put.adb b/testsuite/tests/IA22-004-same-basename/put.adb new file mode 100644 index 000000000..2668ad7b5 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/put.adb @@ -0,0 +1,8 @@ +with ada.text_io; + +package body put is + procedure putchar (c : integer) is + begin + ada.text_io.put (Character'val (C)); + end putchar; +end put; diff --git a/testsuite/tests/IA22-004-same-basename/put.ads b/testsuite/tests/IA22-004-same-basename/put.ads new file mode 100644 index 000000000..f40a17fd6 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/put.ads @@ -0,0 +1,4 @@ +package put is + procedure putchar (c : integer); + pragma export (c, putchar); +end put; diff --git a/testsuite/tests/IA22-004-same-basename/repro.adb b/testsuite/tests/IA22-004-same-basename/repro.adb new file mode 100644 index 000000000..af1c4ac36 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/repro.adb @@ -0,0 +1,8 @@ +with put; + +procedure repro is + procedure c_main; + pragma import (c, c_main); +begin + c_main; +end repro; diff --git a/testsuite/tests/IA22-004-same-basename/test.opt b/testsuite/tests/IA22-004-same-basename/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/IA22-004-same-basename/test.py b/testsuite/tests/IA22-004-same-basename/test.py new file mode 100644 index 000000000..3d4b2f481 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/test.py @@ -0,0 +1,76 @@ +""" +Perform a bunch of xcov related operations to validate the basic toolset +functionalities. +""" + +import os + +from SUITE.context import thistest +from SUITE.cutils import match +from SUITE.tutils import maybe_valgrind, xcov, xrun + + +# Built with: +# powerpc-elf-gcc -g -c d1/func.c -o d1/func.o +# powerpc-elf-gcc -g -c d2/func.c -o d2/func.o +# powerpc-elf-gcc -g -c main.c +# gprbuild --target=powerpc-elf --RTS=zfp-mpc8641 -g repro -largs main.o \ +# */func.o +# mv repro main.elf + +# Context information, basic command line interface checks +print("maybe_valgrind prepends ...", maybe_valgrind([])) + +xrun("main.elf") + +formats = [ + ("xml", "{slug}.xml", r''), + ("html", "{slug}.hunk.js", r'"coverage":"\+",.*"assembly"'), + ("xcov+", "{slug}.xcov", r" *[0-9]+ \+:"), +] + + +# The pre-built binary embeds full paths to the sources at their build +# time location. We need to rebase to find the files in the current +# dir. The paths gnatcov uses are internally canonicalized, which yields +# Windows or Unix paths depending on the host ... + + +def hostify(path): + return ( + "C:" + path.replace("/", "\\") + if thistest.env.build.os.name == "windows" + else path + ) + + +rebase_args = [ + "--source-rebase={}={}".format( + hostify(f"{path}/tests/IA22-004-same-basename"), os.getcwd() + ) + for path in ( + "/home/pmderodat/_git/gnatcoverage/testsuite", + "/home/pmderodat/_git/gnatcoverage-extra", + ) +] + +for fmt, filename, pattern in formats: + xcov( + [ + "coverage", + "--level=insn", + "--annotate=" + fmt, + "main.elf.trace", + "--output-dir=tmp", + ] + + rebase_args, + # The files generated by the binder are not available at coverage time + tolerate_messages="warning: can't open", + ) + + for slug in ("d1-func.c", "d2-func.c"): + output = "tmp/" + filename.format(base="func.c", slug=slug) + thistest.fail_if( + not match(pattern, output), "no line covered in {}".format(output) + ) +thistest.result() diff --git a/testsuite/tests/IA29-020-basic-checks/src/engines.adb b/testsuite/tests/IA29-020-basic-checks/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/IA29-020-basic-checks/src/engines.ads b/testsuite/tests/IA29-020-basic-checks/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/IA29-020-basic-checks/src/test_engines.adb b/testsuite/tests/IA29-020-basic-checks/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/IA29-020-basic-checks/test.opt b/testsuite/tests/IA29-020-basic-checks/test.opt new file mode 100644 index 000000000..d2cc065d3 --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test uses object coverage diff --git a/testsuite/tests/IA29-020-basic-checks/test.py b/testsuite/tests/IA29-020-basic-checks/test.py new file mode 100644 index 000000000..45d850f9a --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/test.py @@ -0,0 +1,87 @@ +""" +Check that a we can run the engines example with all possible coverage +level/annotations without crashing. And check the xcov/xcov+ annotated reports. +""" + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import FatalError, Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +gprbuild(project=gprfor(["test_engines.adb"], srcdirs="../src")) +xrun(exepath_to("test_engines")) +line = ": return E.P < Stable_P and then E.T < Stable_T;" + + +def src_cov(cov_level, annotate_level, line_coverage): + try: + xcov( + [ + "coverage", + "--level=" + cov_level, + "--annotate=" + annotate_level, + "--scos=obj/engines.ali", + tracename_for("test_engines"), + ] + ) + if annotate_level.find("xcov") != -1: + thistest.fail_if( + not match( + "[0-9]+ " + line_coverage + line, "engines.adb.xcov" + ), + "check " + cov_level + " coverage results on engines example", + ) + except FatalError: + pass + + +def obj_cov(cov_level, annotate_level, line_coverage): + symbol = target_info().to_platform_specific_symbol("engines__stable") + xcov( + [ + "coverage", + "--level=" + cov_level, + "--annotate=" + annotate_level, + "--routines={}".format(symbol), + tracename_for("test_engines"), + ] + ) + if annotate_level.find("xcov") != -1: + thistest.fail_if( + not match("[0-9]+ " + line_coverage + line, "engines.adb.xcov"), + "check " + cov_level + " coverage results on engines example", + ) + + +src_cov_levels = ["stmt", "stmt+decision", "stmt+mcdc"] +annotate_levels = ["xcov", "html"] + +obj_cov_levels = ["insn", "branch"] +obj_annotate_levels = annotate_levels + ["asm", "html+", "xcov+"] + +line_coverage = { + "insn": r"\+", + "branch": "!", + "stmt": r"\+", + "stmt+decision": r"\+", + "stmt+mcdc": "!", +} + +for cov_level in obj_cov_levels: + for annotate_level in obj_annotate_levels: + obj_cov(cov_level, annotate_level, line_coverage[cov_level]) + +for cov_level in src_cov_levels: + for annotate_level in annotate_levels: + src_cov(cov_level, annotate_level, line_coverage[cov_level]) + +thistest.result() diff --git a/testsuite/tests/IA29-023-source-search/src/engines.adb b/testsuite/tests/IA29-023-source-search/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/IA29-023-source-search/src/engines.ads b/testsuite/tests/IA29-023-source-search/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/IA29-023-source-search/src/test_engines.adb b/testsuite/tests/IA29-023-source-search/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/IA29-023-source-search/test.py b/testsuite/tests/IA29-023-source-search/test.py new file mode 100644 index 000000000..9a49ab51c --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/test.py @@ -0,0 +1,49 @@ +""" +Basic test on the --source-search option +""" + +import os + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, empty +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(["test_engines.adb"], srcdirs="../src") + ), + covlevel="stmt", + mains=["test_engines"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/engines"], +) + +xcov(xcov_args + ["--source-search=./src"], out="warnings1.txt") +thistest.fail_if(not empty("warnings1.txt"), "no source warning") + +os.rename("../src", "../newsrc") + +xcov(xcov_args + ["--source-search=../newsrc"], out="warnings2.txt") +thistest.fail_if(not empty("warnings2.txt"), "Source search unsuccessful") + +# Same test but with a response file +source_search_filename = os.path.abspath("src-search.txt") +with open(source_search_filename, "w") as f: + f.write(os.path.join("..", "newsrc")) + +xcov( + xcov_args + [f"--source-search=@{source_search_filename}"], + out="warnings3.txt", +) +thistest.fail_if( + not empty("warnings3.txt"), "Source search unsuccessful (response file)" +) + +os.rename("../newsrc", "../src") + +thistest.result() diff --git a/testsuite/tests/J618-019-disa-x86/insn.o b/testsuite/tests/J618-019-disa-x86/insn.o new file mode 100644 index 000000000..edff7874b Binary files /dev/null and b/testsuite/tests/J618-019-disa-x86/insn.o differ diff --git a/testsuite/tests/J618-019-disa-x86/insn.s b/testsuite/tests/J618-019-disa-x86/insn.s new file mode 100644 index 000000000..fcb6f17cf --- /dev/null +++ b/testsuite/tests/J618-019-disa-x86/insn.s @@ -0,0 +1,6 @@ + .text + .globl func + .type func,@function +func: + shld %cl,%eax,%edx + .size func, . - func diff --git a/testsuite/tests/J618-019-disa-x86/test.opt b/testsuite/tests/J618-019-disa-x86/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/J618-019-disa-x86/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/J618-019-disa-x86/test.py b/testsuite/tests/J618-019-disa-x86/test.py new file mode 100644 index 000000000..6670dd589 --- /dev/null +++ b/testsuite/tests/J618-019-disa-x86/test.py @@ -0,0 +1,8 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +Wdir("tmp_") +xcov(["disassemble", "../insn.o"], "insn.dis") +thistest.result() diff --git a/testsuite/tests/J723-017-empty-debug-info/ada_containers-aunit_lists.elf b/testsuite/tests/J723-017-empty-debug-info/ada_containers-aunit_lists.elf new file mode 100644 index 000000000..15473fc10 Binary files /dev/null and b/testsuite/tests/J723-017-empty-debug-info/ada_containers-aunit_lists.elf differ diff --git a/testsuite/tests/J723-017-empty-debug-info/test.opt b/testsuite/tests/J723-017-empty-debug-info/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/J723-017-empty-debug-info/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/J723-017-empty-debug-info/test.py b/testsuite/tests/J723-017-empty-debug-info/test.py new file mode 100644 index 000000000..216b84a79 --- /dev/null +++ b/testsuite/tests/J723-017-empty-debug-info/test.py @@ -0,0 +1,8 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +Wdir("tmp_") +xcov(["dump-lines", "../ada_containers-aunit_lists.elf"], "dwarf.out") +thistest.result() diff --git a/testsuite/tests/JC09-015-set-file/hello.o b/testsuite/tests/JC09-015-set-file/hello.o new file mode 100644 index 000000000..785839fb9 Binary files /dev/null and b/testsuite/tests/JC09-015-set-file/hello.o differ diff --git a/testsuite/tests/JC09-015-set-file/hello.s b/testsuite/tests/JC09-015-set-file/hello.s new file mode 100644 index 000000000..60c75c4a3 --- /dev/null +++ b/testsuite/tests/JC09-015-set-file/hello.s @@ -0,0 +1,319 @@ + .file "hello.adb" + .gnu_attribute 4, 1 + .gnu_attribute 8, 1 + .gnu_attribute 12, 1 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .section .debug_line,"",@progbits +.Ldebug_line0: + .section ".text" +.Ltext0: + .align 2 + .globl _ada_hello + .type _ada_hello, @function +_ada_hello: +.LFB1: + .file 1 "hello.adb" + .loc 1 2 0 + stwu 1,-16(1) + stw 31,12(1) + mr 31,1 + .loc 1 4 0 + nop + .loc 1 5 0 + nop + .loc 1 6 0 + nop + .file 2 "file2.x" + .loc 2 6 0 + nop + .file 3 "file3.x" + .loc 3 6 0 + nop + .file 4 "file4.x" + .loc 4 6 0 + nop + .file 5 "file5.x" + .loc 5 6 0 + nop + .file 6 "file6.x" + .loc 6 6 0 + nop + .file 7 "file7.x" + .loc 7 6 0 + nop + .file 8 "file8.x" + .loc 8 6 0 + nop + .file 9 "file9.x" + .loc 9 6 0 + nop + .file 10 "file10.x" + .loc 10 6 0 + nop + .file 11 "file11.x" + .loc 11 6 0 + nop + .file 12 "file12.x" + .loc 12 6 0 + nop + .file 13 "file13.x" + .loc 13 6 0 + nop + .file 14 "file14.x" + .loc 14 6 0 + nop + .file 15 "file15.x" + .loc 15 6 0 + nop + .file 16 "file16.x" + .loc 16 6 0 + nop + .file 17 "file17.x" + .loc 17 6 0 + nop + .file 18 "file18.x" + .loc 18 6 0 + nop + .file 19 "file19.x" + .loc 19 6 0 + nop + .file 20 "file20.x" + .loc 20 6 0 + nop + .file 21 "file21.x" + .loc 21 6 0 + nop + .file 22 "file22.x" + .loc 22 6 0 + nop + .file 23 "file23.x" + .loc 23 6 0 + nop + .file 24 "file24.x" + .loc 24 6 0 + nop + .file 25 "file25.x" + .loc 25 6 0 + nop + .file 26 "file26.x" + .loc 26 6 0 + nop + .file 27 "file27.x" + .loc 27 6 0 + nop + .file 28 "file28.x" + .loc 28 6 0 + nop + .file 29 "file29.x" + .loc 29 6 0 + nop + .file 30 "file30.x" + .loc 30 6 0 + nop + .file 31 "file31.x" + .loc 31 6 0 + nop + .file 32 "file32.x" + .loc 32 6 0 + nop + .file 33 "file33.x" + .loc 33 6 0 + nop + .file 34 "file34.x" + .loc 34 6 0 + nop + .file 35 "file35.x" + .loc 35 6 0 + nop + .file 36 "file36.x" + .loc 36 6 0 + nop + .file 37 "file37.x" + .loc 37 6 0 + nop + .file 38 "file38.x" + .loc 38 6 0 + nop + .file 39 "file39.x" + .loc 39 6 0 + nop + .file 40 "file40.x" + .loc 40 6 0 + nop + .file 41 "file41.x" + .loc 41 6 0 + nop + .file 42 "file42.x" + .loc 42 6 0 + nop + .file 43 "file43.x" + .loc 43 6 0 + nop + .file 44 "file44.x" + .loc 44 6 0 + nop + .file 45 "file45.x" + .loc 45 6 0 + nop + .file 46 "file46.x" + .loc 46 6 0 + nop + .file 47 "file47.x" + .loc 47 6 0 + nop + .file 48 "file48.x" + .loc 48 6 0 + nop + .file 49 "file49.x" + .loc 49 6 0 + nop + .file 50 "file50.x" + .loc 50 6 0 + nop + .file 51 "file51.x" + .loc 51 6 0 + nop + .file 52 "file52.x" + .loc 52 6 0 + nop + .file 53 "file53.x" + .loc 53 6 0 + nop + .file 54 "file54.x" + .loc 54 6 0 + nop + .file 55 "file55.x" + .loc 55 6 0 + nop + .file 56 "file56.x" + .loc 56 6 0 + nop + .file 57 "file57.x" + .loc 57 6 0 + nop + .file 58 "file58.x" + .loc 58 6 0 + nop + .file 59 "file59.x" + .loc 59 6 0 + nop + .file 60 "file60.x" + .loc 60 6 0 + nop + .file 61 "file61.x" + .loc 61 6 0 + nop + .file 62 "file62.x" + .loc 62 6 0 + nop + .file 63 "file63.x" + .loc 63 6 0 + nop + .file 64 "file64.x" + .loc 64 6 0 + nop + .file 65 "file65.x" + .loc 65 6 0 + nop + .file 66 "file66.x" + .loc 66 6 0 + nop + .file 67 "file67.x" + .loc 67 6 0 + nop + .file 68 "file68.x" + .loc 68 6 0 + nop + .file 69 "file69.x" + .loc 69 6 0 + nop + addi 11,31,16 + lwz 31,-4(11) + mr 1,11 + blr +.LFE1: + .size _ada_hello, .-_ada_hello + .align 2 +.LEFDE0: + .section ".text" +.Letext0: + .section .debug_info + .4byte 0x3a + .2byte 0x2 + .4byte .Ldebug_abbrev0 + .byte 0x4 + .uleb128 0x1 + .4byte .LASF0 + .byte 0xd + .4byte .LASF1 + .4byte .LASF2 + .4byte .Ltext0 + .4byte .Letext0 + .4byte .Ldebug_line0 + .uleb128 0x2 + .byte 0x1 + .4byte .LASF3 + .byte 0x1 + .byte 0x2 + .4byte .LASF4 + .4byte .LFB1 + .4byte .LFE1 + .4byte .LLST0 + .byte 0x0 + .section .debug_abbrev + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x10 + .uleb128 0x6 + .byte 0x0 + .byte 0x0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0x0 + .uleb128 0x3f + .uleb128 0xc + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x2007 + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x40 + .uleb128 0x6 + .byte 0x0 + .byte 0x0 + .byte 0x0 + .section .debug_str,"MS",@progbits,1 +.LASF2: + .string "/Users/gingold/TN/JC09-015" +.LASF4: + .string "_ada_hello" +.LASF1: + .string "hello.adb" +.LASF0: + .string "GNU Ada 4.5.2 20101004 for GNAT Pro 6.4.0w (20101003)" +.LASF3: + .string "hello" + .ident "GCC: (GNU) 4.5.2 20101004 for GNAT Pro 6.4.0w (20101003)" diff --git a/testsuite/tests/JC09-015-set-file/test.opt b/testsuite/tests/JC09-015-set-file/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/JC09-015-set-file/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/JC09-015-set-file/test.py b/testsuite/tests/JC09-015-set-file/test.py new file mode 100644 index 000000000..fb83b2ba5 --- /dev/null +++ b/testsuite/tests/JC09-015-set-file/test.py @@ -0,0 +1,8 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +Wdir("tmp_") +xcov(["dump-lines", "../hello.o"], "dwarf.out") +thistest.result() diff --git a/testsuite/tests/K214-014-gc-sections/src/foo.adb b/testsuite/tests/K214-014-gc-sections/src/foo.adb new file mode 100644 index 000000000..cb2edf643 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/src/foo.adb @@ -0,0 +1,7 @@ +with Pck; use Pck; + +procedure Foo is +begin + Break_Me (1); + Break_Me (True); +end Foo; diff --git a/testsuite/tests/K214-014-gc-sections/src/pck.adb b/testsuite/tests/K214-014-gc-sections/src/pck.adb new file mode 100644 index 000000000..7eaf4b4b4 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/src/pck.adb @@ -0,0 +1,16 @@ +package body Pck is + procedure Break_Me (I : Integer) is + begin + null; -- COVERED + end Break_Me; + + procedure Discard is + begin + null; -- ELIMINATED + end Discard; + + procedure Break_Me (B : Boolean) is + begin + null; + end Break_Me; +end Pck; diff --git a/testsuite/tests/K214-014-gc-sections/src/pck.ads b/testsuite/tests/K214-014-gc-sections/src/pck.ads new file mode 100644 index 000000000..4def5b16d --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/src/pck.ads @@ -0,0 +1,5 @@ +package Pck is + procedure Break_Me (I : Integer); + procedure Discard; + procedure Break_Me (B : Boolean); +end Pck; diff --git a/testsuite/tests/K214-014-gc-sections/test.opt b/testsuite/tests/K214-014-gc-sections/test.opt new file mode 100644 index 000000000..fcd9f35d9 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/test.opt @@ -0,0 +1,3 @@ +ppc-vx6 XFAIL minor issue of debug info not stripped through gc-section, L815-002 +e500v2-vx6 XFAIL minor issue of debug info not stripped through gc-section, L815-002 +!bin-traces DEAD Test a behavior that is specific to binary traces diff --git a/testsuite/tests/K214-014-gc-sections/test.py b/testsuite/tests/K214-014-gc-sections/test.py new file mode 100644 index 000000000..c14f43399 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/test.py @@ -0,0 +1,42 @@ +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +extralargs = ",--entry=foo" if target_info().partiallinks else "" + +gprbuild( + gprfor(["foo.adb"], srcdirs="../src"), + extracargs="-ffunction-sections", + largs="-Wl,--gc-sections" + extralargs, +) +xrun(exepath_to("foo")) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos=obj/pck.ali", + tracename_for("foo"), + ], + out="ignore.out", +) + +thistest.fail_if( + not match(r"\.: null; -- ELIMINATED", "pck.adb.xcov"), + "eliminated code not reported", +) +thistest.fail_if( + not match(r"\+: null; -- COVERED", "pck.adb.xcov"), + "code not eliminated not reported", +) +thistest.result() diff --git a/testsuite/tests/K317-011_raven-textio/src/test_textio.adb b/testsuite/tests/K317-011_raven-textio/src/test_textio.adb new file mode 100644 index 000000000..c6398d035 --- /dev/null +++ b/testsuite/tests/K317-011_raven-textio/src/test_textio.adb @@ -0,0 +1,8 @@ +with Text_IO; +procedure test_textio is +begin + Text_IO.Put_Line ("cover me"); -- # run +end; + +--# test_textio.adb +-- /self/ l+ ## 0 diff --git a/testsuite/tests/K317-011_raven-textio/test.opt b/testsuite/tests/K317-011_raven-textio/test.opt new file mode 100644 index 000000000..65d7415e5 --- /dev/null +++ b/testsuite/tests/K317-011_raven-textio/test.opt @@ -0,0 +1,2 @@ +powerpc,RTS_RAVENSCAR +ALL DEAD diff --git a/testsuite/tests/K317-011_raven-textio/test.py b/testsuite/tests/K317-011_raven-textio/test.py new file mode 100644 index 000000000..4cf790490 --- /dev/null +++ b/testsuite/tests/K317-011_raven-textio/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase(category=None).run() +thistest.result() diff --git a/testsuite/tests/K804-031_raise-taken/src/args.adb b/testsuite/tests/K804-031_raise-taken/src/args.adb new file mode 100644 index 000000000..174c74e35 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/args.adb @@ -0,0 +1,6 @@ +package body Args is + function Id (X : Num) return Num is + begin + return X; + end; +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/args.ads b/testsuite/tests/K804-031_raise-taken/src/args.ads new file mode 100644 index 000000000..d2fdc703e --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/args.ads @@ -0,0 +1,8 @@ +package Args is + + -- Constrained value subject to easy out-of-range check failure + + type Num is range -10 .. 10; + + function Id (X : Num) return Num; +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb b/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb new file mode 100644 index 000000000..b88d8be4f --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb @@ -0,0 +1,13 @@ +with Args, Val; use Args, Val; + +procedure Test_Val_CE is + X : Boolean; +begin + X := Ge0 (Num'Last); +end; + +--# val.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb new file mode 100644 index 000000000..eb69a8f69 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb @@ -0,0 +1,11 @@ +with Args, Vif; use Args, Vif; + +procedure Test_Vif_R is +begin + Check_Ge0 (Num'Last); +end; + +--# vif.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb new file mode 100644 index 000000000..0e8ba168f --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb @@ -0,0 +1,12 @@ +with Args, Vif; use Args, Vif; + +procedure Test_Vif_RF is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (-1); +end; + +--# vif.adb +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb new file mode 100644 index 000000000..beabace2c --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb @@ -0,0 +1,12 @@ +with Args, Vif; use Args, Vif; + +procedure Test_Vif_RT is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (1); +end; + +--# vif.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb new file mode 100644 index 000000000..6a1ef2945 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb @@ -0,0 +1,11 @@ +with Args, Vifn; use Args, Vifn; + +procedure Test_Vifn_R is +begin + Check_Ge0 (Num'Last); +end; + +--# vifn.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb new file mode 100644 index 000000000..2aa979cfc --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb @@ -0,0 +1,12 @@ +with Args, Vifn; use Args, Vifn; + +procedure Test_Vifn_RF is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (-1); +end; + +--# vifn.adb +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb new file mode 100644 index 000000000..81b04d990 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb @@ -0,0 +1,12 @@ +with Args, Vifn; use Args, Vifn; + +procedure Test_Vifn_RT is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (1); +end; + +--# vifn.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /handler/ l+ ## 0 diff --git a/testsuite/tests/K804-031_raise-taken/src/val.adb b/testsuite/tests/K804-031_raise-taken/src/val.adb new file mode 100644 index 000000000..d3b37c0c8 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/val.adb @@ -0,0 +1,20 @@ +package body Val is + + -- Tests rely on the runtime check for the Id argument: we need a runtime + -- check even when compiled with -gnatp. + + pragma Unsuppress (All_Checks); + + function GE0 (X : Num) return Boolean is + begin + if Id (X + 1) > 0 then -- # eval + return True; -- # true + else + return False; -- # false + end if; + exception + when Constraint_Error => + return X >= 0; -- # handler + end; + +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/val.ads b/testsuite/tests/K804-031_raise-taken/src/val.ads new file mode 100644 index 000000000..2f63303a1 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/val.ads @@ -0,0 +1,5 @@ +with Args; use Args; + +package Val is + function GE0 (X : Num) return Boolean; +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vif.adb b/testsuite/tests/K804-031_raise-taken/src/vif.adb new file mode 100644 index 000000000..9e29b3a52 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vif.adb @@ -0,0 +1,18 @@ +package body Vif is + + -- Tests rely on the runtime check for the Id argument: we need a runtime + -- check even when compiled with -gnatp. + + pragma Unsuppress (All_Checks); + + procedure Check_GE0 (X : Num) is + begin + if Id (X + 1) > 0 then -- # eval + N_Ge0 := N_Ge0 + 1; -- # true + end if; + exception + when Constraint_Error => + N_Check_Raise := N_Check_Raise + 1; -- # handler + end; + +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vif.ads b/testsuite/tests/K804-031_raise-taken/src/vif.ads new file mode 100644 index 000000000..df057bbd9 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vif.ads @@ -0,0 +1,7 @@ +with Args; use Args; + +package Vif is + N_Ge0 : Integer := 0; + N_Check_Raise : Integer := 0; + procedure Check_GE0 (X : Num); +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vifn.adb b/testsuite/tests/K804-031_raise-taken/src/vifn.adb new file mode 100644 index 000000000..e5570de7e --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vifn.adb @@ -0,0 +1,18 @@ +package body Vifn is + + -- Tests rely on the runtime check for the Id argument: we need a runtime + -- check even when compiled with -gnatp. + + pragma Unsuppress (All_Checks); + + procedure Check_GE0 (X : Num) is + begin + if not (Id (X + 1) <= 0) then -- # eval + N_Ge0 := N_Ge0 + 1; -- # true + end if; + exception + when Constraint_Error => + N_Check_Raise := N_Check_Raise + 1; -- # handler + end; + +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vifn.ads b/testsuite/tests/K804-031_raise-taken/src/vifn.ads new file mode 100644 index 000000000..2e3173472 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vifn.ads @@ -0,0 +1,7 @@ +with Args; use Args; + +package Vifn is + N_Ge0 : Integer := 0; + N_Check_Raise : Integer := 0; + procedure Check_GE0 (X : Num); +end; diff --git a/testsuite/tests/K804-031_raise-taken/test.py b/testsuite/tests/K804-031_raise-taken/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb b/testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb new file mode 100644 index 000000000..bcbcba5cd --- /dev/null +++ b/testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb @@ -0,0 +1,6 @@ +procedure MyInc is + X : Integer := 1; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.opt b/testsuite/tests/KB30-011-eargs-gnatemu/test.opt new file mode 100644 index 000000000..83daf7326 --- /dev/null +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.opt @@ -0,0 +1,5 @@ +native DEAD checking argument passing to qemu & gnatemu, NA on this platform +visium-elf DEAD checking argument passing to qemu & gnatemu, NA on this platform +lmp-elf DEAD checking argument passing to qemu & gnatemu, NA on this platform +vxworks XFAIL mcdc without scos run on purpose, trace size limit overrun +src-traces DEAD test specific to gnatcov run diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.py b/testsuite/tests/KB30-011-eargs-gnatemu/test.py new file mode 100644 index 000000000..4750959f0 --- /dev/null +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.py @@ -0,0 +1,136 @@ +import os.path +import re + +from e3.os.process import Run + +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of, to_list +from SUITE.tutils import gprbuild, gprfor, tracename_for, unixpath_to, xrun + + +Wdir("tmp_") + +pgm = "myinc" +unit = pgm + ".adb" +exe = unixpath_to(pgm) +trace = tracename_for(pgm) + +# "gnatcov run" normalizes the name of the output trace file before spawning +# the low-level trace producer. Because GNAT's filename normalization is +# different from Python's, we cannot guess here what is the extract trace file +# name that will appear in logs. Workaround this by only try to match the +# basename. +trace_basename = os.path.basename(trace) + +gprbuild(gprfor(mains=[unit], srcdirs=[".."])) + + +def check_eargs(output, eargs, exe, protect_eargs=False): + m = re.search("exec: .*gnatemu.*", output) + e = m.group(0) + if protect_eargs: + eargs = " ".join([f"'{arg}'" for arg in eargs.split(" ")]) + thistest.fail_if( + not re.search( + "'--eargs' .*%(eargs)s.* '--eargs-end'.*%(exe)s" + % {"eargs": eargs, "exe": exe}, + e, + ), + "failed to match eargs='%s' and exe='%s' in output: <<\n%s\n>>" + % (eargs, exe, output), + ) + + +def gnatcovrun(extra, exe, register_failure=False, eargs=None): + outfile = "gnatcov.out" + xrun( + "-v %(extra)s %(exe)s %(eargs)s" + % { + "extra": extra, + "exe": exe, + "eargs": ("-eargs %s" % eargs) if eargs else "", + }, + out=outfile, + register_failure=register_failure, + ) + return contents_of(outfile) + + +def gnatemulator(args, exe): + outfile = "gnatemu.out" + Run( + to_list( + "%(target)s-gnatemu %(args)s %(kernel)s %(exe)s" + % { + "target": env.target.triplet, + "args": args, + "kernel": ( + ("--kernel=" + thistest.options.kernel) + if thistest.options.kernel + else "" + ), + "exe": exe, + } + ), + output=outfile, + ) + return contents_of(outfile) + + +# stmt coverage, base check on exe expansion + no history request for traces +# absence of eargs +extra = "--level=stmt" +thistest.log(extra) +output = gnatcovrun(extra=extra, exe=exe) +check_eargs(output, eargs=trace, exe=exe) + +# Check absence of "history" trace request for decision coverage +extra = "--level=stmt+decision" +thistest.log(extra) +output = gnatcovrun(extra=extra, exe=exe) +check_eargs(output, eargs=trace, exe=exe) + +# Check "history" trace request + warning for mcdc coverage without scos. +# This should activate the history for all branches and might overrun the +# trace size limits in some configurations. In particular VxWorks, where we +# run the entire OS, and targets where we might encounter busy loops in the +# runtime for cache management. +extra = "--level=stmt+mcdc" +thistest.log(extra) +is_ignored_target = any(t in env.target.triplet for t in ["vx", "aarch64"]) +output = gnatcovrun( + register_failure=not is_ignored_target, extra=extra, exe=exe +) +check_eargs(output, eargs="history,[^,]*%s" % trace_basename, exe=exe) +thistest.fail_if( + not re.search("warning: No SCOs specified for MC/DC level", output), + "failed to match no-sco warning", +) + +# Check "history" trace request with map + absence of warning. The decision map +# filename is random, so use a wide matcher (anything but a comma) for it. +extra = "--level=stmt+mcdc --scos=obj/%s.ali" % pgm +thistest.log(extra) +output = gnatcovrun(extra=extra, exe=exe) +check_eargs(output, eargs="histmap=[^,]+,[^,]*%s" % trace_basename, exe=exe) + +# Basic call with -eargs, check that they are included in the (single) +# --eargs group as well, and check that qemu sees them +eargs = "-version -m 512" +extra = "--level=stmt" +thistest.log(extra + " eargs for qemu") +output = gnatcovrun(extra=extra, exe=exe, eargs=eargs) +check_eargs(output, eargs=eargs, exe=exe, protect_eargs=True) + +eargs1 = "-m 512" +eargs2 = "-version" +output = gnatemulator( + "-v --eargs %s --eargs-end --eargs %s --eargs-end" % (eargs1, eargs2), exe +) +thistest.fail_if( + not re.search("exec:.*qemu.*%s.*%s" % (eargs1, eargs2), output), + "failed to match both --eargs sequences", +) + +thistest.result() diff --git a/testsuite/tests/KC06-023-list_as_ali/plist b/testsuite/tests/KC06-023-list_as_ali/plist new file mode 100644 index 000000000..b0f4e4021 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/plist @@ -0,0 +1 @@ +obj/p.ali diff --git a/testsuite/tests/KC06-023-list_as_ali/src/p.adb b/testsuite/tests/KC06-023-list_as_ali/src/p.adb new file mode 100644 index 000000000..f7c91e133 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/src/p.adb @@ -0,0 +1 @@ +procedure P is begin null; end; diff --git a/testsuite/tests/KC06-023-list_as_ali/test.opt b/testsuite/tests/KC06-023-list_as_ali/test.opt new file mode 100644 index 000000000..a29228f15 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise map-routines, specific to binary trace mode diff --git a/testsuite/tests/KC06-023-list_as_ali/test.py b/testsuite/tests/KC06-023-list_as_ali/test.py new file mode 100644 index 000000000..f25d7ba15 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/test.py @@ -0,0 +1,22 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir("tmp_") +gprbuild(gprfor(["p.adb"], srcdirs="../src")) + +# Expect silent success +xcov(["map-routines", "--scos=@../plist", "obj/p.o"]) + +# Expect failure +p = xcov( + ["map-routines", "--scos=../plist", "obj/p.o"], + out="list_as_ali.out", + register_failure=False, +) +thistest.fail_if( + p.status == 0 or not match("malformed ALI file", "list_as_ali.out"), + "no error on malformed ALI file", +) +thistest.result() diff --git a/testsuite/tests/KC23-012-ocov-exemptions/p.adb b/testsuite/tests/KC23-012-ocov-exemptions/p.adb new file mode 100644 index 000000000..a93fe4634 --- /dev/null +++ b/testsuite/tests/KC23-012-ocov-exemptions/p.adb @@ -0,0 +1,24 @@ + +procedure P is + + procedure Assert (T : Boolean) is + begin + pragma Annotate (Xcov, Exempt_On, "assert expected never to trip"); + if not T then -- # expect-never-true + raise Program_Error; -- # expect-uncovered + end if; + pragma Annotate (Xcov, Exempt_Off, "assert expected never to trip"); + end; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; + end; + + V : Integer := 12; + pragma Volatile (V); + +begin + Inc (V); + Assert (V = 13); +end; diff --git a/testsuite/tests/KC23-012-ocov-exemptions/test.opt b/testsuite/tests/KC23-012-ocov-exemptions/test.opt new file mode 100644 index 000000000..d2cc065d3 --- /dev/null +++ b/testsuite/tests/KC23-012-ocov-exemptions/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test uses object coverage diff --git a/testsuite/tests/KC23-012-ocov-exemptions/test.py b/testsuite/tests/KC23-012-ocov-exemptions/test.py new file mode 100644 index 000000000..62c35b5c0 --- /dev/null +++ b/testsuite/tests/KC23-012-ocov-exemptions/test.py @@ -0,0 +1,63 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +# Build and run a program with an "assert" function whose body is covered by an +# exemption region. +gpr = gprfor(srcdirs=[".."], mains=["p.adb"]) +gprbuild(gpr) +xrun(exepath_to("p")) + +# Exercise branch coverage different ways ... +# +# Without any sco/ali designation, the exemption region is expected not to be +# honored. With --scos or --alis designating the proper ali, the exemption +# region is expected to exempt something: +base_coverage = [ + "coverage", + "--level=branch", + "--annotate=xcov", + tracename_for("p"), +] + + +def check(ali_spec): + xcov(base_coverage + ali_spec) + this_report = contents_of("p.adb.xcov") + + xnote_never_true = r"\*" if ali_spec else "!" + xnote_uncovered = r"\*" if ali_spec else "-" + hint = " ".join(ali_spec) if ali_spec else "no ali" + thistest.fail_if( + not re.search( + pattern="%s:.*# expect-never-true" % xnote_never_true, + string=this_report, + ), + "%s, unmatched expected-never-true" % hint, + ) + thistest.fail_if( + not re.search( + pattern="%s:.*# expect-uncovered" % xnote_uncovered, + string=this_report, + ), + "%s, unmatched expected-uncovered" % hint, + ) + + +check(ali_spec=[]) +check(ali_spec=["--scos=obj/p.ali"]) +check(ali_spec=["--alis=obj/p.ali"]) +check(ali_spec=["-P", "gen.gpr"]) +thistest.result() diff --git a/testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb b/testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb new file mode 100644 index 000000000..96021eae6 --- /dev/null +++ b/testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb @@ -0,0 +1,18 @@ +procedure Dom_Debug is + + procedure Proc is begin null; end Proc; + function F return Integer is begin return 0; end F; + + X0 : Integer; + pragma Debug (Proc); + + procedure P is begin null; end P; + -- The presence of this body prevents direct chaining of the following + -- declaration to X0, instead a dominance marker denoting the pragma Debug + -- permits propagation. + + X1 : Integer := F; + +begin + null; +end Dom_Debug; diff --git a/testsuite/tests/L112-050-pro-through-disabled/test.py b/testsuite/tests/L112-050-pro-through-disabled/test.py new file mode 100644 index 000000000..d32dce67e --- /dev/null +++ b/testsuite/tests/L112-050-pro-through-disabled/test.py @@ -0,0 +1,33 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["dom_debug.adb"]) + ), + covlevel="stmt", + mains=["dom_debug"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/dom_debug"], + extra_gprbuild_args=["-O0"], +) + +# We expect the first variable declaration to be covered (through back +# propagation through disabled dominant pragma Debug). +thistest.fail_if( + not match(r"[0-9]+ \+:.*X0 : Integer;", "dom_debug.adb.xcov"), + "expect X0 to be covered", +) + +# The pragma itself is disabled and must be reported as NO CODE +thistest.fail_if( + not match(r"[0-9]+ \.:.*pragma Debug", "dom_debug.adb.xcov"), + "expect pragma Debug to be marked no-code", +) +thistest.result() diff --git a/testsuite/tests/L209-010-asm-outfile/src/plop.adb b/testsuite/tests/L209-010-asm-outfile/src/plop.adb new file mode 100644 index 000000000..ebbea1340 --- /dev/null +++ b/testsuite/tests/L209-010-asm-outfile/src/plop.adb @@ -0,0 +1,6 @@ +procedure Plop is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 12; +end; diff --git a/testsuite/tests/L209-010-asm-outfile/test.opt b/testsuite/tests/L209-010-asm-outfile/test.opt new file mode 100644 index 000000000..cbe3ef302 --- /dev/null +++ b/testsuite/tests/L209-010-asm-outfile/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs object coverage diff --git a/testsuite/tests/L209-010-asm-outfile/test.py b/testsuite/tests/L209-010-asm-outfile/test.py new file mode 100644 index 000000000..a489167fd --- /dev/null +++ b/testsuite/tests/L209-010-asm-outfile/test.py @@ -0,0 +1,53 @@ +""" +Check that gnatcov coverage -o produces report in output file for =asm or +=report requests. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, match +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +pgm = "plop" +pgreport = pgm + ".cov" +pgout = pgm + ".stdout" + +gprbuild(project=gprfor(pgm + ".adb", srcdirs="../src")) +xrun(exepath_to(pgm)) + + +def check_output(spec): + fmt = spec["fmt"] + level = spec["level"] + key = spec["key"] + + xcov( + "coverage --level=%s --annotate=%s --scos=%s -o %s %s" + % (level, fmt, "obj/" + pgm + ".ali", pgreport, tracename_for(pgm)), + out=pgout, + ) + thistest.fail_if( + not match(key, pgreport), + "expect asm dump in -o argument (%s), %s format" % (pgreport, fmt), + ) + thistest.fail_if( + len(contents_of(pgout)) > 0, + "expect empty stdout (directed to %s), %s format" % (pgout, fmt), + ) + + +for spec in [ + {"level": "branch", "fmt": "asm", "key": "level"}, + {"level": "stmt", "fmt": "report", "key": "VIOLATIONS"}, +]: + check_output(spec) +thistest.result() diff --git a/testsuite/tests/L411-031_missing_gnateS/src/checks.adb b/testsuite/tests/L411-031_missing_gnateS/src/checks.adb new file mode 100644 index 000000000..387579035 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/src/checks.adb @@ -0,0 +1,15 @@ +package body Checks is + + -- To control compilation options, we produce our own local project, + -- without any libsupport consideration. We must make sure that we don't + -- need a libsupport at all: + + pragma Suppress (All_Checks); + + procedure Assert (Cond : Boolean) is + begin + if not Cond then + Assert_Failures := Assert_Failures + 1; + end if; + end; +end; diff --git a/testsuite/tests/L411-031_missing_gnateS/src/checks.ads b/testsuite/tests/L411-031_missing_gnateS/src/checks.ads new file mode 100644 index 000000000..07333acac --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/src/checks.ads @@ -0,0 +1,14 @@ +package Checks is + + -- Weak assertion checking service that just counts assertion + -- failures. + + -- The point of this code is to offer something to build and run to check + -- for warnings about missing compilation options. We don't care about the + -- actual coverage assessments here and need to minimize dependencies + -- against runtime services such as an exception last chance handler. + + Assert_Failures : Natural := 0; + procedure Assert (Cond : Boolean); + +end; diff --git a/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb b/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb new file mode 100644 index 000000000..e35764b90 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb @@ -0,0 +1,8 @@ +with Checks; + +procedure Test_Assert is + X : Integer := 12; + pragma Volatile (X); +begin + Checks.Assert (X = 12); +end; diff --git a/testsuite/tests/L411-031_missing_gnateS/test.opt b/testsuite/tests/L411-031_missing_gnateS/test.opt new file mode 100644 index 000000000..05bc2e529 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/test.opt @@ -0,0 +1 @@ +src-traces DEAD Checks compilation flags for binary coverage diff --git a/testsuite/tests/L411-031_missing_gnateS/test.py b/testsuite/tests/L411-031_missing_gnateS/test.py new file mode 100644 index 000000000..22df94680 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/test.py @@ -0,0 +1,91 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exepath_to, gprbuild, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# The intent of this test is to check that gnatcov warns when it is queried to +# perform source coverage analysis on a unit for which a critical compilation +# option was not used. We exercise various combinations of option selections. +critical_opts = ("-g", "-fdump-scos", "-fpreserve-control-flow") + +# We need full control over the compilation options here, so disconnect +# all the default ones +_cargs = {"scovcargs": False, "suitecargs": False} + +gprtemplate = """ +project %(name)s is + for Source_Dirs use ("../src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada"); + package Compiler is + for Default_Switches ("Ada") use (%(opts)s); + end Compiler; +end %(name)s; +""" + + +def trywith(thisid, thisopts): + gprname = thisid + ".gpr" + with open(gprname, "w") as gpr: + gpr.write( + gprtemplate + % { + "name": thisid, + "opts": ",".join('"%s"' % opt for opt in thisopts), + } + ) + + gprbuild(gprname, gargs=["test_assert.adb"], **_cargs) + xrun(exepath_to("test_assert")) + out = thisid + ".out" + ali = "obj/checks.ali" + xcov( + [ + "coverage", + "--level=stmt+decision", + "--annotate=xcov", + "--scos=%s" % ali, + tracename_for("test_assert"), + ], + out=out, + ) + + # Check that we get warning for each critical option not in the set we + # passed. For warning checks purposes, equate -gnateS to -fdump-scos. + thisopts = ["-fdump-scos" if opt == "-gnateS" else opt for opt in thisopts] + out = contents_of(out) + + for opt in critical_opts: + if opt not in thisopts: + thistest.fail_if( + not re.search( + "warning: %s: unit compiled without .*%s" % (ali, opt), out + ), + 'case "%s" missing warning on %s' % (thisid, opt), + ) + + +# Now exercise the variants, with shortcut for option names +g = "-g" +p = "-fpreserve-control-flow" +d = "-fdump-scos" + +trywith(thisid="g", thisopts=[g]) +trywith(thisid="p", thisopts=[p]) +trywith(thisid="d", thisopts=[d]) + +trywith(thisid="pdg", thisopts=[p, d, g]) + +trywith(thisid="gp", thisopts=[g, p]) +trywith(thisid="gd", thisopts=[g, d]) +trywith(thisid="pd", thisopts=[p, d]) + +# Check that -gnateS can be used as a replacement for -fdump-scos +trywith(thisid="epg", thisopts=["-gnateS", p, g]) + +thistest.result() diff --git a/testsuite/tests/L613-012/app.gpr b/testsuite/tests/L613-012/app.gpr new file mode 100644 index 000000000..8fd71da09 --- /dev/null +++ b/testsuite/tests/L613-012/app.gpr @@ -0,0 +1,8 @@ +project App is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + package Coverage is + for Units use ("PAK1", "PAK2"); + -- PAK1 exists with different casing, PAK2 does not exist + end Coverage; +end App; diff --git a/testsuite/tests/L613-012/pak1.ads b/testsuite/tests/L613-012/pak1.ads new file mode 100644 index 000000000..edc923d23 --- /dev/null +++ b/testsuite/tests/L613-012/pak1.ads @@ -0,0 +1,2 @@ +package Pak1 is +end Pak1; diff --git a/testsuite/tests/L613-012/test.opt b/testsuite/tests/L613-012/test.opt new file mode 100644 index 000000000..d05c6047b --- /dev/null +++ b/testsuite/tests/L613-012/test.opt @@ -0,0 +1 @@ +src-traces DEAD Test specific to binary traces diff --git a/testsuite/tests/L613-012/test.py b/testsuite/tests/L613-012/test.py new file mode 100644 index 000000000..068f94870 --- /dev/null +++ b/testsuite/tests/L613-012/test.py @@ -0,0 +1,21 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprbuild, xcov + + +wd = Wdir("tmp_") + +gprbuild("../app.gpr") +xcov( + args="map-routines -P../app ../obj/pak1.o", + out="xcov.out", + tolerate_messages=( + r"no unit PAK2 in project App \(coverage.units attribute\)" + ), +) +output = contents_of("xcov.out") + +thistest.fail_if( + "no unit PAK2 in project App (coverage.units attribute)" not in output +) +thistest.result() diff --git a/testsuite/tests/L619-040-output-to-objdir/pgm.adb b/testsuite/tests/L619-040-output-to-objdir/pgm.adb new file mode 100644 index 000000000..a65e57e0c --- /dev/null +++ b/testsuite/tests/L619-040-output-to-objdir/pgm.adb @@ -0,0 +1,13 @@ +procedure PGM is + + -- This is GPR specific test for which we produce our own local project, + -- without any libsupport consideration. We must make sure that we don't + -- need a libsupport at all: + + pragma Suppress (All_Checks); + + X : Integer := 12; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/L619-040-output-to-objdir/test.py b/testsuite/tests/L619-040-output-to-objdir/test.py new file mode 100644 index 000000000..ddaf47d90 --- /dev/null +++ b/testsuite/tests/L619-040-output-to-objdir/test.py @@ -0,0 +1,52 @@ +""" +Check that gnatcov coverage uses the root project file's object dir to store +reports by default. Check that this can be overriden with --output-dir. +""" + +import os.path + +from e3.fs import rm + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir(subdir="tmp_") + +# Setup a project file with an explicit object directory specified, build it +# and execute the main. +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor( + mains=["pgm.adb"], srcdirs=[".."], objdir="obj", exedir="obj" + ) + ), + gpr_obj_dir="obj", + covlevel="stmt", + mains=["pgm"], + gpr_exe_dir="obj", + extra_coverage_args=["--annotate=xcov"], +) + +# Analyze, letting gnatcov pick a place for the report. Check that it picks the +# project's object dir: +rm("obj/pgm.adb.xcov") +xcov(xcov_args, out="coverage1.log") +thistest.fail_if( + not os.path.exists("obj/pgm.adb.xcov"), + "could not find expected report in obj dir", +) + +# Analyze again, requesting a specific place for the report. Check that it is +# created there: +rm("pgm.adb.xcov") +xcov(xcov_args + ["--output-dir=."], out="coverage2.log") +thistest.fail_if( + not os.path.exists("pgm.adb.xcov"), + "could not find expected report in current dir", +) + +thistest.result() diff --git a/testsuite/tests/L707-006-src-in-cwd/engines.adb b/testsuite/tests/L707-006-src-in-cwd/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/L707-006-src-in-cwd/engines.ads b/testsuite/tests/L707-006-src-in-cwd/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/L707-006-src-in-cwd/test.opt b/testsuite/tests/L707-006-src-in-cwd/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/L707-006-src-in-cwd/test.py b/testsuite/tests/L707-006-src-in-cwd/test.py new file mode 100644 index 000000000..a464f698a --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/test.py @@ -0,0 +1,26 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") + +gprbuild(gprfor(["test_engines.adb"], srcdirs="..")) +xrun(exepath_to("test_engines")) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + tracename_for("test_engines"), + "--scos=obj/engines.ali", + ] +) +thistest.result() diff --git a/testsuite/tests/L707-006-src-in-cwd/test_engines.adb b/testsuite/tests/L707-006-src-in-cwd/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/L929-006/leon-elf-emptys.s b/testsuite/tests/L929-006/leon-elf-emptys.s new file mode 100644 index 000000000..386a6c360 --- /dev/null +++ b/testsuite/tests/L929-006/leon-elf-emptys.s @@ -0,0 +1,44 @@ +# With +# - empty symbols at the beginning, +# - empty symbol and orphan region in the middle, +# - empty symbol at the end + + .section ".text" + # + .global empty_sym_at_start + .type empty_sym_at_start, #function +empty_sym_at_start: + .size empty_sym_at_start, 0 + # + .global plop + .type plop, #function + .proc 020 +plop: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, #function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .global plop1 + .type plop1, #function + .proc 020 +plop1: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop1, .-plop1 + # + .global empty_sym_at_end + .type empty_sym_at_end, #function +empty_sym_at_end: + .size empty_sym_at_end, 0 + \ No newline at end of file diff --git a/testsuite/tests/L929-006/leon-elf-expected.out b/testsuite/tests/L929-006/leon-elf-expected.out new file mode 100644 index 000000000..cc6d005a7 --- /dev/null +++ b/testsuite/tests/L929-006/leon-elf-expected.out @@ -0,0 +1,9 @@ +warning: empty symbol empty_sym_in_between at 00000410 in section .text +warning: empty symbol empty_last_sym at 00000820 in section .text +warning: no symbols for 00000000-000003ff in section .text [ 1 ] +warning: no symbols for 00000410-0000080f in section .text [ 1 ] +warning: no symbols for 00000820-00000c1f in section .text [ 1 ] +warning: empty symbol empty_sym_at_start at 00000000 in section .text +warning: empty symbol empty_sym_in_between at 00000010 in section .text +warning: empty symbol empty_sym_at_end at 00000420 in section .text +warning: no symbols for 00000010-0000040f in section .text [ 1 ] diff --git a/testsuite/tests/L929-006/leon-elf-orphans.s b/testsuite/tests/L929-006/leon-elf-orphans.s new file mode 100644 index 000000000..29006e841 --- /dev/null +++ b/testsuite/tests/L929-006/leon-elf-orphans.s @@ -0,0 +1,44 @@ +# With +# - orphan region at the beginning, +# - empty symbol and orphan region in the middle, +# - empty last symbol, then orphan region at the end + + .section ".text" + # + .skip 1024 + .align 4 + # + .global plop + .type plop, #function + .proc 020 +plop: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, #function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .global plop1 + .type plop1, #function + .proc 020 +plop1: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop1, .-plop1 + # + .global empty_last_sym + .type empty_last_sym, #function +empty_last_sym: + .size empty_last_sym, 0 + # + .skip 1024 + \ No newline at end of file diff --git a/testsuite/tests/L929-006/powerpc-elf-emptys.s b/testsuite/tests/L929-006/powerpc-elf-emptys.s new file mode 100644 index 000000000..7d0bd3f04 --- /dev/null +++ b/testsuite/tests/L929-006/powerpc-elf-emptys.s @@ -0,0 +1,37 @@ +# With +# - empty symbols at the beginning, +# - empty symbol and orphan region in the middle, +# - empty symbol at the end + + .file "t.c" + .section ".text" + # + .global empty_sym_at_start + .type empty_sym_at_start, @function +empty_sym_at_start: + .size empty_sym_at_start, 0 + # + .globl plop + .type plop, @function +plop: + blr + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, @function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .globl plop1 + .type plop1, @function +plop1: + blr + .size plop1, .-plop1 + # + .global empty_sym_at_end + .type empty_sym_at_end, @function +empty_sym_at_end: + .size empty_sym_at_end, 0 + diff --git a/testsuite/tests/L929-006/powerpc-elf-expected.out b/testsuite/tests/L929-006/powerpc-elf-expected.out new file mode 100644 index 000000000..f1c98c903 --- /dev/null +++ b/testsuite/tests/L929-006/powerpc-elf-expected.out @@ -0,0 +1,9 @@ +warning: empty symbol empty_sym_in_between at 00000404 in section .text +warning: empty symbol empty_last_sym at 00000808 in section .text +warning: no symbols for 00000000-000003ff in section .text [ 1 ] +warning: no symbols for 00000404-00000803 in section .text [ 1 ] +warning: no symbols for 00000808-00000c07 in section .text [ 1 ] +warning: empty symbol empty_sym_at_start at 00000000 in section .text +warning: empty symbol empty_sym_in_between at 00000004 in section .text +warning: empty symbol empty_sym_at_end at 00000408 in section .text +warning: no symbols for 00000004-00000403 in section .text [ 1 ] diff --git a/testsuite/tests/L929-006/powerpc-elf-orphans.s b/testsuite/tests/L929-006/powerpc-elf-orphans.s new file mode 100644 index 000000000..95767b520 --- /dev/null +++ b/testsuite/tests/L929-006/powerpc-elf-orphans.s @@ -0,0 +1,36 @@ +# With +# - orphan region at the beginning, +# - empty symbol and orphan region in the middle, +# - empty last symbol, then orphan region at the end + + .section ".text" + # + .skip 1024 + .align 4 + # + .global plop + .type plop, @function +plop: + blr + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, @function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .global plop1 + .type plop1, @function +plop1: + blr + .size plop1, .-plop1 + # + .global empty_last_sym + .type empty_last_sym, @function +empty_last_sym: + .size empty_last_sym, 0 + # + .skip 1024 + \ No newline at end of file diff --git a/testsuite/tests/L929-006/test.opt b/testsuite/tests/L929-006/test.opt new file mode 100644 index 000000000..3ab09a8e9 --- /dev/null +++ b/testsuite/tests/L929-006/test.opt @@ -0,0 +1,3 @@ +leon-elf +powerpc-elf +ALL DEAD test needs adaptation to run for target diff --git a/testsuite/tests/L929-006/test.py b/testsuite/tests/L929-006/test.py new file mode 100644 index 000000000..987697d50 --- /dev/null +++ b/testsuite/tests/L929-006/test.py @@ -0,0 +1,49 @@ +from e3.diff import diff +from e3.os.process import Run + +from SUITE.context import env, thistest +from SUITE.cutils import Wdir, list_to_file +from SUITE.tutils import xcov + + +Wdir("tmp_") + +sfiles_for = { + "leon-elf": ["leon-elf-orphans.s", "leon-elf-emptys.s"], + "powerpc-elf": ["powerpc-elf-orphans.s", "powerpc-elf-emptys.s"], +} + + +def do_for(target): + def to_object(sfile): + ofile = sfile.replace(".s", ".o") + Run([target + "-gcc", "-c", "../" + sfile, "-o", ofile]) + return ofile + + ofiles = [to_object(sfile) for sfile in sfiles_for[target]] + + out_actual = target + "-actual.out" + out_expected = "../" + target + "-expected.out" + + xcov(["scan-objects"] + ofiles, out=out_actual, tolerate_messages=".") + + thistest.fail_if( + diff(out_actual, out_expected), + "%s != %s, using explicit list" % (out_actual, out_expected), + ) + + xcov( + ["scan-objects", "@" + list_to_file(ofiles)], + out=out_actual, + tolerate_messages=".", + ) + + thistest.fail_if( + diff(out_actual, out_expected), + "%s != %s, using list file argument" % (out_actual, out_expected), + ) + + +do_for(env.target.triplet) + +thistest.result() diff --git a/testsuite/tests/LA17-032-scan-decisions/expected.out b/testsuite/tests/LA17-032-scan-decisions/expected.out new file mode 100644 index 000000000..571559db7 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/expected.out @@ -0,0 +1,2 @@ +*** p.adb:7:32: warning: condition is reachable through multiple paths +*** p.adb:9:32: warning: condition is reachable through multiple paths diff --git a/testsuite/tests/LA17-032-scan-decisions/p.adb b/testsuite/tests/LA17-032-scan-decisions/p.adb new file mode 100644 index 000000000..a0ac2c0ae --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/p.adb @@ -0,0 +1,10 @@ +with State; use State; + +procedure P is +begin + X := A and then B; -- tree bdd + + Y := (A and then B) or else C; -- !tree bdd + + Z := (A or else B) and then C; -- !tree bdd +end; diff --git a/testsuite/tests/LA17-032-scan-decisions/state.ads b/testsuite/tests/LA17-032-scan-decisions/state.ads new file mode 100644 index 000000000..3495c72f9 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/state.ads @@ -0,0 +1,4 @@ +package State is + A, B, C : Boolean; + X, Y, Z : Boolean; +end; diff --git a/testsuite/tests/LA17-032-scan-decisions/test.opt b/testsuite/tests/LA17-032-scan-decisions/test.opt new file mode 100644 index 000000000..9366f25e8 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov scan-decisions" diff --git a/testsuite/tests/LA17-032-scan-decisions/test.py b/testsuite/tests/LA17-032-scan-decisions/test.py new file mode 100644 index 000000000..827147640 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/test.py @@ -0,0 +1,23 @@ +""" +Check that scan-decisions reports decisions with !tree BDDs. +""" + +from e3.diff import diff + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir("tmp_") +gprbuild(gprfor(srcdirs=[".."], mains=["p.adb"])) + +xcov(["scan-decisions", "--scos=obj/p.ali"], out="out-alis") +dif = diff("../expected.out", "out-alis") +thistest.fail_if(dif, "out-alis != expected regarding scan-decisions:\n" + dif) + +xcov(["scan-decisions", "-Pgen.gpr"], out="out-gpr") +dif = diff("../expected.out", "out-gpr") +thistest.fail_if(dif, "out-gpr != expected regarding scan-decisions:\n" + dif) + +thistest.result() diff --git a/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb b/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb new file mode 100644 index 000000000..53d02b5e8 --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb @@ -0,0 +1,8 @@ +function Myabs (X : Integer) return Integer is +begin + if X < 0 then + return -X; + else + return X; + end if; +end; diff --git a/testsuite/tests/LA23-016_eargs-exe/src/p.adb b/testsuite/tests/LA23-016_eargs-exe/src/p.adb new file mode 100644 index 000000000..6776953e7 --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/src/p.adb @@ -0,0 +1,7 @@ +with Myabs; + +procedure P is + V : Integer; +begin + V := Myabs (3); +end; diff --git a/testsuite/tests/LA23-016_eargs-exe/test.opt b/testsuite/tests/LA23-016_eargs-exe/test.opt new file mode 100644 index 000000000..8060b1b39 --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests the command-line for "gnatcov run" diff --git a/testsuite/tests/LA23-016_eargs-exe/test.py b/testsuite/tests/LA23-016_eargs-exe/test.py new file mode 100644 index 000000000..5a88c01aa --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/test.py @@ -0,0 +1,72 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, empty, contents_of, match +from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun + + +Wdir("tmp_") + +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +exe = exepath_to("p") + + +# Check that "xcov run p" and "xcov run -eargs p" +# both work and produce the same result. + + +def run_check(slug, args): + rlog = slug + ".rlog" + trace = slug + ".trace" + xrun(["-o", trace] + args, out=rlog) + thistest.fail_if( + not empty(rlog) and not match("/runkernel", rlog), + "unexpected output from %s run:\n%s" % (slug, contents_of(rlog)), + ) + + +def cov_check(slug): + clog = slug + ".clog" + trace = slug + ".trace" + rep = slug + ".rep" + xcov( + [ + "coverage", + "--level=stmt", + "--scos=obj/myabs.ali", + "--annotate=report", + trace, + "-o", + rep, + ], + out=clog, + ) + + thistest.fail_if( + not match("statement not executed", rep), + "missing expected stmt coverage violation note in %s" % rep, + ) + + thistest.fail_if( + not empty(clog), + "unexpected output from %s coverage :\n%s" % (slug, contents_of(clog)), + ) + + +slug = "base" +run_check(slug, args=[exe]) +cov_check(slug) + +slug = "eargs" +run_check(slug, args=["-eargs", exe]) +cov_check(slug) + +# Check that a bare "xcov run" complains about absence of executable +# on the command line. +log = "noexe.log" +xrun("", out=log, register_failure=False) + +thistest.fail_if( + not match(": Please specify an executable to run", log), + "missing expected error in log for run without exe", +) + +thistest.result() diff --git a/testsuite/tests/LB13-031-post-aspect/src/orelse.ads b/testsuite/tests/LB13-031-post-aspect/src/orelse.ads new file mode 100644 index 000000000..de7a3b89f --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/orelse.ads @@ -0,0 +1,3 @@ +package Orelse is + function Or_Else (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/LB13-031-post-aspect/src/passor.adb b/testsuite/tests/LB13-031-post-aspect/src/passor.adb new file mode 100644 index 000000000..6de9d589a --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/passor.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Passor (A, B : Boolean) is +begin + Put_Line ("Hello world"); -- # stmt +end; diff --git a/testsuite/tests/LB13-031-post-aspect/src/passor.ads b/testsuite/tests/LB13-031-post-aspect/src/passor.ads new file mode 100644 index 000000000..cf315df5d --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/passor.ads @@ -0,0 +1,4 @@ +pragma Ada_2012; +pragma Check_Policy (Post, On); +procedure Passor (A, B : Boolean) + with Post => A or else B; -- # eval diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb new file mode 100644 index 000000000..e7927e39c --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb @@ -0,0 +1,14 @@ +with Passor; + +-- nothing called, no stmt covered + +procedure Test_Passor_0 is +begin + null; +end; + +--# passor.ads +-- /eval/ l- ## d- + +--# passor.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb new file mode 100644 index 000000000..a5e536b06 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb @@ -0,0 +1,16 @@ +with Passor, Silent_Last_Chance; + +-- evalcond False only, body stmt covered + +procedure Test_Passor_FF is +begin + Passor (False, False); +exception + when others => null; +end; + +--# passor.ads +-- /eval/ l! ## dT- + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb new file mode 100644 index 000000000..375b04170 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb @@ -0,0 +1,16 @@ +with Passor, Silent_Last_Chance; + +-- evalcond True only (from B), all stmt covered + +procedure Test_Passor_FT is +begin + Passor (False, True); +exception + when others => null; +end; + +--# passor.ads +-- /eval/ l! ## dF- + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb new file mode 100644 index 000000000..a2bc75f47 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb @@ -0,0 +1,17 @@ +with Passor, Silent_Last_Chance; + +-- evalcond true and false, all stmt covered + +procedure Test_Passor_FU is +begin + Passor (True, False); + Passor (False, False); +exception + when others => null; +end; + +--# passor.ads +-- /eval/ l+ ## 0 + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb new file mode 100644 index 000000000..86921fcf7 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb @@ -0,0 +1,16 @@ +with Passor; + +-- evalcond True only (from A), all stmt covered + +procedure Test_Passor_Tx is +begin + for X in False .. True loop + Passor (True, X); + end loop; +end; + +--# passor.ads +-- /eval/ l! ## dF- + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/tc.txt b/testsuite/tests/LB13-031-post-aspect/tc.txt new file mode 100644 index 000000000..cec5a65e4 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/tc.txt @@ -0,0 +1,2 @@ +Check DC on ``A or else B`` as a Post aspect attached to a subprogram +declaration. diff --git a/testsuite/tests/LB13-031-post-aspect/test.opt b/testsuite/tests/LB13-031-post-aspect/test.opt new file mode 100644 index 000000000..0a9ed7ea5 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD testing coverage of expressions in aspects, implemented post 7.0.3 +src-traces XFAIL S606-037: src-traces and contracts +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/LB13-031-post-aspect/test.py b/testsuite/tests/LB13-031-post-aspect/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads b/testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads new file mode 100644 index 000000000..087fa3b2c --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads @@ -0,0 +1,3 @@ +package Andthen is + function And_Then (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb new file mode 100644 index 000000000..1dde59173 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb @@ -0,0 +1,4 @@ +procedure Passand (A, B : Boolean) is +begin + null; -- # stmt +end; diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads new file mode 100644 index 000000000..32744be6d --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads @@ -0,0 +1,4 @@ +pragma Ada_2012; +pragma Check_Policy (Pre, On); +procedure Passand (A, B : Boolean) + with Pre => A and then B; -- # eval diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb new file mode 100644 index 000000000..4d31043f7 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb @@ -0,0 +1,12 @@ +with Passand; + +procedure Test_Passand_0 is +begin + null; +end; + +--# passand.ads +-- /eval/ l- ## d- + +--# passand.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb new file mode 100644 index 000000000..4bf9c372a --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb @@ -0,0 +1,17 @@ +with Passand, Silent_Last_Chance; + +-- eval both True and False, all stmt covered + +procedure Test_Passand_FU is +begin + Passand (True, True); + Passand (True, False); +exception + when others => null; +end; + +--# passand.ads +-- /eval/ l+ ## 0 + +--# passand.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb new file mode 100644 index 000000000..7526e8366 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb @@ -0,0 +1,16 @@ +with Passand, Silent_Last_Chance; + +-- eval False only (from A), body stmt uncovered + +procedure Test_Passand_FX is +begin + Passand (False, True); +exception + when others => null; +end; + +--# passand.ads +-- /eval/ l! ## dT- + +--# passand.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb new file mode 100644 index 000000000..a6462bcaf --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb @@ -0,0 +1,16 @@ +with Passand, Silent_Last_Chance; + +-- eval False only (from B), body stmt uncovered + +procedure Test_Passand_TF is +begin + Passand (True, False); +exception + when others => null; +end; + +--# passand.ads +-- /eval/ l! ## dT- + +--# passand.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb new file mode 100644 index 000000000..e5cc006c8 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb @@ -0,0 +1,14 @@ +with Passand; + +-- eval True only, all stmts covered + +procedure Test_Passand_TT is +begin + Passand (True, True); +end; + +--# passand.ads +-- /eval/ l! ## dF- + +--# passand.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/tc.txt b/testsuite/tests/LB15-031-split-PPC-aspect/tc.txt new file mode 100644 index 000000000..0f50a3a6e --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/tc.txt @@ -0,0 +1,2 @@ +Check DC on ``A and then B`` as a Pre aspect attached to a subprogram +declaration. diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/test.opt b/testsuite/tests/LB15-031-split-PPC-aspect/test.opt new file mode 100644 index 000000000..925ef8d60 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD relies on compiler support for 2012 Aspects, not all in 7.0.3 +7.2.2 DEAD relies on compiler support for 2012 Aspects, not all in 7.2.2 +src-traces XFAIL S606-037: src-traces and contracts +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/test.py b/testsuite/tests/LB15-031-split-PPC-aspect/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/LibExp/.gitignore b/testsuite/tests/LibExp/.gitignore new file mode 100644 index 000000000..5c1079086 --- /dev/null +++ b/testsuite/tests/LibExp/.gitignore @@ -0,0 +1,2 @@ +C +Ada diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb new file mode 100644 index 000000000..9481eada8 --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb @@ -0,0 +1,49 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V0 is +begin + Run_FF_F; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l- ## s- +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l! ## eT- + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l! ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l! ## eT- diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb new file mode 100644 index 000000000..5f3339502 --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb @@ -0,0 +1,49 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V02 is +begin + Run_FF_F; + Run_TF_F; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l- ## s- +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l+ ## eT- + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l+ ## eT- + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l! ## eT- + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l! ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l! ## eT- diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb new file mode 100644 index 000000000..adc5bd5c4 --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb @@ -0,0 +1,50 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V03 is +begin + Run_FF_F; + Run_TT_T; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l+ ## 0 +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## 0 +-- =/eval-X1 :e:/ l! ## 0 + +-- =/eval-X2 :d:/ l! ## c!:"(X2*)" +-- =/eval-X2 :e:/ l! ## c!:"(X2*)" + +-- =/eval-all :d:/ l! ## c!:"(X2*)" +-- =/eval-all :e:/ l! ## c!:"(X2*)" diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb new file mode 100644 index 000000000..5357df07f --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb @@ -0,0 +1,50 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V23 is +begin + Run_TF_F; + Run_TT_T; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l+ ## 0 +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## c!:"(X1*)" +-- =/eval-X1 :e:/ l! ## c!:"(X1*)" + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l! ## 0 + +-- =/eval-all :d:/ l! ## c!:"(X1*)" +-- =/eval-all :e:/ l! ## c!:"(X1*)" diff --git a/testsuite/tests/LibExp/extra.opt b/testsuite/tests/LibExp/extra.opt new file mode 100644 index 000000000..783e24c6c --- /dev/null +++ b/testsuite/tests/LibExp/extra.opt @@ -0,0 +1,2 @@ +LANG_C,7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/LibExp/group.py b/testsuite/tests/LibExp/group.py new file mode 100644 index 000000000..8815c92cf --- /dev/null +++ b/testsuite/tests/LibExp/group.py @@ -0,0 +1,3 @@ +from SCOV.expgen.generator.engine import run + +run(__file__) diff --git a/testsuite/tests/LibExp/set.txt b/testsuite/tests/LibExp/set.txt new file mode 100644 index 000000000..14b51bf3c --- /dev/null +++ b/testsuite/tests/LibExp/set.txt @@ -0,0 +1,38 @@ +This directory hosts libraries of test drivers and functional +code for expressions of a given topology. Ideas: + +o One family of drivers for e.g. + + X and then Y + X or else Y + etc + +o State expectations for all the possible criteria + (stmt, decision, mcdc) + +o Provide helpers + functional code for a variety + of operand kinds. Drivers should be generic enough + not to care. + +o Each chapter should feature a "instanciation" + request to trigger execution of the test and validation + for the criterion it represents. + +o think about ways to have the tests accounted for in qualification runs + (if not in a subdir of / for example) + +DriverLib + Drivers written in Ada, used for C instances as well + +Ada/ExprLib + Ada implementation of the helpers and functional variants + +C/ExprLib + C implementation of the helpers and functional variants + +Testcase description: + Check correctness of _the criterion_ assessment etc + + +test.py ?? QMAT tree ?? + diff --git a/testsuite/tests/LibExp/src/support.h b/testsuite/tests/LibExp/src/support.h new file mode 100644 index 000000000..d9a58ffff --- /dev/null +++ b/testsuite/tests/LibExp/src/support.h @@ -0,0 +1,9 @@ +#ifndef SUPPORT_H +#define SUPPORT_H + +/* Prototypes for libsupport functions we'll use. */ + +extern void assert (char cond); +extern int identity (int x); + +#endif diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb new file mode 100644 index 000000000..05c5c16ed --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb @@ -0,0 +1,15 @@ +with Assert; +with Values; use Values; + +procedure Test_1 is + B : Bool; +begin + Equal (X => 1, Y => 2, B => B); + Assert (B.Value = False); + Equal2 (X => 1, Y => 1, Z => 4, T => 8, B => B); + Assert (B.Value = False); +end; + +--# values.adb +-- /eq/ l+ ## 0 +-- /andthen/ d=>l+, mu=>l! ## d=>0, mu=>eT- diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb new file mode 100644 index 000000000..684eb1afa --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb @@ -0,0 +1,13 @@ +package body Values is + + procedure Equal (X, Y : Integer; B : out Bool) is + begin + B := (Value => X = Y); -- # eq + end; + + procedure Equal2 (X, Y : Integer; Z, T : Integer; B : out Bool) is + begin + B := (Value => (X = Y) and then (Z = T)); -- # andthen + end; + +end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads b/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads new file mode 100644 index 000000000..e12b8b5bb --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads @@ -0,0 +1,10 @@ +package Values is + + type Bool is record + Value : Boolean; + end record; + + procedure Equal (X, Y : Integer; B : out Bool); + procedure Equal2 (X, Y : Integer; Z, T : Integer; B : out Bool); + +end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/test.py b/testsuite/tests/M204-037-dc-in-aggregate/test.py new file mode 100644 index 000000000..49089f5e1 --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.htc import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M502-040-default-prj-path/.gitignore b/testsuite/tests/M502-040-default-prj-path/.gitignore new file mode 100644 index 000000000..cd56e8c6d --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/.gitignore @@ -0,0 +1,2 @@ +proj/ut/ut.gpr +proj/ut/main.trace diff --git a/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr b/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr new file mode 100644 index 000000000..52baf98c9 --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr @@ -0,0 +1,3 @@ +project Proj is + +end Proj; diff --git a/testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb b/testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb new file mode 100644 index 000000000..5207ed884 --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb @@ -0,0 +1 @@ +procedure Main is begin null; end; diff --git a/testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template b/testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template new file mode 100644 index 000000000..dd9c5f3ef --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template @@ -0,0 +1,11 @@ +project UT extends "proj.gpr" is + + for Source_Dirs use ("."); + for Object_Dir use "obj"; + + for Main use ("main.adb"); + + {pkg_emulator} + +end UT; + diff --git a/testsuite/tests/M502-040-default-prj-path/test.opt b/testsuite/tests/M502-040-default-prj-path/test.opt new file mode 100644 index 000000000..d49846591 --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/test.opt @@ -0,0 +1,2 @@ +native DEAD test works by simulating a missing/non-working native gnatls +src-traces DEAD test specific to gnatcov run diff --git a/testsuite/tests/M502-040-default-prj-path/test.py b/testsuite/tests/M502-040-default-prj-path/test.py new file mode 100644 index 000000000..3c563757c --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/test.py @@ -0,0 +1,26 @@ +import os +import os.path + +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import contents_of, text_to_file +from SUITE.tutils import exepath_to, gpr_emulator_package, gprbuild, xrun + + +env.add_search_path( + env_var="PATH", path=os.path.join(os.getcwd(), "bin"), append=True +) +env.add_search_path( + env_var="GPR_PROJECT_PATH", path=os.path.join(os.getcwd(), "proj") +) + +os.chdir("proj/ut") +text_to_file( + contents_of("ut.gpr.template").format(pkg_emulator=gpr_emulator_package()), + "ut.gpr", +) + +gprbuild("ut") +xrun(["-P", "ut", exepath_to("obj/main")]) + +thistest.result() diff --git a/testsuite/tests/M513-017/driver.adb b/testsuite/tests/M513-017/driver.adb new file mode 100644 index 000000000..0793d4545 --- /dev/null +++ b/testsuite/tests/M513-017/driver.adb @@ -0,0 +1,8 @@ +with Lib; use Lib; + +procedure Driver is +begin + if Get (11) then + raise Program_Error; + end if; +end Driver; diff --git a/testsuite/tests/M513-017/lib.adb b/testsuite/tests/M513-017/lib.adb new file mode 100644 index 000000000..2e206e9ee --- /dev/null +++ b/testsuite/tests/M513-017/lib.adb @@ -0,0 +1,25 @@ +package body Lib is + + function Image (I : Integer) return String is + begin + if I < 0 then + return '-' & Integer'Image (I); + else + return Integer'Image (I); + end if; + end Image; + + function Get (I : Integer) return Boolean is + begin + if Image (I) = Image (1) & "0" then + return True; + else + return False; + end if; + end Get; + + function Get2 (I : Integer) return Boolean is + begin + return Image (I) /= "10" and then Image (I) /= "20"; + end Get2; +end Lib; diff --git a/testsuite/tests/M513-017/lib.ads b/testsuite/tests/M513-017/lib.ads new file mode 100644 index 000000000..fdc97a635 --- /dev/null +++ b/testsuite/tests/M513-017/lib.ads @@ -0,0 +1,4 @@ +package Lib is + function Get (I : Integer) return Boolean; + function Get2 (I : Integer) return Boolean; +end Lib; diff --git a/testsuite/tests/M513-017/test.opt b/testsuite/tests/M513-017/test.opt new file mode 100644 index 000000000..a3304d764 --- /dev/null +++ b/testsuite/tests/M513-017/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov map-routines" diff --git a/testsuite/tests/M513-017/test.py b/testsuite/tests/M513-017/test.py new file mode 100644 index 000000000..22fe6e14b --- /dev/null +++ b/testsuite/tests/M513-017/test.py @@ -0,0 +1,8 @@ +import os.path + +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker(["driver.adb"], alis=[os.path.join("obj", "lib.ali")]).run() +thistest.result() diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb new file mode 100644 index 000000000..a2a98b1ff --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb @@ -0,0 +1,18 @@ +package body Ops is + procedure Compute + (A, B, C : Integer; + X, Y : out Integer) is + begin + -- This test is about checking that gnatcov do not complain when + -- multiple statements are on the same line as long as debug info slocs + -- have column information. + + -- Currently, the compiler generates column information only for + -- conditional branch instructions. We know that the full "mod" + -- implementation involves branches, so we are sure that using such + -- operations in both of our statements will generate column + -- information. + + X := A mod B; Y := A mod C; -- # multi-stmts + end Compute; +end Ops; diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads new file mode 100644 index 000000000..3605ce006 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + procedure Compute + (A, B, C : Integer; + X, Y : out Integer); +end Ops; diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb new file mode 100644 index 000000000..b3aaffea9 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb @@ -0,0 +1,10 @@ +with Ops; use Ops; + +procedure Test_Full is + X, Y : Integer; +begin + Compute (32, 10, 20, X, Y); +end Test_Full; + +--# ops.adb +-- /multi-stmts/ l+ ## 0 diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb new file mode 100644 index 000000000..2dcdd1158 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb @@ -0,0 +1,10 @@ +with Ops; use Ops; + +procedure Test_No is + X, Y : Integer; +begin + null; +end Test_No; + +--# ops.adb +-- /multi-stmts/ l- ## s-, s- diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/test.py b/testsuite/tests/M514-031-multiple-stmts-lines/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/M515-018/return-ternary.c b/testsuite/tests/M515-018/return-ternary.c new file mode 100644 index 000000000..445328d64 --- /dev/null +++ b/testsuite/tests/M515-018/return-ternary.c @@ -0,0 +1,11 @@ +int +my_abs (int n) +{ + return (n < 0) ? -n : n; +} + +int +main (void) +{ + return my_abs (1); +} diff --git a/testsuite/tests/M515-018/test.opt b/testsuite/tests/M515-018/test.opt new file mode 100644 index 000000000..9de3b425b --- /dev/null +++ b/testsuite/tests/M515-018/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD testing properties of C SCOs, implemented post 7.0.3 +!bin-traces DEAD test using map-routines +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/M515-018/test.py b/testsuite/tests/M515-018/test.py new file mode 100644 index 000000000..02d4d5af1 --- /dev/null +++ b/testsuite/tests/M515-018/test.py @@ -0,0 +1,31 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir("tmp_") + +# First build the program +gprbuild(gprfor(mains=["return-ternary.c"], srcdirs="..")) + +# Then invoke map-routines so that SCOs are loaded. +xcov( + [ + "map-routines", + "--scos=obj/return-ternary.c.gli", + "obj/return-ternary.o", + ], + out="map-routines.txt", +) + +# The test fail if we find something like: +# !!! return-ternary.c:3:10: unexpected SCO nesting in SCO #1: STATEMENT at +# return-ternary.c:3:3-25, discarding nested SCO +thistest.fail_if( + any( + line.startswith("!!!") + for line in open("map-routines.txt", "r").readlines() + ), + "map-routines has found something wrong", +) +thistest.result() diff --git a/testsuite/tests/M516-014-direct-bool-operators/req.txt b/testsuite/tests/M516-014-direct-bool-operators/req.txt new file mode 100644 index 000000000..db58c4484 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/req.txt @@ -0,0 +1,12 @@ +The and/or/xor non-shortcircuit operators are allowed for sc and dc +assessments. They shall be processed as any other kind of computational +operator. + +Testing Strategy: +----------------- + +Provide testcases involving and/or/xor operators in decisions. Check +that they are all accepted and processed without any particularity. + +Check that the presence of and/or/xor operators in an expression +doesn't make it a decision out of explicit control-flow contexts. diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/assert.adb b/testsuite/tests/M516-014-direct-bool-operators/src/assert.adb new file mode 100644 index 000000000..075669142 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (X : Boolean) is +begin + if not X then + raise Program_Error; + end if; +end Assert; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/assert.ads b/testsuite/tests/M516-014-direct-bool-operators/src/assert.ads new file mode 100644 index 000000000..ab78e4405 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/assert.ads @@ -0,0 +1 @@ +procedure Assert (X : Boolean); diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb b/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb new file mode 100644 index 000000000..9dec5b304 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb @@ -0,0 +1,15 @@ +package body Ops is + + procedure Eval (A, B : Boolean) is + begin + if A and B then -- # eval-and + N_And := N_And + 1; -- # and-true + end if; + if A or B then -- # eval-or + N_Or := N_Or + 1; -- # or-true + end if; + if A xor B then -- # eval-xor + N_Xor := N_Xor + 1; -- # xor-true + end if; + end; +end; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads b/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads new file mode 100644 index 000000000..817bf3c8c --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + procedure Eval (A, B : Boolean); + + N_And, N_Or, N_Xor : Integer := 0; +end; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb new file mode 100644 index 000000000..3394e7ed0 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_And is +begin + Eval (A => True, B => True); + Eval (A => True, B => False); + Assert (N_And = 1 and then N_Or = 2 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ l+ ## 0 +-- /and-true/ l+ ## 0 +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ l+ ## 0 +-- /xor-true/ l+ ## 0 diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb new file mode 100644 index 000000000..47b17d950 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb @@ -0,0 +1,16 @@ +with Assert; +with Ops; use Ops; + +procedure Test_FF is +begin + Eval (A => False, B => False); + Assert (N_And = 0 and then N_Or = 0 and then N_Xor = 0); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /or-true/ l- ## s- +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /xor-true/ l- ## s- diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb new file mode 100644 index 000000000..3151c40c2 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb @@ -0,0 +1,16 @@ +with Assert; +with Ops; use Ops; + +procedure Test_FT is +begin + Eval (A => False, B => True); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /xor-true/ l+ ## 0 diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb new file mode 100644 index 000000000..0ce5dcfff --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Or is +begin + Eval (A => False, B => False); + Eval (A => True, B => True); + Assert (N_And = 1 and then N_Or = 1 and then N_Xor = 0); +end; + +--# ops.adb +-- /eval-and/ l+ ## 0 +-- /and-true/ l+ ## 0 +-- /eval-or/ l+ ## 0 +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /xor-true/ l- ## s- diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb new file mode 100644 index 000000000..feab57285 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb @@ -0,0 +1,16 @@ +with Assert; +with Ops; use Ops; + +procedure Test_TF is +begin + Eval (A => True, B => False); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /xor-true/ l+ ## 0 diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb new file mode 100644 index 000000000..884d38fa4 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb @@ -0,0 +1,16 @@ +with Assert; +with Ops; use Ops; + +procedure Test_TT is +begin + Eval (A => True, B => True); + Assert (N_And = 1 and then N_Or = 1 and then N_Xor = 0); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /and-true/ l+ ## 0 +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /xor-true/ l- ## s- diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb new file mode 100644 index 000000000..778bf197e --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Xor is +begin + Eval (A => False, B => False); + Eval (A => True, B => False); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ l+ ## 0 +-- /or-true/ l+ ## 0 +-- /eval-xor/ l+ ## 0 +-- /xor-true/ l+ ## 0 diff --git a/testsuite/tests/M516-014-direct-bool-operators/test.py b/testsuite/tests/M516-014-direct-bool-operators/test.py new file mode 100644 index 000000000..64dab3c68 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads new file mode 100644 index 000000000..119c7f9f2 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads @@ -0,0 +1 @@ +procedure Assert (T : Boolean); diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb new file mode 100644 index 000000000..4b1f6d00b --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb @@ -0,0 +1,42 @@ +with Ada.Finalization; use Ada.Finalization; + +package body Foo is + + type Witness is new Ada.Finalization.Controlled with record + Value : Integer; + end record; + + procedure Adjust (X : in out Witness); + procedure Finalize (X : in out Witness); + + procedure Adjust (X : in out Witness) is + begin + N_Adjust := N_Adjust + 1; -- # adjust + end Adjust; + + procedure Finalize (X : in out Witness) is + begin + N_Finalize := N_Finalize + 1; -- # final + end Finalize; + + function Make (V : Integer) return Witness is + Result : constant Witness := (Controlled with V); -- # make + begin + return Result; -- # make + end Make; + + function Val (X : Witness) return Integer is + begin + return X.Value; -- # val + end Val; + + procedure Try (V : Integer) is + begin + if Val (Make (1)) = V or else Val (Make (2)) = V then -- # eval + N_Then := N_Then + 1; -- # then + else + N_Else := N_Else + 1; -- # else + end if; + end Try; + +end; diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads new file mode 100644 index 000000000..aac5f28a9 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads @@ -0,0 +1,5 @@ +package Foo is + procedure Try (V : Integer); + + N_Finalize, N_Adjust, N_Then, N_Else : Natural := 0; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb new file mode 100644 index 000000000..e30c3c0be --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb @@ -0,0 +1,14 @@ +with Foo; use Foo; +with Assert; + +procedure Test_FF is +begin + Foo.Try (V => 4); + Assert (N_Then = 0); + Assert (N_Else = 1); +end; + +--# foo.adb +-- /eval/ l! ## dT- +-- /then/ l- ## s- +-- /else/ l+ ## 0 diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb new file mode 100644 index 000000000..c32b6ee65 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb @@ -0,0 +1,14 @@ +with Foo; use Foo; +with Assert; + +procedure Test_FT is +begin + Foo.Try (V => 2); + Assert (N_Then = 1); + Assert (N_Else = 0); +end; + +--# foo.adb +-- /eval/ l! ## dF- +-- /then/ l+ ## 0 +-- /else/ l- ## s- diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb new file mode 100644 index 000000000..58266d08d --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb @@ -0,0 +1,14 @@ +with Foo; use Foo; +with Assert; + +procedure Test_TX is +begin + Foo.Try (V => 1); + Assert (N_Then = 1); + Assert (N_Else = 0); +end; + +--# foo.adb +-- /eval/ l! ## dF- +-- /then/ l+ ## 0 +-- /else/ l- ## s- diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/test.py b/testsuite/tests/M528-002-transient-finalize/alternate/test.py new file mode 100644 index 000000000..e795c2214 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M528-002-transient-finalize/extra.opt b/testsuite/tests/M528-002-transient-finalize/extra.opt new file mode 100644 index 000000000..3f9ce77c1 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/extra.opt @@ -0,0 +1,4 @@ +RTS_ZFP DEAD Involves controlled objects +RTS_LIGHT_TASKING DEAD Involes controlled objects +7.0.3 DEAD testing transient controlled finalizers, requires post 7.0.3 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/M528-002-transient-finalize/original/src/log.adb b/testsuite/tests/M528-002-transient-finalize/original/src/log.adb new file mode 100644 index 000000000..eadce41ef --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/original/src/log.adb @@ -0,0 +1,12 @@ +with System; + +-- A fake replacement for Put_Line so the original source constructs in +-- callers are generally preserved and we can exercise arbitrary an RTS +-- profile. + +procedure Log (Status : String) is + Outreg : System.Address; + pragma Volatile (Outreg); +begin + Outreg := Status'Address; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb b/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb new file mode 100644 index 000000000..96fe869d3 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb @@ -0,0 +1,62 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Log; + +procedure Test_Main is + + abc : constant Unbounded_String := To_Unbounded_String ("abc"); + def : constant Unbounded_String := To_Unbounded_String ("def"); + ghi : constant Unbounded_String := To_Unbounded_String ("ghi"); + bool : constant Unbounded_String := To_Unbounded_String ("bool"); + + function Foo (Var : Unbounded_String) return Boolean is + begin + if Var = To_Unbounded_String ("abc") -- # evalA + or else Var = To_Unbounded_String ("def") -- # evalB + or else Var = To_Unbounded_String ("ghi") -- # evalC + then + return True; -- # dtrue + else + return False; -- # dfalse + end if; + end Foo; + + +begin + if Foo (abc) then -- # outer_test_xok + Log ("ok"); -- # outer_ok + else + Log ("err"); -- # outer_err_xok + end if; + + if Foo (def) then -- # outer_test_xok + Log ("ok"); -- # outer_ok + else + Log ("err"); -- # outer_err + end if; + + if Foo (ghi) then -- # outer_test_xok + Log ("ok"); -- # outer_ok + else + Log ("err"); -- # outer_err + end if; + + if Foo (bool) then -- # outer_test_xfail + Log ("err"); -- # outer_err + else + Log ("ok"); -- # outer_ok + end if; +end; + +-- Self test, originating from customer, mcdc complete ... + +--# test_main.adb +-- /evalA/ l+ ## 0 +-- /evalB/ l+ ## 0 +-- /evalC/ l+ ## 0 +-- /dtrue/ l+ ## 0 +-- /dfalse/ l+ ## 0 + +-- /outer_test_xok/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /outer_test_xfail/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +-- /outer_err/ l- ## s- +-- /outer_ok/ l+ ## 0 diff --git a/testsuite/tests/M528-002-transient-finalize/original/test.py b/testsuite/tests/M528-002-transient-finalize/original/test.py new file mode 100644 index 000000000..e795c2214 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/original/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb new file mode 100644 index 000000000..eadce41ef --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb @@ -0,0 +1,12 @@ +with System; + +-- A fake replacement for Put_Line so the original source constructs in +-- callers are generally preserved and we can exercise arbitrary an RTS +-- profile. + +procedure Log (Status : String) is + Outreg : System.Address; + pragma Volatile (Outreg); +begin + Outreg := Status'Address; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb new file mode 100644 index 000000000..c85bff4cc --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb @@ -0,0 +1,15 @@ +package body Pkg is + + function Foo (Var : Unbounded_String) return Boolean is + begin + if Var = To_Unbounded_String ("abc") -- # evalA + or else Var = To_Unbounded_String ("def") -- # evalB + or else Var = To_Unbounded_String ("ghi") -- # evalC + then + return True; -- # dtrue + else + return False; -- # dfalse + end if; + end Foo; + +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads new file mode 100644 index 000000000..7708de8f9 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads @@ -0,0 +1,12 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +package Pkg is + + abc : constant Unbounded_String := To_Unbounded_String ("abc"); + def : constant Unbounded_String := To_Unbounded_String ("def"); + ghi : constant Unbounded_String := To_Unbounded_String ("ghi"); + bool : constant Unbounded_String := To_Unbounded_String ("bool"); + + function Foo (Var : Unbounded_String) return Boolean; + +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb new file mode 100644 index 000000000..c93a6dd48 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb @@ -0,0 +1,13 @@ +with Assert, Pkg; use Pkg; + +procedure Test_DF is +begin + Assert (not Foo (bool)); +end; + +--# pkg.adb +-- /evalA/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +-- /evalB/ s=>l+, dmu=>l! ## 0 +-- /evalC/ s=>l+, dmu=>l! ## 0 +-- /dtrue/ l- ## s- +-- /dfalse/ l+ ## 0 diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb new file mode 100644 index 000000000..88a087e61 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb @@ -0,0 +1,13 @@ +with Assert, Pkg; use Pkg; + +procedure Test_DT is +begin + Assert (Foo (abc)); +end; + +--# pkg.adb +-- /evalA/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /evalB/ s=>l+, dmu=>l! ## 0 +-- /evalC/ s=>l+, dmu=>l! ## 0 +-- /dtrue/ l+ ## 0 +-- /dfalse/ l- ## s- diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/test.py b/testsuite/tests/M528-002-transient-finalize/variant1/test.py new file mode 100644 index 000000000..e795c2214 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/bar.c b/testsuite/tests/M625-011-GPR-Cunits/src/bar.c new file mode 100644 index 000000000..3b079e8fe --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/src/bar.c @@ -0,0 +1,7 @@ +#include "bar.h" + +int +bar (int x) +{ + return x + 1; +} diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/bar.h b/testsuite/tests/M625-011-GPR-Cunits/src/bar.h new file mode 100644 index 000000000..7f17a74f5 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/src/bar.h @@ -0,0 +1,12 @@ +#ifndef BAR_H +#define BAR_H + +int bar (int x); + +static int +baz (int x) +{ + return x - 1; +} + +#endif // BAR_H diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/foo.c b/testsuite/tests/M625-011-GPR-Cunits/src/foo.c new file mode 100644 index 000000000..13906f359 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/src/foo.c @@ -0,0 +1,7 @@ +#include "bar.h" + +int +main (void) +{ + return baz (bar (0)); +} diff --git a/testsuite/tests/M625-011-GPR-Cunits/test.py b/testsuite/tests/M625-011-GPR-Cunits/test.py new file mode 100644 index 000000000..22a3ffb01 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/test.py @@ -0,0 +1,45 @@ +""" +Check that gnatcov uses projects files to find SCOs for C units. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, empty, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir("tmp_") + +# Create a very simple C project +gpr = gprfor(mains="foo.c", srcdirs=["../src"], langs=["C"]) + +# By default build_and_run will use -P to designate the units of interest, +# which is what we want here. + +coverage_log = "coverage.log" + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + mains=["foo"], + covlevel="stmt", + extra_coverage_args=["-axcov", "--output-dir=."], + out=coverage_log, +) + +thistest.fail_if( + not empty(coverage_log), + comment='"gnatcov coverage" output not empty:\n' + + contents_of(coverage_log), +) + +check_xcov_reports( + ".", + { + "foo.c.xcov": {"+": {6}}, + "bar.c.xcov": {"+": {6}}, + "bar.h.xcov": {"+": {9}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb new file mode 100644 index 000000000..5fd1782b7 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_1'Length /= 0 -- # first + and then -- # op + Cond_1 (Idx) -- # second + and then -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb new file mode 100644 index 000000000..7d6a5a011 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Second is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_Second; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## 0 +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb new file mode 100644 index 000000000..ede79cdea --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Second_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_Second_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb new file mode 100644 index 000000000..6d414087f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb new file mode 100644 index 000000000..a38dd4472 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb @@ -0,0 +1,9 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + return -- # stmt + Cond_1'Length /= 0 -- # first + and then -- # op + Cond_1 (Idx); -- # second + end Eval; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb new file mode 100644 index 000000000..ce6b7d8d7 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb @@ -0,0 +1,27 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/stmt/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 + +--%cov: --level=stmt\+decision +-- =/stmt/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/stmt/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..9337eddde --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb @@ -0,0 +1,27 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/stmt/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/stmt/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/stmt/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## eF- +-- =/second/ l! ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt new file mode 100644 index 000000000..29a6a1776 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL M716-006: inlining and condition folding diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb new file mode 100644 index 000000000..ff24e14db --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb @@ -0,0 +1,22 @@ +package body Ops is + function Eval_Cond + (Idx : Cond_Index; + Conds : Cond_Array_Option) return Boolean + is + begin + return -- # stmt-2 + Conds.Available -- # first-2 + and then -- # op-2 + Conds.Cond (Idx) -- # second-2 + and then -- # op-2 + Cond_1 (Idx); -- # third-2 + end Eval_Cond; + + function Eval (Idx : Cond_Index) return Boolean is + begin + return -- # stmt-1 + Cond_2 (Idx) -- # first-1 + and then -- # op-1 + Eval_Cond (Idx, (True, Cond_1)); -- # second-1 + end Eval; +end Ops; diff --git a/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb new file mode 100644 index 000000000..5bebd8a67 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb @@ -0,0 +1,42 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/stmt-1/ l- ## s- +-- =/op-1/ l- ## 0 +-- =/first-1/ l- ## 0 +-- =/second-1/ l- ## 0 +-- =/stmt-2/ l- ## s- +-- =/op-2/ l- ## 0 +-- =/first-2/ l- ## 0 +-- =/second-2/ l- ## 0 +-- =/third-2/ l- ## 0 + +--%cov: --level=stmt\+decision +-- =/stmt-1/ l- ## s- +-- =/op-1/ l- ## 0 +-- =/first-1/ l- ## 0 +-- =/second-1/ l- ## 0 +-- =/stmt-2/ l- ## s- +-- =/op-2/ l- ## 0 +-- =/first-2/ l- ## 0 +-- =/second-2/ l- ## 0 +-- =/third-2/ l- ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/stmt-1/ l- ## s- +-- =/op-1/ l- ## 0 +-- =/first-1/ l- ## 0 +-- =/second-1/ l- ## 0 +-- =/stmt-2/ l- ## s- +-- =/op-2/ l- ## 0 +-- =/first-2/ l- ## 0 +-- =/second-2/ l- ## 0 +-- =/third-2/ l- ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb new file mode 100644 index 000000000..9305d0195 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_1 (Idx) -- # first + and then -- # op + Cond_1'Length /= 0 -- # second + and then -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb new file mode 100644 index 000000000..dabe1f5b9 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb new file mode 100644 index 000000000..e5cc0a19f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_First_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb new file mode 100644 index 000000000..6d414087f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb new file mode 100644 index 000000000..78e859bef --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + (Cond_1 (Idx) -- # first + and then -- # op + Cond_1'Length /= 0) -- # second + or else -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb new file mode 100644 index 000000000..d9d5c816a --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (3) = True); + Assert (Eval (4) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb new file mode 100644 index 000000000..504ba7ccf --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Third is +begin + Assert (Eval (2) = True); + Assert (Eval (3) = True); + Assert (Eval (4) = False); +end Test_First_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb new file mode 100644 index 000000000..e6da51c96 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (2) = True); + Assert (Eval (4) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb new file mode 100644 index 000000000..188c5134a --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_Array_Current.Cond (Idx) -- # first + and then -- # op + Cond_Array_Current.Cond'Length /= 0 -- # second + and then -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb new file mode 100644 index 000000000..dabe1f5b9 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb new file mode 100644 index 000000000..e5cc0a19f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_First_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb new file mode 100644 index 000000000..6d414087f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb new file mode 100644 index 000000000..a91e3ce31 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_1 (Idx) -- # first + and then -- # op + Cond_2 (Idx) -- # second + and then -- # op + Cond_1'Length /= 0 -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb new file mode 100644 index 000000000..dabe1f5b9 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb new file mode 100644 index 000000000..685210dbb --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Second is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_First_Second; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## 0 +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb new file mode 100644 index 000000000..74d04868b --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Second is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Second; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## 0 +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/extra.opt b/testsuite/tests/M716-023-constant-conditions/extra.opt new file mode 100644 index 000000000..a6d8c9c4c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD testing support of constant conditions, implemented post 7.0.3 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/M716-023-constant-conditions/src/assert.adb b/testsuite/tests/M716-023-constant-conditions/src/assert.adb new file mode 100644 index 000000000..075669142 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (X : Boolean) is +begin + if not X then + raise Program_Error; + end if; +end Assert; diff --git a/testsuite/tests/M716-023-constant-conditions/src/assert.ads b/testsuite/tests/M716-023-constant-conditions/src/assert.ads new file mode 100644 index 000000000..ab78e4405 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/src/assert.ads @@ -0,0 +1 @@ +procedure Assert (X : Boolean); diff --git a/testsuite/tests/M716-023-constant-conditions/src/ops.ads b/testsuite/tests/M716-023-constant-conditions/src/ops.ads new file mode 100644 index 000000000..0ab93ed51 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/src/ops.ads @@ -0,0 +1,24 @@ +package Ops is + subtype Cond_Index is Natural range 1 .. 4; + type Cond_Array is array (Cond_Index) of Boolean; + Cond_1 : constant Cond_Array := (True, False, True, False); + Cond_2 : constant Cond_Array := (True, True, False, False); + + type Cond_Array_Option (Available : Boolean) is record + case Available is + when False => + null; + when True => + Cond : Cond_Array; + end case; + end record; + + Cond_Array_Unavailable : aliased Cond_Array_Option := + (Available => False); + Cond_Array_Available : aliased Cond_Array_Option := + (Available => True, Cond => Cond_1); + Cond_Array_Current : access Cond_Array_Option := + Cond_Array_Available'Access; + + function Eval (Idx : Cond_Index) return Boolean; +end Ops; diff --git a/testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb b/testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb new file mode 100644 index 000000000..a791a6a85 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb @@ -0,0 +1,33 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Exceptions; +with Ada.Text_IO; use Ada.Text_IO; + +with Strict_Head; +procedure Show_Whether_Local (Var_Name : String) is + use Ada.Exceptions; + + function Is_Local_Var (S : Unbounded_String) return Boolean is + R : Boolean; + begin + if To_String (Strict_Head (S, 2)) = "_L" then -- # evalA + R := True; -- # true + else + R := False; -- # false + end if; + return R; -- # ret + exception + when E : others => + declare + Name : constant String := Exception_Name (E); -- # exc + Msg : constant String := Exception_Message (E); -- # exc + begin + Put_Line ("Got exception: " & Name & "(" & Msg & ")"); -- # exc + end; + raise; -- # exc + end Is_Local_Var; + +begin + if Is_Local_Var (To_Unbounded_String (Var_Name)) then -- # evalD + Put_Line ("local"); -- # true + end if; +end Show_Whether_Local; diff --git a/testsuite/tests/M724-035-eh-warnings/src/strict_head.adb b/testsuite/tests/M724-035-eh-warnings/src/strict_head.adb new file mode 100644 index 000000000..3be38c288 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/strict_head.adb @@ -0,0 +1,11 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +function Strict_Head + (S : Unbounded_String; Len : Positive) return Unbounded_String +is +begin + if Length (S) < Len then + raise Constraint_Error; + end if; + return Head (S, Len); +end Strict_Head; diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_both.adb b/testsuite/tests/M724-035-eh-warnings/src/test_both.adb new file mode 100644 index 000000000..51fe28333 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_both.adb @@ -0,0 +1,13 @@ +with Show_Whether_Local; +procedure Test_Both is +begin + Show_Whether_Local ("_Local"); + Show_Whether_Local ("Global"); +end Test_Both; + +--# show_whether_local.adb +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /ret/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_exc.adb b/testsuite/tests/M724-035-eh-warnings/src/test_exc.adb new file mode 100644 index 000000000..52a67659d --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_exc.adb @@ -0,0 +1,17 @@ +with Show_Whether_Local; +with Ada.Text_IO; use Ada.Text_IO; +procedure Test_Exc is +begin + Show_Whether_Local ("x"); + raise Program_Error with "expected C_E"; +exception + when Constraint_Error => + Put_Line ("got expected exception"); +end Test_Exc; + +--# show_whether_local.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /ret/ l- ## s- +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_glob.adb b/testsuite/tests/M724-035-eh-warnings/src/test_glob.adb new file mode 100644 index 000000000..00ca91ebb --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_glob.adb @@ -0,0 +1,16 @@ +with Show_Whether_Local; +procedure Test_Glob is +begin + Show_Whether_Local ("_Global"); +end Test_Glob; + +--# show_whether_local.adb +-- /evalA/ l! ## dT- +-- /evalD/ l! ## d! +-- /true/ l- ## s- +-- /false/ l+ ## 0 +-- /ret/ l+ ## 0 +-- /exc/ l- ## s- +-- +-- %opts: --trace-mode=src +-- =/evalD/ l! ## dT- diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb b/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb new file mode 100644 index 000000000..35e306b10 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb @@ -0,0 +1,11 @@ +with Show_Whether_Local; +procedure Test_Loc is +begin + Show_Whether_Local ("_Local"); +end Test_Loc; +--# show_whether_local.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /ret/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/M724-035-eh-warnings/test.opt b/testsuite/tests/M724-035-eh-warnings/test.opt new file mode 100644 index 000000000..e0e4e6687 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +native,!RTS_ZFP diff --git a/testsuite/tests/M724-035-eh-warnings/test.py b/testsuite/tests/M724-035-eh-warnings/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/M726-018-trace-exec-check/bar.adb b/testsuite/tests/M726-018-trace-exec-check/bar.adb new file mode 100644 index 000000000..bcd771f66 --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/bar.adb @@ -0,0 +1,31 @@ +with Foo; + +procedure Bar is + + function Fibo (N : Natural) return Natural is + + function Helper (Step, N1, N2 : Natural) return Natural is + begin + if Step >= N then + return N1; + else + return Helper(Step + 1, N2, N1 + N2); + end if; + end Helper; + + begin + return Helper (0, 0, 1); + end Fibo; + + Fibo_Ref : constant array (Natural range <>) of Natural := + (0, 1, 1, 2, 3, 5, 8, 13, 21); + +begin + Foo; + + for N in Fibo_Ref'Range loop + if Fibo (N) /= Fibo_Ref (N) then + raise Program_Error; + end if; + end loop; +end Bar; diff --git a/testsuite/tests/M726-018-trace-exec-check/foo.adb b/testsuite/tests/M726-018-trace-exec-check/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/M726-018-trace-exec-check/test.opt b/testsuite/tests/M726-018-trace-exec-check/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/M726-018-trace-exec-check/test.py b/testsuite/tests/M726-018-trace-exec-check/test.py new file mode 100644 index 000000000..007be7545 --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/test.py @@ -0,0 +1,111 @@ +from collections import namedtuple +import os +import shutil + +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import ( + exename_for, + exepath_to, + tracename_for, + gprbuild, + gprfor, + xrun, + xcov, +) + +# Work in a subdirectory +wd = Wdir(subdir="tmp_") + +gpr = gprfor(mains=["foo.adb", "bar.adb"], srcdirs=[".."]) + +# Executable used to generate the reference trace +expected_program = exename_for("foo") + +# Executable that is different +unexpected_program = exename_for("bar") + +# Executable that is corrupted +corrupted_program = exename_for("foo-corrupted") + +# Real name for the executable used by the trace, convenient for substituing +# other executables still keeping the original one. +program_name = exename_for("program") +program_path = exepath_to("program") +trace_name = tracename_for("program") + +# Prepare the test material +gprbuild(project=gpr) + +expected_timestamp = (os.stat(expected_program).st_mtime,) * 2 +unexpected_timestamp = (expected_timestamp[0] + 10,) * 2 + +shutil.copy(expected_program, corrupted_program) + +# Add a 'A' byte to expected_program, and a 'B' byte to the corrupted_program. +# This way, they will have the same size, but a different checksum. +with open(expected_program, "ab") as f: + f.write(b"\x00") +with open(corrupted_program, "ab") as f: + f.write(b"\x01") + +# Generate the reference trace +shutil.copy(expected_program, program_name) +os.utime(program_name, expected_timestamp) +xrun(program_path) + +# Actually run the tests. +Case = namedtuple("Case", "program timestamp expect_warning label") +for case in ( + Case( + expected_program, + expected_timestamp, + False, + "GOOD filesize, timestamp, checksum", + ), + Case( + expected_program, + unexpected_timestamp, + True, + "GOOD program, checksum; BAD timestamp", + ), + Case( + unexpected_program, + expected_timestamp, + True, + "GOOD timestamp, checksum; BAD program", + ), + Case( + corrupted_program, + expected_timestamp, + True, + "GOOD program, timestamp; BAD checksum", + ), +): + shutil.copy(case.program, program_name) + os.utime(program_name, case.timestamp) + + process = xcov( + "coverage -P{} -c stmt -a report {}".format(gpr, trace_name), + err="log.err", + register_failure=False, + ) + + xcov_warned = contents_of("log.err").startswith("warning: executable file") + + def expected_repr(expected): + return "expected" if expected else "unexpected" + + thistest.fail_if( + xcov_warned != case.expect_warning, + "{} ({})".format( + ( + "Warnings expected, got no one" + if case.expect_warning + else "Expected no warnings, but got one" + ), + case.label, + ), + ) + +thistest.result() diff --git a/testsuite/tests/MA08-031/src/f.adb b/testsuite/tests/MA08-031/src/f.adb new file mode 100644 index 000000000..d97b8b76e --- /dev/null +++ b/testsuite/tests/MA08-031/src/f.adb @@ -0,0 +1,8 @@ +function F (A, B, C, D : Boolean) return Boolean is +begin + if (A and then B) or (C or D) then + return True; + else + return False; + end if; +end; diff --git a/testsuite/tests/MA08-031/test.opt b/testsuite/tests/MA08-031/test.opt new file mode 100644 index 000000000..a3304d764 --- /dev/null +++ b/testsuite/tests/MA08-031/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov map-routines" diff --git a/testsuite/tests/MA08-031/test.py b/testsuite/tests/MA08-031/test.py new file mode 100644 index 000000000..f6980fe96 --- /dev/null +++ b/testsuite/tests/MA08-031/test.py @@ -0,0 +1,10 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import gprfor, gprbuild, xcov + + +Wdir("tmp_") +gprbuild(gprfor(["f.adb"], srcdirs="../src"), gargs="-c") +xcov(["map-routines", "--scos=obj/f.ali", "obj/f.o"], out="xcov.out") +thistest.fail_if(match("warning:", "xcov.out"), "no labeling warning expected") +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb new file mode 100644 index 000000000..5783f905d --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb @@ -0,0 +1,6 @@ +package body Counters is + procedure Bump (X : in out Natural) is + begin + X := X + 1; + end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads new file mode 100644 index 000000000..265d960ea --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads @@ -0,0 +1,5 @@ +package Counters is + Nthen, Nelse : Natural := 0; + + procedure Bump (X : in out Natural); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb new file mode 100644 index 000000000..9d971aa4a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb @@ -0,0 +1,20 @@ +with Support, Counters; use Support; + +procedure Falseonly is + + function Pos (X : Integer) return Boolean is + begin + if X > 0 then -- # test + Counters.Bump (Counters.Nthen); -- # then + return True; -- # then + else + Counters.Bump (Counters.Nelse); -- # else + return False; -- # else + end if; + end Pos; + +begin + Assert (Pos (-1) = False); + Assert (Counters.Nthen = 0); + Assert (Counters.Nelse = 1); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb new file mode 100644 index 000000000..7b04287db --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb @@ -0,0 +1,14 @@ +with Falseonly; + +procedure Test_Falseonly is +begin + Falseonly; +end; + +--# falseonly.adb +-- /test/ l! ## dT- +-- /then/ l. ## 0 +-- /else/ l+ ## 0 + +-- %cov: --non-coverable +-- =/then/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb new file mode 100644 index 000000000..ba3a0de93 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb @@ -0,0 +1,10 @@ +with Truefalse; +procedure Test_Truefalse is +begin + Truefalse; +end; + +--# truefalse.adb +-- /test/ l+ ## 0 +-- /then/ l+ ## 0 +-- /else/ l+ ## 0 diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb new file mode 100644 index 000000000..6f15c64e7 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb @@ -0,0 +1,14 @@ +with Trueonly; + +procedure Test_Trueonly is +begin + Trueonly; +end; + +--# trueonly.adb +-- /test/ l! ## dF- +-- /then/ l+ ## 0 +-- /else/ l. ## 0 + +-- %cov: --non-coverable +-- =/else/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb new file mode 100644 index 000000000..4ead33d1a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb @@ -0,0 +1,21 @@ +with Support, Counters; use Support; + +procedure Truefalse is + + function Pos (X : Integer) return Boolean is + begin + if X > 0 then -- # test + Counters.Bump (Counters.Nthen); -- # then + return True; -- # then + else + Counters.Bump (Counters.Nelse); -- # else + return False; -- # else + end if; + end Pos; + +begin + Assert (Pos (1) = True); + Assert (Pos (-1) = False); + Assert (Counters.Nthen = 1); + Assert (Counters.Nelse = 1); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb new file mode 100644 index 000000000..a6a38c337 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb @@ -0,0 +1,20 @@ +with Support, Counters; use Support; + +procedure Trueonly is + + function Pos (X : Integer) return Boolean is + begin + if X > 0 then -- # test + Counters.Bump (Counters.Nthen); -- # then + return True; -- # then + else + Counters.Bump (Counters.Nelse); -- # else + return False; -- # else + end if; + end Pos; + +begin + Assert (Pos (1) = True); + Assert (Counters.Nthen = 1); + Assert (Counters.Nelse = 0); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt new file mode 100644 index 000000000..22baf97a0 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt @@ -0,0 +1 @@ +bin-traces,!CARGS_O1,!CARGS_gnatn DEAD diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/extra.opt b/testsuite/tests/MB05-039-not-coverable/extra.opt new file mode 100644 index 000000000..aaa8c50c6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/extra.opt @@ -0,0 +1 @@ +src-traces XFAIL S711-049: src-traces and assertion/check policy diff --git a/testsuite/tests/MB05-039-not-coverable/src/state.adb b/testsuite/tests/MB05-039-not-coverable/src/state.adb new file mode 100644 index 000000000..02d6368b4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/src/state.adb @@ -0,0 +1,10 @@ +package body State is + procedure Tick is + begin + Ticks := Ticks + 1; + end; + procedure Dtick is + begin + Dticks := Dticks + 1; + end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/src/state.ads b/testsuite/tests/MB05-039-not-coverable/src/state.ads new file mode 100644 index 000000000..b802e2606 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/src/state.ads @@ -0,0 +1,15 @@ +package State is + + -- Liveness ticks, expected to click + + Ticks : Integer := 0; + pragma Volatile (Ticks); + + -- Death ticks, expected never to clisk + + Dticks : Integer := 0; + pragma Volatile (Dticks); + + procedure Tick; + procedure Dtick; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb new file mode 100644 index 000000000..2124edd7b --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support; + +procedure Check_Local_NRNF is + + type My_Range is range -100 .. -1; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := -12; +begin + Assert (My_Processor.F(X) = Integer(X-4) + My_Factor); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb new file mode 100644 index 000000000..67ff5e5b6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support; + +procedure Check_Local_NRPF is + + type My_Range is range -100 .. -1; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := -12; +begin + Assert (My_Processor.F(X) = Integer(X-4) + 2*My_Factor); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb new file mode 100644 index 000000000..acd743dc4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support; + +procedure Check_Local_PRNF is + + type My_Range is range 1 .. 100; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := 12; +begin + Assert (My_Processor.F(X) = Integer(X+1) + My_Factor); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb new file mode 100644 index 000000000..ce14d35bd --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support; + +procedure Check_Local_PRPF is + + type My_Range is range 1 .. 100; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := 12; +begin + Assert (My_Processor.F(X) = Integer(X+1) + 2*My_Factor); +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb new file mode 100644 index 000000000..536483927 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb @@ -0,0 +1,19 @@ +with Check_Local_NRNF; + +procedure Test_Local_NRNF is +begin + Check_Local_NRNF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- /xpos/ l- ## s- + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb new file mode 100644 index 000000000..85793fb5b --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb @@ -0,0 +1,19 @@ +with Check_Local_NRPF; + +procedure Test_Local_NRPF is +begin + Check_Local_NRPF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- /xpos/ l- ## s- + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb new file mode 100644 index 000000000..834fa47dd --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb @@ -0,0 +1,19 @@ +with Check_Local_PRNF; + +procedure Test_Local_PRNF is +begin + Check_Local_PRNF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- /xneg/ l- ## s- + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb new file mode 100644 index 000000000..5f8e7f497 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb @@ -0,0 +1,19 @@ +with Check_Local_PRPF; + +procedure Test_Local_PRPF is +begin + Check_Local_PRPF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- /xneg/ l- ## s- + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb new file mode 100644 index 000000000..45255c745 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb @@ -0,0 +1,15 @@ +with Values_MRMF; + +procedure Test_Values_MRMF is +begin + Values_MRMF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l+ ## 0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb new file mode 100644 index 000000000..005f5b073 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb @@ -0,0 +1,18 @@ +with Values_NRNF; + +procedure Test_Values_NRNF is +begin + Values_NRNF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l- ## s- +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb new file mode 100644 index 000000000..54097190a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb @@ -0,0 +1,18 @@ +with Values_NRPF; + +procedure Test_Values_NRPF is +begin + Values_NRPF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l- ## s- +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb new file mode 100644 index 000000000..289ba99c7 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb @@ -0,0 +1,18 @@ +with Values_PRNF; + +procedure Test_Values_PRNF is +begin + Values_PRNF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /xneg/ l- ## s- +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb new file mode 100644 index 000000000..03e13dbe4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb @@ -0,0 +1,18 @@ +with Values_PRPF; + +procedure Test_Values_PRPF is +begin + Values_PRPF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /xneg/ l- ## s- +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb new file mode 100644 index 000000000..35b6ce0ae --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb @@ -0,0 +1,32 @@ +with State; use State; + +-- A few items of note here: +-- +-- * The X > 0 test can be always True (or False) for some definitions +-- of Value_T. The compiler would normally optimize this away in instances +-- on request (-O1), even with -fpreserve-control-flow. +-- +-- * The tests on formal "in" parameters are always known at +-- at compiler time for a given instance, and the compiler +-- takes advantage of that to simplify early, even at O0. + +package body Values is + function F (X : in Value_T) return Integer Is + Adjusted_Factor : Integer; + V : Integer; + begin + if X > 0 then -- # test_x + V := Integer (X + 1); -- # xpos + else + V := Integer (X - 4); -- # xneg + end if; + + if Factor > 0 then -- # test_factor + Adjusted_Factor := Factor * 2; -- # fpos + else + Adjusted_Factor := Factor; -- # fneg + end if; + + return V + Adjusted_Factor; -- # stmt + end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads new file mode 100644 index 000000000..7d4be5df4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads @@ -0,0 +1,7 @@ +generic + type Value_T is range <>; + Factor : in Integer; + +package Values is + function F (X : in Value_T) return Integer; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb new file mode 100644 index 000000000..ba0089852 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb @@ -0,0 +1,25 @@ +with Support, Values; use Support; + +package body Values_MRMF is + + type My_P_Range is range 1 .. 100; + My_P_Factor : constant := 3; + + package My_Processor_P is new + Values (Value_T => My_P_Range, Factor => My_P_Factor); + + type My_N_Range is range -100 .. -1; + My_N_Factor : constant := -3; + + package My_Processor_N is new + Values (Value_T => My_N_Range, Factor => My_N_Factor); + + procedure Check is + XP : My_P_Range := 12; + XN : My_N_Range := -12; + begin + Assert (My_Processor_P.F(XP) = Integer(XP+1) + 2*My_P_Factor); + Assert (My_Processor_N.F(XN) = Integer(XN-4) + My_N_Factor); + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads new file mode 100644 index 000000000..d3a1afd9e --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads @@ -0,0 +1,8 @@ + +-- expose a sanity check subprogram operating on two instantiations of the +-- generic Values package with Mixed Ranges (MR, both positive and negative) +-- and Mixed Factors (MF) + +package Values_MRMF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb new file mode 100644 index 000000000..753af3198 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support; + +package body Values_NRNF is + + type My_Range is range -100 .. -1; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := -12; + begin + Assert (My_Processor.F(X) = Integer(X-4) + My_Factor); + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads new file mode 100644 index 000000000..732a4ae90 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads @@ -0,0 +1,3 @@ +package Values_NRNF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb new file mode 100644 index 000000000..dd6b12a21 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support; + +package body Values_NRPF is + + type My_Range is range -100 .. -1; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := -12; + begin + Assert (My_Processor.F(X) = Integer(X-4) + 2*My_Factor); + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads new file mode 100644 index 000000000..f5410660a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads @@ -0,0 +1,3 @@ +package Values_NRPF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb new file mode 100644 index 000000000..7bf04b286 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support; + +package body Values_PRNF is + + type My_Range is range 1 .. 100; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := 12; + begin + Assert (My_Processor.F(X) = Integer(X+1) + My_Factor); + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads new file mode 100644 index 000000000..a18f1bcc1 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads @@ -0,0 +1,8 @@ + +-- expose a sanity check subprogram operating on an instantiation of the +-- generic Values package with a Positive Range (PR) and a Negative Factor +-- (NF) + +package Values_PRNF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb new file mode 100644 index 000000000..cd0e788d4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support; + +package body Values_PRPF is + + type My_Range is range 1 .. 100; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := 12; + begin + Assert (My_Processor.F(X) = Integer(X+1) + 2*My_Factor); + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads new file mode 100644 index 000000000..ace56c6b8 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads @@ -0,0 +1,8 @@ + +-- expose a sanity check subprogram operating on an instantiation of the +-- generic Values package with a Positive Range (PR) and a Positive Factor +-- (PF) + +package Values_PRPF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb new file mode 100644 index 000000000..1eca6801d --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb @@ -0,0 +1,18 @@ +with Values, Support; use Values, Support; + +procedure Test_Values is + V : Integer; +begin + Assert (One = 1.0); + + V := Value_Of (X => 15); + Assert (V = 15); + + Latch (V => 12); + V := Value_Of_X; + Assert (V = 12); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /out/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb new file mode 100644 index 000000000..5d6b9e1fe --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb @@ -0,0 +1,40 @@ +with State; use State; + +package body Values is + + function One return Float is + begin + return 1.0; -- # stmt + exception + when Constraint_Error => + Dtick; -- # out + return 2.0; -- # out + end; + + function Value_Of (X : Integer) return Integer is + begin + return X; -- # stmt + exception + when Constraint_Error => + return 0; -- # out + when Program_Error => + return 66; -- # out + end; + + function Value_Of_X return Integer is + begin + return X; -- # stmt + exception + when others => return 50; -- # out + end; + + procedure Latch (V : Integer) is + begin + Tick; -- # stmt + begin + X := V; -- # stmt + exception + when Program_Error => Dtick; -- # out + end; + end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads new file mode 100644 index 000000000..2c2ec120a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads @@ -0,0 +1,9 @@ +package Values is + X : Integer := 1; + + function One return Float; + + procedure Latch (V : Integer); + function Value_Of (X : Integer) return Integer; + function Value_Of_X return Integer; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt new file mode 100644 index 000000000..6399c1943 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt @@ -0,0 +1,3 @@ +7.0.2 DEAD 7.0 doesn't perform handler elimination reliably +7.0.3 DEAD 7.0 doesn't perform handler elimination reliably +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb new file mode 100644 index 000000000..d481181b6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb @@ -0,0 +1,133 @@ +with State; use State; + +package body IFS is + + -- Expose various cases with if statements controled by constant guards, + -- which are simplified early-on by the compiler front-end. + + -- Whether a code-less "if XX then" stmt becomes coverable itself + -- depends on whether it dominates coverable statements. + + procedure If_F_Var_Last is + begin + Tick; -- # reach + if GF then -- # out + Dtick; -- # out + end if; + end; + + procedure If_F_Cmp_Last is + begin + Tick; -- # reach + if GT = False then -- # out + Dtick; -- # out + end if; + end; + + procedure If_F_Var_Not_Last is + begin + Tick; -- # reach + if GF then -- # test + Dtick; -- # out + end if; + Tick; -- # reach + end; + + procedure If_F_Cmp_Not_Last is + begin + Tick; -- # reach + if GT = False then -- # test + Dtick; -- # out + end if; + Tick; -- # reach + end; + + -- + + procedure Ifelse_F_Var_Last is + begin + Tick; -- # reach + if GF then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + end; + + procedure Ifelse_F_Cmp_Last is + begin + Tick; -- # reach + if GT = False then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + end; + + procedure Ifelse_F_Var_Not_Last is + begin + Tick; -- # reach + if GF then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + Tick; -- # reach + end; + + procedure Ifelse_F_Cmp_Not_Last is + begin + Tick; -- # reach + if GT = False then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + Tick; -- # reach + end; + + -- + + procedure Ifelse_T_Var_Last is + begin + Tick; -- # reach + if GT then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + end; + + procedure Ifelse_T_Cmp_Last is + begin + Tick; -- # reach + if GT = True then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + end; + + procedure Ifelse_T_Var_Not_Last is + begin + Tick; -- # reach + if GT then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + Tick; -- # reach + end; + + procedure Ifelse_T_Cmp_Not_Last is + begin + Tick; -- # reach + if GT = True then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + Tick; -- # reach + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads new file mode 100644 index 000000000..407db93c3 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads @@ -0,0 +1,20 @@ +package IFS is + + GT : constant Boolean := True; + GF : constant Boolean := False; + + procedure If_F_Var_Last; + procedure If_F_Cmp_Last; + procedure If_F_Var_Not_Last; + procedure If_F_Cmp_Not_Last; + + procedure Ifelse_F_Var_Last; + procedure Ifelse_F_Cmp_Last; + procedure Ifelse_F_Var_Not_Last; + procedure Ifelse_F_Cmp_Not_Last; + + procedure Ifelse_T_Var_Last; + procedure Ifelse_T_Cmp_Last; + procedure Ifelse_T_Var_Not_Last; + procedure Ifelse_T_Cmp_Not_Last; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb new file mode 100644 index 000000000..c413bf51a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb @@ -0,0 +1,46 @@ +with Ifs, State; use Ifs, State; +with Support; use Support; + +procedure Test_Ifs is +begin + If_F_Var_Last; + Assert (Ticks = 1); + + If_F_Cmp_Last; + Assert (Ticks = 2); + + If_F_Var_Not_Last; + Assert (Ticks = 4); + + If_F_Cmp_Not_Last; + Assert (Ticks = 6); + + Ifelse_F_Var_Last; + Assert (Ticks = 8); + + Ifelse_F_Cmp_Last; + Assert (Ticks = 10); + + Ifelse_F_Var_Not_Last; + Assert (Ticks = 13); + + Ifelse_F_Cmp_Not_Last; + Assert (Ticks = 16); + + Ifelse_T_Var_Last; + Assert (Ticks = 18); + + Ifelse_T_Cmp_Last; + Assert (Ticks = 20); + + Ifelse_T_Var_Not_Last; + Assert (Ticks = 23); + + Ifelse_T_Cmp_Not_Last; + Assert (Ticks = 26); +end; + +--# ifs.adb +-- /reach/ l+ ## 0 +-- /out/ l0 ## s0 +-- /test/ l+ ## 0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb new file mode 100644 index 000000000..888f7a0a9 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb @@ -0,0 +1,50 @@ +with State; use State; + +-- # out is used to mark statements that we expect to be taken out always. +-- # opt_out is for statements taken out only when optimizing. + +package body Misc is + + -- A local library level subprogram just unused. + + procedure Dump_Old_Log; + + procedure Dump_Old_Log is + begin + Dtick; -- # opt_out + end; + + -- A local subprogram which only gets called in a section guarded by a + -- constant False test: + + procedure Dump_Debug_Log is + begin + Dtick; -- # opt_out + end; + + procedure Check_State is + + -- A nested subprogram just unused + + procedure Crash_Me is + begin + Dtick; -- # out + end; + + -- A nested subprogram called in a guarded false + -- sequence of statements + + procedure Maybe_Crash_Me is + begin + Dtick; -- # out + end; + + begin + Tick; -- # stmt + if GF then -- # out + Dump_Debug_Log; -- # out + Maybe_Crash_Me; -- # out + end if; + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads new file mode 100644 index 000000000..e665e9029 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads @@ -0,0 +1,5 @@ +package Misc is + GF : constant Boolean := False; + + procedure Check_State; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb new file mode 100644 index 000000000..a20bd4961 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb @@ -0,0 +1,18 @@ +with Support, Misc, State; use Support, Misc; + +procedure Test_Misc is +begin + Check_State; + Assert (State.Ticks = 1); + Assert (State.Dticks = 0); +end; + +--# misc.adb +-- /stmt/ l+ ## 0 +-- /out/ l0 ## s0 + +-- %cargs: !-O1 +-- /opt_out/ l- ## s- + +-- %cargs: -O1 +-- /opt_out/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst new file mode 100644 index 000000000..6dbe56d4e --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst @@ -0,0 +1,12 @@ +Exercise statements within eliminated subprograms + +Verify that statements within eliminated subprograms are reported +non-coverable on request. Check + +* private library level or local subprograms not called at all + +* private library level or local subprograms called only in a + conditional section guarded by a constant False test + + + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb new file mode 100644 index 000000000..57eeefa72 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb @@ -0,0 +1,13 @@ +with State, Support, Values; use State, Support, Values; + +procedure Test_Values is +begin + Assert (Abs_Of(5) = 5); + Assert (Abs_Of(-2) = 2); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /neg/ l+ ## 0 +-- /out/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb new file mode 100644 index 000000000..754621e56 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb @@ -0,0 +1,19 @@ +with State; use State; + +package body Values is + + function Abs_Of (X : Integer) return Integer is + + begin + if X > 0 then -- # stmt + return X; -- # xpos + else + return -X; -- # xneg + end if; + + -- We always return prior to this point + + Dtick; -- # out + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads new file mode 100644 index 000000000..bccc61f00 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads @@ -0,0 +1,6 @@ + +package Values is + + function Abs_Of (X : Integer) return Integer; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.adb b/testsuite/tests/MB15-040-if-cst/src/monitor.adb new file mode 100644 index 000000000..1ad4d8e9e --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.adb @@ -0,0 +1,14 @@ + +package body Monitor is + + Moncalls : Natural := 0; + pragma Volatile (Moncalls); + + procedure Op is + begin + if Count_Ops then -- # called + Opcount := Opcount + 1; -- # cond-stmt + end if; + Moncalls := Moncalls + 1; -- # called + end; +end; diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.ads b/testsuite/tests/MB15-040-if-cst/src/monitor.ads new file mode 100644 index 000000000..3e20fa134 --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.ads @@ -0,0 +1,7 @@ + +package Monitor is + Count_Ops : constant Boolean := False; + Opcount : Natural := 0; + + procedure Op; +end; diff --git a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb new file mode 100644 index 000000000..e4a954430 --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb @@ -0,0 +1,17 @@ +with Monitor; +procedure Test_Ifcst_Call is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 1; + Monitor.Op; +end; + +--# monitor.adb +-- /called/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /cond-stmt/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /cond-stmt/ l- ## s- diff --git a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb new file mode 100644 index 000000000..10dd454ee --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb @@ -0,0 +1,16 @@ +with Monitor; +procedure Test_Ifcst_None is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 1; +end; + +--# monitor.adb +-- /called/ l- ## s- +-- +--%opts: --trace-mode=bin +-- /cond-stmt/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /cond-stmt/ l- ## s- diff --git a/testsuite/tests/MB15-040-if-cst/test.opt b/testsuite/tests/MB15-040-if-cst/test.opt new file mode 100644 index 000000000..e06a09849 --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD constant conditions, compiler change on 2013-11-18, not in 7.0.3 +7.2.2 DEAD constant conditions, compiler change on 2013-11-18, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/MB15-040-if-cst/test.py b/testsuite/tests/MB15-040-if-cst/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/foo.adb b/testsuite/tests/MB15-041-verbose-open-crc32/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/MB15-041-verbose-open-crc32/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.opt b/testsuite/tests/MB15-041-verbose-open-crc32/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.py b/testsuite/tests/MB15-041-verbose-open-crc32/test.py new file mode 100644 index 000000000..63ac31221 --- /dev/null +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.py @@ -0,0 +1,121 @@ +from binascii import crc32 +import os.path +import re + +from e3.os.fs import unixpath + +from SUITE.cutils import Wdir, FatalError, lines_of +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + thistest, + tracename_for, + xcov, + xrun, +) + +tmp_ = Wdir("tmp_") + +GPR_FILE = gprfor("foo.adb", srcdirs="..") +EXE_FILE = exepath_to("foo") +TRACE_FILE = tracename_for("foo") +SCOS_FILES = [ + os.path.join("obj", "foo.ali"), +] + +CWD_LINE_PREFIX = "CWD = " +LOG_OPEN_RE = re.compile( + r'\[GNATCOV\.MISC\] --- notice: open "(?P[^"]+)"' + r" \(CRC32 = 0x(?P[0-9a-f]{8})\)" +) + + +def list_to_text(items): + return ( + "".join(" - {}\n".format(item) for item in items) + or " \n" + ) + + +def check_same_files(expected, found): + expected = {unixpath(path) for path in expected} + found = {unixpath(path) for path in found} + thistest.fail_if( + expected != found, + "Expecting:\n{}" + "but found:\n{}".format(list_to_text(expected), list_to_text(found)), + ) + + +def check_logging(log_file, expected_files): + """ + Check that `log_file` contains correct checksums for all `expected_files`, + and only for them. + """ + # Rebase all input path to the temporary directory. + base = os.getcwd() + expected_files = {os.path.join(base, path) for path in expected_files} + + checksums = {} + gnatcov_cwd = None + + # First, get GNATcov's CWD and all the CRC32 checksums from the verbose + # logging. + for line in lines_of(log_file): + if line.startswith(CWD_LINE_PREFIX): + gnatcov_cwd = line[len(CWD_LINE_PREFIX) :].strip() + + else: + m = LOG_OPEN_RE.match(line) + if not m: + continue + + thistest.stop_if( + not gnatcov_cwd, + FatalError("Got a checksum before GNATcov's CWD"), + ) + + filepath = os.path.join(gnatcov_cwd, m.group("file")) + checksums[filepath] = int(m.group("crc32"), 16) + + # Check that these checksums match the set of files. + check_same_files(expected_files, set(checksums.keys())) + + # Then check that each checksum is valid. + for filename, checksum in checksums.items(): + with open(filename, "rb") as fp: + expected_checksum = crc32(fp.read()) & 0xFFFFFFFF + thistest.fail_if( + expected_checksum != checksum, + f"Bad checksum for {filename}:" + f" expecting CRC32={expected_checksum:#08x}," + f" but found {checksum:#08x}", + ) + + +# Build the project +gprbuild(GPR_FILE) + +# Produce some trace and check the verbose logging. +xrun( + ["--verbose", "--level=stmt+mcdc", "-P{}".format(GPR_FILE), EXE_FILE], + out="xcov-run.log", +) +check_logging("xcov-run.log", [EXE_FILE] + SCOS_FILES) + +# Then compute the coverage report and check again the verbose logging. +xcov( + [ + "coverage", + "--verbose", + "--level=stmt+mcdc", + "--annotate=report", + "-P{}".format(GPR_FILE), + TRACE_FILE, + ], + out="xcov-coverage.log", +) +check_logging("xcov-coverage.log", [EXE_FILE, TRACE_FILE] + SCOS_FILES) + +thistest.result() diff --git a/testsuite/tests/MB19-016-subprogram-less-code/foo.c b/testsuite/tests/MB19-016-subprogram-less-code/foo.c new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/MB19-016-subprogram-less-code/foo.c @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/MB19-016-subprogram-less-code/test.opt b/testsuite/tests/MB19-016-subprogram-less-code/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/MB19-016-subprogram-less-code/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/MB19-016-subprogram-less-code/test.py b/testsuite/tests/MB19-016-subprogram-less-code/test.py new file mode 100644 index 000000000..d299e4fd2 --- /dev/null +++ b/testsuite/tests/MB19-016-subprogram-less-code/test.py @@ -0,0 +1,64 @@ +""" +Check that we can compute object coverage .xcov reports from +a binary which contains asm-level debug line info not attached +to any subprogram from the dwarf standpoint. +""" + +import os.path + +from e3.fs import rm + +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + thistest, + tracename_for, + xcov, + xrun, +) + +rm("tmp_", recursive=True) +tmp_ = Wdir("tmp_") + +# We are producing object coverage reports and need fine control over the +# compilation options here +_cargs = {"scovcargs": False, "suitecargs": False} + +# First stage: compile the C source code to assembly. We want no debug +# information at this stage. +gpr_stage1 = gprfor( + "foo.c", + prjid="stage1", + srcdirs="..", + exedir=".", + main_cargs="-g0 -save-temps", + langs=("C",), +) +gprbuild(gpr_stage1, gargs="-c", **_cargs) + +# Second stage: assemble to object code with debug information relative to the +# assembly. +gpr_stage2 = gprfor( + "foo.s", + prjid="stage2", + srcdirs="obj", + exedir=".", + main_cargs="-g", + langs=("Asm",), +) +gprbuild(gpr_stage2, **_cargs) + +gnatcov_flags = ["-P", gpr_stage2, "--level=branch"] + +# Run and compute code coverage. +xrun(gnatcov_flags + [exepath_to("foo")]) +xcov(["coverage"] + gnatcov_flags + ["--annotate=xcov", tracename_for("foo")]) + +thistest.fail_if( + not os.path.exists(os.path.join("obj", "foo.s.xcov")), + "There is no XCOV report for foo.s", +) + +thistest.result() diff --git a/testsuite/tests/MC05-011-ref-executable/src/app.adb b/testsuite/tests/MC05-011-ref-executable/src/app.adb new file mode 100644 index 000000000..e2a65643e --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/app.adb @@ -0,0 +1,6 @@ +with Assert, Double, Bump; + +procedure App is +begin + null; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/assert.adb b/testsuite/tests/MC05-011-ref-executable/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/bump.adb b/testsuite/tests/MC05-011-ref-executable/src/bump.adb new file mode 100644 index 000000000..48e8439eb --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/bump.adb @@ -0,0 +1,4 @@ +procedure Bump (X : in out Integer) is +begin + X := X + 1; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/double.adb b/testsuite/tests/MC05-011-ref-executable/src/double.adb new file mode 100644 index 000000000..15e28161b --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/double.adb @@ -0,0 +1,4 @@ +procedure Double (X : in out Integer) is +begin + X := X * 2; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/test_bump.adb b/testsuite/tests/MC05-011-ref-executable/src/test_bump.adb new file mode 100644 index 000000000..0940bcec8 --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/test_bump.adb @@ -0,0 +1,8 @@ +with Assert, Bump; + +procedure Test_Bump is + X : Integer := 12; +begin + Bump (X); + Assert (X = 13); +end; diff --git a/testsuite/tests/MC05-011-ref-executable/test.py b/testsuite/tests/MC05-011-ref-executable/test.py new file mode 100644 index 000000000..01a61e3aa --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/test.py @@ -0,0 +1,52 @@ +""" +Check that statements from a unit entirely untested are reported uncovered +regardless of the visibility on the unit object code in the analysis scope. +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import exepath_to, gprfor, xcov + + +Wdir("tmp_") + + +# Build App which encloses two units (bump and double), and a unit test for +# just the bump unit. Then run the unit test. +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=["../src"], mains=["test_bump.adb", "app.adb"] + ) + ), + covlevel="stmt", + mains=["test_bump"], + extra_coverage_args=["--annotate=report"], + scos=["obj/bump", "obj/double"], +) + + +# Do stmt coverage analysis providing scos for all the units and the unit test +# trace. Check that we have diagnostics of absence of coverage on the elements +# part of the untested unit with or without an additional --exec. + + +def trycov(exec_args): + p = xcov(xcov_args + exec_args) + thistest.fail_if( + not re.search(r"double.adb:\d+:\d+: statement not executed", p.out), + "Missing stmt violation on double.adb, exec_args: %s" % str(exec_args), + ) + + +trycov(exec_args=[]) + +# --exec does not make sense (and is not allowed) in source trace mode +if thistest.options.trace_mode == "bin": + trycov(exec_args=["--exec=%s" % exepath_to("app")]) + +thistest.result() diff --git a/testsuite/tests/N106-020-tempfiles/src/actions.adb b/testsuite/tests/N106-020-tempfiles/src/actions.adb new file mode 100644 index 000000000..46b90c0bc --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/src/actions.adb @@ -0,0 +1,33 @@ +package body Actions is + + Value : Integer := 0; + pragma Volatile (Value); + + procedure Process_Positive (X : Integer) is + begin + if X <= 0 then -- # test_pos + raise Constraint_Error; -- # unreach_pos + end if; + Value := Value + X; -- # do_pos + end; + + procedure Process_Negative (X : Integer) is + begin + if X >= 0 then -- # test_neg + raise Constraint_Error; -- # unreach_neg + end if; + Value := Value + X; -- # do_neg + end; + + procedure Process_Zero (X : Integer) is + begin + if X /= 0 then -- # test_zero + raise Constraint_Error; -- # unreach_zero + end if; + end; + + procedure Process (X : Integer; Action : Action_Access) is + begin + Action.all (X); + end; +end; diff --git a/testsuite/tests/N106-020-tempfiles/src/actions.ads b/testsuite/tests/N106-020-tempfiles/src/actions.ads new file mode 100644 index 000000000..bf5e169f9 --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/src/actions.ads @@ -0,0 +1,11 @@ +package Actions is + + type Action_Access is access procedure (X : Integer); + + procedure Process_Positive (X : Integer); + procedure Process_Negative (X : Integer); + procedure Process_Zero (X : Integer); + + procedure Process (X : Integer; Action : Action_Access); + +end; diff --git a/testsuite/tests/N106-020-tempfiles/src/test_tags.adb b/testsuite/tests/N106-020-tempfiles/src/test_tags.adb new file mode 100644 index 000000000..1a9b18784 --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/src/test_tags.adb @@ -0,0 +1,29 @@ +with Actions; use Actions; + +-- Basic test for the %tags support in expectations, allowing +-- conditional sections of expectation statements depending on +-- the testsuite discriminants. + +procedure Test_Tags is +begin + Process (5, Process_Positive'Access); + Process (-5, Process_Negative'Access); + Process (0, Process_Zero'Access); +end; + +-- ALL is expected to always be part of the suite discriminants +-- NEVER is expected never to be there + +--# actions.adb + +-- %tags: ALL +-- /unreach_pos/ l- ## s- + +-- %tags: !NEVER +-- /unreach_neg/ l- ## s- + +-- %tags: ALL, !NEVER +-- /unreach_zero/ l- ## s- + +-- %tags: NEVER +-- /check/ l- ## s- diff --git a/testsuite/tests/N106-020-tempfiles/test.py b/testsuite/tests/N106-020-tempfiles/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/N107-020-dhtml/foo.adb b/testsuite/tests/N107-020-dhtml/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/N107-020-dhtml/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/N107-020-dhtml/test.py b/testsuite/tests/N107-020-dhtml/test.py new file mode 100644 index 000000000..ae6cd1f24 --- /dev/null +++ b/testsuite/tests/N107-020-dhtml/test.py @@ -0,0 +1,43 @@ +""" +Check that --annotate=dthml succeeds and produces something, with a project +file or without. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +def check(label, scos): + """ + Check that --annotate=dhtml produces something, using -P or --scos. + """ + wd = Wdir(subdir=f"tmp_{label}") + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["foo.adb"], srcdirs=[".."]) + ), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["--annotate=dhtml", "--output-dir=dhtml-report"], + scos=scos, + ) + + index = os.path.join("dhtml-report", "index.html") + thistest.fail_if( + not os.path.isfile(index) or os.path.getsize(index) == 0, + f"missing or empty {index} for {label}", + ) + + wd.to_homedir() + + +check("scos", scos=["obj/foo"]) +check("prj", scos=None) + +thistest.result() diff --git a/testsuite/tests/N107-029-crc32-validity/foo.adb b/testsuite/tests/N107-029-crc32-validity/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/N107-029-crc32-validity/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/N107-029-crc32-validity/test.opt b/testsuite/tests/N107-029-crc32-validity/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/N107-029-crc32-validity/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/N107-029-crc32-validity/test.py b/testsuite/tests/N107-029-crc32-validity/test.py new file mode 100644 index 000000000..c1479699f --- /dev/null +++ b/testsuite/tests/N107-029-crc32-validity/test.py @@ -0,0 +1,68 @@ +""" +This test sanity checks that the CRC32 value computed by gnatcov for the +executable file for an example program, stored in excution trace headers, +matches the CRC32 value computed by a reference implementation on the same +executable. The Python library is used as the reference implementation. +""" + +import binascii + +from SUITE.context import thistest +from SUITE.cutils import lines_of, Wdir +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +# Work in a subdirectory +wd = Wdir(subdir="tmp_") + +# Generate the program executable, then run it to get an execution trace: +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) +gprbuild(project=gpr) + +program_path = exepath_to("foo") +trace_name = tracename_for("foo") + +xrun(program_path) + +# Fetch the CRC32 value computed by gnatcov and stored in the trace header as: +# +# Tag : EXEC_FILE_CRC32 +# Data : +xcov(["dump-trace", trace_name], out="trace.dump") +trace_dump = [line.strip() for line in lines_of("trace.dump")] + +tag_line_no = trace_dump.index("Tag : EXEC_FILE_CRC32") +data_line = trace_dump[tag_line_no + 2] + +# Get the decimal checksum +prefix = "Data : " +thistest.stop_if( + not data_line.startswith(prefix), + ValueError( + 'Invalid trace text dump (invalid "Data" line): {!r}'.format(data_line) + ), +) +gnatcov_checksum = int(data_line[len(prefix) :]) + +# And then compare it with the one Python computes +with open(program_path, "rb") as f: + # binascii.crc32 returns a signed 32-bit integer. Make it unsigned to be + # consistent with GNATcoverage. + expected_checksum = binascii.crc32(f.read()) & 0xFFFFFFFF +thistest.stop_if( + gnatcov_checksum != expected_checksum, + ValueError( + "CRC32 mismatch: {} (expected) != {} (got)".format( + expected_checksum, gnatcov_checksum + ) + ), +) + +thistest.result() diff --git a/testsuite/tests/N129-008-c-constant-conditions/src/foo.c b/testsuite/tests/N129-008-c-constant-conditions/src/foo.c new file mode 100644 index 000000000..2d9e9cddb --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/src/foo.c @@ -0,0 +1,10 @@ +#include "foo.h" + +int +foo (int a, int b) +{ + if (((long int) (sizeof (long long))) < 0) // # cond-expr + return a; // # cond-true + else + return b; // # cond-false +} diff --git a/testsuite/tests/N129-008-c-constant-conditions/src/foo.h b/testsuite/tests/N129-008-c-constant-conditions/src/foo.h new file mode 100644 index 000000000..8f101cdc7 --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/src/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +extern int foo (int a, int b); + +#endif diff --git a/testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c b/testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c new file mode 100644 index 000000000..e68af6451 --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c @@ -0,0 +1,31 @@ +#include "foo.h" + +int +main (void) +{ + foo (1, 2); + return 0; +} + +//# foo.c + +// For binary traces, as the if condition is constant, the then part will +// be no code, and there won't be a decision obligation. + +//%opts: --trace-mode=bin +// /cond-expr/ l+ ## 0 +// /cond-true/ l. ## 0 +// /cond-false/ l+ ## 0 + +//%opts: --trace-mode=src +// /cond-true/ l- ## s- +// /cond-false/ l+ ## 0 + +//%cov: --level=stmt %opts: --trace-mode=src +// =/cond-expr/ l+ ## 0 + +//%cov: --level=stmt\+decision %opts: --trace-mode=src +// =/cond-expr/ l! ## dT- + +//%cov: --level=stmt\+(uc_)?mcdc %opts: --trace-mode=src +// =/cond-expr/ l! ## dT- diff --git a/testsuite/tests/N129-008-c-constant-conditions/test.opt b/testsuite/tests/N129-008-c-constant-conditions/test.opt new file mode 100644 index 000000000..a00b47c87 --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD test relies on a compiler change introduced on 2014-01, not in 7.0.3 +7.2.2 DEAD test relies on a compiler change introduced on 2014-01, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N129-008-c-constant-conditions/test.py b/testsuite/tests/N129-008-c-constant-conditions/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/N203-040-same-c-basename/src/a/foo.h b/testsuite/tests/N203-040-same-c-basename/src/a/foo.h new file mode 100644 index 000000000..22cefa132 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/src/a/foo.h @@ -0,0 +1,8 @@ +static int +foo (int a) +{ + if (a) // # toplev-stmt + return a + 1; // # toplev-true + else + return a - 1; // # toplev-false +} diff --git a/testsuite/tests/N203-040-same-c-basename/src/b/foo.h b/testsuite/tests/N203-040-same-c-basename/src/b/foo.h new file mode 100644 index 000000000..2f225bf99 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/src/b/foo.h @@ -0,0 +1,8 @@ +static int +other_foo (int a) +{ + if (a) // # other-stmt + return 2 * a; // # other-true + else + return a / 2; // # other-false +} diff --git a/testsuite/tests/N203-040-same-c-basename/src/test_foo.c b/testsuite/tests/N203-040-same-c-basename/src/test_foo.c new file mode 100644 index 000000000..7a1d12ce3 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/src/test_foo.c @@ -0,0 +1,24 @@ +#include "a/foo.h" +#include "b/foo.h" + +int +main (void) +{ + volatile int a = 1; // # dummy + a = foo (a) * other_foo (a); // # dummy + + return 0; // # dummy +} + +//# test_foo.c +// /dummy/ l+ ## 0 + +//# +a/foo.h +// /toplev-stmt/ l+ ## 0 +// /toplev-true/ l+ ## 0 +// /toplev-false/ l- ## s- + +//# +b/foo.h +// /other-stmt/ l+ ## 0 +// /other-true/ l+ ## 0 +// /other-false/ l- ## s- diff --git a/testsuite/tests/N203-040-same-c-basename/test.opt b/testsuite/tests/N203-040-same-c-basename/test.opt new file mode 100644 index 000000000..a49fdb1c9 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N203-040-same-c-basename/test.py b/testsuite/tests/N203-040-same-c-basename/test.py new file mode 100644 index 000000000..16cdeae96 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/test.py @@ -0,0 +1,61 @@ +""" +Test that there is no issue with C sources that have the same basename. +""" + +import os.path + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +# This must work for source coverage... +TestCase(category=CAT.stmt).run() + +# ... and for object coverage, too! +tmp_ = Wdir("tmp_") + +gprfile = gprfor("test_foo.c", srcdirs=os.path.join("..", "src")) +exefile = exepath_to("test_foo") +tracefile = tracename_for("test_foo") +logfile = "xcov-coverage.log" + +routinesfile = "routines.list" +with open(routinesfile, "w") as f: + for symbol in ("main", "foo", "other_foo"): + f.write("{}\n".format(symbol)) + +gprbuild(gprfile) +xrun(exefile) + +# If this test fail, we expect this is because the following command will emit +# warnings about various source files having the same base name. +xcov( + [ + "coverage", + "-P{}".format(gprfile), + "--level=insn", + "--annotate=xcov", + "--routines=@{}".format(routinesfile), + tracefile, + ], + out=logfile, +) + +thistest.fail_if( + os.path.getsize(logfile) > 0, + "xcov standard output not empty ({}):\n--\n{}".format( + logfile, contents_of(logfile) + ), +) + +thistest.result() diff --git a/testsuite/tests/N204-011-precond-aspects/src/foo.adb b/testsuite/tests/N204-011-precond-aspects/src/foo.adb new file mode 100644 index 000000000..3c1a66d82 --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/foo.adb @@ -0,0 +1,8 @@ +package body Foo is + + function Bar (L, R : Integer) return Integer is + begin + return L - R; + end Bar; + +end Foo; diff --git a/testsuite/tests/N204-011-precond-aspects/src/foo.ads b/testsuite/tests/N204-011-precond-aspects/src/foo.ads new file mode 100644 index 000000000..c2012b4c0 --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/foo.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Foo is + + function Bar (L, R : Integer) return Integer + with Pre => + L > 100 -- # decision-1 + and then R < 100; -- # decision-2 + +end Foo; diff --git a/testsuite/tests/N204-011-precond-aspects/src/log.adb b/testsuite/tests/N204-011-precond-aspects/src/log.adb new file mode 100644 index 000000000..082ac3f1c --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/log.adb @@ -0,0 +1,5 @@ +procedure Log (I : Integer) is + pragma Unreferenced (I); +begin + null; +end; diff --git a/testsuite/tests/N204-011-precond-aspects/src/test_foo.adb b/testsuite/tests/N204-011-precond-aspects/src/test_foo.adb new file mode 100644 index 000000000..e16d1f46f --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/test_foo.adb @@ -0,0 +1,12 @@ +with Foo; +with Log; + +procedure Test_Foo is + +begin + Log (Foo.Bar (110, 70)); +end Test_Foo; + +--# foo.ads +-- =/decision-1/ l! ## dF- +-- =/decision-2/ l- ## 0 diff --git a/testsuite/tests/N204-011-precond-aspects/test.opt b/testsuite/tests/N204-011-precond-aspects/test.opt new file mode 100644 index 000000000..925ef8d60 --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD relies on compiler support for 2012 Aspects, not all in 7.0.3 +7.2.2 DEAD relies on compiler support for 2012 Aspects, not all in 7.2.2 +src-traces XFAIL S606-037: src-traces and contracts +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N204-011-precond-aspects/test.py b/testsuite/tests/N204-011-precond-aspects/test.py new file mode 100644 index 000000000..5c679f78e --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/test.py @@ -0,0 +1,11 @@ +""" +Test that there is no static analysis issue with Pre aspects (preconditions). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/N321-039-disas-wrapping/foo.s b/testsuite/tests/N321-039-disas-wrapping/foo.s new file mode 100644 index 000000000..e510c949c --- /dev/null +++ b/testsuite/tests/N321-039-disas-wrapping/foo.s @@ -0,0 +1,14 @@ +.cpu cortex-m4 +.arch armv7e-m +.fpu fpv4-sp-d16 +.file "foo.c" +.text +.align 2 +.syntax unified +.thumb +.thumb_func +.type _start, %function +_start: +mov r0, r1 +mov r0, r1 +.size _start, .-_start diff --git a/testsuite/tests/N321-039-disas-wrapping/test.opt b/testsuite/tests/N321-039-disas-wrapping/test.opt new file mode 100644 index 000000000..11de9f8f2 --- /dev/null +++ b/testsuite/tests/N321-039-disas-wrapping/test.opt @@ -0,0 +1,2 @@ +arm-elf +ALL DEAD diff --git a/testsuite/tests/N321-039-disas-wrapping/test.py b/testsuite/tests/N321-039-disas-wrapping/test.py new file mode 100644 index 000000000..ee3f705af --- /dev/null +++ b/testsuite/tests/N321-039-disas-wrapping/test.py @@ -0,0 +1,38 @@ +""" +Check that the 'dump-cfg' and 'disassemble-insn-properties' subcommands handle +well instructions at the end of the address space. +""" + +from e3.os.process import Run + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + +tmp_ = Wdir("tmp_") + +# We want to link the code (4 bytes) at the end of the address space, so get +# the correct upper address depending on the architecture. + +address = (2**32 if "32bits" in thistest.options.tags else 2**64) - 4 + +exefile = "foo" +log_file = "gcc.log" +p = Run( + [ + "arm-eabi-gcc", + "-o", + exefile, + "../foo.s", + "-nostdlib", + f"-Ttext={hex(address)}", + ], + output=log_file, +) +thistest.fail_if(p.status != 0, "gcc failed:\n" + contents_of(log_file)) + +for subcmd in ("dump-cfg", "disassemble-insn-properties"): + # As long as GNATcov do not crash/hangs, everything is fine! + xcov([subcmd, exefile, "_start"]) + +thistest.result() diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/foo.adb b/testsuite/tests/N321-045-ppc-disas-large-input/foo.adb new file mode 100644 index 000000000..b14199355 --- /dev/null +++ b/testsuite/tests/N321-045-ppc-disas-large-input/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (I : Integer) return Integer is + begin + if I <= 1 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; +begin + if Fact (6) /= 0 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/test.opt b/testsuite/tests/N321-045-ppc-disas-large-input/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/N321-045-ppc-disas-large-input/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/test.py b/testsuite/tests/N321-045-ppc-disas-large-input/test.py new file mode 100644 index 000000000..4de3f4861 --- /dev/null +++ b/testsuite/tests/N321-045-ppc-disas-large-input/test.py @@ -0,0 +1,18 @@ +""" +Check that the PPC disassembler (the Disassemble_Insn procedure) handles well +input that is larger than a single instruction. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, gprbuild, xcov + +tmp_ = Wdir("tmp_") + +gprfile = gprfor(["foo.adb"], srcdirs="..") +gprbuild(gprfile) + +# As long as GNATcov do not crash/hangs, everything is fine! +xcov(["disassemble-insn-properties", "foo", "_ada_foo"]) + +thistest.result() diff --git a/testsuite/tests/N411-046-asm-consolidation/p.c b/testsuite/tests/N411-046-asm-consolidation/p.c new file mode 100644 index 000000000..f89e9a25e --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/p.c @@ -0,0 +1,5 @@ +void +p (void) +{ + return; +} diff --git a/testsuite/tests/N411-046-asm-consolidation/test.c b/testsuite/tests/N411-046-asm-consolidation/test.c new file mode 100644 index 000000000..82a82bc31 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/test.c @@ -0,0 +1,8 @@ +extern void p (void); + +int +main (void) +{ + p (); + return 0; +} diff --git a/testsuite/tests/N411-046-asm-consolidation/test.opt b/testsuite/tests/N411-046-asm-consolidation/test.opt new file mode 100644 index 000000000..c194a3994 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/test.opt @@ -0,0 +1,2 @@ +bin-traces +ALL DEAD Binary traces specific testcase diff --git a/testsuite/tests/N411-046-asm-consolidation/test.py b/testsuite/tests/N411-046-asm-consolidation/test.py new file mode 100644 index 000000000..a68ae4a1b --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/test.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +""" +Check that if GNATcov is provided twice the same trace file, it consolidates as +expected an assembly-defined procedure assembled with -g (it has a compile +unit DIE, but no subprogram DIE in the DWARF info). +""" + +import os.path +import shutil + +from OCOV.tc import TestCase +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, tracename_for + + +test_drivers = { + "test": {"p.s": ["-g"]}, +} + +coverage_expectations = { + # There is only one "p" routine and we should consolidate them: we expect + # only one "+" covered "p" routine. + "p": {"-": 0, "!": 0, "+": 1}, +} + +# Generate a project just so that we use the C toolchain in order to generate +# the assembly sources (-save-temps). Make sure we do not generate debug info +# in the assembly code (-g0). +tmp = Wdir("tmp_asm") +prj = gprfor(mains=[], srcdirs=[".."], langs=["C"]) +gprbuild(prj, gargs=["-c", "-u", "p.c"], extracargs=["-save-temps", "-g0"]) +tmp.to_homedir() + +# Run the consolidation check +tmp = Wdir("tmp_") +shutil.copy(os.path.join("..", "test.c"), "test.c") +shutil.copy(os.path.join("..", "tmp_asm", "obj", "p.s"), "p.s") + +TestCase( + test_drivers, + coverage_expectations, + extra_xcov_args=[tracename_for("test")], +).run() +thistest.result() diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/assert.adb b/testsuite/tests/N423-015-exempt-in-separate/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb b/testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb new file mode 100644 index 000000000..1b90a70d2 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb @@ -0,0 +1,12 @@ + +separate (Pck) +procedure Check (Valid : Boolean) is +begin + if Valid then + Valids := Valids + 1; -- # valids + else + pragma Annotate (Xcov, Exempt_On, "Invalids unexpected"); -- # invalids + Invalids := Invalids + 1; -- # invalids_inc + pragma Annotate (Xcov, Exempt_Off); -- # invalids + end if; +end; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/pck.adb b/testsuite/tests/N423-015-exempt-in-separate/src/pck.adb new file mode 100644 index 000000000..9c1d9baac --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/pck.adb @@ -0,0 +1,3 @@ +package body Pck is + procedure Check (Valid : Boolean) is separate; +end Pck; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/pck.ads b/testsuite/tests/N423-015-exempt-in-separate/src/pck.ads new file mode 100644 index 000000000..8fd9a0a99 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/pck.ads @@ -0,0 +1,4 @@ +package Pck is + procedure Check (Valid : Boolean); + Valids, Invalids : Natural := 0; +end Pck; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb b/testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb new file mode 100644 index 000000000..b1659d4ff --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb @@ -0,0 +1,14 @@ +with Pck, Assert; + +procedure Test_I is +begin + Pck.Check (Valid => False); + Assert (Pck.Valids = 0); + Assert (Pck.Invalids = 1); +end; + +--# pck.adb + +--# pck-check.adb +-- /valids/ l- ## s- +-- /invalids/ l# ## x0 diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb b/testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb new file mode 100644 index 000000000..280e84bf9 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb @@ -0,0 +1,15 @@ +with Pck, Assert; + +procedure Test_V is +begin + Pck.Check (Valid => True); + Assert (Pck.Valids = 1); + Assert (Pck.Invalids = 0); +end; + +--# pck.adb + +--# pck-check.adb +-- /valids/ l+ ## 0 +-- /invalids/ l* ## x+ +-- /invalids_inc/ l= ## Xs- diff --git a/testsuite/tests/N423-015-exempt-in-separate/test.opt b/testsuite/tests/N423-015-exempt-in-separate/test.opt new file mode 100644 index 000000000..fb7c5a771 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD ticket exposed a compiler issue fixed on 2014-04, not in 7.0.3 +7.2.2 DEAD ticket exposed a compiler issue fixed on 2014-04, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N423-015-exempt-in-separate/test.py b/testsuite/tests/N423-015-exempt-in-separate/test.py new file mode 100644 index 000000000..11e55638b --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c b/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c new file mode 100644 index 000000000..935c9b727 --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c @@ -0,0 +1,28 @@ +#include + +void +write_error (const char *) +{ +} + +// Dummy implementation of assert that expands to multiple statements. +#define assert(expr) \ + ({ \ + int _result = expr; \ + if (!_result) \ + write_error ("assertion failure: " #expr); \ + }) + +int +main (int argc, char *argv[]) +{ + volatile int a = 0; // # stmt-simple + assert (a == 0); // # stmt-assert + return 0; // # stmt-simple +} + +//# test_assert.c +// /stmt-simple/ l+ ## 0 +// /stmt-assert/ l! ## s- +// Given the current state of the technology, one of the expanded +// statements is expected not to be covered. See NB17-025. diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt new file mode 100644 index 000000000..55366c383 --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt @@ -0,0 +1,2 @@ +!bin-traces DEAD Coverage for C supported only with binary traces +windows DEAD This test variant has platform-specific expectations diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py new file mode 100644 index 000000000..473958a65 --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs="-no-integrated-cpp", + category=CAT.stmt, +).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c b/testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c new file mode 100644 index 000000000..7d4111e0d --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c @@ -0,0 +1,15 @@ +#include + +int +main (int argc, char *argv[]) +{ + volatile int a = 0; // # stmt-simple + assert (a == 0); // # stmt-assert + return 0; // # stmt-simple +} + +//# test_assert.c +// /stmt-simple/ l+ ## 0 +// /stmt-assert/ l+ ## 0 +// On Windows, "assert" is usually implemented as a macro which, after +// expansion, yields a single statement. diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt new file mode 100644 index 000000000..91ba4f86e --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt @@ -0,0 +1,2 @@ +!native DEAD Test relies on host standard header files +!windows DEAD This test variant has platform-specific expectations diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py new file mode 100644 index 000000000..473958a65 --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs="-no-integrated-cpp", + category=CAT.stmt, +).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-tern-folding/src/foo.c b/testsuite/tests/N429-018-c-tern-folding/src/foo.c new file mode 100644 index 000000000..624a59003 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/foo.c @@ -0,0 +1,11 @@ +#include "foo.h" + +int +foo (int a, int b) +{ + /* Currently, the following expression is folded by GCC's C frontend into: + !(a == 0) || (b == 0) + Because of this, SCOs won't match sources and thus reported violations + will not be the expected ones. */ + return (a == 0) ? (b == 0) : 1; // # decision +} diff --git a/testsuite/tests/N429-018-c-tern-folding/src/foo.h b/testsuite/tests/N429-018-c-tern-folding/src/foo.h new file mode 100644 index 000000000..8f101cdc7 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +extern int foo (int a, int b); + +#endif diff --git a/testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c new file mode 100644 index 000000000..7dcd99fe6 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c @@ -0,0 +1,17 @@ +#include "foo.h" + +int +main (int argc, char *argv[]) +{ + foo (0, 0); + foo (1, 0); + return 0; +} + +//# foo.c +//%cov: --level=stmt +// =/decision/ l+ ## 0 +//%cov: --level=stmt\+decision +// =/decision/ l+ ## 0 +//%cov: --level=stmt\+(uc_)?mcdc +// =/decision/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c new file mode 100644 index 000000000..0f0886342 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c @@ -0,0 +1,20 @@ +#include "foo.h" + +int +main (int argc, char *argv[]) +{ + foo (0, 0); + return 0; +} + +//# foo.c +//%cov: --level=stmt +// =/decision/ l+ ## 0 +//%cov: --level=stmt\+decision %opts: --trace-mode=bin +// =/decision/ l! ## d! +//%cov: --level=stmt\+decision %opts: --trace-mode=src +// =/decision/ l! ## dF- +//%cov: --level=stmt\+(uc_)?mcdc %opts: --trace-mode=bin +// =/decision/ l! ## d! +//%cov: --level=stmt\+(uc_)?mcdc %opts: --trace-mode=src +// =/decision/ l! ## dF- diff --git a/testsuite/tests/N429-018-c-tern-folding/test.opt b/testsuite/tests/N429-018-c-tern-folding/test.opt new file mode 100644 index 000000000..5bd7238f9 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/test.opt @@ -0,0 +1 @@ +!native DEAD test relies on host standard header files diff --git a/testsuite/tests/N429-018-c-tern-folding/test.py b/testsuite/tests/N429-018-c-tern-folding/test.py new file mode 100644 index 000000000..2f452a6da --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/test.py @@ -0,0 +1,13 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs="-no-integrated-cpp", + category=cat, + ).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-void-ternary/src/foo.c b/testsuite/tests/N429-018-c-void-ternary/src/foo.c new file mode 100644 index 000000000..fd00ea014 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/foo.c @@ -0,0 +1,16 @@ +#include "foo.h" +#include "helpers.h" + +int +foo (int cond) +{ + if (identity (cond)) // # if-expr + bar1 (); // # if-then + else + bar2 (); // # if-else + + (identity (cond)) ? bar1 () : bar2 (); // # tern-void-stmt + (identity (cond)) ? identity (cond) : identity (!cond); // # tern-int-stmt + + return ((identity (cond)) ? bar1 () : bar2 ()), 1; // # tern-void-expr +} diff --git a/testsuite/tests/N429-018-c-void-ternary/src/foo.h b/testsuite/tests/N429-018-c-void-ternary/src/foo.h new file mode 100644 index 000000000..8be1505e5 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +extern int foo (int cond); + +#endif diff --git a/testsuite/tests/N429-018-c-void-ternary/src/helpers.c b/testsuite/tests/N429-018-c-void-ternary/src/helpers.c new file mode 100644 index 000000000..f62c5ba4b --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/helpers.c @@ -0,0 +1,9 @@ +void +bar1 (void) +{ +} + +void +bar2 (void) +{ +} diff --git a/testsuite/tests/N429-018-c-void-ternary/src/helpers.h b/testsuite/tests/N429-018-c-void-ternary/src/helpers.h new file mode 100644 index 000000000..785fa787c --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/helpers.h @@ -0,0 +1,9 @@ +#ifndef HELPERS_H +#define HELPERS_H + +extern int identity (int cond); /* from libsupport. */ + +extern void bar1 (void); +extern void bar2 (void); + +#endif diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c new file mode 100644 index 000000000..caa7e38bf --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c @@ -0,0 +1,19 @@ +#include "foo.h" +#include "helpers.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "foo". */ + if (identity (0)) + foo (0); + return 0; +} + +//# foo.c +// /if-expr/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- +// /tern-void-stmt/ l- ## s-, s-, s- +// /tern-int-stmt/ l- ## s- +// /tern-void-expr/ l- ## s- diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c new file mode 100644 index 000000000..00ca4c517 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c @@ -0,0 +1,16 @@ +#include "foo.h" + +int +main (void) +{ + foo (0); + return 0; +} + +//# foo.c +// /if-expr/ l+ ## 0 +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 +// /tern-void-stmt/ l! ## s- +// /tern-int-stmt/ l+ ## 0 +// /tern-void-expr/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c new file mode 100644 index 000000000..7c49b5990 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c @@ -0,0 +1,16 @@ +#include "foo.h" + +int +main (void) +{ + foo (1); + return 0; +} + +//# foo.c +// /if-expr/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- +// /tern-void-stmt/ l! ## s- +// /tern-int-stmt/ l+ ## 0 +// /tern-void-expr/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c new file mode 100644 index 000000000..fb2fa4b5d --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c @@ -0,0 +1,17 @@ +#include "foo.h" + +int +main (void) +{ + foo (0); + foo (1); + return 0; +} + +//# foo.c +// /if-expr/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 +// /tern-void-stmt/ l+ ## 0 +// /tern-int-stmt/ l+ ## 0 +// /tern-void-expr/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-void-ternary/test.opt b/testsuite/tests/N429-018-c-void-ternary/test.opt new file mode 100644 index 000000000..5ea0df450 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD test requires compiler change from 2014-04, not in 7.0.3 +7.2.2 DEAD test requires compiler change from 2014-04, not in 7.2.2 +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N429-018-c-void-ternary/test.py b/testsuite/tests/N429-018-c-void-ternary/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/N429-020-loop-on-line-ada/foo.adb b/testsuite/tests/N429-020-loop-on-line-ada/foo.adb new file mode 100644 index 000000000..202138979 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line-ada/foo.adb @@ -0,0 +1,24 @@ +procedure Foo is + type Void_PP is access Integer; + + N : Integer := 0; + P : Void_PP; + pragma Volatile (P); +begin + N := 1; + while N < 32 and then p.all /= 0 loop N := N + 1; end loop; + + null; + + -- Note: we used to have here: + + -- if N = 32 then + -- N := N - 1; + -- end if; + + -- But this is eliminated entirely at -O1 (because the value of + -- N is never used), so use a NULL statement instead so that we + -- don't get an additional junk warning for no cond branch found + -- for the IF statement. + +end Foo; diff --git a/testsuite/tests/N429-020-loop-on-line-ada/test.opt b/testsuite/tests/N429-020-loop-on-line-ada/test.opt new file mode 100644 index 000000000..a3304d764 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line-ada/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov map-routines" diff --git a/testsuite/tests/N429-020-loop-on-line-ada/test.py b/testsuite/tests/N429-020-loop-on-line-ada/test.py new file mode 100644 index 000000000..a2d878217 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line-ada/test.py @@ -0,0 +1,7 @@ +import os.path + +from SCOV.map import MapChecker +from SUITE.tutils import thistest + +MapChecker(["foo.adb"], alis=[os.path.join("obj", "foo.ali")]).run() +thistest.result() diff --git a/testsuite/tests/N429-020-loop-on-line/main.c b/testsuite/tests/N429-020-loop-on-line/main.c new file mode 100644 index 000000000..564499405 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line/main.c @@ -0,0 +1,17 @@ +#define MAX_FD 32 +#define NULL ((void *) 0) + +int +main (int argc, char *argv[]) +{ + // void** p = &get_api_data()->file_desc[STDERR_FILENO+1]; + void **p; + int n = 0; + for (n = 1; n < MAX_FD && *p != NULL; n++, p++) + ; + if (n == MAX_FD) + { + n = -1; + } + return n; +} diff --git a/testsuite/tests/N429-020-loop-on-line/test.opt b/testsuite/tests/N429-020-loop-on-line/test.opt new file mode 100644 index 000000000..7d9cc4034 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD test with map-routines diff --git a/testsuite/tests/N429-020-loop-on-line/test.py b/testsuite/tests/N429-020-loop-on-line/test.py new file mode 100644 index 000000000..72ca70f3f --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line/test.py @@ -0,0 +1,7 @@ +import os.path + +from SCOV.map import MapChecker +from SUITE.tutils import thistest + +MapChecker(["main.c"], alis=[os.path.join("obj", "main.c.gli")]).run() +thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/extra.opt b/testsuite/tests/N430-005-c-static-inline/extra.opt new file mode 100644 index 000000000..0182653a4 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c new file mode 100644 index 000000000..671c373ee --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c @@ -0,0 +1,9 @@ +#include "foo.h" + +int * +bar_false (void) +{ + get_process (1); // # bar-false + set_current (identity (0)); // # bar-false + return process_current (); // # bar-false +} diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c new file mode 100644 index 000000000..225eaae3c --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c @@ -0,0 +1,9 @@ +#include "foo.h" + +int * +bar_true (void) +{ + get_process (1); // # bar-true + set_current (identity (1)); // # bar-true + return process_current (); // # bar-true +} diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/foo.c b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.c new file mode 100644 index 000000000..c4aba3221 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.c @@ -0,0 +1,22 @@ +#include "foo.h" + +static int current = 0; +static int processes[10]; + +void +set_current (int p) +{ + current = p; // # foo-exercised +} + +int +get_current (void) +{ + return current; // # foo-exercised +} + +int * +get_process (int p) +{ + return &processes[p]; // # foo-exercised +} diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/foo.h b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.h new file mode 100644 index 000000000..2bc03f114 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.h @@ -0,0 +1,22 @@ +#ifndef FOO_H +#define FOO_H + +extern int identity (int x); /* from libsupport. */ + +extern void set_current (int p); +extern int get_current (void); +extern int *get_process (int p); + +extern int *bar_false (void); +extern int *bar_true (void); + +static inline int * +process_current (void) +{ + if (get_current ()) // # if-expr + return get_process (get_current ()); // # if-then + else + return (int *) 0; // # if-else +} + +#endif diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c new file mode 100644 index 000000000..0e1baae2c --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c @@ -0,0 +1,27 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "bar_*". */ + if (identity (0)) + { + bar_true (); + bar_false (); + } + else + return 0; +} + +//# bar_true.c +// /bar-true/ l- ## s- +//# bar_false.c +// /bar-false/ l- ## s- + +//# foo.c +// /foo-exercised/ l- ## s- + +//# foo.h +// /if-expr/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c new file mode 100644 index 000000000..1a884fd72 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c @@ -0,0 +1,24 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "bar_true". */ + if (identity (0)) + bar_true (); + bar_false (); + return 0; +} + +//# bar_true.c +// /bar-true/ l- ## s- +//# bar_false.c +// /bar-false/ l+ ## 0 + +//# foo.c +// /foo-exercised/ l+ ## 0 + +//# foo.h +// /if-expr/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c new file mode 100644 index 000000000..afd636bf0 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c @@ -0,0 +1,24 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "bar_false". */ + if (identity (0)) + bar_false (); + bar_true (); + return 0; +} + +//# bar_true.c +// /bar-true/ l+ ## 0 +//# bar_false.c +// /bar-false/ l- ## s- + +//# foo.c +// /foo-exercised/ l+ ## 0 + +//# foo.h +// /if-expr/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c new file mode 100644 index 000000000..97d75556a --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c @@ -0,0 +1,22 @@ +#include "foo.h" + +int +main (void) +{ + bar_true (); + bar_false (); + return 0; +} + +//# bar_true.c +// /bar-true/ l+ ## 0 +//# bar_false.c +// /bar-false/ l+ ## 0 + +//# foo.c +// /foo-exercised/ l+ ## 0 + +//# foo.h +// /if-expr/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/N430-005-c-static-inline/supported/test.py b/testsuite/tests/N430-005-c-static-inline/supported/test.py new file mode 100644 index 000000000..2f452a6da --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/test.py @@ -0,0 +1,13 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs="-no-integrated-cpp", + category=cat, + ).run() +thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c new file mode 100644 index 000000000..5c10f8ccc --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c @@ -0,0 +1,15 @@ +int +one_int (void) +{ +#define TYPE int +#include "foo.h" +#undef TYPE +} + +unsigned +one_unsigned (void) +{ +#define TYPE unsigned +#include "foo.h" +#undef TYPE +} diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h new file mode 100644 index 000000000..52d517fd9 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h @@ -0,0 +1,2 @@ +TYPE ret = 0; +return (TYPE) ret + 1; diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c b/testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c new file mode 100644 index 000000000..24d8d44fb --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c @@ -0,0 +1,10 @@ +extern int one_int (void); +extern unsigned one_unsigned (void); + +int +main (void) +{ + return one_unsigned () - one_int (); +} + +//# foo.c diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py new file mode 100644 index 000000000..6afa40593 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py @@ -0,0 +1,59 @@ +""" +Check that gnatcov reject SCO overlapping cases with a warning. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir(subdir="tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_foo.c"], + srcdirs=os.path.join("..", "src"), + langs=["C"], + ), + units=["foo.c"], + ), + covlevel="stmt", + mains=["test_foo"], + extra_coverage_args=["-axcov"], + tolerate_instrument_messages="unexpected SCO overlapping", +) + +# With source traces, the warning is emitted at instrumentation time, whereas +# it is emitted at coverage time with binary traces. +# +# As SCOs source locations differ for binary and source traces, we get +# different warnings. Note that the instrumentation warning is the most +# precise. + +if thistest.options.trace_mode == "src": + output_string = "gnatcov instrument output" + output_file = "instrument.log" + expected_output = ( + "!!! foo.h:1:1: unexpected SCO overlapping with SCO #1: " + "STATEMENT at foo.h:1:1-13, discarding overlapping SCO\n" + "!!! foo.h:2:1: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:1-21, discarding overlapping SCO" + ) +else: + output_string = "gnatcov coverage output" + output_file = "coverage.log" + expected_output = ( + "!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:8-20, discarding overlapping SCO" + ) + +thistest.fail_if_no_match( + output_string, expected_output, contents_of(output_file) +) + +thistest.result() diff --git a/testsuite/tests/N505-008-c99-main-return/src/test_main.c b/testsuite/tests/N505-008-c99-main-return/src/test_main.c new file mode 100644 index 000000000..9f028c342 --- /dev/null +++ b/testsuite/tests/N505-008-c99-main-return/src/test_main.c @@ -0,0 +1,7 @@ +int +main (int argc, char *argv[]) +{ + return 0; +} + +//# test_main.c diff --git a/testsuite/tests/N505-008-c99-main-return/test.opt b/testsuite/tests/N505-008-c99-main-return/test.opt new file mode 100644 index 000000000..0182653a4 --- /dev/null +++ b/testsuite/tests/N505-008-c99-main-return/test.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N505-008-c99-main-return/test.py b/testsuite/tests/N505-008-c99-main-return/test.py new file mode 100644 index 000000000..b6519cc2b --- /dev/null +++ b/testsuite/tests/N505-008-c99-main-return/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt, extracargs="-std=c99").run() +thistest.result() diff --git a/testsuite/tests/N505-026-multstmtln-nocode/src/helper.c b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.c new file mode 100644 index 000000000..16a8eb65d --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.c @@ -0,0 +1,5 @@ +void +nop (void) +{ + return; +} diff --git a/testsuite/tests/N505-026-multstmtln-nocode/src/helper.h b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.h new file mode 100644 index 000000000..000ce51b0 --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.h @@ -0,0 +1 @@ +extern void nop (void); diff --git a/testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c b/testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c new file mode 100644 index 000000000..b91509b0f --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c @@ -0,0 +1,18 @@ +#include "helper.h" + +int +check (int argc) +{ + (argc < 10) ? (void) 0 : nop (); // # tern + return 0; +} + +int +main (void) +{ + (void) check (1); + return 0; +} + +//# test_foo.c +// /tern/ sd=>l! ## s=>s-, d=>s-,dF- diff --git a/testsuite/tests/N505-026-multstmtln-nocode/test.opt b/testsuite/tests/N505-026-multstmtln-nocode/test.opt new file mode 100644 index 000000000..922d8fb08 --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD 7.0.3 required SCO support for C implemented post 7.0 (may 2014) +7.2.2 DEAD 7.2.2 required SCO support for C implemented post 7.2 (may 2014) +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N505-026-multstmtln-nocode/test.py b/testsuite/tests/N505-026-multstmtln-nocode/test.py new file mode 100644 index 000000000..64dab3c68 --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c new file mode 100644 index 000000000..9ca02dbed --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c @@ -0,0 +1,19 @@ + +/* All the runtimes we link against expose abort(), and we have it on native + platforms as well. It causes abnormal termination on these platforms + though, so we'd better use exit in this case. But exit isn't available + everywhere ... */ + +#include + +extern __attribute__ ((noreturn)) void abort (); +extern __attribute__ ((weak, noreturn)) void exit (int code); + +__attribute__ ((noinline)) void +abort_or_exit (int code) +{ + if (exit != 0) + exit (code); + else + abort (); +} diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h new file mode 100644 index 000000000..e7ba0083a --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h @@ -0,0 +1 @@ +__attribute__ ((noinline, noreturn)) void abort_or_exit (int code); diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c b/testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c new file mode 100644 index 000000000..26ef84543 --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c @@ -0,0 +1,29 @@ +#include + +__attribute__ ((noinline)) __attribute__ ((noreturn)) void +stop (int code) +{ + if (code < 0) // # stop-cond + code = -code + 1; // # stop-then + abort_or_exit (code); +} + +int +check (int code) +{ + if (code > 0) // # check-cond + code = 0; + + stop (code); +} + +int +main (int argc, char *argv[]) +{ + check (1); +} + +//# test_stop.c +// /stop-cond/ l! ## dT- +// /stop-then/ l- ## s- +// /check-cond/ l! ## dF- diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/test.opt b/testsuite/tests/N506-014-crash-on-padding-nop/test.opt new file mode 100644 index 000000000..817e5694a --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +!bin-traces DEAD Testing binary traces-specific bug +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/test.py b/testsuite/tests/N506-014-crash-on-padding-nop/test.py new file mode 100644 index 000000000..247e9585a --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/test.py @@ -0,0 +1,10 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + extracargs=["-no-integrated-cpp", "-falign-functions=32"], + category=CAT.decision, +).run() +thistest.result() diff --git a/testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c b/testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c new file mode 100644 index 000000000..a2719905d --- /dev/null +++ b/testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c @@ -0,0 +1,15 @@ +int +check (int argc) +{ + (argc < 10) ? (void) 0 : (void) (argc = argc / 2 + 1); // # tern + return argc; +} + +int +main (int argc, char *argv[]) +{ + return check (0); +} + +//# test_main.c +// /tern/ l! ## dF-, s- diff --git a/testsuite/tests/N513-004-dom-info-c-tern/test.opt b/testsuite/tests/N513-004-dom-info-c-tern/test.opt new file mode 100644 index 000000000..eebe9f4af --- /dev/null +++ b/testsuite/tests/N513-004-dom-info-c-tern/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD requires compiler change from 2014-05, not in 7.0.3 +7.2.2 DEAD requires compiler change from 2014-05, not in 7.2.2 +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N513-004-dom-info-c-tern/test.py b/testsuite/tests/N513-004-dom-info-c-tern/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/N513-004-dom-info-c-tern/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb new file mode 100644 index 000000000..cf3851287 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb @@ -0,0 +1,41 @@ + +package body Hello is + + function Get_Hello (Formal : Boolean) return String; + -- Returns Hello or Hi depending on the Formal parameter + + --------------- + -- Get_Hello -- + --------------- + + function Get_Hello (Formal : Boolean) return String is + begin + if Formal then -- # test_formal + return "Hello"; -- # formal + else + return "Hi"; -- # casual + end if; + end Get_Hello; + + procedure Process (S : String) is + Len : Integer; + pragma Volatile (Len); + begin + Len := S'Length; + end; + + --------------- + -- Say_Hello -- + --------------- + + procedure Say_Hello (Who : String; Formal : Boolean := True) is + Hello : constant String := Get_Hello (Formal); + begin + if Who = "" then -- # test_nobody + Process (Hello & "!"); -- # nobody + else + Process (Hello & " " & Who & "!"); -- # someone + end if; + end Say_Hello; + +end Hello; diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads new file mode 100644 index 000000000..1c09682ef --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads @@ -0,0 +1,3 @@ +package Hello is + procedure Say_Hello (Who : String; Formal : Boolean := True); +end Hello; diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb new file mode 100644 index 000000000..c7647d427 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb @@ -0,0 +1,14 @@ +with Hello; use Hello; + +procedure Test_Casual_Nobody is +begin + Say_Hello ("", Formal => False); +end; + +--# hello.adb +-- /test_nobody/ l! ## dF- +-- /nobody/ l+ ## 0 +-- /someone/ l- ## s- +-- /test_formal/ l! ## dT- +-- /formal/ l- ## s- +-- /casual/ l+ ## 0 diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb new file mode 100644 index 000000000..0dbf294db --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb @@ -0,0 +1,14 @@ +with Hello; use Hello; + +procedure Test_Casual_Someone is +begin + Say_Hello ("Jerome", Formal => False); +end; + +--# hello.adb +-- /test_nobody/ l! ## dT- +-- /nobody/ l- ## s- +-- /someone/ l+ ## 0 +-- /test_formal/ l! ## dT- +-- /formal/ l- ## s- +-- /casual/ l+ ## 0 diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb new file mode 100644 index 000000000..ba140c6f3 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb @@ -0,0 +1,14 @@ +with Hello; use Hello; + +procedure Test_Formal_Nobody is +begin + Say_Hello ("", Formal => True); +end; + +--# hello.adb +-- /test_nobody/ l! ## dF- +-- /nobody/ l+ ## 0 +-- /someone/ l- ## s- +-- /test_formal/ l! ## dF- +-- /formal/ l+ ## 0 +-- /casual/ l- ## s- diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb new file mode 100644 index 000000000..266073e48 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb @@ -0,0 +1,14 @@ +with Hello; use Hello; + +procedure Test_Formal_Someone is +begin + Say_Hello ("Jerome", Formal => True); +end; + +--# hello.adb +-- /test_nobody/ l! ## dT- +-- /nobody/ l- ## s- +-- /someone/ l+ ## 0 +-- /test_formal/ l! ## dF- +-- /formal/ l+ ## 0 +-- /casual/ l- ## s- diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/test.opt b/testsuite/tests/N521-029-dc-dynstack-twoways/test.opt new file mode 100644 index 000000000..2d37e0886 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD ticket exposed a compiler issue fixed on 2014-05, not in 7.0.3 +7.2.2 DEAD ticket exposed a compiler issue fixed on 2014-05, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/test.py b/testsuite/tests/N521-029-dc-dynstack-twoways/test.py new file mode 100644 index 000000000..5c679f78e --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/test.py @@ -0,0 +1,11 @@ +""" +Test that there is no static analysis issue with Pre aspects (preconditions). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/N610-006-library/libops.gpr b/testsuite/tests/N610-006-library/libops.gpr new file mode 100644 index 000000000..7fd74d5ed --- /dev/null +++ b/testsuite/tests/N610-006-library/libops.gpr @@ -0,0 +1,10 @@ +library project Libops is + for Languages use ("Ada"); + for Source_Dirs use ("libops"); + for Object_Dir use "obj"; + + for Library_Name use "ops"; + for Library_Kind use "static"; + for Library_Dir use "lib"; + +end Libops; diff --git a/testsuite/tests/N610-006-library/libops/inc.adb b/testsuite/tests/N610-006-library/libops/inc.adb new file mode 100644 index 000000000..faf7049d7 --- /dev/null +++ b/testsuite/tests/N610-006-library/libops/inc.adb @@ -0,0 +1,4 @@ +procedure Inc (X : in out Integer; Amount : Integer) is +begin + X := X + Amount; +end; diff --git a/testsuite/tests/N610-006-library/libops/mult.adb b/testsuite/tests/N610-006-library/libops/mult.adb new file mode 100644 index 000000000..11251a64b --- /dev/null +++ b/testsuite/tests/N610-006-library/libops/mult.adb @@ -0,0 +1,4 @@ +procedure Mult (X : in out Integer; Amount : Integer) is +begin + X := X * Amount; +end; diff --git a/testsuite/tests/N610-006-library/test.py b/testsuite/tests/N610-006-library/test.py new file mode 100644 index 000000000..59cc4dc9e --- /dev/null +++ b/testsuite/tests/N610-006-library/test.py @@ -0,0 +1,84 @@ +import re + +from SCOV.minicheck import build_and_run +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# We have a library with two units and a test exercising only one +# of them. Check that gnatcov reports the untested stmts as uncovered +# and emits an explicit notice of absence of object code on stderr +# with --verbose. + +prj = gprfor( + ["test_inc.adb"], srcdirs=[".."], objdir="obj", deps=["../libops"] +) + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=[], +) + + +def trycov(verbose, annotate): + # last argument of xcov_args it the trace_file name + # Note that coverage collection is on the library, not on + # the test project given to build_and_run + base_cov_command = ( + "coverage --level=stmt --annotate=%s -P../libops.gpr %s" + % (annotate, xcov_args[-1]) + ) + + cov_command = base_cov_command + if verbose: + cov_command += " --verbose" + + if annotate != "report": + cov_command += " --source-search=libops --output-dir=." + + p = xcov(cov_command) + + nocode_notified = re.search( + pattern="no object code for mult.ali", string=p.out + ) + + bin_mode = thistest.options.trace_mode == "bin" + + if bin_mode and verbose and not nocode_notified: + thistest.failed( + "missing notice of absence of object code," + " verbose=%s, annotate=%s" % (verbose, annotate) + ) + + if bin_mode and nocode_notified and not verbose: + thistest.failed( + "unexpected notice of absence of object code," + " verbose=%s, annotate=%s" % (verbose, annotate) + ) + + if annotate == "report": + thistest.fail_if( + not re.search( + pattern="mult.adb.*: statement not executed", string=p.out + ), + "missing expected stmt violation for mult.adb in report", + ) + + if annotate == "xcov": + thistest.fail_if( + not re.search( + pattern="[0-9]+ -:", string=contents_of("mult.adb.xcov") + ), + "missing expected l- in mult.adb.xcov", + ) + + +for v in (True, False): + for a in ("report", "xcov"): + trycov(verbose=v, annotate=a) + +thistest.result() diff --git a/testsuite/tests/N610-006-library/test_inc.adb b/testsuite/tests/N610-006-library/test_inc.adb new file mode 100644 index 000000000..7c30dbe39 --- /dev/null +++ b/testsuite/tests/N610-006-library/test_inc.adb @@ -0,0 +1,7 @@ +with Inc; + +procedure Test_Inc is + X : Integer := 0; +begin + Inc (X, 1); +end; diff --git a/testsuite/tests/N610-006-library/test_mult.adb b/testsuite/tests/N610-006-library/test_mult.adb new file mode 100644 index 000000000..d856d26c7 --- /dev/null +++ b/testsuite/tests/N610-006-library/test_mult.adb @@ -0,0 +1,7 @@ +with Mult; + +procedure Test_Mult is + X : Integer := 2; +begin + Mult (X, 2); +end; diff --git a/testsuite/tests/N630-009-forward_p_x/foo.adb b/testsuite/tests/N630-009-forward_p_x/foo.adb new file mode 100644 index 000000000..13c90e6cd --- /dev/null +++ b/testsuite/tests/N630-009-forward_p_x/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("hello there"); +end; diff --git a/testsuite/tests/N630-009-forward_p_x/test.opt b/testsuite/tests/N630-009-forward_p_x/test.opt new file mode 100644 index 000000000..bcaa349a6 --- /dev/null +++ b/testsuite/tests/N630-009-forward_p_x/test.opt @@ -0,0 +1,2 @@ +native DEAD testing gnatcov/gnatemu interaction, no gnatemu on native +src-traces DEAD gnatcov/gnatemu interaction not relevant for the trace mode diff --git a/testsuite/tests/N630-009-forward_p_x/test.py b/testsuite/tests/N630-009-forward_p_x/test.py new file mode 100644 index 000000000..967b17228 --- /dev/null +++ b/testsuite/tests/N630-009-forward_p_x/test.py @@ -0,0 +1,33 @@ +"""Check that the -P and -X command line args are passed to gnatemu.""" + +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + + +# Work in a subdirectory +wd = Wdir(subdir="tmp_") + +# Build a program expected to run fine for our current target +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) +gprbuild(project=gpr) + +program_path = exepath_to("foo") + +# Pass a correct -P and fake -X options together with -v. Check that the -P +# and -X options are found in the gnatemu command executed, as displayed by +# -v. Beware that the -P option may be passed down in various ways, e.g. +# -P gen.gpr or -Pgen.gpr, regardless of how we pass it to gnatcov run. +xargs = ["-XFOO=foo1", "-Xbar=bar1"] +xcovargs = ["-P", gpr, "-v", program_path] + xargs + +p = xrun(xcovargs) +for arg in xargs + ["'-P' '*%s'" % re.escape(gpr)]: + thistest.fail_if( + not re.search("gnatemu.*%s" % arg, p.out), + 'couldn\'t find "%s" on the gnatemu command line out of %s' + % (arg, " ".join(xcovargs)), + ) +thistest.result() diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/abs.c b/testsuite/tests/NA29-019-unit-filters-for-C/abs.c new file mode 100644 index 000000000..67338f5e4 --- /dev/null +++ b/testsuite/tests/NA29-019-unit-filters-for-C/abs.c @@ -0,0 +1,8 @@ +int +absval (int x) +{ + if (x < 0) + return -x; + else + return x; +} diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test.opt b/testsuite/tests/NA29-019-unit-filters-for-C/test.opt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test.py b/testsuite/tests/NA29-019-unit-filters-for-C/test.py new file mode 100644 index 000000000..0b8761981 --- /dev/null +++ b/testsuite/tests/NA29-019-unit-filters-for-C/test.py @@ -0,0 +1,102 @@ +""" +Verify the correct behavior of the unit selection facilities for C. + +We perform basic tests here and assume that more sophisticated will work as +well as they all build up on top of the same internal circuits. + +We have one functional unit and one test driver unit, with a template project +file from which we can build, then analyse. We perform different analysis +attempts, all intended to produce results for the functional unit only. This is +achieved by either exluding the harness unit out of the default, leaving only +the functional unit, or by explicitly including the functional unit only. +""" + +import re + +from e3.fs import mkdir, ls + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +Wdir("tmp_") + + +def gengpr(attributes, prjname): + return gprfor( + mains=["test_abs.c"], + prjid=prjname, + srcdirs="..", + objdir="obj", + exedir=".", + langs=["C"], + extra=""" + package Coverage is + {} + end Coverage; + """.format( + "\n".join(attributes) + ), + ) + + +# Build and run first +gprname = gengpr(attributes=[], prjname="build") +xcov_args = build_and_run( + GPRswitches(gprname), + "stmt", + ["test_abs"], + extra_coverage_args=["--annotate=xcov"], +) + +# Now analyse with different unit selection schemes ... Assign a different +# directory to each attempt. Expect reports for the functional unit(s) only. + + +def trycov(attributes, outdir): + # Create dedicated dir and analyse with the specific attributes: + mkdir(outdir) + gprname = gengpr(attributes=attributes, prjname=outdir) + xcov("%s -P%s --output-dir=%s" % (" ".join(xcov_args), gprname, outdir)) + + # Check that we have no report for the harness unit and that we have + # a report which looks correct for the functional unit: + harness_reports = ls("%s/test*.xcov" % outdir) + thistest.fail_if( + harness_reports, + "unexpected coverage reports for harness units: %s" + % str(harness_reports), + ) + + all_reports = ls("%s/*.xcov" % outdir) + thistest.fail_if( + not all_reports, + "missing expected coverage reports for !harness units in %s" % outdir, + ) + + # We expect to find a mix of coverage notes in each expected + # report: + + def check_report(r): + contents = contents_of(r) + + for note in ("+", "-", "."): + notes = re.findall(r"\d+ \%c:" % note, contents) + thistest.fail_if( + not notes, "missing expected '%c' notes in %s" % (note, r) + ) + + for r in all_reports: + check_report(r) + + +trycov( + attributes=['for excluded_units use ("test_abs.c");'], + outdir="exclude_harness", +) +trycov(attributes=['for units use ("abs.c");'], outdir="include_functional") + +thistest.result() diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c b/testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c new file mode 100644 index 000000000..a3ee16d25 --- /dev/null +++ b/testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c @@ -0,0 +1,15 @@ +extern int absval (int x); + +void +test_abs (void) +{ + volatile int x = -5; + volatile int y = absval (x); +} + +int +main (void) +{ + test_abs (); + return 0; +} diff --git a/testsuite/tests/NB07-026-header-shadow/src/box.h b/testsuite/tests/NB07-026-header-shadow/src/box.h new file mode 100644 index 000000000..bd0e9f3af --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/box.h @@ -0,0 +1,7 @@ +static int +twice (int x) +{ + return x * 2; +} + +extern void print_log (const char *fmt, ...); diff --git a/testsuite/tests/NB07-026-header-shadow/src/m1.c b/testsuite/tests/NB07-026-header-shadow/src/m1.c new file mode 100644 index 000000000..56a8eb6e6 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/m1.c @@ -0,0 +1,13 @@ +#include "box.h" +#include + +static int v = 12; + +void +m1 (bool compute) +{ + if (compute) + print_log ("m1: twice (v) = %d\n", twice (v)); // # m1-true + else + print_log ("m1: don't compute\n"); // # m1-false +} diff --git a/testsuite/tests/NB07-026-header-shadow/src/m2.c b/testsuite/tests/NB07-026-header-shadow/src/m2.c new file mode 100644 index 000000000..492bec425 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/m2.c @@ -0,0 +1,13 @@ +#include "box.h" +#include + +static int v = 7; + +void +m2 (bool compute) +{ + if (compute) + print_log ("m2: twice (v) = %d\n", twice (v)); // # m2-true + else + print_log ("m2: don't compute\n"); // # m2-false +} diff --git a/testsuite/tests/NB07-026-header-shadow/src/test_main.c b/testsuite/tests/NB07-026-header-shadow/src/test_main.c new file mode 100644 index 000000000..c114c8e83 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/test_main.c @@ -0,0 +1,24 @@ +#include + +extern void m1 (bool compute); +extern void m2 (bool compute); + +void +print_log (const char *fmt, ...) +{ +} + +int +main () +{ + m1 (true); + m2 (false); + return 0; +} + +//# m1.c +// /m1-true/ l+ ## 0 +// /m1-false/ l- ## s- +//# m2.c +// /m2-true/ l- ## s- +// /m2-false/ l+ ## 0 diff --git a/testsuite/tests/NB07-026-header-shadow/test.opt b/testsuite/tests/NB07-026-header-shadow/test.opt new file mode 100644 index 000000000..f8b21b735 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD fixed by a compiler change introduced in the 7.4.0w timeframe, ported to 7.3 +7.2.2 DEAD fixed by a compiler change introduced in the 7.4.0w timeframe, ported to 7.3 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/NB07-026-header-shadow/test.py b/testsuite/tests/NB07-026-header-shadow/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/NC02-014-gpr-X/main.adb b/testsuite/tests/NC02-014-gpr-X/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/NC02-014-gpr-X/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/NC02-014-gpr-X/test.py b/testsuite/tests/NC02-014-gpr-X/test.py new file mode 100644 index 000000000..298083f18 --- /dev/null +++ b/testsuite/tests/NC02-014-gpr-X/test.py @@ -0,0 +1,79 @@ +""" +Exercise the use of -X on the gnatcov command line to control project files +operations, with -X appearing either before or after -P. +""" + +import os.path +import shutil + +from e3.fs import ls + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +# We use a scenario variable to select the output directory for coverage +# reports. +extra = """ + type Report_Type is ("f", "g", "all"); + This_Report : Report_Type := external ("THIS_REPORT", "all"); + package Coverage is + for Switches ("coverage") use ("--output-dir", "output-" & This_Report); + end Coverage; +""" + +report_types = ["f", "g"] + + +def output_dir(what): + return "output-{}".format(what) + + +# Build and run once, in a dedicated temp directory +wd = Wdir("tmp_") + +base_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."], extra=extra) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + + +# Now perform analysis variants + + +def trycov(this_report, where): + # Clear output directories, to notice what is created that should not + for what in report_types: + d = output_dir(what) + if os.path.isdir(d): + shutil.rmtree(d) + + # THIS_REPORT conveys what value to pass as -XTHIS_REPORT. + # WHERE conveys whether -X should be placed 'before' or 'after' -P. + args = list(base_args) + arg_i = len(args) if where == "after" else 1 + args.insert(arg_i, "-XTHIS_REPORT={}".format(this_report)) + xcov(args) + + this_output_dir = output_dir(this_report) + expected_report = os.path.join(this_output_dir, "main.adb.xcov") + reports = ls(os.path.join(output_dir("*"), "*.xcov")) + + thistest.fail_if( + len(reports) > 1 or expected_report not in reports, + "expected a single {}, got {}".format(expected_report, reports), + ) + + +for what in report_types: + for where in ("before", "after"): + trycov(this_report=what, where=where) + +thistest.result() diff --git a/testsuite/tests/NC08-027-target_attr/foo.adb b/testsuite/tests/NC08-027-target_attr/foo.adb new file mode 100644 index 000000000..13c90e6cd --- /dev/null +++ b/testsuite/tests/NC08-027-target_attr/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("hello there"); +end; diff --git a/testsuite/tests/NC08-027-target_attr/test.opt b/testsuite/tests/NC08-027-target_attr/test.opt new file mode 100644 index 000000000..418d1af51 --- /dev/null +++ b/testsuite/tests/NC08-027-target_attr/test.opt @@ -0,0 +1,2 @@ +native DEAD testing --target interactions, no --target at all for native. +src-traces DEAD test specific to gnatcov run diff --git a/testsuite/tests/NC08-027-target_attr/test.py b/testsuite/tests/NC08-027-target_attr/test.py new file mode 100644 index 000000000..9f471ee43 --- /dev/null +++ b/testsuite/tests/NC08-027-target_attr/test.py @@ -0,0 +1,64 @@ +""" +Alternate test for NC08-027, complementary to the one within the GPR subset of +our suite. +""" + +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, indent +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + + +# Work in a subdirectory +wd = Wdir(subdir="tmp_") + +# Build a program expected to run fine for our current target +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) +gprbuild(project=gpr) + +program_path = exepath_to("foo") + +# Check that a Target attribute in a project file is accounted for +# by gnatcov run. +# +# Try to run with a project file containing a fake Target value. +# Expect an error complaining about an unknown target. +gpr = gprfor(mains=[], srcdirs=[".."], extra='for Target use "foo-bar";\n') +runargs = ["-P", gpr, program_path] +p = xrun( + runargs, + register_failure=False, + auto_config_args=False, + auto_target_args=False, +) + +if thistest.bits() == 32: + thistest.fail_if( + not re.search( + "No builtin or GNATemulator execution driver found for" + " target: foo-bar", + p.out, + ), + "couldn't find indication of unknown target error in gnatcov" + " run output:\n {}".format(indent(p.out)), + ) +else: + # thistest.bits() == 64 + # In that case, as gnatcov32 is picked by default if the given target + # is invalid, it will fail when loading the executable file. + + thistest.fail_if( + not re.search("unsupported ELF class", p.out), + "couldn't find indication of ELF class unsupported error in gnatcov" + " run output:\n {}".format(indent(p.out)), + ) + +# Check that an explicit --target on the command line overrides the +# Target project file attribute. +# +# Same arguments as in the previous test, plus correct --target and --RTS +# arguments. This one should succeed. +xrun(runargs, auto_config_args=False, auto_target_args=True) + +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.adb b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.adb new file mode 100644 index 000000000..aafef59db --- /dev/null +++ b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.adb @@ -0,0 +1,35 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package body Nested is + + function One return Integer is + begin + pragma Assert -- # success + (T and then (F or else (T and then (T or else F)))); -- # fail + return 1; -- # success + end One; + + -- One of the branches of the if expression is never exercised. + -- No violation is expected since gnatcov should not look into nested + -- decisions in assertions (FIXME: for now) + function Two return Integer is + begin + pragma Assert -- # success + ((if T then T else F) and then (F or else -- # success + (T and then (if (T and then F) -- # success + then T -- # success + else T)))); -- # success + return 2; -- # success + end Two; + + function Three return Integer is + begin + pragma Assert (if (T and then (T and then -- # success + (if T then T else F))) -- # success + then (T and then T) -- # success + else T); -- # success + return 3; -- # success + end Three; + +end nested; diff --git a/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.ads b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.ads new file mode 100644 index 000000000..cfe105f92 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.ads @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Nested is + + T : Boolean := True; -- # success + F : Boolean := False; -- # success + + function One return Integer + with Pre => (T and then T) or else F, -- # fail_ac + Post => One'Result = 1 and then -- # fail_part + (T and then -- # fail_part + (T or else -- # fail_part + (F or else T))); -- # fail_2_ac + + function Two return Integer + with Pre => (T and then (if T then T else T)) or else F, -- # fail_ac + Post => (if Two'Result = 2 and then -- # success + (T and then -- # success + (F or else (T or else F))) -- # success + then T -- # success + else F); -- # success + + function Three return Integer + with Post => (if (Three'Result = 2 and then (T and then -- # success + (if T then T else F))) -- # success + then (T and then T) -- # success + else T); -- # success +end Nested; diff --git a/testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb b/testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb new file mode 100644 index 000000000..ca43ce5ba --- /dev/null +++ b/testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb @@ -0,0 +1,21 @@ +with Nested; use Nested; + +-- Test the behavior of gnatcov when presented with assertions with nested +-- decisions. No violations are expected in nested decisions as gnatcov should +-- not look inside them. (FIXME: for now) + +procedure Test_Nested is + Dummy : Integer := One; +begin + Dummy := Two; + Dummy := Three; +end Test_Nested; + +--# nested.ads +-- /success/ l+ ## 0 +-- /fail_part/ l! ## 0 +-- /fail_ac/ l! ## ac! +-- /fail_2_ac/ l! ## ac!,ac! +--# nested.adb +-- /success/ l+ ## 0 +-- /fail/ l! ## ac! diff --git a/testsuite/tests/O212-062-assertions/atcc-nested/test.py b/testsuite/tests/O212-062-assertions/atcc-nested/test.py new file mode 100644 index 000000000..db03ebbfe --- /dev/null +++ b/testsuite/tests/O212-062-assertions/atcc-nested/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/expr_func/src/expr_func.adb b/testsuite/tests/O212-062-assertions/expr_func/src/expr_func.adb new file mode 100644 index 000000000..adfd417e4 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/expr_func/src/expr_func.adb @@ -0,0 +1,25 @@ +pragma Assertion_Policy (Check); +pragma Ada_2012; + +with Silent_Last_Chance; + +procedure Expr_Func +is + -- Expression function without a prior declaration. + function Foo (X : Integer) return Integer is (X) -- # foo_decl + with Pre => X >= 0, -- # foo_pre + Post => Foo'Result = X; -- # foo_post + + -- Expression function with aspects on prior declaration + function Bar (X : Integer) return Integer + with Pre => X > 0, -- # bar_pre + Post => Bar'Result = X and then X = 0; -- # bar_post + + function Bar (X : Integer) return Integer is (X); -- # bar_def + + Dummy : Integer; -- # dummy_decl +begin + Dummy := Foo (0); -- # foo_call + + Dummy := Bar (42); -- # bar_call +end Expr_Func; diff --git a/testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb b/testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb new file mode 100644 index 000000000..93335e1c8 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb @@ -0,0 +1,26 @@ +with Ada.Assertions; +with Expr_Func; + +-- Test the correct assertion coverage reporting for an expression function +-- with a precondition and a postcondition expressed as aspects. This is +-- tested with and without a prior declaration. + +procedure Test_Expr_Func is +begin + begin + Expr_Func; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_Expr_Func; + +--# expr_func.adb +-- /foo_decl/ l+ ## 0 +-- /foo_pre/ l+ ## 0 +-- /foo_post/ l+ ## 0 +-- /bar_pre/ l+ ## 0 +-- /bar_post/ l- ## aT- +-- /bar_def/ l+ ## 0 +-- /dummy_decl/ l+ ## 0 +-- /foo_call/ l+ ## 0 +-- /bar_call/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/expr_func/test.py b/testsuite/tests/O212-062-assertions/expr_func/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/expr_func/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/extra.opt b/testsuite/tests/O212-062-assertions/extra.opt new file mode 100644 index 000000000..c102bbe0c --- /dev/null +++ b/testsuite/tests/O212-062-assertions/extra.opt @@ -0,0 +1,3 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces +5.04a1 DEAD Test contains expression functions and Ada_2012 features +7.1.2 DEAD Test contains expression functions and Ada_2012 features diff --git a/testsuite/tests/O212-062-assertions/fail_loop_inv/src/fail_loop_inv.adb b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/fail_loop_inv.adb new file mode 100644 index 000000000..18684d117 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/fail_loop_inv.adb @@ -0,0 +1,16 @@ +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +procedure Fail_Loop_Inv is +begin + declare + High : Integer := 3; -- # high_decl + begin + for J in 1 .. High loop -- # loop_cond + pragma Loop_Invariant (High < 0); -- # loop_inv + end loop; + exception + when Ada.Assertions.Assertion_Error => null; -- # catch + end; +end Fail_Loop_Inv; diff --git a/testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb new file mode 100644 index 000000000..9312707c8 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb @@ -0,0 +1,14 @@ +with Fail_Loop_Inv; + +-- Test the coverage state of a failed loop invariant. + +procedure Test_Fail_Loop_Inv is +begin + Fail_Loop_Inv; +end Test_Fail_Loop_Inv; + +--# fail_loop_inv.adb +-- /high_decl/ l+ ## 0 +-- /loop_cond/ l+ ## 0 +-- /loop_inv/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/fail_loop_inv/test.py b/testsuite/tests/O212-062-assertions/fail_loop_inv/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/fail_loop_inv/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/others/src/fail_but_ok_cond.adb b/testsuite/tests/O212-062-assertions/others/src/fail_but_ok_cond.adb new file mode 100644 index 000000000..9cfa8edd1 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/fail_but_ok_cond.adb @@ -0,0 +1,17 @@ +pragma Assertion_Policy (Check); + +with Ada.Assertions; +with Functions; use Functions; + +procedure Fail_But_Ok_Cond +is + X : Integer := 1; +begin + begin + -- This assertion fails, all conditions are evaluated + + pragma Assert (Baz (X) /= 1 or else X = 0); -- # assertion + exception + when Ada.Assertions.Assertion_Error => null; -- # catch + end; +end Fail_But_Ok_Cond; diff --git a/testsuite/tests/O212-062-assertions/others/src/failed_pre.adb b/testsuite/tests/O212-062-assertions/others/src/failed_pre.adb new file mode 100644 index 000000000..3c73fbbb1 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/failed_pre.adb @@ -0,0 +1,11 @@ +with Functions; use Functions; + +procedure Failed_Pre +is + Y : Integer := 2; +begin + -- Call to Foo with a parameter that does not satisfy the + -- precondition. + + Y := Foo (-2); -- # foo_call +end Failed_Pre; diff --git a/testsuite/tests/O212-062-assertions/others/src/functions.adb b/testsuite/tests/O212-062-assertions/others/src/functions.adb new file mode 100644 index 000000000..2112d5325 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/functions.adb @@ -0,0 +1,59 @@ +pragma Assertion_Policy (Check); +pragma Ada_2012; + +package body Functions is + + --------- + -- Foo -- + --------- + + function Foo (I : Integer) return Integer + is + High : Integer := 3; -- # foo_hi_decl + begin + for J in 1 .. High loop -- # foo_loop_1 + pragma Loop_Invariant (J = J + 1 - 1 and then J < 4); -- # foo_inv_1 + end loop; + + for J in 1 .. High loop -- # foo_loop_2 + pragma Loop_Invariant (J = J + 1 - 1 or else J < 4); -- # foo_inv_2 + end loop; + return I; -- # foo_return + end Foo; + + ---------- + -- Same -- + ---------- + + function Same (A, B : Boolean) return Boolean + is + -- Subprogram body with aspect without prior declaration + + function Id (C : Boolean) return Boolean + with Pre => C or else (C or else not C), -- # id_pre + Post => Id'Result = C -- # id_post + is + begin + return C; -- # id_ret + end Id; + + begin + -- Decision nested as parameter of a function call within an assertion. + -- The function parameter should not be seen as a condition for the + -- assertion decision. + + -- Last two conditions are not evaluated + + pragma Assert (Id (A or else B) or else A or else B); -- # nested_1 + + -- Last condition is not evaluated + + pragma Assert (B or else A or else Id (A or else B)); -- # nested_2 + + -- All conditions are evaluated + + pragma Assert (B or else Id (A or else B)); -- # nested_3 + return B; -- # same_ret + end Same; + +end Functions; diff --git a/testsuite/tests/O212-062-assertions/others/src/functions.ads b/testsuite/tests/O212-062-assertions/others/src/functions.ads new file mode 100644 index 000000000..1e506475a --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/functions.ads @@ -0,0 +1,17 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Functions is + + function Foo (I : Integer) return Integer + with Pre => (I >= 0 and then False) or else I >= 0, -- # foo_pre + Post => (I = Foo'Result or else Foo'Result /= 42); -- # foo_post + + function Bar (I : Integer) return Integer is (I) -- # bar_expr + with Pre => (I < 0 or else I >= 0) or else (I = 42); -- # bar_pre + + function Baz (I : Integer) return Integer is (I); -- # baz_expr + + function Same (A, B : Boolean) return Boolean; + +end Functions; diff --git a/testsuite/tests/O212-062-assertions/others/src/test_fail_but_ok_cond.adb b/testsuite/tests/O212-062-assertions/others/src/test_fail_but_ok_cond.adb new file mode 100644 index 000000000..559c45d17 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/test_fail_but_ok_cond.adb @@ -0,0 +1,33 @@ +with Fail_But_Ok_Cond; + +-- Test the coverage state when all conditions of a failing assertion are +-- executed. + +procedure Test_Fail_But_Ok_Cond is +begin + Fail_But_Ok_Cond; +end Test_Fail_But_Ok_Cond; + +--# functions.ads +-- /foo_pre/ l- ## a- +-- /foo_post/ l- ## a- +-- /bar_expr/ l- ## s- +-- /bar_pre/ l- ## a- +-- /baz_expr/ l+ ## 0 +--# functions.adb +-- /foo_hi_decl/ l- ## s- +-- /foo_loop_1/ l- ## s- +-- /foo_inv_1/ l- ## s- +-- /foo_loop_2/ l- ## s- +-- /foo_inv_2/ l- ## s- +-- /foo_return/ l- ## s- +-- /id_pre/ l- ## a- +-- /id_post/ l- ## a- +-- /id_ret/ l- ## s- +-- /nested_1/ l- ## s- +-- /nested_2/ l- ## s- +-- /nested_3/ l- ## s- +-- /same_ret/ l- ## s- +-- # fail_but_ok_cond.adb +-- /assertion/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/others/src/test_failed_pre.adb b/testsuite/tests/O212-062-assertions/others/src/test_failed_pre.adb new file mode 100644 index 000000000..cdb408044 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/test_failed_pre.adb @@ -0,0 +1,39 @@ +with Ada.Assertions; +with Silent_Last_Chance; + +With Failed_Pre; + +-- Check the coverage states when calling Foo with a parameter not satisfying +-- the its precondition. + +procedure Test_Failed_Pre is +begin + begin + Failed_Pre; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_Failed_Pre; + +--# functions.ads +-- /foo_pre/ l- ## aT- +-- /foo_post/ l- ## a- +-- /bar_expr/ l- ## s- +-- /bar_pre/ l- ## a- +-- /baz_expr/ l- ## s- +--# functions.adb +-- /foo_hi_decl/ l- ## s- +-- /foo_loop_1/ l- ## s- +-- /foo_inv_1/ l- ## s- +-- /foo_loop_2/ l- ## s- +-- /foo_inv_2/ l- ## s- +-- /foo_return/ l- ## s- +-- /id_pre/ l- ## a- +-- /id_post/ l- ## a- +-- /id_ret/ l- ## s- +-- /nested_1/ l- ## s- +-- /nested_2/ l- ## s- +-- /nested_3/ l- ## s- +-- /same_ret/ l- ## s- +--# failed_pre.adb +-- /foo_call/ l+ ## c! diff --git a/testsuite/tests/O212-062-assertions/others/src/test_various_tests.adb b/testsuite/tests/O212-062-assertions/others/src/test_various_tests.adb new file mode 100644 index 000000000..772ad7d26 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/test_various_tests.adb @@ -0,0 +1,36 @@ +with Various_Tests; + +-- Test various assertion scenarios. The details can be found directly in +-- various_tests.adb. + +procedure Test_Various_Tests is +begin + Various_Tests; +end Test_Various_Tests; + +--# functions.ads +-- /foo_pre/ l+ ## 0 +-- /foo_post/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /bar_expr/ l+ ## 0 +-- /bar_pre/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /baz_expr/ l- ## s- +--# functions.adb +-- /foo_hi_decl/ l+ ## 0 +-- /foo_loop_1/ l+ ## 0 +-- /foo_inv_1/ l+ ## 0 +-- /foo_loop_2/ l+ ## 0 +-- /foo_inv_2/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /foo_return/ l+ ## 0 +-- /id_pre/ a=>l+, c=>l! ## a=>0, c=>ac!,ac! +-- /id_post/ l+ ## 0 +-- /id_ret/ l+ ## 0 +-- /nested_1/ a=>l+, c=>l! ## a=>0, c=>ac!,ac! +-- /nested_2/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /nested_3/ l+ ## 0 +-- /same_ret/ l+ ## 0 +-- # various_tests.adb +-- /assert_1/ a=>l+, c=>l! ## a=>0, c=>ac!,ac! +-- /foo/ l+ ## 0 +-- /if_false/ l! ## dT- +-- /assert_2/ l- ## s- +-- /bar/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/others/src/various_tests.adb b/testsuite/tests/O212-062-assertions/others/src/various_tests.adb new file mode 100644 index 000000000..9dbd6bbf4 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/various_tests.adb @@ -0,0 +1,38 @@ +pragma Assertion_Policy (Check); + +with Functions; use Functions; + +procedure Various_Tests +is + X : Integer := 0; + Y : Integer := X; + A : Boolean := True; + B : Boolean := False; +begin + -- Only the first condition is evaluated + + pragma Assert ((X = 0 or else A) or else X = 8, "msg"); -- # assert_1 + + -- Call a function. Evaluate all conditions of the precondition; + -- evaluate only the first condition of the postcondition. The first + -- loop invariant is entirely covered while the last condition of the + -- second loop invariant is not evaluated. + + Y := Foo (0); -- # foo + + -- The if's decision is False, so the statement contained is not executed + + if X /= 0 then -- # if_false + pragma Assert (X /= 0 or else False); -- # assert_2 + end if; + + -- Call an expression function with a precondition of which the last + -- condition is not evaluated. + + Y := Bar (0); -- # bar + + -- Call to function with an aspect defined with the function body. + + A := Same (A, B); + +end Various_Tests; diff --git a/testsuite/tests/O212-062-assertions/others/test.py b/testsuite/tests/O212-062-assertions/others/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/pragmas/src/pragmas.adb b/testsuite/tests/O212-062-assertions/pragmas/src/pragmas.adb new file mode 100644 index 000000000..a64ae5aeb --- /dev/null +++ b/testsuite/tests/O212-062-assertions/pragmas/src/pragmas.adb @@ -0,0 +1,29 @@ +pragma Assertion_Policy (Check); +pragma Ada_2012; + +with Ada.Assertions; + +procedure Pragmas (T : Boolean := True; F : Boolean := False) +is + function Id (B : Boolean) return Boolean is (B); -- # id +begin + begin + -- No assertion error + pragma Assume (T and then (F or else T)); -- # assume + + pragma Check (Precondition, F or else not T or else T); -- # c_pre + pragma Check (Postcondition, not Id (F)); -- # c_post + pragma Check (Type_Invariant, T or else Id (T)); -- # c_ti + pragma Check (Invariant, T); -- # c_inv + pragma Check (Assertion, T or else T); -- # c_assert + + pragma Assert_And_Cut (T -- # cut_1 + or else (F -- # cut_2 + or else T)); -- # cut_3 + + -- Assertion error + pragma Assume (Id (F) or else F); -- # fail + exception + when Ada.Assertions.Assertion_Error => null; -- # catch + end; +end Pragmas; diff --git a/testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb b/testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb new file mode 100644 index 000000000..122c87bc8 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb @@ -0,0 +1,23 @@ +with Pragmas; + +-- Test the correct reporting of coverage for all supported pragmas. +-- All assertion are executed, some have conditions that are not. + +procedure Test_Pragmas is +begin + Pragmas; +end Test_Pragmas; + +--# pragmas.adb +-- /id/ l+ ## 0 +-- /assume/ l+ ## 0 +-- /c_pre/ l+ ## 0 +-- /c_post/ l+ ## 0 +-- /c_ti/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /c_inv/ l+ ## 0 +-- /c_assert/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /cut_1/ a=>l+, c=>l! ## a=>0, c=>0 +-- /cut_2/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /cut_3/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /fail/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/pragmas/test.py b/testsuite/tests/O212-062-assertions/pragmas/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/pragmas/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads b/testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads new file mode 100644 index 000000000..1c1b08602 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads @@ -0,0 +1,20 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Pkg is + + type Rec is private; -- # rec_decl + + function Make_Rec (B : Boolean) return Rec; + +private + + type Rec is record -- # rec_def + B : Boolean := True; -- # rec_b + end record -- # rec_end + with Type_Invariant => B; -- # type_inv + -- Record with a type invariant expressed as an aspect + + function Make_Rec (B : Boolean) return Rec is ((B => B)); -- # return + +end Pkg; diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb b/testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb new file mode 100644 index 000000000..dfc4b61a1 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb @@ -0,0 +1,33 @@ +with Silent_Last_Chance; +with Ada.Assertions; + +with Pkg; + +-- Assertion test for type invariant of a record. +-- +-- Create a record with a field value that does not respect the type +-- invariant. This raises an assertion error. Test that the coverage state of +-- the type invariant is set to "not covered". + +procedure Test_False +is + use Pkg; +begin + begin + declare + Dummy : constant Rec := Make_Rec (False); + begin + null; + end; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_False; + +--# pkg.ads +-- /rec_decl/ l+ ## 0 +-- /rec_def/ l+ ## 0 +-- /rec_b/ l+ ## 0 +-- /rec_end/ l+ ## 0 +-- /type_inv/ l! ## aT- +-- /return/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb b/testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb new file mode 100644 index 000000000..1a17c7c78 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb @@ -0,0 +1,16 @@ +-- Assertion test for type invariant of a record. +-- +-- Test that an non-executed type invariant is reported as such. + +procedure Test_Null is +begin + null; +end Test_Null; + +--# pkg.ads +-- /rec_decl/ l- ## s- +-- /rec_def/ l- ## s- +-- /rec_b/ l- ## 0 +-- /rec_end/ l- ## 0 +-- /type_inv/ l- ## a- +-- /return/ l- ## s- diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb b/testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb new file mode 100644 index 000000000..e66343357 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb @@ -0,0 +1,24 @@ +with Pkg; + +-- Assertion test for type invariant of a record. +-- +-- Creating a record with a field value that respects the type invariant. +-- This raises no assertion error. Test that the coverage state of the type +-- invariant is set to "covered". + +procedure Test_True +is + use Pkg; + + Dummy : Rec := Make_Rec (True); +begin + null; +end Test_True; + +--# pkg.ads +-- /rec_decl/ l+ ## 0 +-- /rec_def/ l+ ## 0 +-- /rec_b/ l+ ## 0 +-- /rec_end/ l+ ## 0 +-- /type_inv/ l+ ## 0 +-- /return/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/type_invariant/test.py b/testsuite/tests/O212-062-assertions/type_invariant/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected new file mode 100644 index 000000000..249a711bc --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected @@ -0,0 +1,47 @@ +(.|\n)* + +2\.3\. MCDC COVERAGE +-+ + +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0, C3 + T T F T -> TRUE In a pair for C3 + T T T - -> TRUE In a pair for C0 + +pkg\.adb:29:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE In a pair for C0 + T - - -> TRUE In a pair for C0 + +pkg\.adb:30:25: contract expression outcome FALSE never exercised +pkg\.adb:30:39: decision never evaluated +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + +pkg\.adb:45:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE In a pair for C0 + T T - -> TRUE In a pair for C0 + + +9 violations\. + +2\.4\. ATC COVERAGE +-+ + +No violation\. + +2\.5\. ATCC COVERAGE +-+ + +No violation\. diff --git a/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected new file mode 100644 index 000000000..97338c0af --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected @@ -0,0 +1,48 @@ +(.|\n)* + +2\.3\. UC_MCDC COVERAGE +-+ + +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0 + T T T - -> TRUE In a pair for C0 + T T F T -> TRUE Not part of any pair + +pkg\.adb:29:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE In a pair for C0 + T - - -> TRUE In a pair for C0 + +pkg\.adb:30:25: contract expression outcome FALSE never exercised +pkg\.adb:30:39: decision never evaluated +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + +pkg\.adb:45:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE In a pair for C0 + T T - -> TRUE In a pair for C0 + + +10 violations\. + +2\.4\. ATC COVERAGE +-+ + +No violation. + +2\.5\. ATCC COVERAGE +-+ + +No violation. diff --git a/testsuite/tests/O212-062-show-condition-vectors/main.adb b/testsuite/tests/O212-062-show-condition-vectors/main.adb new file mode 100644 index 000000000..801b5e835 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/main.adb @@ -0,0 +1,10 @@ +with Pkg; use Pkg; +procedure Main is +begin + Mystery (False, True, True); + Mystery (False, False, False); + Mystery (True, True, True); + Mystery (True, True, False); + Other_Proc (True, True); + Other_Proc (False, True); +end Main; diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.adb b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb new file mode 100644 index 000000000..adb1d51f9 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb @@ -0,0 +1,50 @@ +pragma Assertion_Policy (Check); + +with Ada.Text_IO; use Ada.Text_IO; +with Silent_Last_Chance; + +package body Pkg is + + procedure Mystery (A, B, C : Boolean) + is + function Id (B : Boolean) return Boolean; + + function Id (B : Boolean) return Boolean is + begin + return B; + end Id; + begin + begin + if (A and then B and then C) or else A then + Put_Line ("Great success!"); + else + Put_Line ("Failed"); + end if; + if A then + Put_Line ("A is True"); + else + Put_Line ("A is False"); + end if; + + pragma Assert (Id (A or else B) or else A or else B); + pragma Assert (B or else Id (A or else B)); + exception + when others => null; + end; + end Mystery; + + procedure Other_Proc (A, B : Boolean) is + begin + begin + if A and then B then + Put_Line ("Stuff"); + else + Put_Line ("not Stuff"); + end if; + + pragma Assert ((A and then B) or else A); + exception + when others => null; + end; + end Other_Proc; +end Pkg; diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.ads b/testsuite/tests/O212-062-show-condition-vectors/pkg.ads new file mode 100644 index 000000000..c5528490a --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.ads @@ -0,0 +1,6 @@ +package Pkg is + + procedure Mystery (A, B, C : Boolean); + + procedure Other_Proc (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected new file mode 100644 index 000000000..4a0d7dc35 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected @@ -0,0 +1,47 @@ +(.|\n)* + +2\.3\. MCDC COVERAGE +-+ + +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0, C3 + T T F T -> TRUE In a pair for C3 + T T T - -> TRUE In a pair for C0 + +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + + +3 violations\. +(.|\n)* + +2\.5\. ATCC COVERAGE +-+ + +pkg\.adb:29:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE + T - - -> TRUE + +pkg\.adb:30:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:30:25: Decision of the form \(C0 or else C1\) +Evaluation vectors found: + T - -> TRUE + +pkg\.adb:45:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE + T T - -> TRUE + + +4 violations\. +(.|\n)* diff --git a/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected new file mode 100644 index 000000000..91e97090c --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected @@ -0,0 +1,47 @@ +(.|\n)* + +2\.3\. UC_MCDC COVERAGE +-+ + +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0 + T T T - -> TRUE In a pair for C0 + T T F T -> TRUE Not part of any pair + +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + + +4 violations\. +(.|\n)* + +2\.5\. ATCC COVERAGE +-+ + +pkg\.adb:29:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE + T - - -> TRUE + +pkg\.adb:30:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:30:25: Decision of the form \(C0 or else C1\) +Evaluation vectors found: + T - -> TRUE + +pkg\.adb:45:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE + T T - -> TRUE + + +4 violations\. diff --git a/testsuite/tests/O212-062-show-condition-vectors/test.py b/testsuite/tests/O212-062-show-condition-vectors/test.py new file mode 100644 index 000000000..338277d6a --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/test.py @@ -0,0 +1,81 @@ +""" +Check that --show-condition-vectors works as expected for MCDC/UC_MCDC and +ATCC. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Generate a project, instrument it if necessary and run it, +p = gprfor(mains=["main.adb"], srcdirs=[".."]) +xcov_args_mcdc = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc+atcc", + mains=["main"], + extra_coverage_args=[], +) + + +def run_and_check(args, output_file, expected_file): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_file: File containing text we expected to find in the + coverage report. + """ + xcov(args, out=output_file) + + thistest.fail_if_no_match( + '"gnatcov coverage" output ({})'.format(output_file), + contents_of(expected_file).replace("\r\n", "\n"), + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace("\r\n", "\n"), + ) + + +# For the following test, a different behavior is expected for source and bin +# traces as assertion coverage is currently not supported in binary traces. +# Assertion decisions are expected to be treated as any other decision. + +# Check that mcdc/atcc vectors are displayed under the corresponding +# condition violations, and show the conditions indexes in violation messages. + +mcdc_atcc_ref_file = ( + "../bin-mcdc-atcc.expected" + if thistest.options.trace_mode == "bin" + else "../src-mcdc-atcc.expected" +) + + +run_and_check( + xcov_args_mcdc + ["-areport", "--show-condition-vectors"], + "report-stdout-mcdc-atcc.txt", + mcdc_atcc_ref_file, +) + + +# Check that evaluation vectors not part of any pair are displayed below the +# other vectors. + +ucmcdc_atcc_ref_file = ( + "../bin-ucmcdc-atcc.expected" + if thistest.options.trace_mode == "bin" + else "../src-ucmcdc-atcc.expected" +) + +run_and_check( + xcov_args_mcdc + + ["--level=stmt+uc_mcdc+atcc", "-areport", "--show-condition-vectors"], + "report-stdout-ucmcdc-atcc.txt", + ucmcdc_atcc_ref_file, +) + +thistest.result() diff --git a/testsuite/tests/O212-062-xml/main.adb b/testsuite/tests/O212-062-xml/main.adb new file mode 100644 index 000000000..dcb65ce75 --- /dev/null +++ b/testsuite/tests/O212-062-xml/main.adb @@ -0,0 +1,27 @@ +pragma Assertion_Policy (Check); + +procedure Main +is + function ATCC_Violation (X : Boolean) return Boolean + is + function Id (X : Boolean) return Boolean is + begin + if X or else X then + return X; + end if; + return X; + end Id; + + Dummy : Boolean := Id (True); + begin + pragma Assert (X or else not X); + return Id (False); + end ATCC_Violation; +begin + declare + Dummy : Boolean := ATCC_Violation (True); + begin + null; + end; + return; +end Main; diff --git a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected new file mode 100644 index 000000000..c5b89fb57 --- /dev/null +++ b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/O212-062-xml/test.opt b/testsuite/tests/O212-062-xml/test.opt new file mode 100644 index 000000000..74b2fb73e --- /dev/null +++ b/testsuite/tests/O212-062-xml/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces diff --git a/testsuite/tests/O212-062-xml/test.py b/testsuite/tests/O212-062-xml/test.py new file mode 100644 index 000000000..4fd66d1c7 --- /dev/null +++ b/testsuite/tests/O212-062-xml/test.py @@ -0,0 +1,28 @@ +""" +Check the content of an XML summary for assertion coverage. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, FilePathRefiner +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +wd = Wdir("tmp_") + +gpr = gprfor(["main.adb"], srcdirs="..") +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt+mcdc+atcc", + mains=["main"], + extra_coverage_args=["-axml"], +) + +thistest.fail_if_diff( + os.path.join("..", "src-traces-index.xml.expected"), + os.path.join("obj", "index.xml"), + output_refiners=[FilePathRefiner()], +) + +thistest.result() diff --git a/testsuite/tests/O302-015-src-path-in-project/p.gpr b/testsuite/tests/O302-015-src-path-in-project/p.gpr new file mode 100644 index 000000000..8453bffd8 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/p.gpr @@ -0,0 +1,7 @@ +project P is + for Languages use ("Ada"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Main use ("main.adb"); + +end P; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/main.adb b/testsuite/tests/O302-015-src-path-in-project/src/main.adb new file mode 100644 index 000000000..7d5971394 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/main.adb @@ -0,0 +1,6 @@ +with Pkg.HW; + +procedure Main is +begin + Pkg.HW.Hello_World; +end Main; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb new file mode 100644 index 000000000..1423f3f61 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb @@ -0,0 +1,8 @@ +with Pkg.IO; + +package body Pkg.HW is + procedure Hello_World is + begin + Pkg.IO.Put_Line ("Hello, world!"); + end Hello_World; +end Pkg.HW; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads new file mode 100644 index 000000000..7fda7d644 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads @@ -0,0 +1,3 @@ +package Pkg.HW is + procedure Hello_World; +end Pkg.HW; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb new file mode 100644 index 000000000..1e0c0d562 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb @@ -0,0 +1,6 @@ +package body Pkg.IO is + procedure Put_Line (S : String) is + begin + null; + end Put_Line; +end Pkg.IO; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads new file mode 100644 index 000000000..cfb9eb837 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads @@ -0,0 +1,3 @@ +package Pkg.IO is + procedure Put_Line (S : String); +end Pkg.IO; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg.ads b/testsuite/tests/O302-015-src-path-in-project/src/pkg.ads new file mode 100644 index 000000000..2131e57ff --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + pragma Warnings (Off); +end Pkg; diff --git a/testsuite/tests/O302-015-src-path-in-project/test.py b/testsuite/tests/O302-015-src-path-in-project/test.py new file mode 100644 index 000000000..718bad33d --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/test.py @@ -0,0 +1,82 @@ +""" +Check that we can build, run and analyse a program featuring dummy units with +or without a project file, relying on debug info to locate the sources in the +case. +""" + +import os.path + +from e3.fs import rm + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +bin_traces = thistest.options.trace_mode == "bin" + + +# Precompute absolute paths before going to the temporary directory +prj_path = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") +pkg_ads_report_path = os.path.join(obj_dir, "pkg.ads.xcov") +scos = [ + os.path.join(obj_dir, name) for name in ("pkg", "pkg-hw", "pkg-io", "main") +] + +wd = Wdir(subdir="tmp_") + + +# Build the project and produce a trace for its main. This is using MCDC + SCOs +# as in the original test we received (when SCOs are available, i.e. in binary +# trace mode). +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj_path), + covlevel="stmt+mcdc", + mains=["main"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + scos=scos, + extra_coverage_args=["--annotate=xcov"], +) +trace_file = xcov_args[-1] + + +# Now check that analysis works one way or the other: with SCOs and with -P in +# binary trace mode, and with -P only in other modes. + + +def try_coverage(xcov_args, use_project): + thistest.log(f"== try_coverage(use_project={use_project})") + rm(pkg_ads_report_path) + + if not use_project: + xcov_args = xcov_args + ["--output-dir={}".format(obj_dir)] + p = xcov(xcov_args) + + thistest.fail_if( + p.out, '"gnatcov coverage" output is not empty:\n--\n{}'.format(p.out) + ) + thistest.fail_if( + not os.path.isfile(pkg_ads_report_path), + '"gnatcov coverage" could not produce a report file for pkg.ads', + ) + + +try_coverage(xcov_args, use_project=False) +if bin_traces: + try_coverage( + [ + "coverage", + "-P", + prj_path, + "--level=stmt+mcdc", + "--annotate=xcov", + trace_file, + ], + use_project=True, + ) + +thistest.result() diff --git a/testsuite/tests/O529-021-wrong-elf-class/code-32.o b/testsuite/tests/O529-021-wrong-elf-class/code-32.o new file mode 100644 index 000000000..71ebc15ed Binary files /dev/null and b/testsuite/tests/O529-021-wrong-elf-class/code-32.o differ diff --git a/testsuite/tests/O529-021-wrong-elf-class/code-64.o b/testsuite/tests/O529-021-wrong-elf-class/code-64.o new file mode 100644 index 000000000..ce5646097 Binary files /dev/null and b/testsuite/tests/O529-021-wrong-elf-class/code-64.o differ diff --git a/testsuite/tests/O529-021-wrong-elf-class/code.s b/testsuite/tests/O529-021-wrong-elf-class/code.s new file mode 100644 index 000000000..6a9de549b --- /dev/null +++ b/testsuite/tests/O529-021-wrong-elf-class/code.s @@ -0,0 +1,2 @@ +.text + nop diff --git a/testsuite/tests/O529-021-wrong-elf-class/test.opt b/testsuite/tests/O529-021-wrong-elf-class/test.opt new file mode 100644 index 000000000..f13339489 --- /dev/null +++ b/testsuite/tests/O529-021-wrong-elf-class/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disassemble, specific to binary trace mode diff --git a/testsuite/tests/O529-021-wrong-elf-class/test.py b/testsuite/tests/O529-021-wrong-elf-class/test.py new file mode 100644 index 000000000..286d5b8de --- /dev/null +++ b/testsuite/tests/O529-021-wrong-elf-class/test.py @@ -0,0 +1,26 @@ +import re + +from SUITE.context import thistest +from SUITE.tutils import xcov + + +# Note: test material was generated with the following commands with GCC for +# x86_64-linux: +# $ gcc -o code-32.o -m32 -c code.s +# $ gcc -o code-64.o -m64 -c code.s +bits = "32" if "64bits" in thistest.options.tags else "64" +expected_pattern = ( + r".*gnatcov.*: code-{bits}\.o:" + r" unsupported ELF class \({bits}bit\)".format(bits=bits) +) + +p = xcov(["disassemble", "code-{}.o".format(bits)], register_failure=False) +got_output = p.out.strip() +thistest.fail_if( + not re.match(expected_pattern, got_output), + "Could not match:\n" + " {}\n" + "against output:\n" + " {}".format(expected_pattern, got_output), +) +thistest.result() diff --git a/testsuite/tests/O916-035-padding-cons/foo-x86-linux.s b/testsuite/tests/O916-035-padding-cons/foo-x86-linux.s new file mode 100644 index 000000000..29c420c5c --- /dev/null +++ b/testsuite/tests/O916-035-padding-cons/foo-x86-linux.s @@ -0,0 +1,194 @@ + .file "foo.c" + .text +.Ltext0: + .align 2 + .type foo, @function +foo: +.LFB0: + .file 1 "foo.c" + .loc 1 3 0 + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + .loc 1 4 0 + movl $0, %eax + nop + .loc 1 5 0 + popl %ebp + .cfi_restore 5 + .cfi_def_cfa 4, 4 + ret + .cfi_endproc + {padding} +.LFE0: + .size foo, .-foo + .align 2 + .globl main + .type main, @function +main: +.LFB1: + .loc 1 9 0 + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + .loc 1 10 0 + call foo + nop + .loc 1 11 0 + popl %ebp + .cfi_restore 5 + .cfi_def_cfa 4, 4 + ret + .cfi_endproc +.LFE1: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x53 + .value 0x4 + .long .Ldebug_abbrev0 + .byte 0x4 + .uleb128 0x1 + .long .LASF0 + .byte 0x1 + .long .LASF1 + .long .LASF2 + .long .Ltext0 + .long .Letext0-.Ltext0 + .long .Ldebug_line0 + .uleb128 0x2 + .string "foo" + .byte 0x1 + .byte 0x2 + .long 0x3a + .long .LFB0 + .long .LFE0-.LFB0 + .uleb128 0x1 + .byte 0x9c + .uleb128 0x3 + .byte 0x4 + .byte 0x5 + .string "int" + .uleb128 0x4 + .long .LASF3 + .byte 0x1 + .byte 0x8 + .long 0x3a + .long .LFB1 + .long .LFE1-.LFB1 + .uleb128 0x1 + .byte 0x9c + .byte 0 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x10 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2116 + .uleb128 0x19 + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x1c + .value 0x2 + .long .Ldebug_info0 + .byte 0x4 + .byte 0 + .value 0 + .value 0 + .long .Ltext0 + .long .Letext0-.Ltext0 + .long 0 + .long 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF2: + .string "/home/pmderodat/gnatcov-inttests/O916-035-padding-cons" +.LASF3: + .string "main" +.LASF0: + .string "GNU C 4.9.4 20150910 (for GNAT Pro 7.4.0w 20150910) -mtune=generic -march=pentium4 -g" +.LASF1: + .string "foo.c" + .ident "GCC: (GNU) 4.9.4 20150910 (for GNAT Pro 7.4.0w 20150910)" + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/tests/O916-035-padding-cons/foo-x86-windows.s b/testsuite/tests/O916-035-padding-cons/foo-x86-windows.s new file mode 100644 index 000000000..d3a7ab32d --- /dev/null +++ b/testsuite/tests/O916-035-padding-cons/foo-x86-windows.s @@ -0,0 +1,187 @@ + .file "foo.c" + .text +Ltext0: + .cfi_sections .debug_frame + .align 2 + .def _foo; .scl 3; .type 32; .endef +_foo: +LFB0: + .file 1 "foo.c" + .loc 1 3 0 + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + .loc 1 4 0 + movl $0, %eax + nop + .loc 1 5 0 + popl %ebp + .cfi_restore 5 + .cfi_def_cfa 4, 4 + ret + .cfi_endproc + {padding} +LFE0: + .def ___main; .scl 2; .type 32; .endef + .align 2 + .globl _main + .def _main; .scl 2; .type 32; .endef +_main: +LFB1: + .loc 1 9 0 + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + andl $-16, %esp + call ___main + .loc 1 10 0 + call _foo + nop + .loc 1 11 0 + leave + .cfi_restore 5 + .cfi_def_cfa 4, 4 + ret + .cfi_endproc +LFE1: +Letext0: + .section .debug_info,"dr" +Ldebug_info0: + .long 0xea + .word 0x4 + .secrel32 Ldebug_abbrev0 + .byte 0x4 + .uleb128 0x1 + .ascii "GNU C 4.9.3 20141210 for GNAT Pro 7.4.0w (20141209) -mtune=generic -march=pentiumpro -g\0" + .byte 0x1 + .ascii "foo.c\0" + .ascii "C:\\home\\derodat\\_git\\gnatcoverage-extra\\tests\\O916-035-padding-cons\0" + .long Ltext0 + .long Letext0-Ltext0 + .secrel32 Ldebug_line0 + .uleb128 0x2 + .ascii "foo\0" + .byte 0x1 + .byte 0x2 + .long 0xd0 + .long LFB0 + .long LFE0-LFB0 + .uleb128 0x1 + .byte 0x9c + .uleb128 0x3 + .byte 0x4 + .byte 0x5 + .ascii "int\0" + .uleb128 0x4 + .ascii "main\0" + .byte 0x1 + .byte 0x8 + .long 0xd0 + .long LFB1 + .long LFE1-LFB1 + .uleb128 0x1 + .byte 0x9c + .byte 0 + .section .debug_abbrev,"dr" +Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0x8 + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x1b + .uleb128 0x8 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x10 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2116 + .uleb128 0x19 + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"dr" + .long 0x1c + .word 0x2 + .secrel32 Ldebug_info0 + .byte 0x4 + .byte 0 + .word 0 + .word 0 + .long Ltext0 + .long Letext0-Ltext0 + .long 0 + .long 0 + .section .debug_line,"dr" +Ldebug_line0: + .section .debug_str,"dr" + .ident "GCC: (GNU) 4.9.3 20141210 for GNAT Pro 7.4.0w (20141209)" diff --git a/testsuite/tests/O916-035-padding-cons/foo.c b/testsuite/tests/O916-035-padding-cons/foo.c new file mode 100644 index 000000000..3b3bdd9b0 --- /dev/null +++ b/testsuite/tests/O916-035-padding-cons/foo.c @@ -0,0 +1,11 @@ +static int +foo (void) +{ + return 0; +} + +int +main (void) +{ + return foo (); +} diff --git a/testsuite/tests/O916-035-padding-cons/test.opt b/testsuite/tests/O916-035-padding-cons/test.opt new file mode 100644 index 000000000..b0fbd8dd5 --- /dev/null +++ b/testsuite/tests/O916-035-padding-cons/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Check behavior specific to binary traces diff --git a/testsuite/tests/O916-035-padding-cons/test.py b/testsuite/tests/O916-035-padding-cons/test.py new file mode 100644 index 000000000..035b11aab --- /dev/null +++ b/testsuite/tests/O916-035-padding-cons/test.py @@ -0,0 +1,231 @@ +import os.path + +from SUITE.control import target_info +from SUITE.context import env, thistest +from SUITE.cutils import Wdir, contents_of, match, text_to_file +from SUITE.tutils import ( + exepath_to, + gprfor, + gprbuild, + tracename_for, + xcov, + xrun, +) + + +# This test checks that GNATcoverage properly matches padding instructions... +# and the ones that are not! +# +# A bit of context: on some platforms such as Windows, the executable binary +# format does not encode the length of symbols. As a result, when extracting +# routines bytes, GNATcoverage also fetches instructions inserted by the linker +# to pad bytes before the next routine (for alignemnt purposes). This triggers +# issues during consolidation as GNATcoverage assumes that all instances of a +# consolidated routine are binary equivalent: if one has padding bytes but not +# another one, GNATcoverage needs to know which instructions are there for +# padding so that it can ignore them. +# +# For instance: imagine we have the following routine instances: +# : +# [regular instructions] +# : +# [regular instructions] +# nop +# When consolidating the two, GNATcoverage needs to acknowledge that the NOP +# can be discarded in order to have two routines with the same instructions. +# +# This testcase does exactly that: it has one reference assembly file got from +# the compilation of a C source (one assembly file per platform: see foo.c and +# foo-*.s). This reference assembly file is built as a program and we also +# generate variants of this assembly file to embed various padding (and +# not-padding!) instructions. Then, we generate trace for all of these and we +# try to consolidate them: then we only have to check that GNATcoverage raises +# errors for variants with non-padding instructions and behaves fine with +# padding ones. + + +# As the set of padding instructions is completely architecture-dependent (we +# are talking about ISA), we need some testcase database. Upper-case ones come +# from the Intel Manual (look for: Recommended Multi-Byte Sequence of NOP +# Instruction). + +insns_x86 = [ + # 1-byte padding + (True, "nop"), + # 2-bytes padding + (True, "xchg %ax, %ax"), + (False, "xchg %ax, %bx"), + (True, "# 66 NOP\n" ".byte 0x66, 0x90"), + # 3-bytes padding + (True, "lea 0x0(%eax),%eax"), + (True, "lea 0x0(%esi),%esi"), + (False, "lea 0x0(%eax),%esi"), + (False, "lea 0x1(%eax),%eax"), + (False, "lea 0x0(%eax,%eax),%eax"), + (False, "lea 0x0(%eax,%eax,2),%eax"), + (True, "lea 0x0(%eax,2),%eax"), + (True, "# NOP DWORD ptr [EAX]\n" ".byte 0x0F, 0x1F, 0x00"), + # 4-bytes padding + (True, "# lea 0x0(%esi,%eiz,1),%esi\n" ".byte 0x8d, 0x74, 0x26, 0x00"), + (True, "# lea 0x0(%esi,%eiz,2),%esi\n" ".byte 0x8d, 0x74, 0x66, 0x00"), + (False, "# lea 0x0(%ebp,%eiz,1),%esi\n" ".byte 0x8d, 0x74, 0x25, 0x00"), + (False, "# lea 0x0(%esi,%esi,1),%esi\n" ".byte 0x8d, 0x74, 0x36, 0x00"), + (True, "# NOP DWORD ptr [EAX + 00H]\n" ".byte 0x0F, 0x1F, 0x40, 0x00"), + # 5-bytes padding + ( + True, + "# NOP DWORD ptr [EAX + EAX*1 + 00H]\n" + ".byte 0x0F, 0x1F, 0x44, 0x00, 0x00", + ), + # 6-bytes padding + ( + True, + "# lea 0x0(%esi),%esi\n" ".byte 0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(%eax),%esi\n" ".byte 0x8d, 0xb0, 0x00, 0x00, 0x00, 0x00", + ), + ( + True, + "# 66 NOP DWORD ptr [EAX + EAX*1 + 00H]\n" + ".byte 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00", + ), + # 7-bytes padding + ( + True, + "# lea 0x0(%esi,%eiz,1),%esi\n" + ".byte 0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(%ebp,%eiz,1),%esi\n" + ".byte 0x8d, 0xb4, 0x25, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(,%eiz,1),%esi\n" + ".byte 0x8d, 0x34, 0x25, 0x00, 0x00, 0x00, 0x00", + ), + ( + True, + "# lea 0x0(,%esi,1),%esi\n" + ".byte 0x8d, 0x34, 0x35, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(,%edi,1),%esi\n" + ".byte 0x8d, 0x34, 0x3d, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(%eax,%eax,1),%esi\n" + ".byte 0x8d, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00", + ), + ( + True, + "# NOP DWORD ptr [EAX + 00000000H]\n" + ".byte 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00", + ), + # 8-bytes padding + ( + True, + "# NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n" + ".byte 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00", + ), + # 9-bytes padding + ( + True, + "# 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n" + ".byte 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00", + ), +] + + +test_database = { + "x86-linux": insns_x86, + "x86-windows": insns_x86, +} + + +def run_test(platform, insns): + asm_src = os.path.abspath("foo-{}.s".format(platform)) + Wdir("tmp_") + + def build_material(name, padding_insn=None): + tmp = Wdir("build-{}".format(name)) + + asm_code = contents_of(asm_src).format(padding=padding_insn or "") + asm_filename = text_to_file(asm_code, "foo.s") + project = gprfor( + [asm_filename], srcdirs=["."], objdir=".", langs=["Asm"] + ) + # The assembly files already contain debug information: ask the + # assembler not to produce it itself. + gprbuild(project, extracargs="-g0") + xrun(exepath_to("foo")) + trace_name = os.path.abspath(tracename_for("foo")) + + tmp.to_homedir() + return trace_name + + # First, build all test material: build programs (reference and + # with-padding programs) and generate traces for them. + + trace_ref = build_material("ref") + traces = [] + for i, (_, insn) in enumerate(insns): + traces.append(build_material(str(i), insn)) + + # Then try to consolidate each with-padding program with the reference one + routine = target_info().to_platform_specific_symbol("foo") + for i, ((is_padding, insn), trace_file) in enumerate(zip(insns, traces)): + args = [ + "coverage", + "--level=insn", + "--annotate=asm", + "--routines={}".format(routine), + trace_ref, + trace_file, + ] + out_file = "object-cons-{}.txt".format(i) + p = xcov(args, out=out_file, register_failure=False) + + insn_label = insn.split("\n")[0] + consolidation_failed = p.status != 0 + command = "gnatcov {}".format(" ".join(args)) + + # First, if consolidation failed, make sure it is because of symbol + # matching. + thistest.fail_if( + consolidation_failed + and not match("TRACES_NAMES.CONSOLIDATION_ERROR", out_file), + '[{}] "gnatcov coverage" failed in an unexpected way\n' + " Command was: {}".format(i, command), + ) + + # Now, check if GNATcoverage correctly matched inserted code as padding + # (or as no padding). + if is_padding: + thistest.fail_if( + consolidation_failed, + '[{}] "{}" was not considered as padding (it is)\n' + " Command was: {}".format(i, insn_label, command), + ) + else: + thistest.fail_if( + not consolidation_failed, + '[{}] "{}" was considered as padding (it is not)\n' + " Command was: {}".format(i, insn_label, command), + ) + + +platform = env.target.platform +try: + insns = test_database[platform] +except KeyError: + thistest.comment("Nothing to test for {}".format(platform)) +else: + run_test(platform, insns) + +thistest.result() diff --git a/testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb b/testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb new file mode 100644 index 000000000..d67dbe807 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb @@ -0,0 +1,8 @@ +with Pkg; + +-- This is prj1's foo.adb + +procedure Foo is +begin + Pkg.Do_Nothing; +end Foo; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb new file mode 100644 index 000000000..899286010 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + procedure Do_Nothing is + begin + null; + end Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads new file mode 100644 index 000000000..0fca99536 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb b/testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb new file mode 100644 index 000000000..4557dafd7 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb @@ -0,0 +1,10 @@ +with Pkg; + +-- This is prj2's foo.adb + +procedure Foo is +begin + for I in 1 .. 10 loop + Pkg.Do_Nothing; + end loop; +end Foo; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb new file mode 100644 index 000000000..899286010 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + procedure Do_Nothing is + begin + null; + end Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads new file mode 100644 index 000000000..0fca99536 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/test.opt b/testsuite/tests/OA16-009-exec-prefix/test.opt new file mode 100644 index 000000000..1aa3b57f9 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test for --exec-prefix, which is useless without binary traces diff --git a/testsuite/tests/OA16-009-exec-prefix/test.py b/testsuite/tests/OA16-009-exec-prefix/test.py new file mode 100644 index 000000000..343fce512 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/test.py @@ -0,0 +1,75 @@ +"""Test that the --exec-prefix option is implemented properly.""" + +import os +import os.path +import shutil + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import ( + exename_for, + tracename_for, + gprfor, + gprbuild, + xrun, + xcov, +) + + +# This test needs a clean temporary directory because already existing files +# from previous testsuite runs will disturb the executable lookup process. +if os.path.exists("tmp_"): + shutil.rmtree("tmp_") +wd = Wdir("tmp_") + +# Build the two set of sources as two projects. Each one has its own object +# directory (which is the exec directory as well). +for src_dir in ("prj1", "prj2"): + obj_dir = "obj-{}".format(src_dir) + gprbuild( + gprfor( + srcdirs=[os.path.join("..", src_dir)], + objdir=obj_dir, + exedir=obj_dir, + mains=["foo.adb"], + ) + ) + +exename = exename_for("foo") +tracename = tracename_for("foo") + +prj1_exe = os.path.join("obj-prj1", exename) +prj2_exe = os.path.join("obj-prj2", exename) +doesnotexist_exe = os.path.join("doesnotexist", exename) + +# Generate traces and coverage report for prj2's foo.adb while there is a "foo" +# executable in the current directory: make sure it works on prj2's program by +# making sure we find prj2 source chunks in Xcov reports. +shutil.copy(prj1_exe, exename) +xrun([prj2_exe]) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos={}".format(os.path.join("obj-prj2", "foo.ali")), + tracename, + ] +) +thistest.fail_if( + "This is prj2's foo.adb" not in contents_of("foo.adb.xcov"), + '"gnatcov coverage" did not use the correct program', +) + +# Now, when the provided path does not exists, make sure GNATcoverage does not +# find the executable in the current directory without the --exec-prefix +# option. +p = xrun([doesnotexist_exe], register_failure=False) +thistest.fail_if( + p.status == 0, '"gnatcov run" found a program without --exec-prefix' +) + +# And finally make sure it finds the executable with --exec-prefix +p = xrun([doesnotexist_exe, "--exec-prefix=obj-prj2"], register_failure=True) + +thistest.result() diff --git a/testsuite/tests/OA16-009-windows-suffix/foo.adb b/testsuite/tests/OA16-009-windows-suffix/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/OA16-009-windows-suffix/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/OA16-009-windows-suffix/test.opt b/testsuite/tests/OA16-009-windows-suffix/test.opt new file mode 100644 index 000000000..1c3d0106a --- /dev/null +++ b/testsuite/tests/OA16-009-windows-suffix/test.opt @@ -0,0 +1,2 @@ +bin-traces,windows-host +ALL DEAD This test variant has platform specific expectations and checks "gnatcov run" (bin traces specific) diff --git a/testsuite/tests/OA16-009-windows-suffix/test.py b/testsuite/tests/OA16-009-windows-suffix/test.py new file mode 100644 index 000000000..0cf25b6fc --- /dev/null +++ b/testsuite/tests/OA16-009-windows-suffix/test.py @@ -0,0 +1,39 @@ +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov, xrun + + +wd = Wdir("tmp_") +gprbuild(gprfor(srcdirs=[".."], mains=["foo.adb"])) + +# We want to check that "gnatcov run" will find the executable even though the +# input casing is different and even though it misses the ".exe" suffix. +# +# This test runs only on Windows, and binary traces support for Windows is not +# supported anymore, so executables produced by gprbuild by default never have +# the "exe" extension. +os.rename("foo", "Foo.Exe") +xrun("foo") + +# Here, we also want to check that the default filename for the trace file is +# based on the actual filesystem name, not the name "gnatcov run" received in +# the command line. +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos=obj\\foo.ali", + "Foo.Exe.trace", + ] +) + +thistest.fail_if( + not os.path.exists("foo.adb.xcov"), + '"gnatcov coverage" did not produce a XCOV report for the main source' + " file.", +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/.gitignore b/testsuite/tests/OA27-059-inlined-separate-cons/.gitignore new file mode 100644 index 000000000..4425349ca --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/.gitignore @@ -0,0 +1,5 @@ +bin +obj +obj1 +obj2 +tmp_ diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr b/testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr new file mode 100644 index 000000000..5371325d3 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr @@ -0,0 +1,5 @@ +project Pkg is + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + +end Pkg; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb new file mode 100644 index 000000000..156fc47ee --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb @@ -0,0 +1,8 @@ +package body Helpers is + + function Id (I : Integer) return Integer is + begin + return I; + end Id; + +end Helpers; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads new file mode 100644 index 000000000..a0e520804 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads @@ -0,0 +1,3 @@ +package Helpers is + function Id (I : Integer) return Integer; +end Helpers; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb new file mode 100644 index 000000000..ba02473b0 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb @@ -0,0 +1,5 @@ +separate (Pkg) +procedure Test_Driver is +begin + null; +end Test_Driver; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb new file mode 100644 index 000000000..7f459a706 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb @@ -0,0 +1,14 @@ +package body Pkg is + + function Is_Even (I : Integer) return Boolean is + begin + if I mod 2 = 0 then + return True; + else + return False; + end if; + end Is_Even; + + procedure Test_Driver is separate; + +end Pkg; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads new file mode 100644 index 000000000..c374bba3e --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function Is_Even (I : Integer) return Boolean; + procedure Test_Driver; +end Pkg; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test.py b/testsuite/tests/OA27-059-inlined-separate-cons/test.py new file mode 100644 index 000000000..00688fd4d --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test.py @@ -0,0 +1,129 @@ +""" +Test that we have no consolidation error in source coverage for two binaries +that bring different versions of the same separate procedure. The separate +procedure is part of an unit of interest, but the coverage campaign ignores the +separate itself. +""" + +import os +import os.path +import shutil + +from SCOV.minicheck import ( + build_run_and_coverage, + checked_xcov, + check_xcov_reports, +) +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import tracename_for, xcov + + +wd = Wdir("tmp_") + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return os.path.join("..", "{}.gpr".format(self.name)) + + @property + def main(self): + return "main_{}".format(self.name) + + def obj_dir(self, *args): + return os.path.join("..", self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join("..", "bin", *args) + + @property + def tracename(self): + return tracename_for("main_{}".format(self.name)) + + @property + def checkpoint(self): + return "{}.ckpt".format(self.name) + + +def clean_output_directory(): + if os.path.exists("output"): + shutil.rmtree("output") + os.mkdir("output") + + +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") +testcases = [test1, test2] + +covlevel = "stmt+decision" +extra_args = (["--units=pkg"],) +output_arg = "--output-dir=output" + + +# Build the test material (program and traces) and produce checkpoints +for testcase in testcases: + thistest.log(f"== {testcase.name} ==") + build_run_and_coverage( + gprsw=GPRswitches(root_project=testcase.project_file, units=["pkg"]), + covlevel=covlevel, + mains=[testcase.main], + ignored_source_files=["pkg-test_driver.adb"], + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=["--save-checkpoint", testcase.checkpoint], + out="ckpt-{}.log".format(testcase.name), + scos_for_run=False, + ) + +# When inlining is enabled, consolidation without checkpoints cannot work, even +# with --ignore-source-files. +if thistest.options.trace_mode == "bin" and "-O1" in thistest.suite_cargs_for( + "Ada" +): + p = xcov( + [ + "coverage", + "-c", + covlevel, + "--annotate=report", + output_arg, + test1.tracename, + test2.tracename, + ] + ) + thistest.fail_if( + p.status == 0, + '"gnatcov coverage" is supposed to complain about different symbols' + " during consolidation, but it did not.", + ) + +# Check that consolidation behaves as expected with the --ignore-source-files +# switch: expected number of reports and expected report content. +clean_output_directory() +checked_xcov( + [ + "coverage", + "-c", + covlevel, + "--annotate=xcov", + output_arg, + "-C", + test1.checkpoint, + "-C", + test2.checkpoint, + ], + "cons.log", +) + +# Finally, check we have the expected reports +check_xcov_reports( + "output", + {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5, 6, 8}}}, +) +thistest.result() diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr b/testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr new file mode 100644 index 000000000..59494366d --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr @@ -0,0 +1,7 @@ +project Test1 extends "pkg.gpr" is + for Source_Dirs use ("test1"); + for Main use ("main_test1.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj1"; + +end Test1; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb new file mode 100644 index 000000000..bed186fbb --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_Test1 is +begin + Pkg.Test_Driver; +end Main_Test1; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb new file mode 100644 index 000000000..b441fe324 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Helpers; + +separate (Pkg) +procedure Test_Driver is +begin + if not Is_Even (Helpers.Id (0)) then + Put_Line ("Error!"); + end if; +end Test_Driver; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr b/testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr new file mode 100644 index 000000000..0dc0d50a5 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr @@ -0,0 +1,7 @@ +project Test2 extends "pkg.gpr" is + for Source_Dirs use ("test2"); + for Main use ("main_test2.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj2"; + +end Test2; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb new file mode 100644 index 000000000..4df94b631 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_Test2 is +begin + Pkg.Test_Driver; +end Main_Test2; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb new file mode 100644 index 000000000..83c43eba6 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Helpers; + +separate (Pkg) +procedure Test_Driver is + +begin + + if Is_Even (Helpers.Id (Helpers.Id (1))) then + Put_Line ("Error!"); + end if; + +end Test_Driver; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore b/testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore new file mode 100644 index 000000000..4425349ca --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore @@ -0,0 +1,5 @@ +bin +obj +obj1 +obj2 +tmp_ diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr new file mode 100644 index 000000000..f917b4339 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr @@ -0,0 +1,16 @@ +project Pkg_Under_Test is + + for Source_Dirs use ("src_under_test"); + for Exec_Dir use "bin"; + for Object_Dir use "obj"; + + package Coverage is + for Switches ("coverage") use + ("--level=stmt+decision", "--annotate=xcov"); + for Switches ("instrument") use ("--level=stmt+decision"); + for Units use ("Pkg_Under_Test"); + for Ignored_Source_Files use ("pkg_under_test-some_procedure.adb"); + end Coverage; + + +end Pkg_Under_Test; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..fc818434d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb @@ -0,0 +1,6 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is +begin + null; +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb new file mode 100644 index 000000000..4c6a7306c --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb @@ -0,0 +1,6 @@ +separate (Pkg_Under_Test) + +procedure Some_Procedure is +begin + null; +end Some_Procedure; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb new file mode 100644 index 000000000..d2290fb5f --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb @@ -0,0 +1,17 @@ +with ADA.TEXT_IO; + +package body PKG_UNDER_TEST is + + procedure PROC_UNDER_TEST (A : in Integer) is + begin + if (A > 10) then + ADA.TEXT_IO.PUT_LINE ("A is over 10"); + else + ADA.TEXT_IO.PUT_LINE ("A is under 10"); + end if; + end PROC_UNDER_TEST; + + procedure PKG_TEST is separate; + procedure Some_Procedure is separate; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads new file mode 100644 index 000000000..3d7431733 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads @@ -0,0 +1,6 @@ +package PKG_UNDER_TEST is + + procedure PKG_TEST; + procedure Some_Procedure; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py new file mode 100644 index 000000000..92c1cab3d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py @@ -0,0 +1,119 @@ +""" +Using similar material as for OA27-059-separate-consolidation, test that the +Coverage'Ignore_Source_Files project attribute is overidden by the +--ignore-source-files command line argument. +""" + +import os.path + +from e3.fs import mkdir, rm, sync_tree + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild + + +wd = Wdir("tmp_") + +# Copy project sources in the temporary director +for f in [ + "pkg_under_test.gpr", + "src_under_test", + "test1", + "test1.gpr", + "test2", + "test2.gpr", +]: + sync_tree(os.path.join("..", f), f) + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return f"{self.name}.gpr" + + @property + def main(self): + return f"main_{self.name}" + + def obj_dir(self, *args): + return os.path.join(self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join("bin", *args) + + +def clean_output_directory(): + rm("output") + mkdir("output") + + +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") +testcases = [test1, test2] +gprsw_for_cov = GPRswitches(root_project="pkg_under_test.gpr") + +# The goal of this testcase is to check that the --ignore-source-files +# command-line argument, when provided, takes precedence over the +# Coverage'Ignored_Source_Files project attribute. +# +# In pkg_under_test.gpr, that attribute is defined so that +# pkg_under_test-some_procedure.adb is ignored. To check that +# --ignore-source-files take precedence, we pass it to ignore only +# pkg_under_test-pkg_test.adb, so that pkg_under_test-some_procedure.adb +# should show up in coverage reports. +overriding_ignored_source_file = "pkg_under_test-pkg_test.adb" + +# Build the test material: program and traces +trace_files = [] +for testcase in testcases: + xcov_args = build_and_run( + gprsw=GPRswitches(root_project=testcase.project_file), + covlevel=None, + mains=[testcase.main], + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=[], + ignored_source_files=[overriding_ignored_source_file], + gprsw_for_coverage=gprsw_for_cov, + scos_for_run=False, + ) + trace_files.append(xcov_args.pop()) + +# This testcase builds extending projects and then runs gnatcov on the extended +# project. This requires the extended project to have its own ALI/SID files, so +# build this project (in binary trace mode, to get ALI files) or instrument it +# (in source trace mode, to get SID files). Since instrumentation uses the +# "ignore source files" information, we also need to pass --ignore-source-files +# here. +if thistest.options.trace_mode == "bin": + gprbuild(gprsw_for_cov.root_project) +else: + xcov_instrument( + gprsw=gprsw_for_cov, + covlevel=None, + extra_args=[f"--ignore-source-files={overriding_ignored_source_file}"], + ) + +# The presence of pkg_under_test-some_procedure.adb and the absence of +# pkg_under_test-pkg_test.adb prove that --ignored-source-files took +# precedence over the Coverage'Ignored_Source_Files project attribute. +clean_output_directory() +p = checked_xcov(xcov_args + ["--output-dir=output"] + trace_files, "cons.log") +check_xcov_reports( + "output", + { + "pkg_under_test.ads.xcov": {}, + "pkg_under_test.adb.xcov": {"+": {7, 8, 10}}, + "pkg_under_test-some_procedure.adb.xcov": {"-": {5}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr new file mode 100644 index 000000000..5e0c3f34b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr @@ -0,0 +1,8 @@ +project Test1 extends "pkg_under_test" is + + for Source_Dirs use ("test1"); + for Main use ("main_test1.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj1"; + +end Test1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb new file mode 100644 index 000000000..f43dbb391 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST1 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..91abb676b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb @@ -0,0 +1,10 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(5); + PROC_UNDER_TEST(7); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr new file mode 100644 index 000000000..ddd07adc3 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr @@ -0,0 +1,8 @@ +project Test2 extends "pkg_under_test" is + + for Source_Dirs use ("test2"); + for Main use ("main_test2.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj2"; + +end Test2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb new file mode 100644 index 000000000..9f2707841 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST2 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..546a5d974 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb @@ -0,0 +1,9 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(15); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/.gitignore b/testsuite/tests/OA27-059-sep-cons-prj/.gitignore new file mode 100644 index 000000000..4425349ca --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/.gitignore @@ -0,0 +1,5 @@ +bin +obj +obj1 +obj2 +tmp_ diff --git a/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr b/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr new file mode 100644 index 000000000..a23fceecc --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr @@ -0,0 +1,16 @@ +project Pkg_Under_Test is + + for Source_Dirs use ("src_under_test"); + for Exec_Dir use "bin"; + for Object_Dir use "obj"; + + package Coverage is + for Switches ("coverage") use + ("--level=stmt+decision", "--annotate=xcov"); + for Switches ("instrument") use ("--level=stmt+decision"); + for Units use ("Pkg_Under_Test"); + for Ignored_Source_Files use ("pkg_under_test-pkg_test.adb"); + end Coverage; + + +end Pkg_Under_Test; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..fc818434d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb @@ -0,0 +1,6 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is +begin + null; +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb new file mode 100644 index 000000000..87089da4d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb @@ -0,0 +1,17 @@ +with ADA.TEXT_IO; + +package body PKG_UNDER_TEST is + + procedure PROC_UNDER_TEST (A : in Integer) is + begin + if (A > 10) then + ADA.TEXT_IO.PUT_LINE ("A is over 10"); + else + ADA.TEXT_IO.PUT_LINE ("A is under 10"); + end if; + end PROC_UNDER_TEST; + + + procedure PKG_TEST is separate; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads new file mode 100644 index 000000000..9ca0a0d9b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads @@ -0,0 +1,5 @@ +package PKG_UNDER_TEST is + + procedure PKG_TEST; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test.py b/testsuite/tests/OA27-059-sep-cons-prj/test.py new file mode 100644 index 000000000..cb8c039e6 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test.py @@ -0,0 +1,99 @@ +""" +Using similar material as for OA27-059-separate-consolidation, test that the +Coverage'Ignore_Source_Files project attribute is handled correctly. +""" + +import os.path + +from e3.fs import mkdir, rm, sync_tree + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild + + +wd = Wdir("tmp_") + +# Copy project sources in the temporary director +for f in [ + "pkg_under_test.gpr", + "src_under_test", + "test1", + "test1.gpr", + "test2", + "test2.gpr", +]: + sync_tree(os.path.join("..", f), f) + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return f"{self.name}.gpr" + + @property + def main(self): + return f"main_{self.name}" + + def obj_dir(self, *args): + return os.path.join(self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join("bin", *args) + + +def clean_output_directory(): + rm("output") + mkdir("output") + + +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") +testcases = [test1, test2] +gprsw_for_cov = GPRswitches(root_project="pkg_under_test.gpr") + +# Build the test material: program and traces +trace_files = [] +for testcase in testcases: + xcov_args = build_and_run( + gprsw=GPRswitches(root_project=testcase.project_file), + covlevel=None, + mains=[testcase.main], + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=[], + gprsw_for_coverage=gprsw_for_cov, + scos_for_run=False, + ) + trace_files.append(xcov_args.pop()) + +# This testcase builds extending projects and then runs gnatcov on the extended +# project. This requires the extended project to have its own ALI/SID files, so +# build this project (in binary trace mode, to get ALI files) or instrument it +# (in source trace mode, to get SID files). +if thistest.options.trace_mode == "bin": + gprbuild(gprsw_for_cov.root_project) +else: + xcov_instrument(gprsw=gprsw_for_cov, covlevel=None) + +# Check that the Ignore_Source_Files project attribute makes gnatcov ignore the +# conflicting symbols between test1 and test2, and succeeds to create a report +# with the expected coverage data. +clean_output_directory() +p = checked_xcov(xcov_args + ["--output-dir=output"] + trace_files, "cons.log") +check_xcov_reports( + "output", + { + "pkg_under_test.ads.xcov": {}, + "pkg_under_test.adb.xcov": {"+": {7, 8, 10}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test1.gpr b/testsuite/tests/OA27-059-sep-cons-prj/test1.gpr new file mode 100644 index 000000000..5e0c3f34b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test1.gpr @@ -0,0 +1,8 @@ +project Test1 extends "pkg_under_test" is + + for Source_Dirs use ("test1"); + for Main use ("main_test1.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj1"; + +end Test1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb b/testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb new file mode 100644 index 000000000..f43dbb391 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST1 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..91abb676b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb @@ -0,0 +1,10 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(5); + PROC_UNDER_TEST(7); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test2.gpr b/testsuite/tests/OA27-059-sep-cons-prj/test2.gpr new file mode 100644 index 000000000..ddd07adc3 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test2.gpr @@ -0,0 +1,8 @@ +project Test2 extends "pkg_under_test" is + + for Source_Dirs use ("test2"); + for Main use ("main_test2.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj2"; + +end Test2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb b/testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb new file mode 100644 index 000000000..9f2707841 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST2 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..546a5d974 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb @@ -0,0 +1,9 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(15); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr b/testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr new file mode 100644 index 000000000..381f24b46 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr @@ -0,0 +1,8 @@ +project PKG_UNDER_TEST is + + for SOURCE_DIRS use ("src_under_test"); + + for EXEC_DIR use "bin"; + for OBJECT_DIR use "obj"; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb new file mode 100644 index 000000000..87089da4d --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb @@ -0,0 +1,17 @@ +with ADA.TEXT_IO; + +package body PKG_UNDER_TEST is + + procedure PROC_UNDER_TEST (A : in Integer) is + begin + if (A > 10) then + ADA.TEXT_IO.PUT_LINE ("A is over 10"); + else + ADA.TEXT_IO.PUT_LINE ("A is under 10"); + end if; + end PROC_UNDER_TEST; + + + procedure PKG_TEST is separate; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads new file mode 100644 index 000000000..9ca0a0d9b --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads @@ -0,0 +1,5 @@ +package PKG_UNDER_TEST is + + procedure PKG_TEST; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py new file mode 100644 index 000000000..760c59998 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -0,0 +1,126 @@ +""" +Test that we have no consolidation error in source coverage for two binaries +that bring different versions of the same separate procedure. The separate +procedure is part of an unit of interest, but the coverage campaign ignores the +separate itself. +""" + +import glob +import os +import os.path +import shutil + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +# Clean up projects build artifacts +for obj_dir in ("bin", "obj1", "obj2"): + if os.path.exists(obj_dir): + shutil.rmtree(obj_dir) + +wd = Wdir("tmp_") + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return os.path.join("..", "{}.gpr".format(self.name)) + + @property + def main(self): + return "main_{}".format(self.name) + + def obj_dir(self, *args): + return os.path.join("..", self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join("..", "bin", *args) + + +def clean_objdir(): + if os.path.exists("output"): + shutil.rmtree("output") + os.mkdir("output") + for t in glob.glob("*.srctrace"): + os.unlink(t) + + +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") +testcases = [test1, test2] + + +def build_and_run_tests(ignored_source_files=None): + """ + Build the test material: program and traces. + """ + trace_files = [] + for testcase in testcases: + xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=testcase.project_file, units=["pkg_under_test"] + ), + covlevel="stmt+decision", + mains=[testcase.main], + ignored_source_files=ignored_source_files, + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=["--annotate=xcov", "--output-dir=output"], + scos_for_run=False, + ) + + # Rename the trace file so that 1) the next iteration does not + # overwrite it if trace filenames are stable and 2) we get + # deterministic filenames, useful for warning baselines below. + filename = xcov_args.pop() + renamed = f"t-{testcase.name}.srctrace" + os.rename(filename, renamed) + trace_files.append(renamed) + + return xcov_args + trace_files + + +# Build and run tests without ignored source files. Check that we indeed have a +# consolidation error by default. +clean_objdir() +xcov_args = build_and_run_tests() +bin_traces = thistest.options.trace_mode == "bin" +p = xcov(xcov_args, out="cons-1.log", register_failure=False) +if bin_traces: + thistest.fail_if( + p.status == 0, + '"gnatcov coverage" is supposed to complain about different symbols' + " during consolidation, but it did not.", + ) +else: + thistest.fail_if_not_equal( + "'gnatcov coverage' output (cons-1.log)", + "warning: traces for separate pkg_under_test.pkg_test (from" + " t-test1.srctrace) are inconsistent with the corresponding Source" + " Instrumentation Data", + contents_of("cons-1.log").strip(), + ) + +# Build and run tests with ignored source files. Check that the new option +# makes it ignore the problematic symbols, and succeeds to create a report with +# the expected coverage data. +clean_objdir() +xcov_args = build_and_run_tests(["pkg_under_test-pkg_test.adb"]) +p = checked_xcov(xcov_args, "cons-2.log") +check_xcov_reports( + "output", + { + "pkg_under_test.adb.xcov": {"+": {7, 8, 10}}, + "pkg_under_test.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-separate-consolidation/test1.gpr b/testsuite/tests/OA27-059-separate-consolidation/test1.gpr new file mode 100644 index 000000000..bb4754a75 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test1.gpr @@ -0,0 +1,10 @@ +project TEST1 is + + for SOURCE_DIRS use ("src_under_test", "test1"); + + for MAIN use ("main_test1.adb"); + + for EXEC_DIR use "bin"; + for OBJECT_DIR use "obj1"; + +end TEST1; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb b/testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb new file mode 100644 index 000000000..f43dbb391 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST1 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST1; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..91abb676b --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb @@ -0,0 +1,10 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(5); + PROC_UNDER_TEST(7); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test2.gpr b/testsuite/tests/OA27-059-separate-consolidation/test2.gpr new file mode 100644 index 000000000..2cca9363d --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test2.gpr @@ -0,0 +1,10 @@ +project TEST2 is + + for SOURCE_DIRS use ("src_under_test", "test2"); + + for MAIN use ("main_test2"); + + for EXEC_DIR use "bin"; + for OBJECT_DIR use "obj2"; + +end TEST2; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb b/testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb new file mode 100644 index 000000000..9f2707841 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST2 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST2; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..546a5d974 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb @@ -0,0 +1,9 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(15); + +end PKG_TEST; diff --git a/testsuite/tests/OB23-036/foo.adb b/testsuite/tests/OB23-036/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/OB23-036/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/OB23-036/test.opt b/testsuite/tests/OB23-036/test.opt new file mode 100644 index 000000000..b553eb717 --- /dev/null +++ b/testsuite/tests/OB23-036/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disp-routines, specific to binary trace mode diff --git a/testsuite/tests/OB23-036/test.py b/testsuite/tests/OB23-036/test.py new file mode 100644 index 000000000..7962fc26d --- /dev/null +++ b/testsuite/tests/OB23-036/test.py @@ -0,0 +1,28 @@ +""" +Test that "gnatcov disp-routines" command does not crash with twice the same +program. +""" + +import os +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exename_for, gprbuild, gprfor, xcov + + +wd = Wdir("tmp_") + +gprbuild(gprfor(srcdirs=[os.path.join(wd.homedir)], mains=["foo.adb"])) +exename = exename_for("foo") + +xcov( + ["disp-routines", "--include", exename, "--exclude", exename], + out="disp-routines.out", +) +thistest.fail_if( + contents_of("disp-routines.out") != "", + '"gnatcov disp-routines" did not yield the expected list of routines', +) + +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads new file mode 100644 index 000000000..d53e7a32a --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads @@ -0,0 +1,38 @@ +pragma Ada_2012; + +package Tcheck is + pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex + + type SI is new Int with private; + type CI is new Int with private; + type STI is new Int with private; + type CTI is new Int with private; + +private + + -- Invariant Aspects, Simple then Complex + + type SI is new Int with null record + with Invariant => SI.Value <= SI.UB; -- # si + + type CI is new Int with null record + with Invariant => + CI.Value <= CI.UB and then CI.Value > 0; -- # ci + + -- Type_Invariant Aspects, Simple then Complex + + type STI is new Int with null record + with Type_Invariant => STI.Value > 0; -- # si + + type CTI is new Int with null record + with Type_Invariant => + CTI.Value <= CTI.UB and then CTI.Value > 0; -- # ci + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads new file mode 100644 index 000000000..d5ac47bc6 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads @@ -0,0 +1,26 @@ +pragma Ada_2012; + +package Tnocheck is + pragma Assertion_Policy (Invariant => Disable, Type_Invariant => Disable); + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex + + type SI is new Int with private; + type STI is new Int with private; + +private + + -- Invariant and Type_Invariant Aspects, Simple + + type SI is new Int with null record + with Invariant => SI.Value <= SI.UB; -- # si + + type STI is new Int with null record + with Type_Invariant => STI.Value > 0; -- # si + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt b/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt new file mode 100644 index 000000000..afdb47546 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt @@ -0,0 +1 @@ +7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/test.py b/testsuite/tests/OB26-040-type-invariants/Aspects/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb new file mode 100644 index 000000000..075998536 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb @@ -0,0 +1,18 @@ +with Types_A; use Types_A; + +procedure Test_T is + SIO : SI (UB => 5); + CIO : CI (UB => 2); + STIO : STI (UB => 10); + CTIO : CTI (UB => 4); + +begin + null; +end; + +--# types_a.ads +-- /base/ l! ## dF- +-- /si/ l! ## dF- +-- /ci/ l! ## dF- +-- /sti/ l! ## dF- +-- /cti/ l! ## dF- diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb new file mode 100644 index 000000000..7cb145d93 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb @@ -0,0 +1,8 @@ +package body Types_A is + + function Valid (X : Int) return Boolean is + begin + return X.Value <= X.UB; + end; + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads new file mode 100644 index 000000000..c459314f0 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads @@ -0,0 +1,41 @@ +pragma Ada_2012; + +package Types_A is + pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); + + type Int (UB : Integer) is tagged private + with Type_Invariant'Class => Valid (Int); -- # base + + function Valid (X : Int) return Boolean; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex + + type SI is new Int with private; + type CI is new Int with private; + type STI is new Int with private; + type CTI is new Int with private; + +private + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- Invariant Aspects, Simple then Complex + + type SI is new Int with null record + with Invariant => SI.Value > 0; -- # si + + type CI is new Int with null record + with Invariant => CI.Value > 0; -- # ci + + -- Type_Invariant Aspects, Simple then Complex + + type STI is new Int with null record + with Type_Invariant => STI.Value > 0; -- # sti + + type CTI is new Int with null record + with Type_Invariant => CTI.Value > 0; -- # cti + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt new file mode 100644 index 000000000..e248e7893 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt @@ -0,0 +1 @@ +ALL SKIP processing of Invariant_Class aspects, not defined yet diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads new file mode 100644 index 000000000..1529c8292 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads @@ -0,0 +1,40 @@ +pragma Ada_2012; + +package TCheck is + pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex. + + type SI is new Int with private; + type CI is new Int with private; + type STI is new Int with private; + type CTI is new Int with private; + +private + + -- Invariant Pragmas, Simple then Complex + + type SI is new Int with null record; + pragma Invariant + (SI, Check => SI.Value <= SI.UB); -- # si + + type CI is new Int with null record; + pragma Invariant + (CI, Check => CI.Value <= CI.UB and then CI.Value > 0); -- # ci + + -- Type_Invariant Pragmas, Simple then Complex + + type STI is new Int with null record; + pragma Type_Invariant + (STI, Check => STI.Value <= STI.UB); -- # si + + type CTI is new Int with null record; + pragma Type_Invariant + (CTI, Check => CTI.Value <= CTI.UB and then CTI.Value > 0); -- # ci + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads new file mode 100644 index 000000000..c092cd08f --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads @@ -0,0 +1,26 @@ +pragma Ada_2012; + +package TNocheck is + pragma Assertion_Policy (Invariant => Ignore, Type_Invariant => Ignore); + + type Int (UB : Integer) is tagged record + Value : Integer; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex. + + type SI is new Int with private; + type STI is new Int with private; + +private + + type SI is new Int with null record; + pragma Invariant + (SI, Check => SI.Value <= SI.UB); -- # si + + type STI is new Int with null record; + pragma Type_Invariant + (STI, Check => STI.Value <= STI.UB); -- # si + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt new file mode 100644 index 000000000..afdb47546 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt @@ -0,0 +1 @@ +7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/test.py b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/extra.opt b/testsuite/tests/OB26-040-type-invariants/extra.opt new file mode 100644 index 000000000..ee78ca999 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD extension declarations not available in 5.04 diff --git a/testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb b/testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb new file mode 100644 index 000000000..90f283c6c --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb @@ -0,0 +1,20 @@ +with tcheck; use tCheck; + +procedure Test_tCheck_T is + SIO : SI (UB => 5); + CIO : CI (UB => 2); + STIO : STI (UB => 10); + CTIO : CTI (UB => 4); + +begin + null; +end; + +--# tcheck.ads +-- +--%opts: --trace-mode=bin +-- /si/ l! ## dF- +-- /ci/ l! ## dF- +-- +-- In source-traces mode, we do not emit coverage obligations for the +-- pragmas by default, as we don't know what the assertion policy is. diff --git a/testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb b/testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb new file mode 100644 index 000000000..4232f6556 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb @@ -0,0 +1,22 @@ +with tNoCheck; use tNoCheck; + +procedure Test_tNocheck_T is + SIO : SI (UB => 5); + STIO : STI (UB => 10); +begin + null; +end; + +--# tnocheck.ads + +-- We expect only l. or l+ on type declarations in +-- this case (invariants disabled), which depends on +-- whether or not code gets generated, in turn varying +-- with the kind of runtime configuration. + +-- Not worth tracking the exact different scenarii, so +-- we don't state any particular expectation so l+ or +-- l. will go by regardless. + +-- If code gets generated and turns out uncovered, we +-- will get a failure out of an unexpected violation. diff --git a/testsuite/tests/P505-032-path-spaces/foo.adb b/testsuite/tests/P505-032-path-spaces/foo.adb new file mode 100644 index 000000000..8d89dda55 --- /dev/null +++ b/testsuite/tests/P505-032-path-spaces/foo.adb @@ -0,0 +1,5 @@ +with Ada.Text_IO; use Ada.Text_IO; +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/P505-032-path-spaces/test.opt b/testsuite/tests/P505-032-path-spaces/test.opt new file mode 100644 index 000000000..e0b4e7570 --- /dev/null +++ b/testsuite/tests/P505-032-path-spaces/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercizes "gnatcov run" diff --git a/testsuite/tests/P505-032-path-spaces/test.py b/testsuite/tests/P505-032-path-spaces/test.py new file mode 100644 index 000000000..a588fd8ec --- /dev/null +++ b/testsuite/tests/P505-032-path-spaces/test.py @@ -0,0 +1,37 @@ +""" +This test checks that "gnatcov run" behaves correctly when the main program and +the output file paths passed to it contain whitespaces. + +This used not to work with the DynamoRIO adapter on x86-windows. +""" + +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import ( + exename_for, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp/with spaces") + +gpr_file = gprfor(srcdirs=["../.."], mains=["foo.adb"], objdir="obj") +gprbuild(gpr_file) + +foo_exe = os.path.abspath(exename_for("foo")) +foo_trace = os.path.abspath(tracename_for("foo")) + +xrun(["-o", foo_trace, foo_exe]) +xcov(["coverage", "-P", gpr_file, "-c", "stmt", "-a", "xcov", foo_trace]) + +thistest.fail_if( + not match(r"4 \+: *Put_Line", os.path.join("obj", "foo.adb.xcov")), + "Statement at foo.adb:4 is not covered whereas it should be", +) +thistest.result() diff --git a/testsuite/tests/P526-035-origin-project/src-p1/p1.adb b/testsuite/tests/P526-035-origin-project/src-p1/p1.adb new file mode 100644 index 000000000..993018799 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/src-p1/p1.adb @@ -0,0 +1,12 @@ +package body P1 is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end P1; diff --git a/testsuite/tests/P526-035-origin-project/src-p1/p1.ads b/testsuite/tests/P526-035-origin-project/src-p1/p1.ads new file mode 100644 index 000000000..cd9d6a897 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/src-p1/p1.ads @@ -0,0 +1,5 @@ +package P1 is + + function Next (I : Integer) return Integer; + +end P1; diff --git a/testsuite/tests/P526-035-origin-project/src-p2/p2.adb b/testsuite/tests/P526-035-origin-project/src-p2/p2.adb new file mode 100644 index 000000000..23b6dcf98 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/src-p2/p2.adb @@ -0,0 +1,7 @@ +with P1; + +procedure P2 is + Dummy : constant Integer := P1.Next (1); +begin + null; +end P2; diff --git a/testsuite/tests/P526-035-origin-project/test.opt b/testsuite/tests/P526-035-origin-project/test.opt new file mode 100644 index 000000000..a2f909ef8 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/test.opt @@ -0,0 +1 @@ +src-traces DEAD Option "projects" not working rightfully with source coverage. diff --git a/testsuite/tests/P526-035-origin-project/test.py b/testsuite/tests/P526-035-origin-project/test.py new file mode 100644 index 000000000..264e2c628 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/test.py @@ -0,0 +1,85 @@ +""" +Check that gnatcov correctly handles the Origin_Project project attribute. +""" + +import glob +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, tracename_for + +tmp = Wdir("tmp_") + + +def xcov_list(): + """ + Return the list of *.xcov files in the "obj" subdirectory. + """ + return { + os.path.basename(f) for f in glob.glob(os.path.join("obj", "*.xcov")) + } + + +def clean_xcov(): + """ + Remove all *.xcov files in the "obj" subdirectory. + """ + for filename in glob.glob(os.path.join("obj", "*.xcov")): + os.remove(filename) + + +gprfor(prjid="p1", srcdirs=["../src-p1"], mains=None, langs="Ada") + +p2 = gprfor( + prjid="p2", + srcdirs=["../src-p2"], + mains=["p2.adb"], + deps=["p1"], + extra='for Origin_Project use "p1";', +) + +# Check that the Origin_Project provides a default for coverage analysis and +# that this default is overiden by the --projects switch. +for args, xcovs in [ + ([], {"p1.adb.xcov"}), + (["--projects=p2"], {"p2.adb.xcov"}), + (["--projects=p1", "--projects=p2"], {"p1.adb.xcov", "p2.adb.xcov"}), +]: + clean_xcov() + + # Build the projects and produce a trace for the main + # Passing the same --projects option as given to `gnatcov coverage` + # to be consistent with gnatcov use model. + # If these options are not accounted at instrumentation time, + # there won't be SID files for every wanted unit of interest. + build_run_and_coverage( + gprsw=GPRswitches(root_project=p2), + covlevel="stmt", + mains=["p2"], + extra_coverage_args=["-a", "xcov", "--no-subprojects"], + extra_args=args, + ) + + p2_trace = tracename_for("p2") + + expected = ( + "\n".join("* {}".format(f) for f in sorted(xcovs)) or " " + ) + got = ( + "\n".join("* {}".format(f) for f in sorted(xcov_list())) or " " + ) + + thistest.fail_if( + expected != got, + "[{}switches: {}]\n" + "Unexpected XCOV files. Expected:\n" + "{}\n" + "But got instead:\n" + "{}\n".format(p2_trace, " ".join(args), expected, got), + ) + +thistest.result() diff --git a/testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt b/testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt new file mode 100644 index 000000000..8f7220705 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt @@ -0,0 +1,37 @@ +drivers=test_add|test_area + +-- We have the test on map area using a mult operation from the Math unit. +-- +-- But this is not part of the tests of this unit per se, and is not specifying +-- any expectation for it. We expect the indirect coverage to be visible when +-- consolidating from traces, not from checkpoints. +-- +-- In source trace mode, the trace for the "area" test does not contain any +-- coverage information for the "math" unit, so trace-based consolidation +-- behaves like the checkpoint-based one. + +--# maps.adb +-- /eval/ l+ ## 0 + +--# math.adb + +-- %cons: traces %opts: --trace-mode=bin + +-- /check-add/ l+ ## 0 +-- /add/ l+ ## 0 +-- /check-mult/ l! ## dF- +-- /mult/ l+ ## 0 + +-- %cons: traces %opts: --trace-mode=src + +-- /check-add/ l! ## dF- +-- /add/ l+ ## 0 +-- /check-mult/ l- ## s- +-- /mult/ l- ## s- + +-- %cons: checkpoints + +-- /check-add/ l! ## dF- +-- /add/ l+ ## 0 +-- /check-mult/ l- ## s- +-- /mult/ l- ## s- diff --git a/testsuite/tests/P614-002-incidental-coverage/src/maps.adb b/testsuite/tests/P614-002-incidental-coverage/src/maps.adb new file mode 100644 index 000000000..e4bc2c70f --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/maps.adb @@ -0,0 +1,14 @@ + + +-- We happen to use the Math package for basic operations here, +-- but we're not part of the unit tests for this unit. + +with Math; use Math; + +package body Maps is + + function Area (R : Rectangle_T) return Natural is + begin + return Eval (Mult, R.L, R.W); -- # eval + end; +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/maps.ads b/testsuite/tests/P614-002-incidental-coverage/src/maps.ads new file mode 100644 index 000000000..c43312868 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/maps.ads @@ -0,0 +1,7 @@ +package Maps is + type Rectangle_T is record + L, W : Natural; + end record; + + function Area (R : Rectangle_T) return Natural; +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/math.adb b/testsuite/tests/P614-002-incidental-coverage/src/math.adb new file mode 100644 index 000000000..426783d0e --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/math.adb @@ -0,0 +1,23 @@ +package body Math is + + N_Adds, N_Mults : Natural := 0; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # inc + end; + + function Eval (Op : Binop_T; X, Y : Integer) return Integer is + begin + if Op = Add then -- # check-add + Inc (N_Adds); -- # add + return X + Y; -- # add + end if; + + if Op = Mult then -- # check-mult + Inc (N_Mults); -- # mult + return X * Y; -- # mult + end if; + end; + +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/math.ads b/testsuite/tests/P614-002-incidental-coverage/src/math.ads new file mode 100644 index 000000000..f9dbfa318 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/math.ads @@ -0,0 +1,5 @@ +package Math is + + type Binop_T is (Add, Mult); + function Eval (Op : Binop_T; X, Y : Integer) return Integer; +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb b/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb new file mode 100644 index 000000000..413f54770 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb @@ -0,0 +1,13 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Add is +begin + Assert (Eval (Op => Add, X => 4, Y => 5) = 9); +end; + +--# math.adb +-- /check-add/ l! ## dF- +-- /add/ l+ ## 0 +-- /check-mult/ l- ## s- +-- /mult/ l- ## s- diff --git a/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb b/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb new file mode 100644 index 000000000..17127bb77 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb @@ -0,0 +1,15 @@ +with Support; use Support; +with Maps; use Maps; + +-- This is a unit test for the Maps unit + +procedure Test_Area is + R : Rectangle_T := (L => 3, W => 9); +begin + Assert (Area (R) = 27); +end; + +-- No expectation on the Math unit here + +--# maps.adb +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/P614-002-incidental-coverage/test.py b/testsuite/tests/P614-002-incidental-coverage/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/P622-010-stack-restore/src/characterize.adb b/testsuite/tests/P622-010-stack-restore/src/characterize.adb new file mode 100644 index 000000000..45444187b --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/characterize.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Characterize (X : Integer) is + Ximg : constant String := Integer'Image (X); -- # decl +begin + if X > 0 then -- # first-cond + Put_Line (Ximg & " is Positive"); -- # first-stmt + elsif X < 0 then -- # second-cond + Put_Line (Ximg & " is Negative"); -- # second-stmt + else + Put_Line (Ximg & " is Null"); -- # third-stmt + end if; +end; diff --git a/testsuite/tests/P622-010-stack-restore/src/test_0.adb b/testsuite/tests/P622-010-stack-restore/src/test_0.adb new file mode 100644 index 000000000..d3049377d --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_0.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_0 is +begin + null; +end Test_0; + +--# characterize.adb +-- /decl/ l- ## s- +-- /first-cond/ l- ## s- +-- /first-stmt/ l- ## s- +-- /second-cond/ l- ## s- +-- /second-stmt/ l- ## s- +-- /third-stmt/ l- ## s- diff --git a/testsuite/tests/P622-010-stack-restore/src/test_n.adb b/testsuite/tests/P622-010-stack-restore/src/test_n.adb new file mode 100644 index 000000000..02152c474 --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_n.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_N is +begin + Characterize (-1); +end Test_N; + +--# characterize.adb +-- /decl/ l+ ## 0 +-- /first-cond/ l! ## dT- +-- /first-stmt/ l- ## s- +-- /second-cond/ l! ## dF- +-- /second-stmt/ l+ ## 0 +-- /third-stmt/ l- ## s- diff --git a/testsuite/tests/P622-010-stack-restore/src/test_p.adb b/testsuite/tests/P622-010-stack-restore/src/test_p.adb new file mode 100644 index 000000000..29d148c16 --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_p.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_P is +begin + Characterize (1); +end Test_P; + +--# characterize.adb +-- /decl/ l+ ## 0 +-- /first-cond/ l! ## dF- +-- /first-stmt/ l+ ## 0 +-- /second-cond/ l- ## s- +-- /second-stmt/ l- ## s- +-- /third-stmt/ l- ## s- diff --git a/testsuite/tests/P622-010-stack-restore/src/test_z.adb b/testsuite/tests/P622-010-stack-restore/src/test_z.adb new file mode 100644 index 000000000..af8c456fb --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_z.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_Z is +begin + Characterize (0); +end Test_Z; + +--# characterize.adb +-- /decl/ l+ ## 0 +-- /first-cond/ l! ## dT- +-- /first-stmt/ l- ## s- +-- /second-cond/ l! ## dT- +-- /second-stmt/ l- ## s- +-- /third-stmt/ l+ ## 0 diff --git a/testsuite/tests/P622-010-stack-restore/test.py b/testsuite/tests/P622-010-stack-restore/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/math.adb b/testsuite/tests/P907-005-ckpt-covlevel/src/math.adb new file mode 100644 index 000000000..426783d0e --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/math.adb @@ -0,0 +1,23 @@ +package body Math is + + N_Adds, N_Mults : Natural := 0; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # inc + end; + + function Eval (Op : Binop_T; X, Y : Integer) return Integer is + begin + if Op = Add then -- # check-add + Inc (N_Adds); -- # add + return X + Y; -- # add + end if; + + if Op = Mult then -- # check-mult + Inc (N_Mults); -- # mult + return X * Y; -- # mult + end if; + end; + +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/math.ads b/testsuite/tests/P907-005-ckpt-covlevel/src/math.ads new file mode 100644 index 000000000..2e567f79d --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/math.ads @@ -0,0 +1,4 @@ +package Math is + type Binop_T is (Add, Mult); + function Eval (Op : Binop_T; X, Y : Integer) return Integer; +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb b/testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb new file mode 100644 index 000000000..139595116 --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Add is +begin + Assert (Eval (Op => Add, X => 4, Y => 5) = 9); +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb b/testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb new file mode 100644 index 000000000..e0b809d3a --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Mult is +begin + Assert (Eval (Op => Mult, X => 4, Y => 5) = 20); +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/test.py b/testsuite/tests/P907-005-ckpt-covlevel/test.py new file mode 100644 index 000000000..94643283b --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/test.py @@ -0,0 +1,94 @@ +import os +import os.path +import re +import shutil + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir("tmp_") + + +def create_checkpoint(name, covlevel): + gpr_exe_dir = "exe-{}".format(name) + gpr_obj_dir = "obj-{}".format(name) + prj_file = gprfor( + mains=["test_{}.adb".format(name)], + prjid=name, + srcdirs=os.path.join("..", "src"), + objdir=gpr_obj_dir, + exedir=gpr_exe_dir, + extra="package Coverage is\n" + ' for Units use ("math");\n' + "end Coverage;", + ) + ckpt = "test_{}.ckpt".format(name) + build_run_and_coverage( + gprsw=GPRswitches(root_project=prj_file), + covlevel=covlevel, + mains=["test_{}".format(name)], + gpr_obj_dir=gpr_obj_dir, + gpr_exe_dir=gpr_exe_dir, + extra_coverage_args=["--save-checkpoint={}".format(ckpt)], + ) + return ckpt + + +def clean_output_directory(): + if os.path.exists("output"): + shutil.rmtree("output") + os.mkdir("output") + + +# Create two checkpoints with different coverage levels +add_ckpt = create_checkpoint("add", "stmt") +mult_ckpt = create_checkpoint("mult", "stmt+decision") + +# Consolidate both. The only attempt that is expected to suceed is the one +# with the weakest common coverage level criteria, i.e. stmt. +args = [ + "coverage", + "--annotate=xcov", + "--output-dir=output", + "-C", + add_ckpt, + "-C", + mult_ckpt, +] + +# Attempting to consolidate them in stmt+decision mode should fail since one +# checkpoint was produced with a weaker coverage criteria (stmt). +# TODO: refine the expected error message. +clean_output_directory() +p = xcov( + args + ["--level=stmt+decision"], + "cons-stmt-decision.log", + register_failure=False, +) +thistest.fail_if( + p.status == 0 + or not re.match( + r".*gnatcov.*: incompatible coverage level: .*test_add.*ckpt was" + r' produced with "stmt" but we expect at least "stmt\+decision"', + contents_of("cons-stmt-decision.log").strip(), + ), + "gnatcov did not complain about inconsistent coverage criteria across" + " input checkpoints", +) + +clean_output_directory() +xcov(args + ["--level=stmt"], "cons-stmt.log") + +expected = { + "math.adb.xcov": {"+": {7, 12, 13, 14, 17, 18, 19}}, + "math.ads.xcov": {}, +} + +# Finally, check we have the expected reports for the --level=stmt +# consolidation. +check_xcov_reports("output", expected, discard_empty=False) +thistest.result() diff --git a/testsuite/tests/P907-005-incremental/src/math.adb b/testsuite/tests/P907-005-incremental/src/math.adb new file mode 100644 index 000000000..426783d0e --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/math.adb @@ -0,0 +1,23 @@ +package body Math is + + N_Adds, N_Mults : Natural := 0; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # inc + end; + + function Eval (Op : Binop_T; X, Y : Integer) return Integer is + begin + if Op = Add then -- # check-add + Inc (N_Adds); -- # add + return X + Y; -- # add + end if; + + if Op = Mult then -- # check-mult + Inc (N_Mults); -- # mult + return X * Y; -- # mult + end if; + end; + +end; diff --git a/testsuite/tests/P907-005-incremental/src/math.ads b/testsuite/tests/P907-005-incremental/src/math.ads new file mode 100644 index 000000000..2e567f79d --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/math.ads @@ -0,0 +1,4 @@ +package Math is + type Binop_T is (Add, Mult); + function Eval (Op : Binop_T; X, Y : Integer) return Integer; +end; diff --git a/testsuite/tests/P907-005-incremental/src/test_add.adb b/testsuite/tests/P907-005-incremental/src/test_add.adb new file mode 100644 index 000000000..139595116 --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/test_add.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Add is +begin + Assert (Eval (Op => Add, X => 4, Y => 5) = 9); +end; diff --git a/testsuite/tests/P907-005-incremental/src/test_mult.adb b/testsuite/tests/P907-005-incremental/src/test_mult.adb new file mode 100644 index 000000000..e0b809d3a --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/test_mult.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Mult is +begin + Assert (Eval (Op => Mult, X => 4, Y => 5) = 20); +end; diff --git a/testsuite/tests/P907-005-incremental/test.py b/testsuite/tests/P907-005-incremental/test.py new file mode 100644 index 000000000..c81ca7a35 --- /dev/null +++ b/testsuite/tests/P907-005-incremental/test.py @@ -0,0 +1,61 @@ +import os +import os.path + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir("tmp_") + +# Generate a project for test drivers, build and run them to get trace files +prj_file = gprfor( + ["test_add.adb", "test_mult.adb"], + srcdirs=os.path.join("..", "src"), + extra="package Coverage is" + '\n for Units use ("math");' + "\nend Coverage;", +) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj_file), + covlevel="stmt+decision", + mains=["test_add", "test_mult"], + extra_coverage_args=[], +) + +# Extract trace files arguments from "xcov_args" +base_args = xcov_args[:-2] +add_trace = xcov_args[-2] +mult_trace = xcov_args[-1] + +# Now, consolidate one trace file after the other, accumulating results in a +# single checkpoint (this is incremental coverage). +checked_xcov( + base_args + ["--save-checkpoint=c1.ckpt", add_trace], "checkpoint-1.log" +) +checked_xcov( + base_args + + ["--checkpoint=c1.ckpt", "--save-checkpoint=c2.ckpt", mult_trace], + "checkpoint-2.log", +) + +# Generate the final report and check we have the expected result +checked_xcov( + base_args + ["--annotate=xcov", "--checkpoint=c2.ckpt", "--output-dir=."], + "report.log", +) + + +# Finally, check we have the expected reports +check_xcov_reports( + ".", + { + "math.adb.xcov": {"+": {7, 12, 13, 14, 18, 19}, "!": {17}}, + "math.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/P907-005-stubbing-generic/.gitignore b/testsuite/tests/P907-005-stubbing-generic/.gitignore new file mode 100644 index 000000000..e12db4626 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/.gitignore @@ -0,0 +1,2 @@ +sensors-gnatcov-instr +*.sid diff --git a/testsuite/tests/P907-005-stubbing-generic/common.gpr b/testsuite/tests/P907-005-stubbing-generic/common.gpr new file mode 100644 index 000000000..cf829a932 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/common.gpr @@ -0,0 +1,5 @@ +abstract project common is + package compiler is + for switches ("Ada") use ("-gnata"); + end compiler; +end common; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads b/testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads new file mode 100644 index 000000000..10909b979 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads @@ -0,0 +1,7 @@ +with Temperature_Control; +with Pressure_Control; + +package Int_Control is + package TC is new Temperature_Control (Integer); + package PC is new Pressure_Control (Integer); +end Int_Control; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb new file mode 100644 index 000000000..3667230fc --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb @@ -0,0 +1,22 @@ +package body Pressure_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 3; + + Live_Pressure : T := 6; + + procedure Update_Live_Pressure is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Pressure := Live_Pressure + 1; + end if; + end; + + function Current_Pressure return T is + begin + Update_Live_Pressure; + return Live_Pressure; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads new file mode 100644 index 000000000..c0585bb6c --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads @@ -0,0 +1,5 @@ +generic + type T is range <>; +package Pressure_Control is + function Current_Pressure return T; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr b/testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr new file mode 100644 index 000000000..c262fcf29 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr @@ -0,0 +1,3 @@ +project sensors is + for languages use ("Ada"); +end sensors; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb new file mode 100644 index 000000000..fef1aefbe --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb @@ -0,0 +1,22 @@ +package body Temperature_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 5; + + Live_Temperature : T := 0; + + procedure Update_Live_Temperature is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Temperature := Live_Temperature + 1; + end if; + end; + + function Current_Temperature return T is + begin + Update_Live_Temperature; + return Live_Temperature; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads new file mode 100644 index 000000000..06c689e59 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads @@ -0,0 +1,5 @@ +generic + type T is range <>; +package Temperature_Control is + function Current_Temperature return T; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb b/testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb new file mode 100644 index 000000000..489708a65 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb @@ -0,0 +1,6 @@ +package body Pressure_Control is + function Current_Pressure return T is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb b/testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb new file mode 100644 index 000000000..5588bd745 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb @@ -0,0 +1,6 @@ +package body Temperature_Control is + function Current_Temperature return T is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/test.py b/testsuite/tests/P907-005-stubbing-generic/test.py new file mode 100644 index 000000000..eface7a3a --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test.py @@ -0,0 +1,89 @@ +import os +import os.path +import shutil + +from SCOV.minicheck import ( + build_run_and_coverage, + checked_xcov, + check_xcov_reports, +) +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +class TestDriver(object): + def __init__(self, test_dir, exename): + self.test_dir = test_dir + self.exename = exename + + self.obj_dir = os.path.join("..", test_dir, "obj") + self.prj_file = os.path.join("..", test_dir, "test_runner.gpr") + self.ckpt_file = exename + ".ckpt" + + +test_drivers = [ + TestDriver("test_p", "tp1"), + TestDriver("test_t", "tt1"), + TestDriver("test_sensors", "ts1"), +] + + +# Cleanup any previous test run artefacts +for td in test_drivers: + if os.path.exists(td.obj_dir): + shutil.rmtree(td.obj_dir) + + +wd = Wdir("tmp_") + + +# Build projects, generate trace and checkpoints for each test drivers +for td in test_drivers: + build_run_and_coverage( + gprsw=GPRswitches(root_project=td.prj_file), + covlevel="stmt+decision", + mains=[td.exename], + gpr_obj_dir=td.obj_dir, + gpr_exe_dir=td.obj_dir, + extra_coverage_args=["--save-checkpoint", td.ckpt_file], + out="ckpt-{}.log".format(td.exename), + scos_for_run=False, + ) + + +# Now, generate the final report +ckpt_args = ["--checkpoint={}".format(td.ckpt_file) for td in test_drivers] +checked_xcov( + [ + "coverage", + "-P", + os.path.join("..", "sensors", "sensors.gpr"), + "--level=stmt+decision", + "--annotate=xcov", + "--output-dir=.", + ] + + ckpt_args, + "cons.log", +) + +# Finally, check we have the expected reports +check_xcov_reports( + ".", + { + "pressure_control.ads.xcov": {}, + "pressure_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, + }, + "temperature_control.ads.xcov": {}, + "temperature_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, + }, + }, +) + +thistest.result() diff --git a/testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr b/testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr new file mode 100644 index 000000000..5b9a81650 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_temperature", "."); + for Object_Dir use "obj"; + for Main use ("tp1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb b/testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb new file mode 100644 index 000000000..f4c953661 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb @@ -0,0 +1,10 @@ +with Int_Control; use Int_Control; + +procedure TP1 is + T : Integer; +begin + T := TC.Current_Temperature; + pragma Assert (T < 0); + T := PC.Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr b/testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr new file mode 100644 index 000000000..81f347636 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Main use ("ts1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control", "temperature_control"); + end Coverage; +end test_runner; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb b/testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb new file mode 100644 index 000000000..b2de37530 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb @@ -0,0 +1,10 @@ +with Int_Control; use Int_Control; + +procedure TS1 is + T : Integer; +begin + T := TC.Current_Temperature; + pragma Assert (T >= 0); + T := PC.Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr b/testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr new file mode 100644 index 000000000..09957b890 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_pressure", "."); + for Object_Dir use "obj"; + for Main use ("tt1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("temperature_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb b/testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb new file mode 100644 index 000000000..0e20b55df --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb @@ -0,0 +1,10 @@ +with Int_Control; use Int_Control; + +procedure TT1 is + T : Integer; +begin + T := TC.Current_Temperature; + pragma Assert (T >= 0); + T := PC.Current_Pressure; + pragma Assert (T < 0); +end; diff --git a/testsuite/tests/P907-005-stubbing/.gitignore b/testsuite/tests/P907-005-stubbing/.gitignore new file mode 100644 index 000000000..e12db4626 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/.gitignore @@ -0,0 +1,2 @@ +sensors-gnatcov-instr +*.sid diff --git a/testsuite/tests/P907-005-stubbing/common.gpr b/testsuite/tests/P907-005-stubbing/common.gpr new file mode 100644 index 000000000..cf829a932 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/common.gpr @@ -0,0 +1,5 @@ +abstract project common is + package compiler is + for switches ("Ada") use ("-gnata"); + end compiler; +end common; diff --git a/testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb new file mode 100644 index 000000000..1d27794a9 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb @@ -0,0 +1,22 @@ +package body Pressure_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 3; + + Live_Pressure : Integer := 6; + + procedure Update_Live_Pressure is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Pressure := Live_Pressure + 1; + end if; + end; + + function Current_Pressure return Integer is + begin + Update_Live_Pressure; + return Live_Pressure; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads new file mode 100644 index 000000000..f7138110d --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads @@ -0,0 +1,3 @@ +package Pressure_Control is + function Current_Pressure return Integer; +end; diff --git a/testsuite/tests/P907-005-stubbing/sensors/sensors.gpr b/testsuite/tests/P907-005-stubbing/sensors/sensors.gpr new file mode 100644 index 000000000..c262fcf29 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/sensors.gpr @@ -0,0 +1,3 @@ +project sensors is + for languages use ("Ada"); +end sensors; diff --git a/testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb new file mode 100644 index 000000000..845fc4698 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb @@ -0,0 +1,22 @@ +package body Temperature_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 5; + + Live_Temperature : Integer := 0; + + procedure Update_Live_Temperature is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Temperature := Live_Temperature + 1; + end if; + end; + + function Current_Temperature return Integer is + begin + Update_Live_Temperature; + return Live_Temperature; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads new file mode 100644 index 000000000..f51af2995 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads @@ -0,0 +1,3 @@ +package Temperature_Control is + function Current_Temperature return Integer; +end; diff --git a/testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb b/testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb new file mode 100644 index 000000000..9324a5d19 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb @@ -0,0 +1,6 @@ +package body Pressure_Control is + function Current_Pressure return Integer is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb b/testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb new file mode 100644 index 000000000..7a53a14f1 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb @@ -0,0 +1,6 @@ +package body Temperature_Control is + function Current_Temperature return Integer is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing/test.py b/testsuite/tests/P907-005-stubbing/test.py new file mode 100644 index 000000000..c1220ac03 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test.py @@ -0,0 +1,88 @@ +import os +import os.path +import shutil + +from SCOV.minicheck import ( + build_run_and_coverage, + checked_xcov, + check_xcov_reports, +) +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +class TestDriver(object): + def __init__(self, test_dir, exename): + self.test_dir = test_dir + self.exename = exename + + self.obj_dir = os.path.join("..", test_dir, "obj") + self.prj_file = os.path.join("..", test_dir, "test_runner.gpr") + self.ckpt_file = exename + ".ckpt" + + +test_drivers = [ + TestDriver("test_p", "tp1"), + TestDriver("test_t", "tt1"), + TestDriver("test_sensors", "ts1"), +] + + +# Cleanup any previous test run artefacts +for td in test_drivers: + if os.path.exists(td.obj_dir): + shutil.rmtree(td.obj_dir) + + +wd = Wdir("tmp_") + +# Build projects, generate trace and checkpoints for each test drivers +for td in test_drivers: + build_run_and_coverage( + gprsw=GPRswitches(root_project=td.prj_file), + covlevel="stmt+decision", + mains=[td.exename], + gpr_obj_dir=td.obj_dir, + gpr_exe_dir=td.obj_dir, + extra_coverage_args=["--save-checkpoint", td.ckpt_file], + out="ckpt-{}.log".format(td.exename), + scos_for_run=False, + ) + + +# Now, generate the final report +ckpt_args = ["--checkpoint={}".format(td.ckpt_file) for td in test_drivers] +checked_xcov( + [ + "coverage", + "-P", + os.path.join("..", "sensors", "sensors.gpr"), + "--level=stmt+decision", + "--annotate=xcov", + "--output-dir=.", + ] + + ckpt_args, + "cons.log", +) + +# Finally, check we have the expected reports +check_xcov_reports( + ".", + { + "pressure_control.ads.xcov": {}, + "pressure_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, + }, + "temperature_control.ads.xcov": {}, + "temperature_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, + }, + }, +) + +thistest.result() diff --git a/testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr b/testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr new file mode 100644 index 000000000..5b9a81650 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_temperature", "."); + for Object_Dir use "obj"; + for Main use ("tp1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing/test_p/tp1.adb b/testsuite/tests/P907-005-stubbing/test_p/tp1.adb new file mode 100644 index 000000000..e910eafed --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_p/tp1.adb @@ -0,0 +1,11 @@ +with Temperature_Control; use Temperature_Control; +with Pressure_Control; use Pressure_Control; + +procedure TP1 is + T : Integer; +begin + T := Current_Temperature; + pragma Assert (T < 0); + T := Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr b/testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr new file mode 100644 index 000000000..81f347636 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Main use ("ts1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control", "temperature_control"); + end Coverage; +end test_runner; diff --git a/testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb b/testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb new file mode 100644 index 000000000..828164c21 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb @@ -0,0 +1,11 @@ +with Temperature_Control; use Temperature_Control; +with Pressure_Control; use Pressure_Control; + +procedure TS1 is + T : Integer; +begin + T := Current_Temperature; + pragma Assert (T >= 0); + T := Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr b/testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr new file mode 100644 index 000000000..09957b890 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_pressure", "."); + for Object_Dir use "obj"; + for Main use ("tt1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("temperature_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing/test_t/tt1.adb b/testsuite/tests/P907-005-stubbing/test_t/tt1.adb new file mode 100644 index 000000000..f1d204011 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_t/tt1.adb @@ -0,0 +1,11 @@ +with Temperature_Control; use Temperature_Control; +with Pressure_Control; use Pressure_Control; + +procedure TT1 is + T : Integer; +begin + T := Current_Temperature; + pragma Assert (T >= 0); + T := Current_Pressure; + pragma Assert (T < 0); +end; diff --git a/testsuite/tests/P913-011-invalid-project/foo.adb b/testsuite/tests/P913-011-invalid-project/foo.adb new file mode 100644 index 000000000..e9f45d970 --- /dev/null +++ b/testsuite/tests/P913-011-invalid-project/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/P913-011-invalid-project/test.py b/testsuite/tests/P913-011-invalid-project/test.py new file mode 100644 index 000000000..b8a23e768 --- /dev/null +++ b/testsuite/tests/P913-011-invalid-project/test.py @@ -0,0 +1,31 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exename_for, gprbuild, gprfor, xcov + + +wd = Wdir("tmp_") +gprbuild(gprfor(["foo.adb"], srcdirs=[".."])) + +p = xcov( + ["run", "-P", "does_not_exist.gpr", exename_for("foo")], + out="gnatcov-run.out", + err="gnatcov-run.err", + register_failure=False, +) + +thistest.fail_if( + p.status != 1, + "gnatcov returned status code {}, but 1 expected".format(p.status), +) +thistest.fail_if_not_equal( + "'gnatcov run' output", "", contents_of("gnatcov-run.out") +) +thistest.fail_if_no_match( + "'gnatcov run' error output", + 'does_not_exist\\.gpr: error: project file ".*[/\\\\]does_not_exist\\.gpr"' + " not found\n" + ".*gnatcov.*: Could not load the project file, aborting.\n$", + contents_of("gnatcov-run.err"), +) + +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb new file mode 100644 index 000000000..7641add3d --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb @@ -0,0 +1,16 @@ +package body P1 is + + function F1 (A, B : Boolean) return Boolean; + pragma Inline (F1); + + function F1 (A, B : Boolean) return Boolean is + begin + return A and then B; -- # and + end; + + procedure Combine (A, B, C : Boolean) is + begin + R := F1 (A, B) or else C; -- # or + end; + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads new file mode 100644 index 000000000..43fce56ab --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads @@ -0,0 +1,15 @@ +package P1 is + + R : Boolean; + + procedure Combine (A, B, C : Boolean); + + -- A B and C R + -- 1 F X F F F + -- 2 T F F F F + -- 3 T T T X T + + -- 4 F X F T T + -- 5 T F F T T + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb new file mode 100644 index 000000000..fa6cd986e --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_1 is +begin + for X in False .. True loop + Combine (False, X, False); + Assert (R = False); + end loop; +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb new file mode 100644 index 000000000..2d6ed61d4 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_14 is +begin + Combine (False, False, False); + Assert (R = False); + Combine (False, False, True); + Assert (R = True); +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## c!:"F1" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb new file mode 100644 index 000000000..f37e587ad --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_2 is +begin + Combine (True, False, False); + Assert (R = False); +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb new file mode 100644 index 000000000..9f6c55eb8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_3 is +begin + for X in False .. True loop + Combine (True, True, X); + Assert (R = True); + end loop; +end; + + +--# p1.adb +-- /and/ l! ## eF- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb new file mode 100644 index 000000000..0740f9787 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_4 is +begin + for X in False .. True loop + Combine (False, X, True); + Assert (R = True); + end loop; +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb new file mode 100644 index 000000000..1a10c59ba --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_5 is +begin + Combine (True, False, True); + Assert (R = True); +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py new file mode 100644 index 000000000..6987337a8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb new file mode 100644 index 000000000..bef749e58 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb @@ -0,0 +1,13 @@ +package body P1 is + + function Orelse (B, C : Boolean) return Boolean is + begin + return B or else C; -- # or + end; + + procedure Combine (A, B, C, D : Boolean) is + begin + R := A and then Orelse (B, C) and then D; -- # comb + end; + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads new file mode 100644 index 000000000..a31d580ed --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads @@ -0,0 +1,18 @@ +package P1 is + + R : Boolean; + + function Orelse (B, C : Boolean) return Boolean; + pragma Inline (Orelse); + + procedure Combine (A, B, C, D : Boolean); + + -- A && (B C or) && D R + -- 1 F X X X X F + -- 2 T T X T F F + -- 3 T F T T F F + -- 4 T F F F X F + -- 5 T T X T T T + -- 6 T F T T T T + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb new file mode 100644 index 000000000..b4f623cd2 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb @@ -0,0 +1,16 @@ +with Support, P1; use Support, P1; + +procedure Test_1 is +begin + for Xbc in False .. True loop + for Xd in False .. True loop + Combine (False, Xbc, Xbc, Xd); + Assert (R = False); + end loop; + end loop; +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l- ## s- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb new file mode 100644 index 000000000..40d84c582 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb @@ -0,0 +1,18 @@ +with Support, P1; use Support, P1; + +procedure Test_1346 is + X : Boolean := False; +begin + Combine (False, X, X, X); -- 1 + Assert (R = False); + Combine (True, False, True, False); -- 3 + Assert (R = False); + Combine (True, False, False, X); -- 4 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l+ ## 0 +-- /or/ l! ## c!:"B" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb new file mode 100644 index 000000000..64cb7b802 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_2 is +begin + for X in False .. True loop + Combine (True, True, X, False); + Assert (R = False); + end loop; +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb new file mode 100644 index 000000000..9bd46de79 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_3 is +begin + Combine (True, False, True, False); + Assert (R = False); +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb new file mode 100644 index 000000000..ade34ef6e --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb @@ -0,0 +1,16 @@ +with Support, P1; use Support, P1; + +procedure Test_346 is + X : Boolean := False; +begin + Combine (True, False, True, False); -- 3 + Assert (R = False); + Combine (True, False, False, X); -- 4 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l! ## c!:"A" +-- /or/ l! ## c!:"B" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb new file mode 100644 index 000000000..d66b1bd47 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb @@ -0,0 +1,13 @@ +with Support, P1; use Support, P1; + +procedure Test_36 is +begin + Combine (True, False, True, False); -- 3 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l! ## c!:"A",c!:"Or" +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb new file mode 100644 index 000000000..ce8b75293 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_4 is +begin + Combine (True, False, False, False); + Assert (R = False); +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb new file mode 100644 index 000000000..f31af5c70 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb @@ -0,0 +1,15 @@ +with Support, P1; use Support, P1; + +procedure Test_46 is + X : Boolean := True; +begin + Combine (True, False, False, X); -- 4 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + + +--# p1.adb +-- /comb/ l! ## c!:"A",c!:"D" +-- /or/ l! ## c!:"B" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb new file mode 100644 index 000000000..a6d30425c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_5 is +begin + for X in False .. True loop + Combine (True, True, X, True); + Assert (R = True); + end loop; +end; + + +--# p1.adb +-- /comb/ l! ## eF- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb new file mode 100644 index 000000000..b807dde7c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_6 is +begin + Combine (True, False, True, True); + Assert (R = True); +end; + + +--# p1.adb +-- /comb/ l! ## eF- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py new file mode 100644 index 000000000..e4fa11967 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb new file mode 100644 index 000000000..8cc2c424d --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb @@ -0,0 +1,10 @@ +with Twisters; use Twisters; + +package body P1 is + + procedure Andthen (A, B, C : Boolean) is + begin + R := A and then Identity (B) and then C; -- # comb + end; + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads new file mode 100644 index 000000000..954b6d250 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads @@ -0,0 +1,13 @@ +package P1 is + + R : Boolean; + + procedure Andthen (A, B, C : Boolean); + + -- A B C R + -- 1 T T T T + -- 2 T T F F + -- 3 T F X F + -- 4 F X X F + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb new file mode 100644 index 000000000..99b746f9f --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb @@ -0,0 +1,10 @@ +with Support, P1; use Support, P1; + +procedure Test_1 is +begin + Andthen (True, True, True); + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb new file mode 100644 index 000000000..c88c66c3f --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb @@ -0,0 +1,10 @@ +with Test_1, Test_2; + +procedure Test_12 is +begin + Test_1; + Test_2; +end; + +--# p1.adb +-- /comb/ l! ## c!:"A", c!:"Id" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb new file mode 100644 index 000000000..4d1eae5e1 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb @@ -0,0 +1,11 @@ +with Test_1, Test_2, Test_3; + +procedure Test_123 is +begin + Test_1; + Test_2; + Test_3; +end; + +--# p1.adb +-- /comb/ l! ## c!:"A" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb new file mode 100644 index 000000000..0fe912b5c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb @@ -0,0 +1,12 @@ +with Test_1, Test_2, Test_3, Test_4; + +procedure Test_1234 is +begin + Test_1; + Test_2; + Test_3; + Test_4; +end; + +--# p1.adb +-- /comb/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb new file mode 100644 index 000000000..eb22e4c9c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb @@ -0,0 +1,11 @@ +with Test_1, Test_2, Test_4; + +procedure Test_124 is +begin + Test_1; + Test_2; + Test_4; +end; + +--# p1.adb +-- /comb/ l! ## c!:"Id" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb new file mode 100644 index 000000000..d686e7375 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb @@ -0,0 +1,10 @@ +with Test_1, Test_3; + +procedure Test_13 is +begin + Test_1; + Test_3; +end; + +--# p1.adb +-- /comb/ l! ## c!:"A", c!:"C" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb new file mode 100644 index 000000000..792c4ac3b --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb @@ -0,0 +1,11 @@ +with Test_1, Test_3, Test_4; + +procedure Test_134 is +begin + Test_1; + Test_3; + Test_4; +end; + +--# p1.adb +-- /comb/ l! ## c!:"C" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb new file mode 100644 index 000000000..cbd2d1771 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb @@ -0,0 +1,10 @@ +with Test_1, Test_4; + +procedure Test_14 is +begin + Test_1; + Test_4; +end; + +--# p1.adb +-- /comb/ l! ## c!:"Id", c!:"C" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb new file mode 100644 index 000000000..e1c2a23e0 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb @@ -0,0 +1,10 @@ +with Support, P1; use Support, P1; + +procedure Test_2 is +begin + Andthen (True, True, False); + Assert (R = False); +end; + +--# p1.adb +-- /comb/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb new file mode 100644 index 000000000..b68df8fec --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb @@ -0,0 +1,11 @@ +with Support, P1; use Support, P1; + +procedure Test_3 is + X : Boolean := False; +begin + Andthen (True, False, X); + Assert (R = False); +end; + +--# p1.adb +-- /comb/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb new file mode 100644 index 000000000..e568a6391 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb @@ -0,0 +1,11 @@ +with Support, P1; use Support, P1; + +procedure Test_4 is + X : Boolean := False; +begin + Andthen (False, X, X); + Assert (R = False); +end; + +--# p1.adb +-- /comb/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py new file mode 100644 index 000000000..e4fa11967 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb new file mode 100644 index 000000000..0434f60cb --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb @@ -0,0 +1,15 @@ +package body P2 is + + function F2 (X : Integer) return Boolean; + pragma Inline (F2); + + function F2 (X : Integer) return Boolean is + begin + return CX + X > 10; -- # comp + end; + + procedure Combine (C : Boolean; X : Integer) is + begin + R := C or else F2 (X); -- # or + end; +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads new file mode 100644 index 000000000..78394987d --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads @@ -0,0 +1,11 @@ +package P2 is + R : Boolean; + CX : Integer := 0; + procedure Combine (C : Boolean; X : Integer); + + -- V# C X>10 R + -- 1 F F F + -- 2 F T T + -- 3 T X T + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb new file mode 100644 index 000000000..82b6a095e --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb @@ -0,0 +1,10 @@ +with Support, P2; use Support, P2; + +procedure Test_0 is +begin + null; +end; + +--# p2.adb +-- /or/ l- ## s- +-- /comp/ l- ## s- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb new file mode 100644 index 000000000..6acf8892a --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb @@ -0,0 +1,11 @@ +with Support, P2; use Support, P2; + +procedure Test_1 is +begin + Combine (False, 5); + Assert (R = False); +end; + +--# p2.adb +-- /or/ l! ## eT- +-- /comp/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb new file mode 100644 index 000000000..1779292ff --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb @@ -0,0 +1,13 @@ +with Support, P2; use Support, P2; + +procedure Test_12 is +begin + Combine (False, 5); + Assert (R = False); + Combine (False, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## c!:"C" +-- /comp/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb new file mode 100644 index 000000000..ad533f240 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb @@ -0,0 +1,17 @@ +with Support, P2; use Support, P2; + +procedure Test_123 is +begin + Combine (False, 5); + Assert (R = False); + Combine (False, 15); + Assert (R = True); + Combine (True, 5); + Assert (R = True); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l+ ## 0 +-- /comp/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb new file mode 100644 index 000000000..a15765fca --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb @@ -0,0 +1,15 @@ +with Support, P2; use Support, P2; + +procedure Test_13 is +begin + Combine (False, 5); + Assert (R = False); + Combine (True, 5); + Assert (R = True); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## c!:"F2" +-- /comp/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb new file mode 100644 index 000000000..86a26d314 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb @@ -0,0 +1,11 @@ +with Support, P2; use Support, P2; + +procedure Test_2 is +begin + Combine (False, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## eF- +-- /comp/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb new file mode 100644 index 000000000..203b52de2 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb @@ -0,0 +1,15 @@ +with Support, P2; use Support, P2; + +procedure Test_23 is +begin + Combine (False, 15); + Assert (R = True); + Combine (True, 5); + Assert (R = True); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## eF- +-- /comp/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb new file mode 100644 index 000000000..3be63b795 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb @@ -0,0 +1,12 @@ +with Support, P2; use Support, P2; + +procedure Test_3 is +begin + Combine (True, 5); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## eF- +-- /comp/ l- ## s- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py b/testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py new file mode 100644 index 000000000..6987337a8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/extra.opt b/testsuite/tests/PA25-046-inlined-in-decision/extra.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb new file mode 100644 index 000000000..6a805b1bd --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package body Twisters is + function Identity (B : Boolean) return Boolean is + begin + -- The goal is to have conditional branches coming from other + -- functions inlined within decisions. The conditional expression + -- is there to force the production of conditional branches. + return (if B then True else False); + end; +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads new file mode 100644 index 000000000..8aac806c3 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads @@ -0,0 +1,9 @@ +package Twisters is + + function Identity (B : Boolean) return Boolean; + + -- We really care about inlining in the middle of decisions + -- in this series of tests, so: + pragma Inline_Always (Identity); + +end; diff --git a/testsuite/tests/PC09-022-auto-exename/src/main_proc.adb b/testsuite/tests/PC09-022-auto-exename/src/main_proc.adb new file mode 100644 index 000000000..9af7453ca --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/src/main_proc.adb @@ -0,0 +1,4 @@ +procedure Main_Proc is +begin + null; +end Main_Proc; diff --git a/testsuite/tests/PC09-022-auto-exename/src/other_proc.adb b/testsuite/tests/PC09-022-auto-exename/src/other_proc.adb new file mode 100644 index 000000000..00c822a2f --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/src/other_proc.adb @@ -0,0 +1,4 @@ +procedure Other_Proc is +begin + null; +end Other_Proc; diff --git a/testsuite/tests/PC09-022-auto-exename/test.opt b/testsuite/tests/PC09-022-auto-exename/test.opt new file mode 100644 index 000000000..53ce9d379 --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD This test checks "gnatcov run", specific to binary traces diff --git a/testsuite/tests/PC09-022-auto-exename/test.py b/testsuite/tests/PC09-022-auto-exename/test.py new file mode 100644 index 000000000..a4a7ed4ea --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/test.py @@ -0,0 +1,173 @@ +""" +Test that "gnatcov run" properly auto-detects the name of the executable from a +project file, or that it properly reports when there is not one single main. +""" + +from collections import OrderedDict +import os +import os.path +import re + +from SUITE.context import thistest +from SUITE.cutils import FatalError, Wdir, contents_of, indent +from SUITE.tutils import gprbuild, gprfor, xrun + + +wd = Wdir("tmp_") + + +class Project(object): + def __init__( + self, + projects, + name, + srcdir, + mains=(), + deps=(), + build=True, + should_succeed=True, + ): + self.projects = projects + self.name = name + self.srcdir = srcdir + self.mains = list(mains) + self.deps = deps + self.build = build + self.should_succeed = should_succeed + + self.objdir = "obj-{}".format(self.name) + self.exedir = "exe-{}".format(self.name) + + self.prj_file = None + + @property + def dep_projects(self): + """ + Return the list of all projects "self" depends on. + """ + return [self.projects[d] for d in self.deps] + + @property + def all_mains(self): + """ + Return the set of mains for this projects and all its dependencies'. + """ + result = set() + for main in self.mains: + result.add(main.split(".")[0]) + for p in self.dep_projects: + result.update(p.all_mains) + return result + + def prepare(self): + print("Preparing {}...".format(self.name)) + self.prj_file = gprfor( + mains=self.mains, + prjid=self.name, + srcdirs=os.path.join("..", self.srcdir), + objdir=self.objdir, + exedir=self.exedir, + langs=["Ada"], + deps=self.deps, + ) + if self.build: + gprbuild(self.prj_file) + + # Make sure that in all case, output directories exist so that warning + # messages don't pollute gnatcov's error messages. + for dirname in (self.objdir, self.exedir): + if not os.path.isdir(dirname): + os.mkdir(dirname) + + def run(self): + print("") + print("== Running {} ==".format(self.name)) + + error_msg_re = None + all_mains = self.all_mains + + if len(all_mains) != 1: + print("Not exactly one main: should fail") + error_msg_re = ( + r".*gnatcov.*: Please specify an executable to run \(EXE\)" + r" on the command line.*" + ) + elif not self.build: + main = all_mains.pop() + print("Not built: should fail") + error_msg_re = ".*gnatcov.*: .*{}.*: File not found".format( + re.escape(main) + ) + else: + print("Should succeed") + + we_think_it_should_succeed = not error_msg_re + thistest.stop_if( + we_think_it_should_succeed != self.should_succeed, + FatalError( + "Test declaration disagrees with test framework about" + " whether this test should fail" + ), + ) + + log_file = "run-{}.txt".format(self.name) + p = xrun( + ["-P", self.prj_file], + register_failure=not error_msg_re, + out=log_file, + ) + if error_msg_re: + thistest.fail_if( + p.status == 0, + "gnatcov run suceeded whereas it was expected to fail", + ) + out = contents_of(log_file).strip() + thistest.fail_if( + not re.match(error_msg_re, out), + "\nFor {}, error message ({}):" + "\n{}" + "\nDoes not match the expected pattern:" + "\n{}".format( + self.name, log_file, indent(out), indent(error_msg_re) + ), + ) + + +project_files = OrderedDict() +for p in ( + # Test that the most regular case (one project, one main) succeeds + Project( + project_files, + "single", + "src", + mains=("main_proc.adb",), + should_succeed=True, + ), + # We expect an error when there is no main at all + Project(project_files, "nomain", "src", should_succeed=False), + # Likewise when there are too many mains + Project( + project_files, + "double", + "src", + mains=("main_proc.adb", "other_proc.adb"), + should_succeed=False, + ), + # Likewise when there is one main but it has not been built + Project( + project_files, + "no_build", + "src", + mains=("main_proc.adb",), + build=False, + should_succeed=False, + ), +): + assert p.name not in project_files + project_files[p.name] = p + p.prepare() + +for p in project_files.values(): + p.run() + +thistest.result() diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb new file mode 100644 index 000000000..b19d8daf4 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb @@ -0,0 +1,6 @@ +package body Ops.P1 is + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # stmt + end; +end; diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads new file mode 100644 index 000000000..4e6acc2e1 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads @@ -0,0 +1,3 @@ +package Ops.P1 is + procedure Inc (X : in out Integer); +end; diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads new file mode 100644 index 000000000..f4c3f25e7 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads @@ -0,0 +1,3 @@ +package Ops is + pragma Pure; -- # pragma +end; diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb new file mode 100644 index 000000000..c2603ebf7 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb @@ -0,0 +1,13 @@ +with Ops, Ops.P1; + +procedure Test_P1 is + X : Integer := 12; +begin + Ops.P1.Inc (X); +end; + +--# ops.ads +-- /pragma/ l. ## 0 + +--# ops-p1.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py b/testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Q224-032-several-out-of-line/bar.c b/testsuite/tests/Q224-032-several-out-of-line/bar.c new file mode 100644 index 000000000..2e6c8275b --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/bar.c @@ -0,0 +1,5 @@ +void +bar (void) +{ + return; +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/foo.cpp b/testsuite/tests/Q224-032-several-out-of-line/foo.cpp new file mode 100644 index 000000000..8e770502d --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/foo.cpp @@ -0,0 +1,7 @@ +#include "shared.hpp" + +void +foo () +{ + shared (); +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/main.cpp b/testsuite/tests/Q224-032-several-out-of-line/main.cpp new file mode 100644 index 000000000..2031513f2 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/main.cpp @@ -0,0 +1,16 @@ +#include "shared.hpp" + +extern void foo (); + +extern "C" +{ + extern void bar (); +} + +int +main () +{ + shared (); + foo (); + bar (); +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/shared.hpp b/testsuite/tests/Q224-032-several-out-of-line/shared.hpp new file mode 100644 index 000000000..638c8baec --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/shared.hpp @@ -0,0 +1,6 @@ +extern "C" void bar(); +extern void shared(); + +inline void shared() { + bar(); +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/test.opt b/testsuite/tests/Q224-032-several-out-of-line/test.opt new file mode 100644 index 000000000..942aab8f4 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/test.opt @@ -0,0 +1,2 @@ +C++,bin-traces +ALL DEAD Requires a C++ compiler + tests a binary trace-specific behavior diff --git a/testsuite/tests/Q224-032-several-out-of-line/test.py b/testsuite/tests/Q224-032-several-out-of-line/test.py new file mode 100644 index 000000000..01592a6c1 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/test.py @@ -0,0 +1,43 @@ +""" +Check that "gnatcov coverage" does not crash when processing a binary with +debug info that contains multiple definitions for the same function over +different compilation units. + +This testcase does this with the original customer use case: a C++ inline +function defined in a header included in several compilation units. +""" + +from SCOV.minicheck import checked_xcov, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, + gprfor, + gprbuild, + thistest, + tracename_for, + xrun, +) + + +wd = Wdir("tmp_") +main = exepath_to("main") +trace = tracename_for("main") + +gpr = gprfor(["main.cpp"], srcdirs="..", langs=["C", "C++"]) +gprbuild(gpr) + +xrun([main], "run.log") +checked_xcov( + [ + "coverage", + "-P{}".format(gpr), + "-cstmt", + "-axcov", + "--output-dir=.", + trace, + ], + "coverage.log", +) +check_xcov_reports(".", {"bar.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore b/testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore new file mode 100644 index 000000000..ca5215678 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore @@ -0,0 +1,2 @@ +*.trace +install diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb new file mode 100644 index 000000000..165f6ee7b --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb @@ -0,0 +1,7 @@ +with Lib; + +procedure Main is + package B is new Lib; +begin + B.Foo; +end; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb new file mode 100644 index 000000000..db835dcb4 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Lib is + + procedure Foo is + begin + Put_Line ("foo"); + end; + +begin + Put_Line ("elaboration"); +end; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads new file mode 100644 index 000000000..f93bda713 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads @@ -0,0 +1,4 @@ +generic +package Lib is + procedure Foo; +end; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt new file mode 100644 index 000000000..80db95e5d --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt @@ -0,0 +1,2 @@ +bin-traces +ALL DEAD diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py new file mode 100644 index 000000000..77e64c56f --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py @@ -0,0 +1,62 @@ +""" +Check that "gnatcov coverage" does not crash when processing a program that +exposes two paths for the same source (once before and one after installation). + +Note that in this testcase, one absolute path comes from the debug info line +mapping (.debug_lines) while the other only comes from the debug info +DW_TAG_compilation_unit entry (.debug_info). +""" + +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, gprbuild, gprinstall, xrun, xcov + + +# Build libfoo and install it in some prefix, then make the installed project +# available through the GPR_PROJECT_PATH environment variable. +tmp = Wdir("tmp_libfoo") +install_dir = os.path.abspath("install") +libfoo_gpr = gprfor( + prjid="libfoo", + mains=[], + srcdirs=["../libfoo"], + langs=["Ada"], + extra=""" + for Library_Kind use "static"; + for Library_Name use "foo"; + for Library_Dir use "lib"; + """, +) +gprbuild(libfoo_gpr) +gprinstall(libfoo_gpr, gargs=[f"--prefix={install_dir}"]) +os.environ["GPR_PROJECT_PATH"] = os.path.join(install_dir, "share", "gpr") +tmp.to_homedir() + +# Now, in another directory (so that we are sure it is the installed libfoo +# that is used), build the main application, then generate a binary trace for +# it. +tmp = Wdir("tmp_app") +app_gpr = gprfor( + prjid="app", mains=["main.adb"], srcdirs=["../app"], deps=["libfoo"] +) +gprbuild(app_gpr) +xrun("./main") + +# The very goal of this testcase is to compute code coverage for a unit that +# belongs to a project installed with gprinstall, so we need to enable the +# processing of externally built projects. +xcov( + [ + "coverage", + "--annotate=xcov", + "--level=stmt", + "-P", + app_gpr, + "--projects=libfoo", + "--externally-built-projects", + "main.trace", + ] +) +thistest.result() diff --git a/testsuite/tests/Q327-016-glob-ignore/ignore.list b/testsuite/tests/Q327-016-glob-ignore/ignore.list new file mode 100644 index 000000000..77aa615db --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/ignore.list @@ -0,0 +1,5 @@ +# Ignore packages B and C +pkg_[bc].adb + +# Ignore all test procedures +*-test.adb diff --git a/testsuite/tests/Q327-016-glob-ignore/src/main.adb b/testsuite/tests/Q327-016-glob-ignore/src/main.adb new file mode 100644 index 000000000..c5fe5be83 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/main.adb @@ -0,0 +1,8 @@ +with Pkg_A, Pkg_B, Pkg_C; +with Pkg_A.Test, Pkg_B.Test, Pkg_C.Test; + +procedure Main is +begin + Pkg_A.Main; Pkg_B.Main; Pkg_C.Main; + Pkg_A.Test; Pkg_B.Test; Pkg_C.Test; +end Main; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb new file mode 100644 index 000000000..05a599066 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Pkg_A.Test is +begin + Put_Line ("A.Test"); +end Pkg_A.Test; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb new file mode 100644 index 000000000..9d04529f9 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_A is + procedure Main is + begin + Put_Line ("A"); + end Main; +end Pkg_A; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads new file mode 100644 index 000000000..35e72457d --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads @@ -0,0 +1,3 @@ +package Pkg_A is + procedure Main; +end Pkg_A; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb new file mode 100644 index 000000000..2a7eb9178 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Pkg_B.Test is +begin + Put_Line ("B.Test"); +end Pkg_B.Test; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb new file mode 100644 index 000000000..40ecdbd03 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_B is + procedure Main is + begin + Put_Line ("B"); + end Main; +end Pkg_B; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads new file mode 100644 index 000000000..e1489c942 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads @@ -0,0 +1,3 @@ +package Pkg_B is + procedure Main; +end Pkg_B; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb new file mode 100644 index 000000000..3349b06b6 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Pkg_C.Test is +begin + Put_Line ("C.Test"); +end Pkg_C.Test; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb new file mode 100644 index 000000000..6addf3ddc --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_C is + procedure Main is + begin + Put_Line ("C"); + end Main; +end Pkg_C; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads new file mode 100644 index 000000000..c28ad3ce9 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads @@ -0,0 +1,3 @@ +package Pkg_C is + procedure Main; +end Pkg_C; diff --git a/testsuite/tests/Q327-016-glob-ignore/test.py b/testsuite/tests/Q327-016-glob-ignore/test.py new file mode 100644 index 000000000..b8c2d0cd9 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/test.py @@ -0,0 +1,41 @@ +""" +Check that the --ignore-source-file option works as expected. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +src_dir = os.path.abspath("src") +ignore_list = os.path.abspath("ignore.list") + +wd = Wdir("tmp_") + + +# Produce a report with specific patterns to ignore some source files +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(["main.adb"], srcdirs=src_dir)), + covlevel="stmt", + mains=["main"], + ignored_source_files=["@" + ignore_list], + extra_coverage_args=["-a", "xcov", "--output-dir=."], + tolerate_coverage_messages="no SID file found for unit", +) + +# Check we have the expected reports +check_xcov_reports( + ".", + { + "main.adb.xcov": {"+": {6, 7}}, + "pkg_a.adb.xcov": {"+": {6}}, + "pkg_a.ads.xcov": {}, + "pkg_b.ads.xcov": {}, + "pkg_c.ads.xcov": {}, + }, +) +thistest.result() diff --git a/testsuite/tests/Q329-018-create-output-dir/foo.adb b/testsuite/tests/Q329-018-create-output-dir/foo.adb new file mode 100644 index 000000000..e9f45d970 --- /dev/null +++ b/testsuite/tests/Q329-018-create-output-dir/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/Q329-018-create-output-dir/test.py b/testsuite/tests/Q329-018-create-output-dir/test.py new file mode 100644 index 000000000..b1afe1c40 --- /dev/null +++ b/testsuite/tests/Q329-018-create-output-dir/test.py @@ -0,0 +1,36 @@ +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") +output_dir = os.path.join("report", "foo") + +# Generate a project for our sources, build it and generate a trace for it +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(["foo.adb"], srcdirs=src_dir)), + covlevel="stmt", + mains=["foo"], + quiet=False, + extra_coverage_args=["-axcov", "--output-dir={}".format(output_dir)], +) + +# Now, try to produce a report in a directory that does not exist (even its +# parent does not exist!). +assert not os.path.exists("report") +xcov(xcov_args, "coverage.log") + +# Check that gnatcov reports that it creates these directories +thistest.fail_if( + "info: creating output path " not in contents_of("coverage.log"), + "gnatcov does not say it is creating directories, it should", +) + +# Finally, check we have the expected reports +check_xcov_reports(output_dir, {"foo.adb.xcov": {"+": {5}}}) +thistest.result() diff --git a/testsuite/tests/Q414-016-task-accept/src/q.adb b/testsuite/tests/Q414-016-task-accept/src/q.adb new file mode 100644 index 000000000..a20c2e448 --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/src/q.adb @@ -0,0 +1,37 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Q is + Ticks, Laps : Integer := 0; + + task Clock is + entry Start; + entry Tick; + end Clock; + + task body Clock is + Counting : Boolean := False; + begin + loop + select + accept Start do -- # start_accept + Counting := True; -- # start_stmt + end; + or + accept Tick do -- # tick_accept + if Counting then -- # tick_if + Ticks := Ticks + 1; -- # tick_stmt + end if; + end; + or + terminate; + end select; + end loop; + end Clock; + + procedure Tryme is + begin + Clock.Tick; + Put_Line (Integer'Image (Ticks)); + end Tryme; + +end Q; diff --git a/testsuite/tests/Q414-016-task-accept/src/q.ads b/testsuite/tests/Q414-016-task-accept/src/q.ads new file mode 100644 index 000000000..8c9d7983a --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/src/q.ads @@ -0,0 +1,3 @@ +package Q is + procedure Tryme; +end Q; diff --git a/testsuite/tests/Q414-016-task-accept/src/test_tick.adb b/testsuite/tests/Q414-016-task-accept/src/test_tick.adb new file mode 100644 index 000000000..4b206f582 --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/src/test_tick.adb @@ -0,0 +1,13 @@ +with Q; + +procedure Test_Tick is +begin + Q.Tryme; +end Test_Tick; + +--# q.adb +-- /start_accept/ l- ## s- +-- /start_stmt/ l- ## s- +-- /tick_accept/ l+ ## 0 +-- /tick_if/ l+ ## 0 +-- /tick_stmt/ l- ## s- diff --git a/testsuite/tests/Q414-016-task-accept/test.opt b/testsuite/tests/Q414-016-task-accept/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Q414-016-task-accept/test.py b/testsuite/tests/Q414-016-task-accept/test.py new file mode 100644 index 000000000..da130c4cd --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase, thistest +from SCOV.tctl import CAT + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Q519-013-decision-map/bar.adb b/testsuite/tests/Q519-013-decision-map/bar.adb new file mode 100644 index 000000000..7d2ebfea1 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/bar.adb @@ -0,0 +1,6 @@ +package body Bar is + function F (A, B, C : Boolean) return Boolean is + begin + return (A and then B) or else C; + end F; +end Bar; diff --git a/testsuite/tests/Q519-013-decision-map/bar.ads b/testsuite/tests/Q519-013-decision-map/bar.ads new file mode 100644 index 000000000..7c0846550 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/bar.ads @@ -0,0 +1,3 @@ +package Bar is + function F (A, B, C : Boolean) return Boolean; +end Bar; diff --git a/testsuite/tests/Q519-013-decision-map/foo.adb b/testsuite/tests/Q519-013-decision-map/foo.adb new file mode 100644 index 000000000..78cf91a65 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/foo.adb @@ -0,0 +1,7 @@ +with Bar; + +procedure Foo is + B : Boolean := Bar.F (True, False, True); +begin + null; +end Foo; diff --git a/testsuite/tests/Q519-013-decision-map/test.opt b/testsuite/tests/Q519-013-decision-map/test.opt new file mode 100644 index 000000000..e4be71a9a --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Exercizes map-routines diff --git a/testsuite/tests/Q519-013-decision-map/test.py b/testsuite/tests/Q519-013-decision-map/test.py new file mode 100644 index 000000000..316f9d08d --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/test.py @@ -0,0 +1,36 @@ +import os.path +import re + +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import exepath_to, gprbuild, gprfor, thistest, xcov + + +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") +exe_path = exepath_to("foo") +dmap_path = exe_path + ".dmap" + + +# Generate a project for our sources, build it and generate a decision map for +# foo.adb +prj_file = gprfor(["foo.adb"], srcdirs=src_dir, objdir=".") +gprbuild(prj_file) +xcov(["map-routines", "--scos=bar.ali", exe_path]) +xcov(["dump-trace", dmap_path], out="dump-trace.txt") + +dump_trace = contents_of("dump-trace.txt") +pattern = """\ +Kind: DECISION_MAP + +Traces: +[0-9a-f]+-[0-9a-f]+ \\?: 00 ---- +.*""" +thistest.fail_if( + not re.match(pattern, dump_trace, re.DOTALL), + 'Could not match "gnatcov dump-trace" output:\n' + "{}\n" + "against the expected pattern:\n" + "{}\n".format(indent(dump_trace), indent(pattern)), +) + +thistest.result() diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads b/testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads new file mode 100644 index 000000000..376d7b7a8 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads @@ -0,0 +1,3 @@ +with Foo; + +package Bar renames Foo; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb new file mode 100644 index 000000000..8fd05946a --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb @@ -0,0 +1,6 @@ +package body Foo is + procedure P is + begin + null; + end P; +end Foo; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads new file mode 100644 index 000000000..3db125be0 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads @@ -0,0 +1,3 @@ +package Foo is + procedure P; +end Foo; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb b/testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb new file mode 100644 index 000000000..eb59be279 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb @@ -0,0 +1,6 @@ +with Bar; + +procedure Main is +begin + Bar.P; +end Main; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py new file mode 100644 index 000000000..22977477b --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py @@ -0,0 +1,41 @@ +import glob +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + + +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") + + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(["main.adb"], srcdirs=src_dir, objdir=".") + ), + gpr_obj_dir=".", + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint=main.ckpt"], + scos=["bar", "foo", "main"], +) +xcov(["coverage", "-cstmt", "-axcov", "-Cmain.ckpt"]) + +expected_reports = ["foo.adb.xcov", "main.adb.xcov"] +if thistest.options.trace_mode == "src": + expected_reports += ["bar.ads.xcov", "foo.ads.xcov"] +expected_reports.sort() +got_reports = sorted(glob.glob("*.xcov")) +thistest.fail_if( + got_reports != expected_reports, + ( + "Expected the following reports: {}\n" + "But got instead: {}".format( + expected_reports, got_reports + ) + ), +) + +thistest.result() diff --git a/testsuite/tests/Q901-012-report-title/foo.adb b/testsuite/tests/Q901-012-report-title/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/Q901-012-report-title/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/Q901-012-report-title/test.py b/testsuite/tests/Q901-012-report-title/test.py new file mode 100644 index 000000000..567da2454 --- /dev/null +++ b/testsuite/tests/Q901-012-report-title/test.py @@ -0,0 +1,50 @@ +import os.path +import re + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + + +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(["foo.adb"], srcdirs=src_dir, objdir=".") + ), + gpr_obj_dir=".", + covlevel="stmt", + mains=["foo"], + extra_coverage_args=[], + scos=["foo"], +) + + +def run_checks(name, report_title, prefix): + html_dir = "{}-html".format(name) + + args = list(xcov_args) + if report_title is None: + pass + else: + args.append("--report-title={}".format(report_title)) + + xcov(args + ["-ahtml", "--output-dir={}".format(html_dir)]) + + def do_match(title, dirname, filename): + path = os.path.join(dirname, filename) + text = "{}".format(title) + thistest.fail_if( + not match(re.escape(text), path), + "Could not match {} in {}".format(repr(text), path), + ) + + do_match(prefix + "GNATcoverage Report", html_dir, "index.html") + + +run_checks("none", None, "") +run_checks("empty", "", "") +run_checks("full", "My +# +# This is supposed to produce a trace file with only the trace info section +# (header and info entries). + +gpr = gprfor(srcdirs=[".."], mains=["foo.adb"]) + +gprbuild(gpr) + +exefile = exepath_to("foo") + +# We run a straigtht "gnatcov run" of our own, bypassing the 'xcov' +# function circuitry to prevent the addition of a real --target in +# cross configurations. + +bits = env.target.cpu.bits +cmd = ["gnatcov", "run", f"--target=prepare{bits}", exepath_to("foo")] +p = Run(cmd) +thistest.fail_if( + p.status != 0, + "command '%s' failed ; output was:\n%s" % (" ".join(cmd), p.out), +) + +tracefile = tracename_for("foo") + +with open(tracefile, "rb") as fp: + trace = TraceFile.read(ByteStreamDecoder(fp)) + +# Check that the trace file contains the info section and at least some of the +# bits we expect there + +thistest.fail_if(not trace.first_header, "info header missing from trace file") + +thistest.fail_if(not trace.infos, "info entries missing from trace file") + +trace_info = trace.infos.infos + +# Entry kinds we expect to find in the info section header, and a regexp that +# the corresponding value should match. We're not trying to match a specific +# date (e.g. today()) in the exec time stamp to prevent getting into timezone +# intricacies. + +expected_entries = { + InfoKind.ExecFileName: re.escape(exefile.encode("utf-8")), + InfoKind.ExecTimeStamp: ( + r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d".encode("ascii") + ), +} + +found_entries = {} + +for info_entry in trace_info.values(): + thistest.fail_if( + info_entry.kind in found_entries, + "info entry kind %d found more than once in trace" % info_entry.kind, + ) + + if info_entry.kind in expected_entries: + expected_contents = expected_entries[info_entry.kind] + thistest.fail_if( + not re.match(pattern=expected_contents, string=info_entry.data), + "expected contents '%s' not found in entry of kind %d;\n" + "value was '%s'" + % (expected_contents, info_entry.kind, info_entry.data), + ) + found_entries[info_entry.kind] = info_entry + +thistest.fail_if( + len(found_entries) != len(expected_entries), + "trace info section missing expected contents", +) + +# Check that the trace file does not contain the execution section. + +thistest.fail_if( + trace.second_header, "exec section header found in trace file, unexpected" +) + +thistest.result() diff --git a/testsuite/tests/QB14-023-stack-overflow/foo.adb b/testsuite/tests/QB14-023-stack-overflow/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/QB14-023-stack-overflow/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/QB14-023-stack-overflow/test.opt b/testsuite/tests/QB14-023-stack-overflow/test.opt new file mode 100644 index 000000000..a29228f15 --- /dev/null +++ b/testsuite/tests/QB14-023-stack-overflow/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise map-routines, specific to binary trace mode diff --git a/testsuite/tests/QB14-023-stack-overflow/test.py b/testsuite/tests/QB14-023-stack-overflow/test.py new file mode 100644 index 000000000..a9ab004f1 --- /dev/null +++ b/testsuite/tests/QB14-023-stack-overflow/test.py @@ -0,0 +1,24 @@ +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, text_to_file +from SUITE.tutils import exepath_to, gprfor, gprbuild, xcov + + +wd = Wdir("tmp_") +main = exepath_to("foo") + +gpr = gprfor(["foo.adb"], srcdirs="..") +gprbuild(gpr) + +# Patch the SCOs so that a statement covers an insanely huge amount of lines +ali_file = os.path.join("obj", "foo.ali") +text_to_file( + contents_of(ali_file).replace("CS 3:4-3:4", "CS 3:4-1000000:4"), ali_file +) + +# Just check that the following command does not crash (it used to yield a +# stack overflow). +xcov(["map-routines", "-P{}".format(gpr), main]) + +thistest.result() diff --git a/testsuite/tests/QC29-006-index/ref-sid/atc.index b/testsuite/tests/QC29-006-index/ref-sid/atc.index new file mode 100644 index 000000000..9863aea7d --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/atc.index @@ -0,0 +1,27 @@ +atc + +Global: + - 66%, ! 0%, + 33% out of 6 obligations + + +Other sources: + - 66%, ! 0%, + 33% out of 6 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - 0%, ! 0%, + 100% out of 2 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/atcc.index b/testsuite/tests/QC29-006-index/ref-sid/atcc.index new file mode 100644 index 000000000..34af82743 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/atcc.index @@ -0,0 +1,27 @@ +atcc + +Global: + - 81%, ! 0%, + 18% out of 11 obligations + + +Other sources: + - 81%, ! 0%, + 18% out of 11 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 6 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - 50%, ! 0%, + 50% out of 4 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/decision.index b/testsuite/tests/QC29-006-index/ref-sid/decision.index new file mode 100644 index 000000000..7635c019d --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/decision.index @@ -0,0 +1,27 @@ +decision + +Global: + - 57%, ! 42%, + 0% out of 7 obligations + + +Other sources: + - 57%, ! 42%, + 0% out of 7 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 0%, ! 100%, + 0% out of 3 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/lines.index b/testsuite/tests/QC29-006-index/ref-sid/lines.index new file mode 100644 index 000000000..5ecdce6d5 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/lines.index @@ -0,0 +1,27 @@ +lines + +Global: + - 69%, ! 12%, + 18% out of 33 lines + + +Other sources: + - 69%, ! 12%, + 18% out of 33 lines + + a.adb: + - 0%, ! 0%, + 100% out of 1 lines + a.ads: + - -%, ! -%, + -% out of 0 lines + b.ads: + - 100%, ! 0%, + 0% out of 1 lines + bar.adb: + - 100%, ! 0%, + 0% out of 11 lines + bar.ads: + - -%, ! -%, + -% out of 0 lines + foo.adb: + - 100%, ! 0%, + 0% out of 10 lines + foo.ads: + - -%, ! -%, + -% out of 0 lines + lib.ads: + - 0%, ! 33%, + 66% out of 3 lines + main.adb: + - 14%, ! 42%, + 42% out of 7 lines diff --git a/testsuite/tests/QC29-006-index/ref-sid/mcdc.index b/testsuite/tests/QC29-006-index/ref-sid/mcdc.index new file mode 100644 index 000000000..c5cdd49d4 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/mcdc.index @@ -0,0 +1,27 @@ +mcdc + +Global: + - 100%, ! 0%, + 0% out of 13 obligations + + +Other sources: + - 100%, ! 0%, + 0% out of 13 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 3 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 4 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 100%, ! 0%, + 0% out of 6 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/stmt.index b/testsuite/tests/QC29-006-index/ref-sid/stmt.index new file mode 100644 index 000000000..319ac824b --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/stmt.index @@ -0,0 +1,27 @@ +stmt + +Global: + - 74%, ! 0%, + 25% out of 31 obligations + + +Other sources: + - 74%, ! 0%, + 25% out of 31 obligations + + a.adb: + - 0%, ! 0%, + 100% out of 1 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - 100%, ! 0%, + 0% out of 1 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 11 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 10 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - 0%, ! 0%, + 100% out of 1 obligations + main.adb: + - 14%, ! 0%, + 85% out of 7 obligations diff --git a/testsuite/tests/QC29-006-index/ref/atc.index b/testsuite/tests/QC29-006-index/ref/atc.index new file mode 100644 index 000000000..c3487adf5 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/atc.index @@ -0,0 +1,39 @@ +atc + +Global: + - 66%, ! 0%, + 33% out of 6 obligations + + +bar: + - 100%, ! 0%, + 0% out of 1 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 3 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - 0%, ! 0%, + 100% out of 2 obligations + + lib.ads: + - 0%, ! 0%, + 100% out of 2 obligations + +main: + - -%, ! -%, + -% out of 0 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref/atcc.index b/testsuite/tests/QC29-006-index/ref/atcc.index new file mode 100644 index 000000000..af3b52610 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/atcc.index @@ -0,0 +1,39 @@ +atcc + +Global: + - 81%, ! 0%, + 18% out of 11 obligations + + +bar: + - 100%, ! 0%, + 0% out of 1 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 6 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 6 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - 50%, ! 0%, + 50% out of 4 obligations + + lib.ads: + - 50%, ! 0%, + 50% out of 4 obligations + +main: + - -%, ! -%, + -% out of 0 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref/decision.index b/testsuite/tests/QC29-006-index/ref/decision.index new file mode 100644 index 000000000..da1717404 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/decision.index @@ -0,0 +1,39 @@ +decision + +Global: + - 57%, ! 42%, + 0% out of 7 obligations + + +bar: + - 100%, ! 0%, + 0% out of 1 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 3 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - -%, ! -%, + -% out of 0 obligations + + lib.ads: + - -%, ! -%, + -% out of 0 obligations + +main: + - 0%, ! 100%, + 0% out of 3 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 0%, ! 100%, + 0% out of 3 obligations diff --git a/testsuite/tests/QC29-006-index/ref/lines.index b/testsuite/tests/QC29-006-index/ref/lines.index new file mode 100644 index 000000000..7d8d07366 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/lines.index @@ -0,0 +1,39 @@ +lines + +Global: + - 69%, ! 12%, + 18% out of 33 lines + + +bar: + - 100%, ! 0%, + 0% out of 11 lines + + bar.adb: + - 100%, ! 0%, + 0% out of 11 lines + bar.ads: + - -%, ! -%, + -% out of 0 lines + +foo: + - 100%, ! 0%, + 0% out of 11 lines + + b.ads: + - 100%, ! 0%, + 0% out of 1 lines + foo.adb: + - 100%, ! 0%, + 0% out of 10 lines + foo.ads: + - -%, ! -%, + -% out of 0 lines + +lib: + - 0%, ! 33%, + 66% out of 3 lines + + lib.ads: + - 0%, ! 33%, + 66% out of 3 lines + +main: + - 12%, ! 37%, + 50% out of 8 lines + + a.adb: + - 0%, ! 0%, + 100% out of 1 lines + a.ads: + - -%, ! -%, + -% out of 0 lines + main.adb: + - 14%, ! 42%, + 42% out of 7 lines diff --git a/testsuite/tests/QC29-006-index/ref/mcdc.index b/testsuite/tests/QC29-006-index/ref/mcdc.index new file mode 100644 index 000000000..408a15798 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/mcdc.index @@ -0,0 +1,39 @@ +mcdc + +Global: + - 100%, ! 0%, + 0% out of 13 obligations + + +bar: + - 100%, ! 0%, + 0% out of 3 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 3 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 4 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 4 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - -%, ! -%, + -% out of 0 obligations + + lib.ads: + - -%, ! -%, + -% out of 0 obligations + +main: + - 100%, ! 0%, + 0% out of 6 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 100%, ! 0%, + 0% out of 6 obligations diff --git a/testsuite/tests/QC29-006-index/ref/stmt.index b/testsuite/tests/QC29-006-index/ref/stmt.index new file mode 100644 index 000000000..7fec24cb9 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/stmt.index @@ -0,0 +1,39 @@ +stmt + +Global: + - 74%, ! 0%, + 25% out of 31 obligations + + +bar: + - 100%, ! 0%, + 0% out of 11 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 11 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 11 obligations + + b.ads: + - 100%, ! 0%, + 0% out of 1 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 10 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - 0%, ! 0%, + 100% out of 1 obligations + + lib.ads: + - 0%, ! 0%, + 100% out of 1 obligations + +main: + - 12%, ! 0%, + 87% out of 8 obligations + + a.adb: + - 0%, ! 0%, + 100% out of 1 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 14%, ! 0%, + 85% out of 7 obligations diff --git a/testsuite/tests/QC29-006-index/src-lib/lib.ads b/testsuite/tests/QC29-006-index/src-lib/lib.ads new file mode 100644 index 000000000..248add341 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-lib/lib.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Lib is + function Id (B : Boolean) return Boolean is (B) + with Pre => B or else not B or else B, + Post => Id'Result = B; +end Lib; diff --git a/testsuite/tests/QC29-006-index/src-root/a.adb b/testsuite/tests/QC29-006-index/src-root/a.adb new file mode 100644 index 000000000..4d38cf1f6 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/a.adb @@ -0,0 +1,6 @@ +package body A is + procedure A_Proc (Dummy : Boolean) is + begin + null; + end A_Proc; +end A; diff --git a/testsuite/tests/QC29-006-index/src-root/a.ads b/testsuite/tests/QC29-006-index/src-root/a.ads new file mode 100644 index 000000000..7035b4026 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/a.ads @@ -0,0 +1,3 @@ +package A is + procedure A_Proc (Dummy : Boolean); +end A; diff --git a/testsuite/tests/QC29-006-index/src-root/main.adb b/testsuite/tests/QC29-006-index/src-root/main.adb new file mode 100644 index 000000000..6e63c63c7 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/main.adb @@ -0,0 +1,18 @@ +with A; +with Foo; +with Lib; + +procedure Main is + T : Boolean := True; + F : Boolean := False; +begin + if Lib.Id (T) or else F then + T := T and then True; + end if; + + if F and then Foo then + F := F and then False; + end if; + + A.A_Proc (True); +end Main; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/b.ads b/testsuite/tests/QC29-006-index/src-root/src-foo/b.ads new file mode 100644 index 000000000..89a3e5a35 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/b.ads @@ -0,0 +1,3 @@ +package B is + function Return_T return Boolean is (True); +end B; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb new file mode 100644 index 000000000..e9b1738b9 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +with Bar; +with Lib; + +function Foo return Boolean +is + T : Boolean := True; + F : Boolean := False; +begin + if not T then + T := T and then T; + end if; + + begin + if T then + pragma Assert (T); + pragma Assert (T or else T or else T); + pragma Assert (T and then Lib.Id (F)); + end if; + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return T; +end Foo; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads new file mode 100644 index 000000000..b7cfdb3ca --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads @@ -0,0 +1 @@ +function Foo return Boolean; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb new file mode 100644 index 000000000..efc9e191f --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb @@ -0,0 +1,32 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +function Bar return Boolean +is + T : Boolean := True; + F : Boolean := False; + + Res : Boolean := False; + + function MCDC_Violation (A, B : Boolean) return Boolean is + begin + if (A and then not B) or else A then + return True; + end if; + return True; + end MCDC_Violation; + +begin + Res := MCDC_Violation (T, F); + Res := MCDC_Violation (F, F); + + begin + pragma Assert (Res); + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return Res; +end Bar; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads new file mode 100644 index 000000000..f51db2cee --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads @@ -0,0 +1 @@ +function Bar return Boolean; diff --git a/testsuite/tests/QC29-006-index/test.opt b/testsuite/tests/QC29-006-index/test.opt new file mode 100644 index 000000000..3e4bc171a --- /dev/null +++ b/testsuite/tests/QC29-006-index/test.opt @@ -0,0 +1,3 @@ +5.04a1 DEAD Test uses pre/postconditions as apects for ATCC coverage +7.1.2 DEAD Expression function support weak in 7.1.2 +bin-traces DEAD Expected slight differences in coverage percentages diff --git a/testsuite/tests/QC29-006-index/test.py b/testsuite/tests/QC29-006-index/test.py new file mode 100644 index 000000000..c00f7712f --- /dev/null +++ b/testsuite/tests/QC29-006-index/test.py @@ -0,0 +1,169 @@ +""" +Test that the coverage indices generated along the xcov and report format +reports contains the correct information. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov, srctracename_for +from SUITE.gprutils import GPRswitches + +import glob + + +def create_lib_gpr(name, srcdir, objdir, deps=None, extra=""): + """ + Create a gpr file for the library. + + :param name: Name of the library. + """ + + return gprfor( + mains=[], + prjid=name, + srcdirs=[srcdir], + objdir=objdir, + langs=["Ada"], + deps=deps, + extra=extra, + ) + + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.adb"], + prjid="main", + srcdirs=["../src-root"], + objdir="obj", + langs=["Ada"], + deps=["foo", "lib"], +) + +# Create the GPR files for the libraries +lib_gpr = create_lib_gpr( + "lib", + "../src-lib", + "obj-lib", + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) +foo_gpr = create_lib_gpr( + "foo", "../src-root/src-foo", "obj-foo", ["bar", "lib"] +) +bar_gpr = create_lib_gpr("bar", "../src-root/src-foo/src-bar", "obj-bar") + +gprsw = GPRswitches(root_project=src_gpr) + + +def check_indices(metrics, statsdir, refdir=""): + """ + Check that the index file corresponding to each coverage metric in + "metrics" contains the expected statistics. + """ + + for metric in metrics: + filename = f"{metric}.index" + idx = f"{statsdir}/{filename}" + ref = f"{refdir}/{filename}" + ref_path = f"../{ref}" + + if thistest.options.trace_mode == "src": + thistest.fail_if_diff( + ref_path, + idx, + f"unexpected index content for {filename} " + f"with baseline {ref}", + ) + else: + idx_contents = contents_of(idx) + ref_contents = ( + r"(.|\n)*bar:" + r"\n - 100%, ! 0%, \+ 0% out of 15 lines" + r"\n" + r"\n bar.adb:" + r"\n - 100%, ! 0%, \+ 0% out of 15 lines" + r"\n" + r"\nfoo:" + r"\n - 100%, ! 0%, \+ 0% out of 8 lines" + r"\n" + r"\n foo.adb:" + r"\n - 100%, ! 0%, \+ 0% out of 8 lines" + r"\n" + r"\nlib:" + r"\n - 0%, ! 66%, \+ 33% out of 3 lines" + r"\n" + r"\n lib.ads:" + r"\n - 0%, ! 66%, \+ 33% out of 3 lines" + r"\n" + r"\nmain:" + r"\n - 0%, ! 10%, \+ 90% out of 10 lines" + r"\n" + r"\n a.adb:" + r"\n - 0%, ! 0%, \+ 100% out of 3 lines" + r"\n a.ads:" + r"\n - -%, ! -%, \+ -% out of 0 lines" + r"\n main.adb:" + r"\n - 0%, ! 14%, \+ 85% out of 7 lines" + r"(.|\n)*" + ) + thistest.fail_if_no_match( + f"Unexpected coverage index {idx}" " content", + ref_contents, + idx_contents, + ) + + +if thistest.options.trace_mode == "src": + # Instrument and run coverage analysis, then check that the coverage stats + # are correct. + build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt+mcdc+atcc", + mains=["main"], + extra_coverage_args=["--annotate=xcov,report"], + out="coverage.log", + ) + + metrics = ["lines", "stmt", "decision", "mcdc", "atc", "atcc"] + check_indices(metrics, "obj/stats", "ref") + + # Now compute the coverage by using .sid files. There is no project + # information available for the sources and we expected their stats to be + # displayed under the "Other sources" category. + objdirs = glob.glob("obj*") + sids = [] + for objdir in objdirs: + sids += glob.glob(f"{objdir}/*.sid") + + xcov( + [ + "coverage", + "--level=stmt+mcdc+atcc", + "--annotate=xcov,report,cobertura", + ] + + ["--sid=" + file for file in sids] + + ["--trace=" + srctracename_for("main")], + out="coverage.log", + ) + + check_indices(metrics, "stats", "ref-sid") + +else: + metrics = ["lines"] + + build_run_and_coverage( + gprsw=gprsw, + covlevel="branch", + mains=["main"], + extra_coverage_args=["--annotate=xcov+,cobertura"], + out="couverage.log", + ) + + check_indices(metrics, "obj/stats") + +thistest.result() diff --git a/testsuite/tests/R404-023-object-stats/main b/testsuite/tests/R404-023-object-stats/main new file mode 100755 index 000000000..301680ecb Binary files /dev/null and b/testsuite/tests/R404-023-object-stats/main differ diff --git a/testsuite/tests/R404-023-object-stats/main.adb b/testsuite/tests/R404-023-object-stats/main.adb new file mode 100644 index 000000000..052e24d0b --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/main.adb @@ -0,0 +1,9 @@ +with Pkg; use Pkg; + +procedure Main is +begin + Not_Executed_Branch; + Partially_Covered_Branch; + Fully_Covered_Branch (False); + Fully_Covered_Branch (True); +end Main; diff --git a/testsuite/tests/R404-023-object-stats/main.trace.asset b/testsuite/tests/R404-023-object-stats/main.trace.asset new file mode 100644 index 000000000..3aaf17c17 Binary files /dev/null and b/testsuite/tests/R404-023-object-stats/main.trace.asset differ diff --git a/testsuite/tests/R404-023-object-stats/p.gpr b/testsuite/tests/R404-023-object-stats/p.gpr new file mode 100644 index 000000000..1f60edee6 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/p.gpr @@ -0,0 +1,15 @@ +-- In order to regenerate main.trace.asset, run: +-- +-- gprbuild -Pp -p && gnatcov run -Pp -o main.trace.asset + +project P is + for Target use "arm-eabi"; + for Runtime ("Ada") use "zfp-stm32f4"; + for Exec_Dir use "."; + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Compiler is + for Default_Switches ("Ada") use ("-O1", "-gnatp", "-g"); + end Compiler; +end P; diff --git a/testsuite/tests/R404-023-object-stats/pkg.adb b/testsuite/tests/R404-023-object-stats/pkg.adb new file mode 100644 index 000000000..33aad1828 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/pkg.adb @@ -0,0 +1,30 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Not_Executed_Branch (B1, B2 : Boolean := False) is + begin + if B1 then + if B2 then + Put_Line ("Not_Executed_Branch"); + end if; + end if; + end Not_Executed_Branch; + + procedure Partially_Covered_Branch (B : Boolean := False) is + begin + if B then + Put_Line ("Partially_Covered_Branch"); + end if; + end Partially_Covered_Branch; + + procedure Fully_Covered_Branch (B : Boolean) is + begin + if B then + Put_Line ("Fully_Covered_Branch: True"); + else + Put_Line ("Fully_Covered_Branch: False"); + end if; + end Fully_Covered_Branch; + +end Pkg; diff --git a/testsuite/tests/R404-023-object-stats/pkg.ads b/testsuite/tests/R404-023-object-stats/pkg.ads new file mode 100644 index 000000000..71966c409 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + procedure Not_Executed_Branch (B1, B2 : Boolean := False); + procedure Partially_Covered_Branch (B : Boolean := False); + procedure Fully_Covered_Branch (B : Boolean); +end Pkg; diff --git a/testsuite/tests/R404-023-object-stats/routines.txt b/testsuite/tests/R404-023-object-stats/routines.txt new file mode 100644 index 000000000..24ccc62e1 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/routines.txt @@ -0,0 +1,3 @@ +pkg__not_executed_branch +pkg__partially_covered_branch +pkg__fully_covered_branch diff --git a/testsuite/tests/R404-023-object-stats/test.opt b/testsuite/tests/R404-023-object-stats/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/R404-023-object-stats/test.py b/testsuite/tests/R404-023-object-stats/test.py new file mode 100644 index 000000000..9abe3f0cf --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/test.py @@ -0,0 +1,44 @@ +import os.path + +from SUITE.cutils import Wdir, lines_of, indent +from SUITE.tutils import thistest, xcov + +# main.trace.asset contains an absolute path to the corresponding executable. +# As it was produced on some specific machine, this absolute path is not valid +# everywhere, so help gnatcov locate it anyway with the --exec option. + +exec_path = os.path.abspath("main") +tmp = Wdir("tmp_") +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + "--routines=@../routines.txt", + "--exec={}".format(exec_path), + "../main.trace.asset", + ], + out="asm-report.txt", + tolerate_messages="executable file .* does not seem to match trace file", +) +lines = lines_of("asm-report.txt") + +baseline = """\ +26 instructions analyzed: + 14 covered + 12 not executed +4 conditional branches analyzed: + 1 fully covered + 2 partially covered + 1 not executed""" +result = "\n".join(line.rstrip() for line in lines[-7:]) + +thistest.fail_if( + baseline != result, + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(baseline), indent(result)), +) + +thistest.result() diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected new file mode 100644 index 000000000..452f30727 --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -0,0 +1,1194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/R417-010-scope-metrics/src/main.adb b/testsuite/tests/R417-010-scope-metrics/src/main.adb new file mode 100644 index 000000000..2ba30be91 --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/src/main.adb @@ -0,0 +1,74 @@ +pragma Ada_2012; + +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + function "+" (Item : String) return Unbounded_String + renames To_Unbounded_String; + + package A is + + Size_Chunk : constant := 2_048; + + function And_Then (A, B : Boolean) return Boolean; + + function Id (A : Boolean) return Boolean is (A); + end A; + + package body A is + function And_Then (A, B : Boolean) return Boolean is + begin + return A and then B; + end And_Then; + end A; + + protected Obj is + procedure Set (V : Integer); + entry Get (V : out Integer); + private + Local : Integer; + Is_Set : Boolean := False; + end Obj; + + protected body Obj is + procedure Set (V : Integer) is + begin + Local := V; + Is_Set := True; + end Set; + + entry Get (V : out Integer) + when Is_Set is + -- Entry is blocked until the + -- condition is true. The barrier + -- is evaluated at call of entries + -- and at exits of procedures and + -- entries. The calling task sleeps + -- until the barrier is released. + begin + V := Local; + Is_Set := False; + end Get; + end Obj; + + N : Integer := 0; + + task T; + + task body T is + begin + Put_Line ("Task T will delay for 4 seconds..."); + delay 4.0; + Put_Line ("Task T will set Obj..."); + Obj.Set (5); + Put_Line ("Task T has just set Obj..."); + end T; +begin + Put_Line ("Main application will get Obj..."); + Obj.Get (N); + Put_Line ("Main application has just retrieved Obj..."); + Put_Line ("Number is: " & Integer'Image (N)); + +end Main; diff --git a/testsuite/tests/R417-010-scope-metrics/test.opt b/testsuite/tests/R417-010-scope-metrics/test.opt new file mode 100644 index 000000000..e74976535 --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/test.opt @@ -0,0 +1,4 @@ +bin-traces DEAD no support for body metrics with binary traces +RTS_ZFP DEAD no tasking support in light runtimes +RTS_RAVENSCAR DEAD violates restrictions in the Jorvik profile +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 diff --git a/testsuite/tests/R417-010-scope-metrics/test.py b/testsuite/tests/R417-010-scope-metrics/test.py new file mode 100644 index 000000000..ddea1897c --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/test.py @@ -0,0 +1,32 @@ +""" +Check that gnatcov computes correct scope metrics using the XML report format. +produced by gnatcov. Check this for all acceptions: task, entry, subprogram, +package and expression function. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, FilePathRefiner +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[os.path.join("..", "src")], mains=["main.adb"] + ) + ), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--annotate=xml"], +) + +thistest.fail_if_diff( + os.path.join("..", "main.adb.xml.expected"), + os.path.join("obj", "main.adb.xml"), + output_refiners=[FilePathRefiner()], +) +thistest.result() diff --git a/testsuite/tests/R507-014-trailing-byte-insn/f.s b/testsuite/tests/R507-014-trailing-byte-insn/f.s new file mode 100644 index 000000000..ffd7335e7 --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/f.s @@ -0,0 +1,34 @@ + .text + .file "f.c" + .globl f # -- Begin function f + .p2align 4, 0x90 + .type f,@function +f: # @f + .cfi_startproc +# %bb.0: + testl %edi, %edi + jle .LBB0_1 +# %bb.3: + xorl %ecx, %ecx + xorl %eax, %eax + .p2align 4, 0x90 +.LBB0_4: # =>This Inner Loop Header: Depth=1 + movl %ecx, %edx + andl %edi, %edx + addl %edx, %eax + inc %ecx + cmpl %ecx, %edi + jne .LBB0_4 +# %bb.2: + jmp .LBB0_5 +.LBB0_1: + xorl %eax, %eax +.LBB0_5: + retq +.Lfunc_end0: + .size f, .Lfunc_end0-f + .cfi_endproc + # -- End function + + .ident "clang version 6.0.0 (tags/RELEASE_600/final)" + .section ".note.GNU-stack","",@progbits diff --git a/testsuite/tests/R507-014-trailing-byte-insn/main.c b/testsuite/tests/R507-014-trailing-byte-insn/main.c new file mode 100644 index 000000000..be64ef8ba --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/main.c @@ -0,0 +1,10 @@ +#include + +int f (int n); + +int +main () +{ + printf ("%i\n", f (1)); + return 0; +} diff --git a/testsuite/tests/R507-014-trailing-byte-insn/test.opt b/testsuite/tests/R507-014-trailing-byte-insn/test.opt new file mode 100644 index 000000000..1432b0f0b --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires assembly features not in 5.04a1 +!x86_64-linux DEAD Contains assembly code for x86_64-linux diff --git a/testsuite/tests/R507-014-trailing-byte-insn/test.py b/testsuite/tests/R507-014-trailing-byte-insn/test.py new file mode 100644 index 000000000..247082932 --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/test.py @@ -0,0 +1,116 @@ +""" +Check that gnatcov produces expected assembly coverage reports for single-byte +instructions covered by a single-byte trace entry. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tracelib import ( + TraceEntry, + TraceFile, + TraceOp, + TraceKind, + create_exec_infos, + create_trace_header, +) +from SUITE.tutils import ( + do, + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, +) + + +wd = Wdir("tmp_") +main = exepath_to("main") +main_trace = tracename_for("main") + +# Build the 'main' executable +gpr = gprfor(["main.c"], srcdirs="..", langs=("C", "Asm")) +gprbuild(gpr) + +# Get the address of the 'f' symbol in it +for line in do(["nm", main]).splitlines(): + parts = line.split() + name = parts[-1] + if name == "f": + f_addr = int(parts[0], 16) + break +else: + thistest.failed("Cannot find symbol 'f' in executable 'main'") + +# Create a dummy binary trace from it, including a trace block that covers only +# the 1-byte trailing "ret" instruction. +EM_X86_64 = 62 +bits = 64 +pc_size = bits // 8 +tf = TraceFile( + first_header=create_trace_header( + TraceKind.Info, pc_size, big_endian=False, machine=EM_X86_64 + ), + infos=create_exec_infos(main), + second_header=create_trace_header( + TraceKind.Flat, pc_size, big_endian=False, machine=EM_X86_64 + ), + entries=[ + TraceEntry(bits, f_addr + start_off, end_off - start_off, op) + for start_off, end_off, op in [ + (0x0, 0x4, TraceOp.Block | TraceOp.Br1), + (0x4, 0x1C, TraceOp.Block | TraceOp.Br1), + (0x1C, 0x1E, TraceOp.Block), + (0x20, 0x21, TraceOp.Block), + ] + ], +) +with open(main_trace, "wb") as f: + tf.write(f) + +# Make sure we get the expected coverage report +xcov( + ["coverage", "-cbranch", "-aasm", main_trace, "--routines=f"], + out="coverage.log", +) +actual_report = contents_of("coverage.log").splitlines() + + +def fmt(offset): + return hex(f_addr + offset)[2:].rjust(16, "0") + + +expected_report = f"""\ +Coverage level: branch +f !: {fmt(0)}-{fmt(0x20)} +{fmt(0x00)} +: 85 ff test %edi,%edi +{fmt(0x02)} v: 7e 1a jle {hex(f_addr + 0x1e)} +{fmt(0x04)} +: 31 c9 xor %ecx,%ecx +{fmt(0x06)} +: 31 c0 xor %eax,%eax +{fmt(0x08)} +: 0f 1f 84 00 00 00 00 00 nopl 0x0(%rax,%rax,1) +{fmt(0x10)} +: 89 ca mov %ecx,%edx +{fmt(0x12)} +: 21 fa and %edi,%edx +{fmt(0x14)} +: 01 d0 add %edx,%eax +{fmt(0x16)} +: ff c1 inc %ecx +{fmt(0x18)} +: 39 cf cmp %ecx,%edi +{fmt(0x1a)} v: 75 f4 jne {hex(f_addr + 0x10)} +{fmt(0x1c)} +: eb 02 jmp {hex(f_addr + 0x20)} +{fmt(0x1e)} -: 31 c0 xor %eax,%eax +{fmt(0x20)} +: c3 ret +14 instructions analyzed: + 13 covered + 1 not executed +2 conditional branches analyzed: + 0 fully covered + 2 partially covered + 0 not executed +""" +with open("expected.txt", "w") as f: + f.write(expected_report) + +thistest.fail_if_diff( + baseline_file="expected.txt", + actual_file="coverage.log", + failure_message="unexpected coverage report", +) + +thistest.result() diff --git a/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected new file mode 100644 index 000000000..389c11d9f --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/R507-027-xml-summary/data.ads b/testsuite/tests/R507-027-xml-summary/data.ads new file mode 100644 index 000000000..67b68cec0 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/data.ads @@ -0,0 +1,3 @@ +package Data is + One : Integer := 1; +end Data; diff --git a/testsuite/tests/R507-027-xml-summary/main.adb b/testsuite/tests/R507-027-xml-summary/main.adb new file mode 100644 index 000000000..c25a537ac --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/main.adb @@ -0,0 +1,9 @@ +with Data; +with Pkg; + +procedure Main is + X : Boolean := Pkg.F1 (Data.One); + Y : Boolean := Pkg.F2 (Data.One); +begin + null; +end Main; diff --git a/testsuite/tests/R507-027-xml-summary/pkg.adb b/testsuite/tests/R507-027-xml-summary/pkg.adb new file mode 100644 index 000000000..a3c1a0ea4 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/pkg.adb @@ -0,0 +1,23 @@ +package body Pkg is + + function F1 (I : Integer) return Boolean is + begin + if I < 0 then + return False; + else + return True; + end if; + end F1; + + function F2 (I : Integer) return Boolean is + begin + pragma Annotate (Xcov, Exempt_On, "Exempted because this is a test"); + if I > 10 then + return False; + else + return True; + end if; + pragma Annotate (Xcov, Exempt_Off); + end F2; + +end Pkg; diff --git a/testsuite/tests/R507-027-xml-summary/pkg.ads b/testsuite/tests/R507-027-xml-summary/pkg.ads new file mode 100644 index 000000000..d5aa3e275 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function F1 (I : Integer) return Boolean; + function F2 (I : Integer) return Boolean; +end Pkg; diff --git a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected new file mode 100644 index 000000000..0d35b0972 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/R507-027-xml-summary/test.opt b/testsuite/tests/R507-027-xml-summary/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/R507-027-xml-summary/test.py b/testsuite/tests/R507-027-xml-summary/test.py new file mode 100644 index 000000000..062bc114c --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/test.py @@ -0,0 +1,37 @@ +""" +Check the content of an XML summary. This test verifies part of the +implementation done in the course of S213-006 (obligation metrics). +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, FilePathRefiner +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +wd = Wdir("tmp_") + +gpr = gprfor(["main.adb"], srcdirs="..") +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axml"], +) + +if thistest.options.trace_mode == "bin": + thistest.fail_if_diff( + os.path.join("..", "bin-traces-index.xml.expected"), + os.path.join("obj", "index.xml"), + output_refiners=[FilePathRefiner()], + ) +else: + assert thistest.options.trace_mode == "src" + thistest.fail_if_diff( + os.path.join("..", "src-traces-index.xml.expected"), + os.path.join("obj", "index.xml"), + output_refiners=[FilePathRefiner()], + ) + +thistest.result() diff --git a/testsuite/tests/R807-027-symbol-order/p.adb b/testsuite/tests/R807-027-symbol-order/p.adb new file mode 100644 index 000000000..5e8d5a76a --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/p.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure P is +begin + Pkg.Foo; + Pkg.Bar; +end P; diff --git a/testsuite/tests/R807-027-symbol-order/pkg.adb b/testsuite/tests/R807-027-symbol-order/pkg.adb new file mode 100644 index 000000000..0f2fbc4d7 --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + + procedure Foo is null; + procedure Bar is null; + +end Pkg; diff --git a/testsuite/tests/R807-027-symbol-order/pkg.ads b/testsuite/tests/R807-027-symbol-order/pkg.ads new file mode 100644 index 000000000..5b7f7c375 --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/pkg.ads @@ -0,0 +1,6 @@ +package Pkg is + + procedure Foo; + procedure Bar; + +end Pkg; diff --git a/testsuite/tests/R807-027-symbol-order/test.opt b/testsuite/tests/R807-027-symbol-order/test.opt new file mode 100644 index 000000000..df872a03f --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/R807-027-symbol-order/test.py b/testsuite/tests/R807-027-symbol-order/test.py new file mode 100644 index 000000000..645f46f50 --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/test.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + +""" +Check that the order of symbols in GNATcov's assembly coverage report is +deterministic (sorted, even). +""" + +import re +from SUITE.control import target_info +from SUITE.cutils import Wdir, lines_of +from SUITE.tutils import ( + exepath_to, + gprfor, + gprbuild, + thistest, + tracename_for, + xcov, + xrun, +) + + +tmp = Wdir("tmp_") + +symbols = [ + target_info().to_platform_specific_symbol(s) + for s in ["pkg__bar", "pkg__foo"] +] + +routines = "routines.txt" +report = "coverage-report.txt" +with open(routines, "w") as f: + for s in symbols: + f.write(s + "\n") + +prj = gprfor("p.adb", srcdirs="..") +gprbuild(prj) + +xrun(exepath_to("p")) +xcov( + [ + "coverage", + "-cinsn", + "-aasm", + "-o", + report, + "--routines=@routines.txt", + tracename_for("p"), + ] +) + +report_symbols = sorted( + line.split()[0] + for line in lines_of(report) + if re.match("^[a-z_]* [+!-]: [0-9a-f]+-[0-9a-f]+", line.rstrip()) +) + + +def fmt_list(items): + return "\n".join(" " + line for line in items) + + +thistest.fail_if( + symbols != report_symbols, + "Unexpected sequence of symbols, expected:\n" + "{}\n" + "but got:\n" + "{}".format(fmt_list(symbols), fmt_list(report_symbols)), +) + +thistest.result() diff --git a/testsuite/tests/RB13-019-win-paths/.gitignore b/testsuite/tests/RB13-019-win-paths/.gitignore new file mode 100644 index 000000000..6f4743e41 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/.gitignore @@ -0,0 +1,9 @@ +coverage +driver +driver.exe +*.gli +*.dmap +*.o +*.trace +*.i +*.s diff --git a/testsuite/tests/RB13-019-win-paths/Makefile b/testsuite/tests/RB13-019-win-paths/Makefile new file mode 100644 index 000000000..9f68ae1cd --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/Makefile @@ -0,0 +1,14 @@ +CC=gcc +AR=ar +CFLAGS=-fpreserve-control-flow -fdump-scos -g -save-temps +LDFLAGS=$(CFLAGS) -no-pie + +all: libdriver.a + +libdriver.a: driver.o wibble.o + $(AR) cru libdriver.a driver.o wibble.o + +wibble.o: libsrc/wibble.c libsrc/wibble.h + $(CC) -o $@ -c $< $(CFLAGS) +driver.o: libsrc/driver.c libsrc/wibble.h + $(CC) -o $@ -c $< $(CFLAGS) diff --git a/testsuite/tests/RB13-019-win-paths/libsrc/driver.c b/testsuite/tests/RB13-019-win-paths/libsrc/driver.c new file mode 100644 index 000000000..75cfdefd0 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/libsrc/driver.c @@ -0,0 +1,28 @@ +#include "wibble.h" + +#include +#include + +extern void utils_print (const char *msg); + +int +check (int condition) +{ + if (condition) + { + utils_print ("PASS\n"); + } + else + { + utils_print ("FAIL\n"); + } +} + +int +driver_main (void) +{ + check (foo (3, 2) == 0); + check (foo (3, 3) == 1); + // check(foo(3, 7) == 1); + check (foo (0, 0) == 0); +} diff --git a/testsuite/tests/RB13-019-win-paths/libsrc/wibble.c b/testsuite/tests/RB13-019-win-paths/libsrc/wibble.c new file mode 100644 index 000000000..62e0d785b --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/libsrc/wibble.c @@ -0,0 +1,14 @@ +#include "wibble.h" + +int +foo (int a, int b) +{ + if (a > 0 && (b == 3 || b == 7)) + { + return 1; + } + else + { + return 0; + } +} diff --git a/testsuite/tests/RB13-019-win-paths/libsrc/wibble.h b/testsuite/tests/RB13-019-win-paths/libsrc/wibble.h new file mode 100644 index 000000000..2b57aeae1 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/libsrc/wibble.h @@ -0,0 +1,6 @@ +#ifndef __WIBBLE_H +#define __WIBBLE_H + +int foo (int a, int b); + +#endif diff --git a/testsuite/tests/RB13-019-win-paths/main.adb b/testsuite/tests/RB13-019-win-paths/main.adb new file mode 100644 index 000000000..9b3a41998 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/main.adb @@ -0,0 +1,8 @@ +with Utils; + +procedure Main is + procedure Driver_Main; + pragma Import (C, Driver_Main, "driver_main"); +begin + Driver_Main; +end Main; diff --git a/testsuite/tests/RB13-019-win-paths/main.gpr b/testsuite/tests/RB13-019-win-paths/main.gpr new file mode 100644 index 000000000..d71a0deae --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/main.gpr @@ -0,0 +1,33 @@ +-- Template GPR file for tests requiring executables to be built. + +-- This is read by the gprfor() helper routine, which substitutes +-- the python string template fields with proper values. + +with "/home/derodat/_git/gnatcoverage/testsuite/support/lch.gpr"; + +project main extends "/home/derodat/_git/gnatcoverage/testsuite/support/base.gpr" is + + + +for Source_Dirs use ("."); +for Exec_Dir use "."; +for Object_Dir use "./obj"; + +for Languages use ("Ada"); + +package Compiler is +for Switches("main.adb") use + Compiler'Default_Switches ("Ada") & (); + + +end Compiler; + +for Main use ("main.adb"); + +package Emulator is + for Board use "stm32f4"; +end Emulator; + + + +end main; diff --git a/testsuite/tests/RB13-019-win-paths/test.opt b/testsuite/tests/RB13-019-win-paths/test.opt new file mode 100644 index 000000000..b68b45768 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/test.opt @@ -0,0 +1,2 @@ +arm-elf,qemu-stm32,bin-traces +ALL DEAD Test tailored for bin traces on arm-elf/stm32f4 diff --git a/testsuite/tests/RB13-019-win-paths/test.py b/testsuite/tests/RB13-019-win-paths/test.py new file mode 100644 index 000000000..11bafbbf6 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/test.py @@ -0,0 +1,91 @@ +""" +Check that gnatcov does not complain about "same base name for files" and +computes the expected code coverage when C files are compiled with a Makefile. + +This used not to work because in this build scenario on Windows, debug info +used contains unexpected double backslashes as directory separators. +""" + +import os.path + +from e3.fs import cp +from e3.os.process import PIPE, Run, STDOUT + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env +from SUITE.cutils import FatalError, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + + +tmp = Wdir("tmp_") + + +# Copy the C project in this temporary directory to avoid clutter in the test +# sources. +for f in ["Makefile", "libsrc"]: + cp(os.path.join("..", f), f, recursive=True) + +# Build libdriver.a +p = Run( + [ + "make", + f"CC={env.target.triplet}-gcc", + f"AR={env.target.triplet}-ar", + "CFLAGS={}".format( + " ".join( + [ + "-fpreserve-control-flow", + "-fdump-scos", + "-g", + "-save-temps", + # TODO??? This is necessary in order to have the C sources + # build with an arm-elf toolchain and a stm32f4 RTS, it is + # not clear if we could make this more generic. + "-mlittle-endian", + "-mfloat-abi=hard", + "-mcpu=cortex-m4", + "-mfpu=fpv4-sp-d16", + ] + ) + ), + ], + output=PIPE, + error=STDOUT, +) +thistest.log("make output:\n" + p.out) +thistest.stop_if(p.status != 0, FatalError('call to "make" failed')) + +# Build the test program, run it and produce a coverage report +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + prjid="main", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada"], + ), + ), + covlevel="stmt+mcdc", + mains=["main"], + scos=["obj/main"], + extra_gprbuild_args=["-vh"], + extra_gprbuild_largs=[f"-L{os.getcwd()}", "-ldriver"], + extra_coverage_args=[ + "-axcov", + "--output-dir=coverage", + "--scos=wibble.c.gli", + "--scos=driver.c.gli", + ], +) + +check_xcov_reports( + "coverage", + { + "wibble.c.xcov": {"+": {8, 12}, "!": {6}}, + "main.adb.xcov": {"+": {7}}, + "driver.c.xcov": {"+": {13, 24, 25, 27}, "!": {11}, "-": {17}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/RB13-019-win-paths/utils.adb b/testsuite/tests/RB13-019-win-paths/utils.adb new file mode 100644 index 000000000..3ce4e6819 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/utils.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Utils is + + ----------- + -- Print -- + ----------- + + procedure Print (Msg : chars_ptr) is + Ada_Msg : constant String := Value (Msg); + begin + Put_Line (Ada_Msg); + end Print; + +end Utils; diff --git a/testsuite/tests/RB13-019-win-paths/utils.ads b/testsuite/tests/RB13-019-win-paths/utils.ads new file mode 100644 index 000000000..d28436231 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/utils.ads @@ -0,0 +1,6 @@ +with Interfaces.C.Strings; use Interfaces.C.Strings; + +package Utils is + procedure Print (Msg : chars_ptr); + pragma Export (C, Print, "utils_print"); +end Utils; diff --git a/testsuite/tests/RB16-008-gpr-tool/main.adb b/testsuite/tests/RB16-008-gpr-tool/main.adb new file mode 100644 index 000000000..424a11933 --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/main.adb @@ -0,0 +1,8 @@ +with Unit_GNATcoverage, Unit_Env_Var, Unit_X_Arg; + +procedure Main is +begin + Unit_GNATcoverage; + Unit_Env_Var; + Unit_X_Arg; +end Main; diff --git a/testsuite/tests/RB16-008-gpr-tool/test.py b/testsuite/tests/RB16-008-gpr-tool/test.py new file mode 100644 index 000000000..e42603ccc --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/test.py @@ -0,0 +1,86 @@ +""" +Check that gnatcov processes the GPR_TOOL environment variable/scenario +variables as expected. +""" + +import glob +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +# Ways to convey to gnatcov a value for the GPR_TOOL variable +env_var = "env_var" # Environment variable +x_arg = "x_arg" # -X command-line argument + +# List of scenarios to test. Each tuple contains: +# +# 1) The set of ways to convey the GPR_TOOL variable to gnatcov +# 2) The unit of interest we expect for this scenario. +# +# -X arguments take precedence over everything else. Then comes the environment +# variable, and finally, by default GPR_TOOL is supposed to be "gnatcoverage". +test_scenarios = [ + (set(), "unit_gnatcoverage"), + ({env_var}, "unit_env_var"), + ({x_arg}, "unit_x_arg"), + ({env_var, x_arg}, "unit_x_arg"), +] + +for ways, expected_unit in test_scenarios: + ways_str = "-".join(sorted(ways)) or "default" + + wd = Wdir(f"tmp_{ways_str}") + + # Build the test program and produce a trace + gpr = gprfor( + ["main.adb"], + srcdirs="..", + extra=""" + GPR_Tool := external ("GPR_TOOL", ""); + package Coverage is + for Units use ("unit_" & GPR_Tool); + end Coverage; + """, + ) + + # Prepare the (sometimes conflicting) ways to convey the GPR_TOOL variable + # to gnatcov. + common_xcov_args = [] + os.environ.pop("GPR_TOOL", None) + if env_var in ways: + os.environ["GPR_TOOL"] = "env_var" + if x_arg in ways: + common_xcov_args.append("-XGPR_TOOL=x_arg") + + # Produce a coverage report for this configuration + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + extra_args=common_xcov_args, + ) + + # Check that the report contains what we expect + reported_units = sorted(glob.glob(os.path.join("obj", "*.xcov"))) + expected_report = os.path.join("obj", f"{expected_unit}.adb.xcov") + + thistest.fail_if( + reported_units != [expected_report], + "Unexpected set of coverage reports, expected:\n" + " {}\n" + "but got:\n" + "{}".format( + expected_report, + "\n".join(" {}".format(f) for f in reported_units), + ), + ) + + wd.to_homedir() + +thistest.result() diff --git a/testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb b/testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb new file mode 100644 index 000000000..2ca42ee58 --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Unit_Env_Var is +begin + Ada.Text_IO.Put_Line ("In Unit_Env_Var"); +end; diff --git a/testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb b/testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb new file mode 100644 index 000000000..1aeece17c --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Unit_GNATcoverage is +begin + Ada.Text_IO.Put_Line ("In Unit_GNATcoverage"); +end; diff --git a/testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb b/testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb new file mode 100644 index 000000000..0b54fe52b --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Unit_X_Arg is +begin + Ada.Text_IO.Put_Line ("In Unit_X_Arg"); +end; diff --git a/testsuite/tests/RC04-030-bad-trace/.gitignore b/testsuite/tests/RC04-030-bad-trace/.gitignore new file mode 100644 index 000000000..511ee6c49 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/.gitignore @@ -0,0 +1,7 @@ +coverage +driver +driver.exe +*.gli +*.dmap +*.o +*.trace diff --git a/testsuite/tests/RC04-030-bad-trace/main_a.adb b/testsuite/tests/RC04-030-bad-trace/main_a.adb new file mode 100644 index 000000000..eee397a62 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/main_a.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_A is +begin + Pkg.Run (True, False, False); +end Main_A; diff --git a/testsuite/tests/RC04-030-bad-trace/main_b.adb b/testsuite/tests/RC04-030-bad-trace/main_b.adb new file mode 100644 index 000000000..8dafa2700 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/main_b.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_B is +begin + Pkg.Run (False, True, False); +end Main_B; diff --git a/testsuite/tests/RC04-030-bad-trace/main_c.adb b/testsuite/tests/RC04-030-bad-trace/main_c.adb new file mode 100644 index 000000000..107d21a13 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/main_c.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_C is +begin + Pkg.Run (False, False, True); +end Main_C; diff --git a/testsuite/tests/RC04-030-bad-trace/pkg.adb b/testsuite/tests/RC04-030-bad-trace/pkg.adb new file mode 100644 index 000000000..927091668 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/pkg.adb @@ -0,0 +1,22 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + --------- + -- Run -- + --------- + + procedure Run (A, B, C : Boolean) is + begin + if A then + Put_Line ("A is true"); + end if; + if B then + Put_Line ("B is true"); + end if; + if C then + Put_Line ("C is true"); + end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/RC04-030-bad-trace/pkg.ads b/testsuite/tests/RC04-030-bad-trace/pkg.ads new file mode 100644 index 000000000..40be93447 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Run (A, B, C : Boolean); +end Pkg; diff --git a/testsuite/tests/RC04-030-bad-trace/test.opt b/testsuite/tests/RC04-030-bad-trace/test.opt new file mode 100644 index 000000000..a42e26bd4 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test feature related to binary traces diff --git a/testsuite/tests/RC04-030-bad-trace/test.py b/testsuite/tests/RC04-030-bad-trace/test.py new file mode 100644 index 000000000..bfbd2886a --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/test.py @@ -0,0 +1,121 @@ +""" +Check that, with --keep-reading-traces, when processing malformed trace files, +gnatcov emits diagnostics that are useful to identify which trace file is +malformed. Also check that the computation of the coverage report go to +completion, and that gnatcov still exits with an error status code. +""" + +import os +import os.path +import re + +from SCOV.minicheck import check_xcov_reports +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import ( + exepath_to, + gprfor, + gprbuild, + thistest, + tracename_for, + xcov, + xrun, +) + + +def indexes(string, substr): + """ + Return the list of all indexes in "string" at which the given substring can + be found. + """ + result = [] + start = 0 + while start < len(string): + i = string.find(substr, start) + if i == -1: + break + result.append(i) + start = i + 1 + return result + + +tmp = Wdir("tmp_") +os.mkdir("traces") + +mains = ("main_a", "main_b", "main_c") +tracefiles = [os.path.join("traces", tracename_for(m)) for m in mains] + +prj = gprfor(["{}.adb".format(m) for m in mains], srcdirs="..") +gprbuild(prj) + +# Produce trace files for all mains +for main, tracefile in zip(mains, tracefiles): + xrun( + [exepath_to(main), "-o", tracefile, "-T", "Trace for {}".format(main)] + ) + +# Corrupt the trace for main_b. Look for the second trace header and truncate +# the file in the middle of a trace entry. We go through this to get an error +# that is consistent across runs. +with open(tracefiles[1], "rb") as f: + data = f.read() +header_indexes = indexes(data, b"#QEMU-Traces") +header_size = 20 # See Qemu_Traces.Trace_Header +with open(tracefiles[1], "wb") as f: + f.write(data[: header_indexes[1] + header_size + 5]) + + +def gnatcov_coverage(keep_reading_traces): + log_file = "coverage-{}.log".format( + "krt" if keep_reading_traces else "default" + ) + + argv = ["coverage", "-axcov", "-cstmt", "-P{}".format(prj)] + if keep_reading_traces: + argv.append("--keep-reading-traces") + + p = xcov(argv + tracefiles, out=log_file, register_failure=False) + if keep_reading_traces: + thistest.fail_if( + p.status != 0, '"gnatcov coverage" status code is non-zero.' + ) + else: + thistest.fail_if( + p.status == 0, + '"gnatcov coverage" status code is zero (expected error).', + ) + + coverage_log = contents_of(log_file).strip() + diag = "warning" if keep_reading_traces else "gnatcov" + expected_log = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + f"[^\n]*{diag}[^\n]*: traces[/\\\\]main_b[^\n]*.trace: file truncated" + ) + thistest.fail_if( + not expected_log.match(coverage_log), + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(expected_log.pattern), indent(coverage_log)), + ) + + +# Make sure that without --keep-reading-traces, no coverage report is produced +gnatcov_coverage(False) +check_xcov_reports("obj", {}) + + +# Make sure that with it, both the first and the last trace files contributed +# to coverage assessment, while the middle one was skipped. +gnatcov_coverage(True) +check_xcov_reports( + "obj", + { + "pkg.adb.xcov": {"+": {11, 12, 14, 17, 18}, "-": {15}}, + "main_a.adb.xcov": {"+": {5}}, + "main_b.adb.xcov": {"-": {5}}, + "main_c.adb.xcov": {"+": {5}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/extra.opt b/testsuite/tests/Ravenscar/Exceptions/extra.opt new file mode 100644 index 000000000..274d5fa68 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/extra.opt @@ -0,0 +1,3 @@ +block DEAD Tests with exceptions breaking the control flow +RTS_ZFP DEAD no support for exception propagation in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for exception propagation in light-tasking runtimes diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb new file mode 100644 index 000000000..116f8abfb --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb @@ -0,0 +1,10 @@ +with Support; use Support; +with P; use P; + +procedure Raise_Exception is +begin + raise Force_Exception; -- # force_exception +exception + when Force_Exception => + raise Constraint_Error; -- # raise +end Raise_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb new file mode 100644 index 000000000..087584c82 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb @@ -0,0 +1,12 @@ +with Support; use Support; +with P; use P; + +procedure Raise_Exception is + X: Integer; + pragma Unsuppress (All_Checks); +begin + raise Force_Exception; -- # force_exception +exception + when Force_Exception => + X := Identity(5)/Identity (0); -- # raise +end Raise_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb new file mode 100644 index 000000000..e13ecd3c9 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb @@ -0,0 +1,11 @@ +with P; use P; + +procedure Raise_Exception is +begin + raise Constraint_Error; -- # force_exception +exception + when Constraint_Error => + raise; -- # raise + when others => + Wrong_Exception_Propagated := True; -- # wrong_exception +end; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt new file mode 100644 index 000000000..f355d7772 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt @@ -0,0 +1,9 @@ +Check coverage of exceptions that are raised in an exception handler + +We check for exceptions raised: + + - implicitly, e.g. an arithmetic operation that raises CE + + - explicitly, via a "raise CE" stmt + + - reraised exceptions, i.e. via a "raise;" statement diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb new file mode 100644 index 000000000..4a22eb4ef --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb @@ -0,0 +1,12 @@ +with P; use P; +with Raise_Exception; + +procedure Handle_Exception is +begin + Raise_Exception; -- # raise +exception + when Constraint_Error => + Correct_Exception_Propagated := True; -- # handled + when others => + Wrong_Exception_Propagated := True; -- # mis_handled +end Handle_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads new file mode 100644 index 000000000..3a1aacd52 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads @@ -0,0 +1 @@ +procedure Handle_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads new file mode 100644 index 000000000..9c3a26db9 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads @@ -0,0 +1,7 @@ +package P is + Force_Exception: Exception; + + Correct_Exception_Propagated : Boolean := False; + Wrong_Exception_Propagated : Boolean := False; + +end P; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads new file mode 100644 index 000000000..a9ef4e099 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads @@ -0,0 +1 @@ +procedure raise_exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb new file mode 100644 index 000000000..fe5b64e5b --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb @@ -0,0 +1,20 @@ +with Support; use Support; +with P; use P; +with Handle_Exception; +procedure test_raise_exception is +begin + Handle_Exception; + + Assert (Correct_Exception_Propagated = True); + Assert (Wrong_Exception_Propagated = False); + +end; + +--# handle_exception.adb +-- /raise/ l+ ## 0 +-- /handled/ l+ ## 0 +-- /mis_handled/ l- ## s- +--# raise_exception.adb +-- /force_exception/ l+ ## 0 +-- /raise/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb new file mode 100644 index 000000000..0fcc753aa --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb @@ -0,0 +1,31 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val_In_Range: Integer) is +begin + + begin -- outer + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := Val_In_Range; -- # violation + end Pack; + begin + X := Identity (5); -- # stmt + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; + exception + when storage_error | program_error => + Wrong_Exception_Raised := True; -- # wrong_handler + end; --outer +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb new file mode 100644 index 000000000..beab14adb --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb @@ -0,0 +1,33 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val_In_Range: Integer) is +begin + + begin -- outer + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := Val_In_Range; -- # violation + end Pack; + begin + X := Identity (5); -- # stmt + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; + exception + when storage_error | program_error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Correct_Exception_Raised := True; -- # properly_handled + end; --outer +exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_exception + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb new file mode 100644 index 000000000..cbf090676 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb @@ -0,0 +1,25 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val_In_Range: Integer) is +begin + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := Val_In_Range; -- # violation + end Pack; + begin + X := Identity (5); -- # stmt + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb new file mode 100644 index 000000000..98ad04673 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb @@ -0,0 +1,27 @@ +-- Driver to test intrasubprogram package elaboration. +-- Do not call the procedure containing the package elaboration. +-- All of the code should be uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ l- ## s- +-- /violation/ l- ## s- +-- /stmt/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l- ## ~s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb new file mode 100644 index 000000000..dd2017d34 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb @@ -0,0 +1,31 @@ +-- Driver to test intrasubprogram package elaboration. +-- Call procedure Elab so that the package elaboration nested within +-- it does not raise an exception. Check that the entire block is +-- executed and that the code of the exception handlers are +-- uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ l+ ## 0 +-- /violation/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb new file mode 100644 index 000000000..c3d790de7 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb @@ -0,0 +1,31 @@ +-- Driver to test intrasubprogram package elaboration. +-- Call procedure Elab so that the package elaboration nested within +-- it raises an exception. Check that the exception is handled +-- properly, and that the statements of the block in which the +-- exception are uncovered -- i.e. not executed. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ l+ ## 0 +-- /violation/ l+ ## 0 +-- /stmt/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb new file mode 100644 index 000000000..caf6a8b12 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb @@ -0,0 +1,26 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +with SubP; use SubP; +procedure Elab (Val: Integer) is +begin + declare + X : Integer ; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb new file mode 100644 index 000000000..3b6724020 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb @@ -0,0 +1,13 @@ +package body SubP is + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x >=10 then -- # test + raise Constraint_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads new file mode 100644 index 000000000..215f64e9a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads @@ -0,0 +1,5 @@ +package SubP is + + function func (x: integer) return integer; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..370ce569b --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb @@ -0,0 +1,26 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is explicitly raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +--# elab.adb +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb new file mode 100644 index 000000000..78c215ec4 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb @@ -0,0 +1,28 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is implicitly raised. +-- Note: in this case, the exception is actually not propagated to +-- another subprogram, but handled by the same subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_imp_raise is +begin + Elab (1); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +--# elab.adb +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..972c9e1e3 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb @@ -0,0 +1,23 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. Everything should be uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +--# elab.adb +-- /decl/ ~l- ## ~s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..496d00285 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb @@ -0,0 +1,26 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is not raised at all. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +--# elab.adb +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb new file mode 100644 index 000000000..d84bf8f99 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb @@ -0,0 +1,29 @@ +with Support; use Support; +with Global; use Global; +with SubP; use SubP; +procedure Elab (Val: Integer) is + +begin + declare + X : Integer ; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when My_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when My_Error => + Correct_Exception_Raised := True; -- # properly_handled + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_exception + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb new file mode 100644 index 000000000..95d0779b8 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb @@ -0,0 +1,13 @@ +package body SubP is + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x >=10 then -- # test + raise My_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads new file mode 100644 index 000000000..a7202229b --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads @@ -0,0 +1,7 @@ +package SubP is + + function func (x: integer) return integer; + + My_Error: Exception; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..74ee58999 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that a user +-- defined exception is raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..73475c839 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. No exception raised, everything +-- is uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +--# elab.adb +-- /decl/ ~l- ## ~s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..9c04e9f04 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that the user +-- defined exception is not raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb new file mode 100644 index 000000000..1e671b23d --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb @@ -0,0 +1,36 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val: Integer) is + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x > 10 then -- # test + raise Constraint_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +begin + declare + X : Integer range 0..9; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..692bbf7df --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb @@ -0,0 +1,24 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is explicitly raised and propagated to the calling subprogram. +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb new file mode 100644 index 000000000..0932fa3e0 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb @@ -0,0 +1,27 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is implicitly raised. +-- Note: in this case, the exception is actually not propagated to +-- another subprogram, but handled by the same subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_imp_raise is +begin + Elab (1); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..2908d10e8 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb @@ -0,0 +1,23 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. Everything should be uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ ~l- ## ~s- +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..7bae01f87 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is not raised at all. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb new file mode 100644 index 000000000..e0b29a379 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb @@ -0,0 +1,40 @@ +with Support; use Support; +with Global; use Global; +procedure Elab (Val: Integer) is + + My_Error: Exception; -- # exception_decl + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x > 10 then -- # test + raise My_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +begin + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when My_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when My_Error => + Correct_Exception_Raised := True; -- # properly_handled + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_exception + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..74ee58999 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that a user +-- defined exception is raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..d7281c7b3 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb @@ -0,0 +1,32 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. No exception raised, everything +-- is uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /exception_decl/ l- ## s- +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +-- /decl/ l- ## s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/exception_decl/ ~l- ## ~s- +-- =/decl/ ~l- ## ~s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..f1eb5c0cf --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb @@ -0,0 +1,31 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that the user +-- defined exception is not raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt new file mode 100644 index 000000000..f2e3400da --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt @@ -0,0 +1,14 @@ +Check for exception raised during package elaboration: + +We check: + Package elaborations in which the exceptions are raised and + handled within the same subprogram. These packages specs can appear + in a simple block, or a nexted block. The exceptions are either + handled immediately or propagated to an outer block within the same + subprogram. + + Package elaborations in which the exceptions are propagated and + handled by another (calling) subprogram. We test exceptions raised + in library units and exceptions that are raised within a nested + subprogram. User defined as well as predefined (implicit and explicit) + exceptions are tested. diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads new file mode 100644 index 000000000..74eed9e85 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads @@ -0,0 +1,4 @@ +package Global is + Correct_Exception_Raised : Boolean := False; + Wrong_Exception_Raised : Boolean := False; +end Global; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb new file mode 100644 index 000000000..83db74df1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb @@ -0,0 +1,17 @@ +package body Div is + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + if Y = 0 then -- # explicit_check + raise My_Constraint_Error; -- # explicit_raise + else + Res := X/Y; -- # computation + end if; + exception + when My_Constraint_Error => + N_In_MyCE_Handler := N_In_MyCE_Handler + 1; -- # explicit_handler + when Constraint_Error => + N_In_Wrong_Handler := N_In_Wrong_Handler + 1; -- # wrong_handler + when others => + N_In_Wrong_Handler := N_In_Wrong_Handler + 1; -- # wrong_handler + end Divide; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..e1a1e10d1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + + Result : Integer; + +begin + + Divide (12, 0, Result); + + Assert (N_In_MyCE_Handler = 1); + Assert (N_In_Wrong_Handler = 0); + +end Test_Divide_Nok; + +--# div.adb +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l+ ## 0 +-- /computation/ l- ## s- +-- /explicit_handler/ l+ ## 0 +-- /wrong_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..fc4118363 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + + Result : Integer; + +begin + + Divide (12, 2, Result); + + Assert (N_In_MyCE_Handler = 0); + Assert (N_In_Wrong_Handler = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l- ## s- +-- /computation/ l+ ## 0 +-- /explicit_handler/ l- ## s- +-- /wrong_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb new file mode 100644 index 000000000..eecf722d1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb @@ -0,0 +1,11 @@ +pragma Unsuppress (All_Checks); + +package body Div is + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + Res := X/Y; -- # division + exception + when Constraint_Error => + N_In_Handler := N_In_Handler + 1; -- # in_handler + end Divide; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..d330fb368 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,18 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + + Result : Integer; + +begin + + Divide (12, 0, Result); + + Assert (N_In_Handler = 1); + +end Test_Divide_Nok; + +--# div.adb +-- /division/ l+ ## 0 +-- /in_handler/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..6d789ca47 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,18 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + + Result : Integer; + +begin + + Divide (12, 2, Result); + + Assert (N_In_Handler = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /division/ l+ ## 0 +-- /in_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb new file mode 100644 index 000000000..9b7dbcf6e --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb @@ -0,0 +1,21 @@ +package body Div is + function Unhandled_Divide (X, Y: Integer) return Integer is + begin + if Y = 0 then -- # explicit_check + raise Constraint_Error; -- # explicit_raise + else + return X/Y; -- # computation + end if; + end Unhandled_Divide; + + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + Res := Unhandled_Divide (X,Y); -- # division + N_Comp_Success := N_Comp_Success + 1; -- # no_exception + exception + when Constraint_Error => + N_Excpt_Prop := N_Excpt_Prop + 1; -- # propagated_up + when others => + N_Wrong_Excpt_Prop := N_Wrong_Excpt_Prop + 1; -- # wrong_excpt + end; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..bc33e63c2 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + Result: Integer; +begin + Divide (10,0, Result); + + Assert (N_Comp_Success = 0); + Assert (N_Excpt_Prop = 1); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Nok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l- ## s- +-- /propagated_up/ l+ ## 0 +-- /wrong_excpt/ l- ## s- +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l+ ## 0 +-- /computation/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..9d921b47a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + Result: Integer; +begin + Divide (10,5, Result); + + Assert (N_Comp_Success = 1); + Assert (N_Excpt_Prop = 0); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l+ ## 0 +-- /propagated_up/ l- ## s- +-- /wrong_excpt/ l- ## s- +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l- ## s- +-- /computation/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb new file mode 100644 index 000000000..a922b2e57 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb @@ -0,0 +1,19 @@ +pragma Unsuppress (All_Checks); + +package body Div is + function Unhandled_Divide (X, Y: Integer) return Integer is + begin + return X/Y; -- # division + end Unhandled_Divide; + + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + Res := Unhandled_Divide (X,Y); -- # division + N_Comp_Success := N_Comp_Success + 1; -- # no_exception + exception + when Constraint_Error => + N_Excpt_Prop := N_Excpt_Prop + 1; -- # propagated_up + when others => + N_Wrong_Excpt_Prop := N_Wrong_Excpt_Prop + 1; -- # wrong_excpt + end; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..bb791240c --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + Result: Integer; +begin + Divide (10,0, Result); + + Assert (N_Comp_Success = 0); + Assert (N_Excpt_Prop = 1); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Nok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l- ## s- +-- /propagated_up/ l+ ## 0 +-- /wrong_excpt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..e3257f086 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + Result: Integer; +begin + Divide (10,5, Result); + + Assert (N_Comp_Success = 1); + Assert (N_Excpt_Prop = 0); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l+ ## 0 +-- /propagated_up/ l- ## s- +-- /wrong_excpt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt new file mode 100644 index 000000000..bdf1e9301 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt @@ -0,0 +1,11 @@ +Check coverage of excpetions that are raised in a subprogram body. + +We check for exceptions raised: + + - in a subprogram with a local handler + + - in a subprogram without local handler, exception propogated upawards + + - unhandled exceptions? + +Implicitly and Explicitly raised exceptions. diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads new file mode 100644 index 000000000..977ea0f37 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads @@ -0,0 +1,14 @@ +package Div is + + N_In_Handler : Natural := 0; + My_Constraint_Error: exception; + N_In_MyCE_Handler: Natural := 0; + N_In_Wrong_Handler: Natural := 0; + + procedure Divide (X, Y: Integer; Res: out Integer); + + N_Comp_Success : Integer := 0; + N_Excpt_Prop : Integer := 0; + N_Wrong_Excpt_Prop : Integer := 0; + +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb new file mode 100644 index 000000000..063d2c575 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb @@ -0,0 +1,24 @@ +package body Cond_Raise is + + procedure Raise_If (Cond : Boolean) is + begin + if Cond then -- # test_cond + N_Raise := N_Raise + 1; -- # raise + raise Constraint_Error; -- # raise + + -- Repeating # raise is done on purpose here, to let + -- test drivers designate the set of lines/statements + -- that all get to execute or not depending on Cond. + end if; + N_Past_Test := N_Past_Test + 1; -- # past_test + end; + + procedure Check_For (Cond : Boolean) is + begin + Raise_If (Cond => Cond); -- # call + N_Past_Call := N_Past_Call + 1; -- # past_call + exception + when Constraint_Error => + N_In_Handler := N_In_Handler + 1; -- # in_handler + end; +end; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads new file mode 100644 index 000000000..e68f92c1a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads @@ -0,0 +1,5 @@ +package Cond_Raise is + procedure Check_For (Cond : Boolean); + + N_Past_Call, N_In_Handler, N_Raise, N_Past_Test : Natural := 0; +end; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb new file mode 100644 index 000000000..4db6fafcd --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb @@ -0,0 +1,18 @@ +with Support, Cond_Raise; use Support; + +procedure Test_Cond_F is +begin + Cond_Raise.Check_For (Cond => False); + Assert (Cond_Raise.N_Raise = 0); + Assert (Cond_Raise.N_Past_Test = 1); + Assert (Cond_Raise.N_In_Handler = 0); + Assert (Cond_Raise.N_Past_Call = 1); +end; + +--# cond_raise.adb +-- /test_cond/ l+ ## 0 +-- /raise/ l- ## s- +-- /past_test/ l+ ## 0 +-- /call/ l+ ## 0 +-- /past_call/ l+ ## 0 +-- /in_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb new file mode 100644 index 000000000..71bdc398d --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb @@ -0,0 +1,36 @@ +with Support, Cond_Raise; use Support; + +procedure Test_Cond_T is +begin + Cond_Raise.Check_For (Cond => True); + + -- We called once only, raising. So ... + + -- We raised and went into the exception handler once + + Assert (Cond_Raise.N_Raise = 1); + Assert (Cond_Raise.N_In_Handler = 1); + + -- We never reached the code past the test deciding if we should raise + -- (which we only reach when we call the function without raising). + -- Likewise for the code past the inner call, skipped by the exception + -- propagation. + + Assert (Cond_Raise.N_Past_Test = 0); + Assert (Cond_Raise.N_Past_Call = 0); + +end; + +-- Expectations on =xcov and =report coverage outcome follow. Note the single +-- reference to the "raise" marker to designate multiple lines/statements in +-- the Raise_If suprogram, for which we indeed always expect the same kind of +-- outcome (all the lines/statements are expected to be covered/uncovered in +-- a consistent fashion). + +--# cond_raise.adb +-- /test_cond/ l+ ## 0 +-- /raise/ l+ ## 0 +-- /past_test/ l- ## s- +-- /call/ l+ ## 0 +-- /past_call/ l- ## s- +-- /in_handler/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb new file mode 100755 index 000000000..3f77df31a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb @@ -0,0 +1,25 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Class_Wide + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; + Var : Access_T_Class; + +begin + case Check_Var is + when 1 => + Var := new T1_T'(C1 => 1); + when 2 => + Var := new T2_T'(C1 => 1); + when 3 => + Var := new T2_T'(C1 => 101); + when others => + null; + end case; + + Result := Compute_C (Var.all); + +end Check_Class_Wide; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb new file mode 100755 index 000000000..8d04b7297 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation in such a way that a top-level +-- decision in its body is evaluated to False. DC for the called dispatching +-- operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_F is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 2, + Result => Result); + + Assert (Result = 0); +end Test_F; + +--# parent.adb +-- /compute_c_eval/ l! ## dT- +-- /compute_c_true/ l- ## s- +-- /compute_c_false/ l+ ## 0 +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb new file mode 100755 index 000000000..c41102288 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb @@ -0,0 +1,41 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver does not call anything - the check is made that no code of +-- interest is reported as covered. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_No is + Result : Integer; +begin + Assert (True); +end Test_No; + +--# parent.adb +-- /compute_c_eval/ l- ## s- +-- /compute_c_true/ l- ## s- +-- /compute_c_false/ l- ## s- +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb new file mode 100755 index 000000000..0cf209d00 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation in such a way that a top-level +-- decision in its body is evaluated to True. DC for the called dispatching +-- operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_T is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 1, + Result => Result); + + Assert (Result = 1); +end Test_T; + +--# parent.adb +-- /compute_c_eval/ l! ## dF- +-- /compute_c_true/ l+ ## 0 +-- /compute_c_false/ l- ## s- +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb new file mode 100755 index 000000000..6347132f9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb @@ -0,0 +1,52 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation twice, and as a result a top-level +-- decision in its body is evaluated to True and to False. DC for the called +-- dispatching operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_TF is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 1, + Result => Result); + + Assert (Result = 1); + + Check_Class_Wide + (Check_Var => 2, + Result => Result); + + Assert (Result = 0); +end Test_TF; + +--# parent.adb +-- /compute_c_eval/ l+ ## 0 +-- /compute_c_true/ l+ ## 0 +-- /compute_c_false/ l+ ## 0 +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb new file mode 100755 index 000000000..409e4d34d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb @@ -0,0 +1,60 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation three, and as a result a top-level +-- decision in its body is evaluated to True, to False and raises an +-- exception. DC for the called dispatching operations (here we have dynamic +-- dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_TFX is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 1, + Result => Result); + + Assert (Result = 1); + + Check_Class_Wide + (Check_Var => 2, + Result => Result); + + Assert (Result = 0); + + Check_Class_Wide + (Check_Var => 3, + Result => Result); +exception + when others => + Assert (Result = 0); +end; + +--# parent.adb +-- /compute_c_eval/ l+ ## 0 +-- /compute_c_true/ l+ ## 0 +-- /compute_c_false/ l+ ## 0 +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l+ ## 0 +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l! ## dT- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb new file mode 100755 index 000000000..b7471bb37 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb @@ -0,0 +1,47 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation in such a way that evaluation of a +-- top-level decision in its body raises an exception. DC for the called +-- dispatching operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_X is + Result : Integer := 13; +begin + Check_Class_Wide + (Check_Var => 3, + Result => Result); +exception + when others => + Assert (Result = 13); +end Test_X; + +--# parent.adb +-- /compute_c_eval/ l! ## d- +-- /compute_c_true/ l- ## s- +-- /compute_c_false/ l- ## s- +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dT- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l! ## dT- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt new file mode 100755 index 000000000..c20aecec9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt @@ -0,0 +1,6 @@ +Check DC when a class-wide operation is called (not as a condition of some +decision). DC is checked for the code of the dispatching operation itself and +for the code of dispatching operations that can be called by the class-wide +operation. The class-wide operation contains an IF statement (with ELSE part +and with no ELSIF part). The tests are structured according to the +coverage of the decision in this IF statement. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb new file mode 100755 index 000000000..a0b57586a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb @@ -0,0 +1,32 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Class_Wide_Condition + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; -- # dcl + Var : Access_T_Class; -- # dcl + +begin + case Check_Var is -- # case + when 1 => + Var := new T1_T'(C1 => 1); -- # var_1 + when 2 => + Var := new T2_T'(C1 => 1); -- # var_2 + when 3 => + Var := new T1_T'(C1 => 101); -- # var_3 + when others => + null; -- # var_others + end case; + + if Valid_C (Var.all) then -- # eval + Result := 10; -- # true + else + Result := 20; -- # false + end if; + +exception + when Constraint_Error => + Result := 0; -- # exc +end Check_Class_Wide_Condition; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb new file mode 100755 index 000000000..bdd80ecc2 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb @@ -0,0 +1,36 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation in such a way that a decision to +-- check is evaluated to False. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_F is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); +end Test_F; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /false/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb new file mode 100755 index 000000000..8148e3efe --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb @@ -0,0 +1,43 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation twice - first time in such a way +-- that a decision to check is evaluated to False, and second time to +-- evaluate it to True. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_FT is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); + + Check_Class_Wide_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_FT; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb new file mode 100755 index 000000000..5b04769e2 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation three times to get all possible +-- results - False, True and raising an exception. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_FTX is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 2, + Result => Result); + Assert (Result = 20); + + Check_Class_Wide_Condition + (Check_Var => 1, + Result => Result); + Assert (Result = 10); + + Check_Class_Wide_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_FTX; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb new file mode 100755 index 000000000..9ee4505c1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb @@ -0,0 +1,31 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver does not call anything - so nothing from the functional code is +-- expected to be reported as covered. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# check_class_wide_condition.adb +-- /dcl/ l- ## s- +-- /case/ l- ## s- +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb new file mode 100755 index 000000000..7bf0914a0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb @@ -0,0 +1,36 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation in such a way that a decision to +-- check is evaluated to False. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_T is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_T; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb new file mode 100755 index 000000000..57e8050ac --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb @@ -0,0 +1,36 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation in such a way that evaluation if +-- the decision raises an exception. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_X is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_X; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt new file mode 100755 index 000000000..18e8e7ec3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt @@ -0,0 +1,4 @@ +Check DC when a condition contains a call to class-wide operation as a +condition. The simplest structure of a decision is used - it contains the +only condition and no logical operations. The coverage of the code of the +dispatching operations called from the decision is not checked. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt new file mode 100755 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb new file mode 100755 index 000000000..29b9255d3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb @@ -0,0 +1,32 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Dispatching_Condition + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; -- # dcl + Var : Access_T_Class; -- # dcl + +begin + case Check_Var is -- # case + when 1 => + Var := new T1_T'(C1 => 1); -- # var_1 + when 2 => + Var := new T2_T'(C1 => 1); -- # var_2 + when 3 => + Var := new T1_T'(C1 => 101); -- # var_3 + when others => + null; -- # var_others + end case; + + if Valid (Var.all) then -- # eval + Result := 10; -- # true + else + Result := 20; -- # false + end if; + +exception + when Constraint_Error => + Result := 0; -- # exc +end Check_Dispatching_Condition; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb new file mode 100755 index 000000000..c74a84d46 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb @@ -0,0 +1,35 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation in such a way that a decision to +-- check is evaluated to False. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_F is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); +end Test_F; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /false/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb new file mode 100755 index 000000000..6acc7e4f4 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb @@ -0,0 +1,41 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation twice - first time in such a way +-- that a decision to check is evaluated to False, and second time to +-- evaluate it to True. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_FT is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); + Check_Dispatching_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_FT; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb new file mode 100755 index 000000000..1ae69b695 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb @@ -0,0 +1,45 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation three times to get all possible +-- results - False, True and raising an exception. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_FTX is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); + Check_Dispatching_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); + Check_Dispatching_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_FTX; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb new file mode 100755 index 000000000..6d6250895 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb @@ -0,0 +1,30 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver does not call anything - so nothing from the functional code is +-- expected to be reported as covered. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# check_dispatching_condition.adb +-- /dcl/ l- ## s- +-- /case/ l- ## s- +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb new file mode 100755 index 000000000..96a3f722b --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb @@ -0,0 +1,35 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation in such a way that a decision to +-- check is evaluated to True. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_T is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_T; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb new file mode 100755 index 000000000..adf8fb4e7 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb @@ -0,0 +1,35 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation in such a way that evaluation if +-- the decision raises an exception. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_X is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_X; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt new file mode 100755 index 000000000..022f7657a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt @@ -0,0 +1,4 @@ +Check DC when a condition contains a (dynamically resolved) dispatching call +as a condition. The simplest structure of a decision is used - it contains the +only condition and no logical operations. The coverage of the code of the +dispatching operations called from the decision is not checked. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt new file mode 100755 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb new file mode 100755 index 000000000..b3940aa69 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb @@ -0,0 +1,27 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Dynamic_Binding + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; + Var : Access_T_Class; + +begin + case Check_Var is + when 1 => + Var := new T1_T'(C1 => 1); + when 2 => + Var := new T2_T'(C1 => 1); + when 3 => + Var := new T2_T'(C1 => 20); + when 4 => + Var := new T2_T'(C1 => 101); + when others => + null; + end case; + + Result := Compute (Var.all); + +end Check_Dynamic_Binding; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb new file mode 100755 index 000000000..c21be8686 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb @@ -0,0 +1,43 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation in such a way that +-- * operations of T2 are executed +-- * the decision in its body of the primitive that is called first is +-- evaluated to False, +-- * the IF decision in the primitive called from the first primitive is +-- evaluated. to True. + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_F_T is + Result : Integer; +begin + Check_Dynamic_Binding + (Check_Var => 2, + Result => Result); + + Assert (Result = 999); +end Test_2_F_T; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l! ## dT- +-- /compute_true/ l- ## s- +-- /compute_false/ l+ ## 0 +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb new file mode 100755 index 000000000..385db4275 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb @@ -0,0 +1,60 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation three times in such a way that +-- * operations of T2 are executed; +-- * the decision in its body of the primitive that is called first is +-- evaluated to False, to True and raises and exception; +-- * the IF decision in the primitive called from the first primitive is +-- evaluated to False and to True, and ELSIF decision - to True. + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_FTX is + Result : Integer; +begin + Check_Dynamic_Binding + (Check_Var => 2, + Result => Result); + + Assert (Result = 999); + + Check_Dynamic_Binding + (Check_Var => 3, + Result => Result); + + Assert (Result = -20); + + Result := 13; + + Check_Dynamic_Binding + (Check_Var => 4, + Result => Result); + + Assert (False); +exception + when Constraint_Error => + Assert (Result = 13); +end Test_2_FTX; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l+ ## 0 +-- /compute_true/ l+ ## 0 +-- /compute_false/ l+ ## 0 +-- /valid_if_eval/ l+ ## 0 +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l+ ## 0 +-- /valid_elsif_ true/ l+ ## 0 +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb new file mode 100755 index 000000000..d0dea616f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb @@ -0,0 +1,43 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation in such a way that +-- * operations of T2 are executed; +-- * the decision in its body of the primitive that is called first is +-- evaluated to True; +-- * the IF decision in the primitive called from the first primitive is +-- evaluated to False, and ELSIF decision - to True. + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_T_FT is + Result : Integer; +begin + Check_Dynamic_Binding + (Check_Var => 3, + Result => Result); + + Assert (Result = -20); +end Test_2_T_FT; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dT- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l! ## dF- +-- /valid_elsif_ true/ l+ ## 0 +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb new file mode 100755 index 000000000..c87af377d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation in such a way that +-- * operations of T2 are executed; +-- * evaluation of the decision in its body of the primitive raises an +-- exception; +-- * IF and ELSIF decisions in the primitive called from the first primitive +-- are both evaluated to False + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_X is + Result : Integer := 1; +begin + Check_Dynamic_Binding + (Check_Var => 4, + Result => Result); + + Assert (False); +exception + when Constraint_Error => + Assert (Result = 1); +end Test_2_X; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l! ## d- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dT- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l! ## dT- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb new file mode 100755 index 000000000..5507de793 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb @@ -0,0 +1,31 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. Does not call anything, so everything should be reported as +-- non-covered + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt new file mode 100755 index 000000000..45cbee4a0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt @@ -0,0 +1,6 @@ +Check DC when a dispatching operation is called (not as a condition of some +decision, but on its own), and the called subprogram cannot be detected +statically. DC is checked for the code of the dispatching operation itself and +for the code of dispatching operations that can be called by it. The tests are +structured according to the coverage of the decision in this IF statements in +the dispatching operations being executed. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt new file mode 100755 index 000000000..eafa6f3bf --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt @@ -0,0 +1,21 @@ +The following things should be checked: + +1. If a decision in some control structure contains a call to a dispatching + operation as one of the conditions involved then the coverage information + is correctly computed for this construct in case of dynamic binding. + +2. If a decision in some control structure contains a call to a class-wide + operation (containing some dynamic dispatching in its body) as one of the + conditions involved then the coverage information is correctly computed for + this construct in case of dynamic binding. + +3. For the body of a class-wide operation, the coverage information is + correctly computed. + +4. For the body a dispatching operation the coverage information is correctly + computed in case of a dynamic binding. + +For the initial version of the test suite, the simplest form is used for each +decision - it contains exactly one condition. The other parts of the test +suite exercises complex decisions, and here we check only things specific to +Ada OO features. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb new file mode 100755 index 000000000..88896b6dd --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb @@ -0,0 +1,23 @@ +package body Parent.Child1 is + + function Compute (X : T1_T) return Integer is + begin + if Valid (T1_T'Class (X)) then -- # compute_eval + return X.C1; -- # compute_true + else + return 0; -- # compute_false + end if; + end Compute; + + function Valid (X : T1_T) return Boolean is + begin + if X.C1 in -10 .. 10 then -- # valid_if_eval + return True; -- # valid_if_true + elsif X.C1 in -100 .. 100 then -- # valid_elsif_eval + return False; -- # valid_elsif_ true + else + raise Constraint_Error; -- # valid_false + end if; + end Valid; + +end Parent.Child1; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads new file mode 100755 index 000000000..bbd76573c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads @@ -0,0 +1,8 @@ +package Parent.Child1 is + type T1_T is new T with record + C1 : Integer; + end record; + + function Compute (X : T1_T) return Integer; + function Valid (X : T1_T) return Boolean; +end Parent.Child1; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb new file mode 100755 index 000000000..419fcf2d0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb @@ -0,0 +1,23 @@ +package body Parent.Child2 is + + function Compute (X : T2_T) return Integer is + begin + if Valid (T2_T'Class (X)) then -- # compute_eval + return -X.C1; -- # compute_true + else + return 999; -- # compute_false + end if; + end Compute; + + function Valid (X : T2_T) return Boolean is + begin + if X.C1 in -10 .. 10 then -- # valid_if_eval + return False; -- # valid_if_true + elsif X.C1 in -100 .. 100 then -- # valid_elsif_eval + return True; -- # valid_elsif_ true + else + raise Constraint_Error; -- # valid_false + end if; + end Valid; + +end Parent.Child2; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads new file mode 100755 index 000000000..8495e9f89 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads @@ -0,0 +1,8 @@ +package Parent.Child2 is + type T2_T is new T with record + C1 : Integer; + end record; + + function Compute (X : T2_T) return Integer; + function Valid (X : T2_T) return Boolean; +end Parent.Child2; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb new file mode 100755 index 000000000..bde7e0ec1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb @@ -0,0 +1,17 @@ +package body Parent is + + function Compute_C (X : T'Class) return Integer is + begin + if Valid (X) then -- # compute_c_eval + return Compute (X); -- # compute_c_true + else + return 0; -- # compute_c_false + end if; + end Compute_C; + + function Valid_C (X : T'Class) return Boolean is + begin + return Valid (X); -- # valid_c + end Valid_C; + +end Parent; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads new file mode 100755 index 000000000..0dbb3ad1c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads @@ -0,0 +1,10 @@ +package Parent is + type T is abstract tagged null record; + + function Compute (X : T) return Integer is abstract; + function Valid (X : T) return Boolean is abstract; + + + function Compute_C (X : T'Class) return Integer; + function Valid_C (X : T'Class) return Boolean; +end Parent; diff --git a/testsuite/tests/Ravenscar/OOP/req.txt b/testsuite/tests/Ravenscar/OOP/req.txt new file mode 100755 index 000000000..f4c2a8993 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/req.txt @@ -0,0 +1,111 @@ +This is the first attempt to describe the testing strategy for "Tagged Types +and Dispatching" (Ada OO features) part of the gnatcov test suite. + +1. In this particular part of the test suite tagged types and dispatching + should be considered as a specific language feature (a set of features) + that can bring a specific set of problems and difficulties to coverage + assessment tools, so they should be tested namely as a specific feature, + but not along with all the other language constructs. In particular this + means that we does not have to check all possible combinations of Ada OO + features with all possible syntax constructs. + +2. The testing strategy is based on a hypothesis that may be called as a + hypothesis of relative correctness: + + "When testing the interaction between the various language constructs, it + is assumed that each of these constructs is implemented correctly. This + implies that the concrete representation of each construct is not + important." + + Without such a hypothesis we will end up with combinatorial explosion very + soon. + +3. Ada OO features can bring the following difficulties to coverage analysis. + + - Inheritance: in the inheritance hierarchy we may have operations + implicitly inherited from other operations. Such operations may be + called as ordinary subprograms, but they do not have the code + associated with them, instead, the code of the explicitly declared + subprogram the called operation is inherited from is actually executed. + It should be checked that the coverage information is generated for the + code that actually is called, and for nothing else. + + - Overriding: when we have different "implementations" for "the same" + (primitive) operation in some inheritance hierarchy, it should be checked + that the coverage information is generated for the "implementation" that + actually is called, but not for the others (in particular, the coverage + information should not be generated for overridden subprogram in case + when an overriding subprogram is called); + + - Dynamic dispatching (dynamic binding): we may have a situation when it is + not possible to determine which subprogram from the set of different + implementations of a primitive operation of some type is called. We + should check that the coverage information is generated only for the + actually called subprograms; + + - Class-wide operations: they are interested in three aspects. First, + they may be considered as a special case of a subprogram (that can + operate on objects that have types that are not known in advance). + Second, a class-wide operation usually contains dispatching calls that + can be resolved only dynamically. Third, a class-wide operation can be + written for an abstract type when all the type operations defined as + abstract, and it may know nothing at all about subprograms it actually + calls. + +4. Ada OO features are closely related to each other, so we cannot avoid some + overlaps in testing strategy, requirements, test cases. We should not + consider this as any disadvantage, getting rid of these overlaps may be + more expensive for both developers and users of the test suite. + +5. Statement coverage. + +The following aspects should be checked: + +- Inheritance : when a derived subprogram is called, the coverage information + for the explicitly declared parent subprogram is generated + correctly; + +- Static binding: when in the hierarchy of dynamic types the called operation + can be detected statically, the code information for the + is correctly generated for the body of the subprogram that is + actually called, and no other code for no other subprogram + from the hierarchy is reported as covered; + +- Discpatching (dynamic binding) : if the subprogram to call is detected + dynamically, the coverage information is correctly generated + for the subprogram that has actually be called, and no other + code for no other subprogram from the hierarchy is reported as + covered; + +- Class-Wide operations: if a class-wide operation is called, the coverage + information is correctly generated for its code as well as for + all the subprograms called from the class-wide operation. The + subprograms that may be called from the class-wide operation + but that are not actually called with the given argument + should be reported as non-covered. + +- Multiple inheritance: similar to 'Dispatching', but called subprograms could + be from different inheritance hierarchies. + +6. Decision coverage. + +The following aspects should be checked: + +1. If a decision in some control structure contains a call to a dispatching + operation as one of the conditions involved then the coverage information + is correctly computed for this construct in case of dynamic binding. + +2. If a decision in some control structure contains a call to a class-wide + operation (containing some dynamic dispatching in its body) as one of the + conditions involved then the coverage information is correctly computed for + this construct in case of dynamic binding. + +3. For the body of a class-wide operation, the coverage information is + correctly computed, as well as for the dispatching operations that are + actually called from this class-wide operation. + +4. For the body a dispatching operation the coverage information is correctly + computed in case of a dynamic binding. + +The simplest form is used for each decision - it contains exactly one +condition with no logical operation. diff --git a/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb new file mode 100755 index 000000000..b2b94b92a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb @@ -0,0 +1,6 @@ +package body Class_Wide_Ops is + procedure Handle_Alert (A : in out Alert'Class) is + begin + Handle (A); + end Handle_Alert; +end; diff --git a/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads new file mode 100755 index 000000000..89956f0a0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads @@ -0,0 +1,4 @@ +with New_Alert_System; use New_Alert_System; +package Class_Wide_Ops is + procedure Handle_Alert (A : in out Alert'Class); +end; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb new file mode 100755 index 000000000..da6c1abca --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb @@ -0,0 +1,42 @@ +with New_Alert_System.Objects; use New_Alert_System.Objects; + +package body New_Alert_System.Emergency is + + procedure Handle (EA: in out Emergency_Alert) is + begin + Handle (New_Alert_System.Alert (EA)); -- # ea_handle + + if EA.Time_Of_Arrival >= New_Alert_System.Critical_Time then -- # ea_handle + EA.Catastrophe := True; -- # ea_hand_catastrophe + else + EA.Catastrophe := False; -- # ea_hand_no_catastrophe + end if; + end Handle; + + procedure Display (EA : in Emergency_Alert; + On : out Device) + is + begin + if EA.Catastrophe then -- # ea_display + On := 0; -- # ea_displ_catastrophe + else + Display (New_Alert_System.Alert (EA), On); -- # ea_displ_no_catastrophe + end if; + end Display; + + function Log (EA: in Emergency_Alert) return Natural is + begin + return Log (New_Alert_System.Alert (EA)) + 100; -- # ea_log + end Log; + + function Catastrophe (EA: in Emergency_Alert) return Boolean is + begin + return EA.Catastrophe; -- # ea_catastrophe + end Catastrophe; + + function Get_Empty_Emergency_Alert return Emergency_Alert is + begin + return Emergency_Alert'(Empty_Alert with Catastrophe => False); -- # ea_get + end Get_Empty_Emergency_Alert; + +end New_Alert_System.Emergency; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads new file mode 100755 index 000000000..d86d2fee1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads @@ -0,0 +1,20 @@ +with New_Alert_System; +package New_Alert_System.Emergency is + type Emergency_Alert is new New_Alert_System.Alert with private; + + procedure Handle (EA: in out Emergency_Alert); + + procedure Display (EA : in Emergency_Alert; + On : out Device); + + function Log (EA: in Emergency_Alert) return Natural; + + function Catastrophe (EA: in Emergency_Alert) return Boolean; + + function Get_Empty_Emergency_Alert return Emergency_Alert; + +private + type Emergency_Alert is new New_Alert_System.Alert with record + Catastrophe : Boolean; + end record; +end New_Alert_System.Emergency; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads new file mode 100755 index 000000000..b1d96efa9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads @@ -0,0 +1,14 @@ +package New_Alert_System.Objects is + Empty_Alert : Alert := + (Idx => 0, + Time_Of_Arrival => Zero_Time, + Message => No_Message); + + Empty_Low_Alert : Low_Alert := Low_Alert'(Empty_Alert with null record); + + Empty_Medium_Alert : Medium_Alert := + Medium_Alert'(Empty_Alert with Action_Officer => Volunteer); + + Empty_High_Alert : High_Alert := + High_Alert'(Empty_Medium_Alert with Ring_Alarm_At => Zero_Time); +end New_Alert_System.Objects; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb new file mode 100755 index 000000000..91e51baa7 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb @@ -0,0 +1,69 @@ +package body New_Alert_System is + + Current_Idx : Natural := Natural'First; + + function Get_Idx return Natural is + begin + Current_Idx := Current_Idx + 1; -- # get_idx + return Current_Idx - 1; -- # get_idx + end Get_Idx; + + Current_Time : My_Time := My_Time'First; + + function My_Clock return My_Time is + begin + Current_Time := Current_Time + 1; -- # my_clock + return Current_Time; -- # my_clock + end My_Clock; + + procedure Set_Time (New_Time : My_Time) is + begin + Current_Time := New_Time; -- # set_time + end Set_Time; + + procedure Handle (A : in out Alert) is + begin + A.Idx := Get_Idx; -- # a_handle + A.Time_Of_Arrival := My_Clock; -- # a_handle + end Handle; + + procedure Display (A : in Alert; + On : out Device) + is + begin + On := Device (Log (Alert'Class (A))) + Device (A.Time_Of_Arrival); -- # a_display +-- On := Device (Log (Alert'Class (A))) + +-- Device (A.Time_Of_Arrival); + end Display; + + function Log (A : in Alert) return Natural is + begin + return A.Idx; -- # a_log + end Log; + + procedure Handle (MA : in out Medium_Alert) is + begin + Handle (Alert (MA)); -- handle as plain alert -- # ma_handle + MA.Action_Officer := Volunteer; -- # ma_handle + end Handle; + + + procedure Handle (HA : in out High_Alert) is + begin + Handle (Medium_Alert (HA)); -- conversion -- # ha_handle + HA.Action_Officer := Soldier; -- # ha_handle + Set_Alarm (HA); -- # ha_handle + Display (HA, System_Device); -- # ha_handle + end Handle; + + procedure Set_Alarm (HA: in out High_Alert) is + begin + HA.Ring_Alarm_At := HA.Time_Of_Arrival + 1; -- # ha_set_alarm + HA.Action_Officer := Sergeant; -- # ha_set_alarm + end Set_Alarm; + + function Log (HA : in High_Alert) return Natural is + begin + return HA.Idx * 10 + 10; -- # ha_log + end Log; +end New_Alert_System; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads new file mode 100755 index 000000000..52a1a30f0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads @@ -0,0 +1,49 @@ +package New_Alert_System is + + type My_Time is new Natural; + Zero_Time : My_Time := My_Time'First; + Critical_Time : My_Time := 100; + + function My_Clock return My_Time; + procedure Set_Time (New_Time : My_Time); + + type Device is new Natural; + System_Device : Device; + + type Person is (Volunteer, Soldier, Sergeant, Major); + type Text is new String (1 .. 10); + No_Message : Text := (others => ' '); + + type Alert is tagged record + Idx : Natural; + Time_Of_Arrival : My_Time; + Message : Text; + end record; + + procedure Handle (A : in out Alert); + + procedure Display (A : in Alert; + On : out Device); + + function Log (A : in Alert) return Natural; + + + type Low_Alert is new Alert with null record; + + type Medium_Alert is new Alert with record + Action_Officer: Person; + end record; + + -- now override inherited operation + procedure Handle (MA : in out Medium_Alert); + + type High_Alert is new Medium_Alert with record + Ring_Alarm_At: My_Time; + end record; + + procedure Handle (HA : in out High_Alert); + procedure Set_Alarm (HA : in out High_Alert); + function Log (HA : in High_Alert) return Natural; + + +end New_Alert_System; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb new file mode 100755 index 000000000..1a8e13fca --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb @@ -0,0 +1,40 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_1 is +begin + Handle_Alert (Empty_Low_Alert); + Assert (Empty_Low_Alert.Idx = 0); +end Test_1; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb new file mode 100755 index 000000000..9b59b1bc3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb @@ -0,0 +1,40 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_2 is +begin + Handle_Alert (Empty_Medium_Alert); + Assert (Empty_Medium_Alert.Idx = 0); +end Test_2; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb new file mode 100755 index 000000000..a95e97aaa --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb @@ -0,0 +1,40 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_3 is +begin + Handle_Alert (Empty_High_Alert); + Assert (Empty_High_Alert.Idx = 0); +end Test_3; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb new file mode 100755 index 000000000..2bda355a5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb @@ -0,0 +1,42 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_4 is + EA : Emergency_Alert := Get_Empty_Emergency_Alert; + +begin + Handle_Alert (EA); + Assert (Log (EA) = 100); +end Test_4; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l+ ## 0 +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l+ ## 0 +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb new file mode 100755 index 000000000..5446bd214 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb @@ -0,0 +1,51 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. All the +-- implementations of the called discpatching operations are called, so +-- coverage information should be reported for all of them + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_Full is + EA : Emergency_Alert := Get_Empty_Emergency_Alert; + +begin + Handle_Alert (Empty_Low_Alert); + Assert (Empty_Low_Alert.Idx = 0); + + Handle_Alert (Empty_Medium_Alert); + Assert (Empty_Medium_Alert.Idx = 1); + + Handle_Alert (Empty_High_Alert); + Assert (Empty_High_Alert.Idx = 2); + + Handle_Alert (EA); + Assert (Log (EA) = 103); +end Test_Full; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l+ ## 0 +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l+ ## 0 +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb new file mode 100755 index 000000000..ee7c1e083 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb @@ -0,0 +1,39 @@ +-- Test driver for checking the coverage information in case of class-wide +-- operation. Check that when a class-wide operation is not called, nothing +-- from the operation itself as well as from the dispatching operation it can +-- call is reported as covered. + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# new_alert_system.adb +-- /get_idx/ l- ## s- +-- /my_clock/ l- ## s- +-- /set_time/ l- ## s- +-- /a_handle/ l- ## s- +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt new file mode 100755 index 000000000..ee3e66e2a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt @@ -0,0 +1,7 @@ +In the hierarchy of a (tagged) derived types, call primitive subprograms from +the class-wide operation in such a way that the called subprogram is detected +only dinamically. + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb new file mode 100755 index 000000000..fa04fde72 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb @@ -0,0 +1,25 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically. +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_1 is + LA : Alert'Class := Empty_Low_Alert; +begin + Handle (LA); + Assert (LA.Idx = 0); +end Test_1; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb new file mode 100755 index 000000000..29f45f82c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb @@ -0,0 +1,25 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_2 is + MA : Alert'Class := Empty_Medium_Alert; +begin + Handle (MA); + Assert (MA.Idx = 0); +end Test_2; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb new file mode 100755 index 000000000..667715eec --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb @@ -0,0 +1,25 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_3 is + HA : Alert'Class := Empty_High_Alert; +begin + Handle (HA); + Assert (HA.Idx = 0); +end Test_3; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb new file mode 100755 index 000000000..30be2931d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb @@ -0,0 +1,38 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_4 is + EA : Alert'Class := Get_Empty_Emergency_Alert; + +begin + Handle (EA); + Assert (Log (EA) = 100); +end Test_4; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l+ ## 0 +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l+ ## 0 +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt new file mode 100755 index 000000000..33f890e2d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt @@ -0,0 +1,7 @@ +In the hierarchy of a (tagged) derived types, call primitive subprograms in +such a way that the called subprogram is detected only dinamically. No +class-wide operation is involved + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb new file mode 100755 index 000000000..9111476e9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb @@ -0,0 +1,28 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- Checks that in case when an implicitly declared inherited subprogram is +-- called, the coverage information is correctly generated for the explicit +-- subprogram it is derived from + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_Inherited is + Res : Natural := Log (Empty_Medium_Alert); +begin + Assert (Res = 0); + null; +end Test_Inherited; + +--# new_alert_system.adb +-- /get_idx/ l- ## s- +-- /my_clock/ l- ## s- +-- /set_time/ l- ## s- +-- /a_handle/ l- ## s- +-- /a_display/ l- ## s- +-- /a_log/ l+ ## 0 +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb new file mode 100755 index 000000000..b3df889b4 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb @@ -0,0 +1,30 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- Checks that in case when an explicitely declared subprogram that ovverrides +-- the implicitely declared inherited subprogram is called, the coverage +-- information is correctly generated for this explicit subprogram, but not +-- for the (explicitely declared) subprogram from that the overriden +-- subprogram is inherited + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_Overriding is + Res : Natural := Log (Empty_High_Alert); +begin + Assert (Res = 10); + null; +end; + +--# new_alert_system.adb +-- /get_idx/ l- ## s- +-- /my_clock/ l- ## s- +-- /set_time/ l- ## s- +-- /a_handle/ l- ## s- +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt new file mode 100755 index 000000000..e282cc6e9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt @@ -0,0 +1,12 @@ +In the hierarchy of a (tagged) derived types, call inherited subprograms and +subprograms that overrides the implicitly inherited operations. + +Verify that: + +* If an implicitly declared inherited subprogram is called, only (a part of) + the code of the explicitly declared subprogram it is inherited from is + reported as covered; + +* If an explicitly declared subprogram that overrides the implicitly + inherited subprogram is called, the code of the overriding subprogram is + reported as covered, but not the code of the subprogram being overridden; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb new file mode 100755 index 000000000..9b0e433a6 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb @@ -0,0 +1,10 @@ +package body A is + procedure Class_Wide_IA (X : in out IA'Class) is + begin + if Test_IA (X) then -- # class_wide_ia + P_IA_1 (X); -- # if_cw_ia + else + P_IA_2 (X); -- # else_cw_ia + end if; + end Class_Wide_IA; +end A; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads new file mode 100755 index 000000000..146a30855 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads @@ -0,0 +1,10 @@ +package A is + type IA is interface; + + procedure P_IA_1 (X : in out IA) is null; + procedure P_IA_2 (X : in out IA) is null; + + function Test_IA (X : IA) return Boolean is abstract; + + procedure Class_Wide_IA (X : in out IA'Class); +end A; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb new file mode 100755 index 000000000..ad1563185 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb @@ -0,0 +1,10 @@ +package body B is + procedure Class_Wide_IB (X : in out IB'Class) is + begin + if Test_IB (X) then -- # class_wide_ib + P_IB_1 (X); -- # if_cw_ib + else + P_IB_2 (X); -- # else_cw_ib + end if; + end Class_Wide_IB; +end B; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads new file mode 100755 index 000000000..229c75c1d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads @@ -0,0 +1,10 @@ +package B is + type IB is interface; + + procedure P_IB_1 (X : in out IB) is null; + procedure P_IB_2 (X : in out IB) is null; + + function Test_IB (X : IB) return Boolean is abstract; + + procedure Class_Wide_IB (X : in out IB'Class); +end B; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb new file mode 100755 index 000000000..d699720f8 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb @@ -0,0 +1,10 @@ +package body C is + procedure Class_Wide_IC (X : in out IC'Class) is + begin + if Test_IC (X) then -- # class_wide_ic + Class_Wide_IA (X); -- # if_cw_ic + else + Class_Wide_IB (X); -- # else_cw_ic + end if; + end Class_Wide_IC; +end C; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads new file mode 100755 index 000000000..6916a4075 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads @@ -0,0 +1,9 @@ +with A; use A; +with B; use B; +package C is + type IC is interface and IA and IB; + + function Test_IC (X : IC) return Boolean is abstract; + + procedure Class_Wide_IC (X : in out IC'Class); +end C; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb new file mode 100755 index 000000000..653055db2 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_1 is + Var : T_X_A := (I1 => 1, I2 => 1); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = 11 and then Var.I2 = 21); +end Test_1; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l+ ## 0 + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l+ ## 0 +-- /xa_test_ia/ l+ ## 0 + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb new file mode 100755 index 000000000..0316cf09a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_10 is + Var : T_Y_B := (I1 => 1, I2 => 2); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = 100 and then Var.I2 = 100); +end Test_10; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l+ ## 0 +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l+ ## 0 +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l+ ## 0 + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb new file mode 100755 index 000000000..b467713c9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_11 is + Var : T_Y_C := (I1 => 1, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 1 and then Var.I2 = 1); +end Test_11; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l+ ## 0 + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l+ ## 0 +-- /yc_test_ic/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb new file mode 100755 index 000000000..7734075f3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_12 is + Var : T_Y_C := (I1 => 2, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 2 and then Var.I2 = 1); +end Test_12; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l+ ## 0 +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l+ ## 0 +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb new file mode 100755 index 000000000..e27fa2fcb --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_2 is + Var : T_X_A := (I1 => 2, I2 => 1); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = 0 and then Var.I2 = 0); +end Test_2; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l+ ## 0 +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l+ ## 0 + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb new file mode 100755 index 000000000..eb13298e5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_3 is + Var : T_X_B := (I1 => 1, I2 => 1); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = 11 and then Var.I2 = 21); +end Test_3; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l+ ## 0 +-- /xb_test_ib/ l+ ## 0 + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb new file mode 100755 index 000000000..feb842ba5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_4 is + Var : T_X_B := (I1 => 2, I2 => 1); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = 0 and then Var.I2 = 0); +end Test_4; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l+ ## 0 +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l+ ## 0 +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l+ ## 0 + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb new file mode 100755 index 000000000..7a68b9167 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_5 is + Var : T_X_C := (I1 => 1, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 1 and then Var.I2 = 1); +end Test_5; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l+ ## 0 + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l+ ## 0 +-- /xc_test_ic/ l+ ## 0 + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb new file mode 100755 index 000000000..907222b9f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_6 is + Var : T_X_C := (I1 => 2, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 2 and then Var.I2 = 1); +end Test_6; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l+ ## 0 +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l+ ## 0 +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l+ ## 0 + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb new file mode 100755 index 000000000..a02ed6808 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_7 is + Var : T_Y_A := (I1 => 1, I2 => 1); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = -9 and then Var.I2 = -19); +end Test_7; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l+ ## 0 + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l+ ## 0 +-- /ya_test_ia/ l+ ## 0 + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb new file mode 100755 index 000000000..3b9d54a1c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_8 is + Var : T_Y_A := (I1 => 1, I2 => 2); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = 100 and then Var.I2 = 100); +end Test_8; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l+ ## 0 +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l+ ## 0 + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb new file mode 100755 index 000000000..95d9dbfcc --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_9 is + Var : T_Y_B := (I1 => 1, I2 => 1); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = -9 and then Var.I2 = -19); +end Test_9; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l+ ## 0 +-- /yb_test_ib/ l+ ## 0 + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb new file mode 100755 index 000000000..05e049a1f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb @@ -0,0 +1,20 @@ +package body X.A_Child is + + procedure P_IA_1 (X : in out T_X_A) is + begin + X.I1 := 0; -- # xa_p_ia_1 + X.I2 := 0; -- # xa_p_ia_1 + end P_IA_1; + + procedure P_IA_2 (X : in out T_X_A) is + begin + X.I1 := X.I1 + 10; -- # xa_p_ia_2 + X.I2 := X.I2 + 20; -- # xa_p_ia_2 + end P_IA_2; + + function Test_IA (X : T_X_A) return Boolean is + begin + return X.I1 > X.I2; -- # xa_test_ia + end Test_IA; + +end X.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads new file mode 100755 index 000000000..587b2d681 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads @@ -0,0 +1,12 @@ +with A; use A; +package X.A_Child is + type T_X_A is new T_X and IA with record + I2 : Integer; + end record; + + procedure P_IA_1 (X : in out T_X_A); + procedure P_IA_2 (X : in out T_X_A); + + function Test_IA (X : T_X_A) return Boolean; + +end X.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb new file mode 100755 index 000000000..71c7c4ef4 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb @@ -0,0 +1,20 @@ +package body X.B_Child is + + procedure P_IB_1 (X : in out T_X_B) is + begin + X.I1 := 0; -- # xb_p_ib_1 + X.I2 := 0; -- # xb_p_ib_1 + end P_IB_1; + + procedure P_IB_2 (X : in out T_X_B) is + begin + X.I1 := X.I1 + 10; -- # xb_p_ib_2 + X.I2 := X.I2 + 20; -- # xb_p_ib_2 + end P_IB_2; + + function Test_IB (X : T_X_B) return Boolean is + begin + return X.I1 > X.I2; -- # xb_test_ib + end Test_IB; + +end X.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads new file mode 100755 index 000000000..6ef30fd6a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads @@ -0,0 +1,12 @@ +with B; use B; +package X.B_Child is + type T_X_B is new T_X and IB with record + I2 : Integer; + end record; + + procedure P_IB_1 (X : in out T_X_B); + procedure P_IB_2 (X : in out T_X_B); + + function Test_IB (X : T_X_B) return Boolean; + +end X.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb new file mode 100755 index 000000000..69354c022 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb @@ -0,0 +1,18 @@ +package body X.C_Child is + + function Test_IA (X : T_X_C) return Boolean is + begin + return X.I1 > X.I2; -- # xc_test_ia + end Test_IA; + + function Test_IB (X : T_X_C) return Boolean is + begin + return X.I1 > X.I2; -- # xc_test_ib + end Test_IB; + + function Test_IC (X : T_X_C) return Boolean is + begin + return X.I1 > X.I2; -- # xc_test_ic + end Test_IC; + +end X.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads new file mode 100755 index 000000000..2f0516dd1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads @@ -0,0 +1,11 @@ +with C; use C; +package X.C_Child is + type T_X_C is new T_X and IC with record + I2 : Integer; + end record; + + function Test_IA (X : T_X_C) return Boolean; + function Test_IB (X : T_X_C) return Boolean; + function Test_IC (X : T_X_C) return Boolean; + +end X.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads new file mode 100755 index 000000000..beb2b177a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads @@ -0,0 +1,6 @@ +package X is + type T_X is tagged record + I1 : Integer; + end record; + +end X; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb new file mode 100755 index 000000000..9ecb35f84 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb @@ -0,0 +1,20 @@ +package body Y.A_Child is + + procedure P_IA_1 (Y : in out T_Y_A) is + begin + Y.I1 := 100; -- # ya_p_ia_1 + Y.I2 := 100; -- # ya_p_ia_1 + end P_IA_1; + + procedure P_IA_2 (Y : in out T_Y_A) is + begin + Y.I1 := Y.I1 - 10; -- # ya_p_ia_2 + Y.I2 := Y.I2 - 20; -- # ya_p_ia_2 + end P_IA_2; + + function Test_IA (Y : T_Y_A) return Boolean is + begin + return Y.I1 < Y.I2; -- # ya_test_ia + end Test_IA; + +end Y.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads new file mode 100755 index 000000000..e48531e26 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads @@ -0,0 +1,12 @@ +with A; use A; +package Y.A_Child is + type T_Y_A is new T_Y and IA with record + I2 : Integer; + end record; + + procedure P_IA_1 (Y : in out T_Y_A); + procedure P_IA_2 (Y : in out T_Y_A); + + function Test_IA (Y : T_Y_A) return Boolean; + +end Y.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb new file mode 100755 index 000000000..58af4b641 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb @@ -0,0 +1,20 @@ +package body Y.B_Child is + + procedure P_IB_1 (Y : in out T_Y_B) is + begin + Y.I1 := 100; -- # yb_p_ib_1 + Y.I2 := 100; -- # yb_p_ib_1 + end P_IB_1; + + procedure P_IB_2 (Y : in out T_Y_B) is + begin + Y.I1 := Y.I1 - 10; -- # yb_p_ib_2 + Y.I2 := Y.I2 - 20; -- # yb_p_ib_2 + end P_IB_2; + + function Test_IB (Y : T_Y_B) return Boolean is + begin + return Y.I1 < Y.I2; -- # yb_test_ib + end Test_IB; + +end Y.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads new file mode 100755 index 000000000..2ff6bc51b --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads @@ -0,0 +1,12 @@ +with B; use B; +package Y.B_Child is + type T_Y_B is new T_Y and IB with record + I2 : Integer; + end record; + + procedure P_IB_1 (Y : in out T_Y_B); + procedure P_IB_2 (Y : in out T_Y_B); + + function Test_IB (Y : T_Y_B) return Boolean; + +end Y.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb new file mode 100755 index 000000000..c2c23a31f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb @@ -0,0 +1,18 @@ +package body Y.C_Child is + + function Test_IA (Y : T_Y_C) return Boolean is + begin + return Y.I1 > Y.I2; -- # yc_test_ia + end Test_IA; + + function Test_IB (Y : T_Y_C) return Boolean is + begin + return Y.I1 > Y.I2; -- # yc_test_ib + end Test_IB; + + function Test_IC (Y : T_Y_C) return Boolean is + begin + return Y.I1 > Y.I2; -- # yc_test_ic + end Test_IC; + +end Y.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads new file mode 100755 index 000000000..8929513f7 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads @@ -0,0 +1,11 @@ +with C; use C; +package Y.C_Child is + type T_Y_C is new T_Y and IC with record + I2 : Integer; + end record; + + function Test_IA (Y : T_Y_C) return Boolean; + function Test_IB (Y : T_Y_C) return Boolean; + function Test_IC (Y : T_Y_C) return Boolean; + +end Y.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads new file mode 100755 index 000000000..fcecde92d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads @@ -0,0 +1,5 @@ +package Y is + type T_Y is tagged record + I1 : Integer; + end record; +end Y; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt new file mode 100755 index 000000000..d9a6fcec5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt @@ -0,0 +1,7 @@ +In case of multiple inheritance, define class-vide operations for interface +types and then check what is called and reported as covered in different +hierarchies. + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt new file mode 100755 index 000000000..69fd8e815 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt @@ -0,0 +1,4 @@ +5.04a1 DEAD stack overflow not caused by instrumentation in 5.04 +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb new file mode 100755 index 000000000..d1101c699 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb @@ -0,0 +1,24 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically. +with New_Alert_System; use New_Alert_System; + +with Support; use Support; + +procedure Test_1 is + LA : Low_Alert; +begin + Handle (LA); + Assert (LA.Idx = 0); +end Test_1; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb new file mode 100755 index 000000000..1faf46059 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb @@ -0,0 +1,24 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically +with New_Alert_System; use New_Alert_System; + +with Support; use Support; + +procedure Test_2 is + MA : Medium_Alert; +begin + Handle (MA); + Assert (MA.Action_Officer = Volunteer); +end Test_2; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb new file mode 100755 index 000000000..60b1bec10 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb @@ -0,0 +1,24 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically +with New_Alert_System; use New_Alert_System; + +with Support; use Support; + +procedure Test_3 is + HA : High_Alert; +begin + Handle (HA); + Assert (HA.Action_Officer = Sergeant); +end Test_3; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb new file mode 100755 index 000000000..d8ea95b40 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb @@ -0,0 +1,36 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; + +with Support; use Support; + +procedure Test_4 is + EA : Emergency_Alert; +begin + Handle (EA); + Assert (not Catastrophe (EA)); +end Test_4; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l+ ## 0 +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt new file mode 100755 index 000000000..99197908f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt @@ -0,0 +1,7 @@ +In the hierarchy of a (tagged) derived types, call primitive subprograms in +such a way that the called subprogram is statically detected from arguments +types. + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb new file mode 100644 index 000000000..44aa5b867 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb @@ -0,0 +1,20 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /cons/ l+ ## 0 +-- /test/ l! ## dT- +-- /exception/ l- ## s- +-- /put_element/ l+ ## 0 +-- /open_barrier/ l+ ## 0 +-- /get_element/ l+ ## 0 +-- /close_barrier/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- =/entry_guard/ l? ## d? diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt new file mode 100644 index 000000000..9b3f40f99 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR,!native +RTS_FULL,!native +ALL DEAD [M305-011] relies on Ravenscar constructs + strict priority based scheduling diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb new file mode 100644 index 000000000..760a4b17c --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb @@ -0,0 +1,31 @@ +package body Synchronization is + + task body Producer is + begin + Buffer.Put (1); -- # prod + end Producer; + + task body Consumer is + Element : Integer; + begin + Buffer.Get (Element); -- # cons + if Element /= 1 then -- # test + raise Program_Error; -- # exception + end if; + end Consumer; + + protected body Buffer is + procedure Put (Item : Integer) is + begin + Element := Item; -- # put_element + Barrier := True; -- # open_barrier + end Put; + + entry Get (Item : out Integer) when Barrier is -- # entry_guard + begin + Item := Element; -- # get_element + Barrier := False; -- # close_barrier + end Get; + end Buffer; + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads new file mode 100644 index 000000000..dfed4dcfd --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads @@ -0,0 +1,24 @@ +-- Test to check whether we can analyze correctly parts of an execution +-- which are covered after a task is blocked. + +with System; + +package Synchronization is + + task Producer is + pragma Priority (System.Priority'Last - 1); + end Producer; + + task Consumer is + pragma Priority (System.Priority'Last); + end Consumer; + + protected Buffer is + procedure Put (Item : Integer); + entry Get (Item : out Integer); + private + Element : Integer := 0; + Barrier : Boolean := False; + end Buffer; + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb new file mode 100644 index 000000000..5e65baa5c --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb @@ -0,0 +1,17 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /cons/ l+ ## 0 +-- /test/ l+ ## 0 +-- /exception/ l- ## s- +-- /put_element/ l+ ## 0 +-- /open_barrier/ l+ ## 0 +-- /get_element/ l+ ## 0 +-- /close_barrier/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb new file mode 100644 index 000000000..310e4c3e0 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb @@ -0,0 +1,19 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /signal_send/ l+ ## 0 +-- /signal_ack_wait/ l+ ## 0 +-- /test_2/ l! ## dT- +-- /exception_2/ l- ## s- +-- /signal_wait/ l+ ## 0 +-- /test_1/ l! ## dF- +-- /change/ l+ ## 0 +-- /signal_ack_send/ l+ ## 0 +-- /exception_1/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb new file mode 100644 index 000000000..4fd07800d --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb @@ -0,0 +1,27 @@ +with Ada.Synchronous_Task_Control; use Ada.Synchronous_Task_Control; + +package body Synchronization is + + task body Signaler is + begin + Buffer := 1; -- # prod + Set_True (Signal_Sent); -- # signal_send + Suspend_Until_True (Signal_Ack); -- # signal_ack_wait + if Buffer /= 2 then -- # test_2 + raise Program_Error; -- # exception_2 + end if; + end Signaler; + + task body Waiter is + Element : Integer; + begin + Suspend_Until_True (Signal_Sent); -- # signal_wait + if Buffer = 1 then -- # test_1 + Buffer := 2; -- # change + Set_True (Signal_Ack); -- # signal_ack_send + else + raise Program_Error; -- # exception_1 + end if; + end Waiter; + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads new file mode 100644 index 000000000..441b87ba2 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads @@ -0,0 +1,21 @@ +-- Test to check whether we can analyze correctly parts of an execution +-- which are covered after a task is blocked in a suspension object. + +with System; +with Ada.Synchronous_Task_Control; + +package Synchronization is + + task Signaler is + pragma Priority (System.Priority'Last - 1); + end Signaler; + + task Waiter is + pragma Priority (System.Priority'Last); + end Waiter; + + Signal_Sent, Signal_Ack : Ada.Synchronous_Task_Control.Suspension_Object; + Buffer : Integer := 0; + pragma Volatile (Buffer); + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb new file mode 100644 index 000000000..1b71a77f9 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb @@ -0,0 +1,19 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /signal_send/ l+ ## 0 +-- /signal_ack_wait/ l+ ## 0 +-- /test_2/ l+ ## 0 +-- /exception_2/ l- ## s- +-- /signal_wait/ l+ ## 0 +-- /test_1/ l+ ## 0 +-- /change/ l+ ## 0 +-- /signal_ack send/ l+ ## 0 +-- /exception_1/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb new file mode 100644 index 000000000..2c44b2069 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb @@ -0,0 +1,15 @@ +with Blocks_By_Tasks; + +procedure Test_Driver is +begin + null; +end; + + +--# blocks_by_tasks.adb +-- /blk1_tst/ l+ ## 0 +-- /blk1_stmt/ l+ ## 0 +-- /blk2_tst/ l+ ## 0 +-- /blk2_stmt/ l+ ## 0 +-- /blk3_tst/ l! ## dT- +-- /blk3_stmt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb new file mode 100644 index 000000000..09e515f5e --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb @@ -0,0 +1,22 @@ +package body Blocks_By_Tasks is + First_Block, Second_Block, Third_Block : Boolean := False; + + task body Processing is + begin + -- Block to be covered by instances of type Block1 + if Kind = Block1 then -- # blk1_tst + First_Block := True; -- # blk1_stmt + end if; + + -- Block to be covered by instances of type Block2 + if Kind = Block2 then -- # blk2_tst + Second_Block := True; -- # blk2_stmt + end if; + + -- Block to be covered by instances of type Block3, but none + -- created in this test case. + if Kind = Block3 then -- # blk3_tst + Third_Block := True; -- # blk3_stmt + end if; + end Processing; +end Blocks_By_Tasks; diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads new file mode 100644 index 000000000..4d3516581 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads @@ -0,0 +1,19 @@ +-- Test to check whether we can analyze correctly parts of a task type +-- covered by different instances of the type. There are three if +-- statements, each of them checking the discriminant used in the +-- task instantiation. There are two tasks instances, intended to +-- cover the first two blocks, and a third block is not covered +-- because no task instance is declared to cover that block. + +with System; + +package Blocks_By_Tasks is + type Task_Kind is (Block1, Block2, Block3); + + task type Processing (Kind : Task_Kind) is + pragma Priority (System.Priority'Last); + end Processing; + + T1 : Processing (Block1); + T2 : Processing (Block2); +end Blocks_By_Tasks; diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb new file mode 100644 index 000000000..de5339ab1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb @@ -0,0 +1,15 @@ +with Blocks_By_Tasks; + +procedure Test_Driver is +begin + null; +end; + + +--# blocks_by_tasks.adb +-- /blk1_tst/ l+ ## 0 +-- /blk1_stmt/ l+ ## 0 +-- /blk2_tst/ l+ ## 0 +-- /blk2_stmt/ l+ ## 0 +-- /blk3_tst/ l+ ## 0 +-- /blk3_stmt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb new file mode 100644 index 000000000..ff0714f14 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb @@ -0,0 +1,22 @@ +with Sync; use Sync; +procedure Test_1 is +begin + Termination.Wait; +end; + + +--# sync.adb +-- /pro_do/ l+ ## 0 +-- /con_do/ l+ ## 0 +-- /psh_do/ l+ ## 0 +-- /psh_ttell/ l! ## dT- +-- /psh_tell/ l- ## s- +-- /pop_do/ l+ ## 0 +-- /pop_ttell/ l! ## dF- +-- /pop_tell/ l+ ## 0 +-- /rch_do/ l+ ## 0 +-- /wat_do/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- /pop_guard/ l? ## d? +-- /wat_guard/ l? ## d? diff --git a/testsuite/tests/Ravenscar/example0/decision/test.opt b/testsuite/tests/Ravenscar/example0/decision/test.opt new file mode 100644 index 000000000..9b3f40f99 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR,!native +RTS_FULL,!native +ALL DEAD [M305-011] relies on Ravenscar constructs + strict priority based scheduling diff --git a/testsuite/tests/Ravenscar/example0/decision/test.py b/testsuite/tests/Ravenscar/example0/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/example0/src/sync.adb b/testsuite/tests/Ravenscar/example0/src/sync.adb new file mode 100644 index 000000000..ba96f00f6 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/src/sync.adb @@ -0,0 +1,55 @@ +with GNAT.IO; use GNAT.IO; +package body Sync is + + protected body Buffer is + procedure Push (V : Integer; Tell : Boolean) is + begin + if Tell then -- # psh_ttell + Put_Line ("push " & Integer'Image (V)); -- # psh_tell + end if; + Value := V; -- # psh_do + Has_Value := True; -- # psh_do + end; + + entry Pop (V : out Integer; Tell : Boolean) + when Has_Value -- # pop_guard + is + begin + V := Value; -- # pop_do + if Tell then -- # pop_ttell + Put_Line ("pop " & Integer'Image (V)); -- # pop_tell + end if; + Has_Value := False; -- # pop_do + end; + end Buffer; + + protected body Sync_Point is + procedure Reach is + begin + Reaches_So_Far := Reaches_So_Far + 1; -- # rch_do + Pass := Reaches_So_Far >= N; -- # rch_do + end; + + entry Wait when Pass is -- # wat_guard + begin + null; -- # wat_do + end; + end Sync_Point; + + -- + + B0 : Buffer; + + task body Producer is + begin + B0.Push (V => 12, Tell => False); -- # pro_do + Termination.Reach; -- # pro_do + end; + + task body Consumer is + V : Integer; + begin + B0.Pop (V => V, Tell => True); -- # con_do + Termination.Reach; -- # con_do + end; +end; diff --git a/testsuite/tests/Ravenscar/example0/src/sync.ads b/testsuite/tests/Ravenscar/example0/src/sync.ads new file mode 100644 index 000000000..94ff96169 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/src/sync.ads @@ -0,0 +1,48 @@ +with System; + +package Sync is + + -- Simple 1 slot protected buffer + + protected type Buffer is + procedure Push (V : Integer; Tell : Boolean); + entry Pop (V : out Integer; Tell : Boolean); + private + Value : Integer; + Has_Value : Boolean := False; + end; + + -- One producer and one consumer of Buffer data. + -- See the Notes at the end for the choice of priorities. + + task Producer is + pragma Priority (System.Default_Priority-2); + end; + + task Consumer is + pragma Priority (System.Default_Priority-1); + end; + + -- Simple environment termination control + + protected type Sync_Point (N : Positive) is + procedure Reach; + entry Wait; -- until N calls to Reach + private + Reaches_So_Far : Natural := 0; + Pass : Boolean := False; + end; + + -- To let the environment task know when both + -- the Consumer and the Producer tasks are done + + Termination : Sync_Point (N => 2); + + -- Notes: the priorties are chosen to have + -- + -- prio (environment) > prio (consumer) > prio (producer) + -- + -- to make sure that the guards are exercised both ways, False + -- then True. + +end; diff --git a/testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb b/testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb new file mode 100644 index 000000000..fbafee363 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb @@ -0,0 +1,18 @@ +with Sync; use Sync; +procedure Test_1 is +begin + Termination.Wait; +end; + + +--# sync.adb +-- /pro_do/ l+ ## 0 +-- /con_do/ l+ ## 0 +-- /psh_do/ l+ ## 0 +-- /psh_ttell/ l+ ## 0 +-- /psh_tell/ l- ## s- +-- /pop_do/ l+ ## 0 +-- /pop_ttell/ l+ ## 0 +-- /pop_tell/ l+ ## 0 +-- /rch_do/ l+ ## 0 +-- /wat_do/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/example0/stmt/test.opt b/testsuite/tests/Ravenscar/example0/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/example0/stmt/test.py b/testsuite/tests/Ravenscar/example0/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/S213-006-obligation-stats/src/foo.adb b/testsuite/tests/S213-006-obligation-stats/src/foo.adb new file mode 100644 index 000000000..ad66f7103 --- /dev/null +++ b/testsuite/tests/S213-006-obligation-stats/src/foo.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo + (A : Boolean; + B : Boolean; + C : Boolean; + D : Boolean) is +begin + if A and then (B or else + (C and then D)) + then + Put_Line + ("Hello world!"); + end if; +end Foo; diff --git a/testsuite/tests/S213-006-obligation-stats/src/test.adb b/testsuite/tests/S213-006-obligation-stats/src/test.adb new file mode 100644 index 000000000..d263be4d2 --- /dev/null +++ b/testsuite/tests/S213-006-obligation-stats/src/test.adb @@ -0,0 +1,6 @@ +with Foo; + +procedure Test is +begin + Foo (True, True, False, False); +end Test; diff --git a/testsuite/tests/S213-006-obligation-stats/test.py b/testsuite/tests/S213-006-obligation-stats/test.py new file mode 100644 index 000000000..2c256f493 --- /dev/null +++ b/testsuite/tests/S213-006-obligation-stats/test.py @@ -0,0 +1,41 @@ +""" +Checks that coverage obligations spanning on multiple lines are not counted +several times in the reported obligation statistics. Checking the XML content +(which also provides the obligation statistics) is verified in +R507-027-xml-summary. +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +tmp = Wdir("tmp_") + +covargs = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["test.adb"]) + ), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=[], +) + +xcov(covargs + ["-axcov"]) +thistest.fail_if_no_match( + "foo.adb.xcov", + re.compile( + ".*\n" + r"100% statement coverage \(2 out of 2\)\n" + r"0% decision coverage \(0 out of 1\)\n" + r"0% MC/DC coverage \(0 out of 4\)\n" + ".*", + re.DOTALL, + ), + contents_of("obj/foo.adb.xcov"), +) + +thistest.result() diff --git a/testsuite/tests/S218-011-time-option/main.adb b/testsuite/tests/S218-011-time-option/main.adb new file mode 100644 index 000000000..2d5ca66b2 --- /dev/null +++ b/testsuite/tests/S218-011-time-option/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello World!"); +end Main; diff --git a/testsuite/tests/S218-011-time-option/test.py b/testsuite/tests/S218-011-time-option/test.py new file mode 100644 index 000000000..544b66ab0 --- /dev/null +++ b/testsuite/tests/S218-011-time-option/test.py @@ -0,0 +1,46 @@ +import datetime + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +tmp = Wdir("tmp_") + +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-a", "xml"], +) + +# Check that by default, date is displayed in local time +xcov(xcov_args) +timezone_offset = datetime.datetime.now().astimezone().strftime("%z") +formatted_offset = timezone_offset[:3] + ":" + timezone_offset[3:5] +thistest.fail_if( + formatted_offset not in contents_of("obj/trace.xml"), + "Date displayed in xml report should be specified " + "as local time by default.", +) + +# Check that passing explicitely local displays the date under the right format +xcov(xcov_args + ["--timezone=local"]) +thistest.fail_if( + formatted_offset not in contents_of("obj/trace.xml"), + "Date displayed in xml report does not have the right " + "annotation (time offset expected).", +) + +# Check that passing explicitely UTC displays the date under the right format +xcov(xcov_args + ["--timezone=utc"]) +thistest.fail_if( + "UTC" not in contents_of("obj/trace.xml"), + "Date displayed in xml report does not have the right " + "annotation (UTC expected).", +) + +thistest.result() diff --git a/testsuite/tests/S220-058-auto-scos-fetch/main.adb b/testsuite/tests/S220-058-auto-scos-fetch/main.adb new file mode 100644 index 000000000..650125032 --- /dev/null +++ b/testsuite/tests/S220-058-auto-scos-fetch/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("hello there"); +end Main; diff --git a/testsuite/tests/S220-058-auto-scos-fetch/test.py b/testsuite/tests/S220-058-auto-scos-fetch/test.py new file mode 100644 index 000000000..232ef6426 --- /dev/null +++ b/testsuite/tests/S220-058-auto-scos-fetch/test.py @@ -0,0 +1,54 @@ +""" +Test that "gnatcov coverage" does not fetch ALI/SID files when only loading a +checkpoint (i.e. not processing a trace file). +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import gprfor, xcov + + +wd = Wdir("tmp_") + +# Generate a checkpoint +ckpt = "run0.ckpt" +gpr = gprfor(["main.adb"], srcdirs="..") +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint", ckpt], + scos=["obj/main"], +) + +# Override ALI/SID files with invalid content, so that attempts to load them +# result in errors. +for f in ["obj/main.sid", "obj/main.ali"]: + with open(f, "w") as f: + f.write("INVALID FILE\n") + +# Use the checkpoint to produce a report. Since there is no trace file to +# process, this should not try to load any ALI/SID file even though the loaded +# project makes them available. +log = "coverage-ckpt.log" +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--checkpoint", + ckpt, + "-P", + gpr, + "--output-dir=.", + ], + out=log, +) +log_content = contents_of(log) +thistest.fail_if( + log_content, "Output of gnatcov not empty:\n{}".format(indent(log_content)) +) + +thistest.result() diff --git a/testsuite/tests/S506-014-mix-providers/main.adb b/testsuite/tests/S506-014-mix-providers/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/S506-014-mix-providers/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/S506-014-mix-providers/test.opt b/testsuite/tests/S506-014-mix-providers/test.opt new file mode 100644 index 000000000..84ed65118 --- /dev/null +++ b/testsuite/tests/S506-014-mix-providers/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Requires support for binary traces diff --git a/testsuite/tests/S506-014-mix-providers/test.py b/testsuite/tests/S506-014-mix-providers/test.py new file mode 100644 index 000000000..84a937064 --- /dev/null +++ b/testsuite/tests/S506-014-mix-providers/test.py @@ -0,0 +1,183 @@ +""" +Check that gnatcov properly warns when a unit is processed both with +instrumentation and regular SCOs. + +Also check that passing both kind of traces is rejected by gnatcov. +""" + +from e3.fs import cp, mkdir + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +import re + + +tmp = Wdir("tmp_") +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) + + +def check(tc_name, coverage_args, expected_results, expect_failure): + p = xcov( + ["coverage", "-P", prj, "-axcov", "-cstmt"] + coverage_args, + out=f"{tc_name}.log", + register_failure=not expect_failure, + ) + if expect_failure: + thistest.fail_if( + p.status == 0, "gnatcov did not exit with an error ({tc_name})" + ) + + actual = "\n".join( + line.rstrip() for line in contents_of(f"{tc_name}.log").splitlines() + ) + + thistest.fail_if_no_match( + f"unexpected gnatcov output ({tc_name})", + regexp=expected_results, + actual=actual, + ) + + +# First, build and run the program in src-traces mode to produce SIDs and a +# source trace. +src_trace = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + extra_coverage_args=[], + mains=["main"], + extra_gprbuild_args=["-XBUILD_MODE=src-traces"], + trace_mode="src", +)[-1] + +# The build_and_run invocation bellow implicitly invokes gprclean which will +# delete the SID files, so we need to copy them elsewhere to avoid having them +# be deleted. +sids_dir = "sids" +mkdir(sids_dir) +cp("obj/*.sid", sids_dir) + +# Second, build and run the program to produce SCOs (ALIs) and a binary trace +bin_trace = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + extra_coverage_args=[], + mains=["main"], + extra_gprbuild_args=[ + "-XBUILD_MODE=bin-traces", + "-cargs", + "-g", + "-fdump-scos", + "-fpreserve-control-flow", + ], + trace_mode="bin", +)[-1] + +# We can now try to compute code coverage with both the instrumentation +# checpoint and the compiler SCOs. This requires passing --mix-trace-kind +# to gnatcov to allow mixing trace kinds. + +expected_log = re.escape( + "warning: Mixing source traces and binary traces is not supported. " + "Please only use a single kind of traces." + "\nwarning: ignoring duplicate SCOs for main.adb (from main.ali)" + "\nwarning: previous SCOs for this unit came from instrumenting main.adb" + "\nwarning: Using option --sid with binary trace files has no effect." + "\nPlease consider using option --scos or -P in conjunction" + " with --units to specify units of interest." + "\nwarning: Using option --scos with source trace files has no effect." + "\nPlease consider using option --sid or -P in conjunction" + " with --units to specify units of interest." +) + +check( + "trace_mix", + coverage_args=[ + "--mix-trace-kind", + "--scos", + "obj/main.ali", + "--sid", + f"{sids_dir}/main.sid", + src_trace, + bin_trace, + ], + expected_results=expected_log, + expect_failure=False, +) + +# Check that without --mix-trace-kind, providing traces of different kind +# results in an error. + +check( + "mix_not_allowed", + coverage_args=[ + "--scos", + "obj/main.ali", + "--sid", + f"{sids_dir}/main.sid", + src_trace, + bin_trace, + ], + expected_results=r".*gnatcov(\.exe)?: Mixing source traces and binary" + r" traces is not supported\. Please only use a single kind of traces\.", + expect_failure=True, +) + +# Check that using --scos in source trace mode emits a warning. +# Also produce a checkpoint for later testing. + +check( + "scos_with_src", + coverage_args=[ + "--scos", + "obj/main.ali", + "--sid", + f"{sids_dir}/main.sid", + "--save-checkpoint=src.ckpt", + src_trace, + ], + expected_results=re.escape( + "warning: Using option --scos with source trace files" + " has no effect.\nPlease consider using option --sid or" + " -P in conjunction with --units to specify units of" + " interest." + ), + expect_failure=False, +) + +# Check that using --sid with binary traces emits a warning. +# Also produce a checkpoint for later testing. + +check( + "sid_with_bin", + coverage_args=[ + "--scos", + "obj/main.ali", + "--sid", + f"{sids_dir}/main.sid", + "--save-checkpoint=bin.ckpt", + bin_trace, + ], + expected_results=re.escape( + "warning: Using option --sid with binary trace files" + " has no effect.\nPlease consider using option --scos or" + " -P in conjunction with --units to specify units of" + " interest." + ), + expect_failure=False, +) + +# Check that mixing trace kinds through checkpoints is rejected + +check( + "mixed_checkpoint", + coverage_args=["-Csrc.ckpt", "-Cbin.ckpt"], + expected_results=r".*gnatcov(\.exe)?: Mixing source traces and binary" + r" traces is not supported\. Please only use a single kind of traces\.", + expect_failure=True, +) + + +thistest.result() diff --git a/testsuite/tests/S527-004-ckpt-no-level/main.adb b/testsuite/tests/S527-004-ckpt-no-level/main.adb new file mode 100644 index 000000000..0dff0b39e --- /dev/null +++ b/testsuite/tests/S527-004-ckpt-no-level/main.adb @@ -0,0 +1,8 @@ +procedure Main is + Val : Boolean := True; + pragma Volatile (Val); +begin + if Val then + Val := False; + end if; +end Main; diff --git a/testsuite/tests/S527-004-ckpt-no-level/test.py b/testsuite/tests/S527-004-ckpt-no-level/test.py new file mode 100644 index 000000000..72ae42210 --- /dev/null +++ b/testsuite/tests/S527-004-ckpt-no-level/test.py @@ -0,0 +1,44 @@ +""" +Check the warning message that "gnatcov coverage" emits when a checkpoint is +provided but no coverage level is, and check that we got the expected +statement coverage results. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov, thistest + +tmp = Wdir("tmp_") + +# Create a checkpoint with --level=stmt+decision +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), + ), + extra_coverage_args=["--save-checkpoint=my_checkpoint.ckpt"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", +) + +# Try to load the checkpoint without specifying the coverage level and +# check the coverage results expecting stmt level coverage. +log_file = "gnatcov.out" +p = xcov( + ["coverage", "--annotate=xcov", "--checkpoint=my_checkpoint.ckpt"], + out=log_file, + tolerate_messages="Coverage level not specified on the command line.*", +) + + +thistest.fail_if_no_match( + what="Missing warning in the gnatcov coverage output", + regexp=r"warning: Coverage level not specified on the command line" + r' or in the project file \(--level=.*\), defaulting to "stmt"\.', + actual=contents_of(log_file), +) + +check_xcov_reports(".", {"main.adb.xcov": {"+": {2, 5, 6}}}) + +thistest.result() diff --git a/testsuite/tests/S529-038-isi-ckpt/main1.adb b/testsuite/tests/S529-038-isi-ckpt/main1.adb new file mode 100644 index 000000000..2a5e24e04 --- /dev/null +++ b/testsuite/tests/S529-038-isi-ckpt/main1.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Main1 is +begin + Ada.Text_IO.Put_Line ("Hello, world!"); +end Main1; diff --git a/testsuite/tests/S529-038-isi-ckpt/main2.adb b/testsuite/tests/S529-038-isi-ckpt/main2.adb new file mode 100644 index 000000000..5f6babf84 --- /dev/null +++ b/testsuite/tests/S529-038-isi-ckpt/main2.adb @@ -0,0 +1,16 @@ +procedure Main2 is + function And_Then (X, Y : Boolean) return Boolean is + begin + if X and then Y then + return True; + else + return False; + end if; + end And_Then; + + Dummy : array (Positive range <>) of Boolean := + (And_Then (False, False), + And_Then (True, True)); +begin + null; +end Main2; diff --git a/testsuite/tests/S529-038-isi-ckpt/test.py b/testsuite/tests/S529-038-isi-ckpt/test.py new file mode 100644 index 000000000..5d967840e --- /dev/null +++ b/testsuite/tests/S529-038-isi-ckpt/test.py @@ -0,0 +1,139 @@ +""" +Check that gnatcov processes SID files and consolidation checkpoints as +completely separate concepts. + +In particular: check that it complains when a consolidation checkpoint is +provided where an SID file is expected and conversely, and check that +information in SID files does not "leak" to consolidation checkpoints. +""" + +import re + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of, indent, lines_of +from SUITE.tutils import gprfor, srctracename_for, xcov + + +tmp = Wdir("tmp_") + + +def main(i): + return "main{}".format(i) + + +def sid(i): + return "i{}.sid".format(i) + + +def ckpt(i): + return "c{}.ckpt".format(i) + + +def trace(i): + return srctracename_for("main{}".format(i)) + + +def check_error(argv, log_name, expected_error): + p = xcov(argv, out=log_name, register_failure=False) + actual_error = contents_of(log_name).strip() + + expected_re = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + "[^\n]*gnatcov[^\n]*: {}".format(re.escape(expected_error)) + ) + + thistest.fail_if(p.status == 0, "gnatcov was expected to fail, it did not") + thistest.fail_if( + not expected_re.match(actual_error), + 'Unexpected output for "gnatcov coverage" ({}). Expected:\n' + "{}\n" + "but got:\n" + "{}".format( + log_name, indent(repr(expected_re.pattern)), indent(actual_error) + ), + ) + + +gpr = gprfor(["main1.adb", "main2.adb"], srcdirs="..") + +# Prepare material for the checks: instrument both main1 and main2, produce +# traces and create consolidation checkpoints for them. +for i in (1, 2): + sid_file = "obj/main{}.sid".format(i) + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr, units=[main(i)]), + covlevel="stmt+mcdc", + mains=[main(i)], + extra_coverage_args=["--save-checkpoint", ckpt(i), "--sid", sid_file], + trace_mode="src", + ) + cp(sid_file, sid(i)) + + +# Check that gnatcov complains when passing a consolidation checkpoint as an +# SID file. +check_error( + argv=[ + "coverage", + "--annotate=xcov", + "--level=stmt+mcdc", + "--sid", + ckpt(1), + trace(1), + ], + log_name="ckpt_as_sid.log", + expected_error=( + "invalid Source Instrumentation Data (SID) file " + "{}, name of file should have .sid extension".format(ckpt(1)) + ), +) + +# Check that gnatcov complains when passing an SID file as a consolidation +# checkpoint. +check_error( + argv=[ + "coverage", + "--level=stmt+mcdc", + "--checkpoint", + sid(1), + "--checkpoint", + sid(2), + "--save-checkpoint", + "consolidated.ckpt", + ], + log_name="sid_as_ckpt.log", + expected_error="{} is a Source Instrumentation Data (SID) while a" + " checkpoint was expected".format(sid(1)), +) + + +# Finally, check that information from SID files does not leak into +# checkpoints. This means that one needs to provide an SID file in order to +# decode the corresponding source traces. +# +# Here, even though c1.ckpt was produced while i1.sid was loaded, one must +# provide i1.sid in order to decode main1.srctrace: loading c1.ckpt is not +# enough. +xcov( + [ + "coverage", + "-v", + "--annotate=xcov", + "--level=stmt+mcdc", + "--checkpoint", + ckpt(1), + trace(1), + ], + out="leak.log", +) +thistest.fail_if( + "[GNATCOV.MISC] discarding source trace entry for unknown instrumented" + " unit: body of main1" not in lines_of("leak.log") +) + +thistest.result() diff --git a/testsuite/tests/S603-009-externally-built/main/main.adb b/testsuite/tests/S603-009-externally-built/main/main.adb new file mode 100644 index 000000000..84c8ee74b --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/main/main.adb @@ -0,0 +1,8 @@ +with Mylib; + +procedure Main is + Dummy : Natural := Mylib.Fact (1); +begin + null; + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/S603-009-externally-built/mylib/mylib.adb b/testsuite/tests/S603-009-externally-built/mylib/mylib.adb new file mode 100644 index 000000000..608652d6e --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + function Fact (N : Natural) return Natural is + begin + if N < 2 then + return N; + else + return N * Fact (N - 1); + end if; + end Fact; + +end Mylib; diff --git a/testsuite/tests/S603-009-externally-built/mylib/mylib.ads b/testsuite/tests/S603-009-externally-built/mylib/mylib.ads new file mode 100644 index 000000000..e1c518f78 --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + function Fact (N : Natural) return Natural; +end Mylib; diff --git a/testsuite/tests/S603-009-externally-built/mylib/mylib.gpr b/testsuite/tests/S603-009-externally-built/mylib/mylib.gpr new file mode 100644 index 000000000..46809fb8d --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/mylib/mylib.gpr @@ -0,0 +1,5 @@ +library project Mylib is + for Library_Name use "mylib"; + for Library_Dir use "lib"; + for Object_Dir use "obj"; +end Mylib; diff --git a/testsuite/tests/S603-009-externally-built/test.opt b/testsuite/tests/S603-009-externally-built/test.opt new file mode 100644 index 000000000..bdc588b7f --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/test.opt @@ -0,0 +1,7 @@ +src-traces +native +ALL DEAD +-- gnatls -v output does not reflect GPR_PROJECT_PATH modifications (with +-- GNAT5.04a1), and GNATcoll.projects uses it to compute environment +-- information. This should be fixed when transitioning to libgpr2. +5.04a1 XFAIL Incompatibility between gnatls and GNATCOLL.Projects diff --git a/testsuite/tests/S603-009-externally-built/test.py b/testsuite/tests/S603-009-externally-built/test.py new file mode 100644 index 000000000..1d3118c22 --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/test.py @@ -0,0 +1,226 @@ +""" +Check that GNATcoverage does not process externally built projects, unless +--externally-built-projects is passed. +""" + +import os.path +import re +import shutil + +from e3.fs import cp + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor, gprinstall, xcov + + +# Dump triggers to be tested. The default one for the platform and manual for +# source traces, irrelevant for bin traces, we simply need one to run the +# test. +# +# TODO the test seems to be dead for bin traces, can we simplify this??? +dump_triggers = ( + ["manual", "auto"] + if thistest.options.trace_mode == "src" + else ["bin-trace"] +) + + +def check_coverage( + project, externally_built, expected_cov, trace_file, register_failure=True +): + """ + Create a coverage report for project from trace_file, + requesting coverage for externally-built projects based on + externally_built, and check the report against expected_cov. + Return the process handle and the output filename for the + "gnatcov coverage" command and ignore its exit status if + register_failure is False. + """ + output_dir = ( + f"xcov_{os.path.basename(project[:-4])}_" + f"{'ext' if externally_built else 'no_ext'}" + ) + thistest.log(f"coverage in {output_dir}") + gnatcov_log = f"gnatcov_{output_dir}.log" + if os.path.isdir(output_dir): + shutil.rmtree(output_dir) + os.mkdir(output_dir) + + args = [ + "coverage", + "-cstmt", + "-axcov", + "-P", + project, + "--output-dir", + output_dir, + trace_file, + ] + if externally_built: + args.append("--externally-built-projects") + p = xcov(args, out=gnatcov_log, register_failure=register_failure) + + if not register_failure: + return p, gnatcov_log + + check_xcov_reports(output_dir, expected_cov) + + +def check_one(dump_trigger, lib_prj): + """ + Build and run the main project, inspecting externally built projects, + then check all four combinations of project/--externally-built-projects + to check the behaviors and results produced by gnatcov, for a given + dump trigger (if applicable) and installed library project. + """ + tmp.to_subdir(f"tmp_{dump_trigger}") + + # Generate a project file for this subdir + obj_main = os.path.abspath("obj_main") + main_gpr = gprfor( + prjid="main", + mains=["main.adb"], + srcdirs=["../main"], + objdir=obj_main, + exedir=obj_main, + deps=[lib_prj], + ) + thistest.log(f"====== Testing {dump_trigger} =======") + # Build the main project using this and run it to produce a trace file + xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=main_gpr, + externally_built_projects=True, + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + gpr_obj_dir=obj_main, + gpr_exe_dir=obj_main, + gprsw_for_coverage=False, + dump_trigger=dump_trigger, + manual_prj_name="main", + ) + trace_file = xcov_args[-1] + + # Check that the instrumenter hasn't tried to instrument the installed + # project + thistest.fail_if( + os.path.exists( + os.path.join(install_dir, "share", "gpr", "mylib-gnatcov-instr") + ), + '"gnatcov instrument" instrumented the installed project', + ) + + # First, make sure that "gnatcov coverage" on an externally built project + # returns an error. + p, log_filename = check_coverage( + project=installed_mylib_gpr, + externally_built=False, + expected_cov=None, + trace_file=trace_file, + register_failure=False, + ) + thistest.fail_if( + p.status == 0, + "gnatcov was supposed to complain when provided an externally built" + " project", + ) + coverage_log = contents_of(log_filename).strip() + expected_log = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + "[^\n]*gnatcov[^\n]*: {}".format( + re.escape( + "Root project is marked as externally built, while externally" + " built projects are ignored by default. Consider using" + " --externally-built-projects." + ) + ) + ) + thistest.fail_if( + not expected_log.match(coverage_log), + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(expected_log.pattern), indent(coverage_log)), + ) + + # It should not complain with --externally-built-projects + p = check_coverage( + project="mylib.gpr", + externally_built=True, + trace_file=trace_file, + expected_cov={ + "mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, + "mylib.ads.xcov": {}, + }, + ) + + # Make sure coverage computation gives the expected result with and + # without --externally-built-projects + check_coverage( + project=main_gpr, + externally_built=False, + trace_file=trace_file, + expected_cov={"main.adb.xcov": {"+": {4, 6}}}, + ) + check_coverage( + project=main_gpr, + externally_built=True, + trace_file=trace_file, + expected_cov={ + "main.adb.xcov": {"+": {4, 6}}, + "mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, + "mylib.ads.xcov": {}, + }, + ) + + +tmp = Wdir("tmp_") + +# Copy the library sources in the working directory +cp("../mylib", ".", recursive=True) + +mylib_obj_dir = "obj_lib" +mylib_gpr = os.path.join("mylib", "mylib.gpr") + +# Create the installation directory and add it to gprbuild's project lookup +# path. +install_dir = os.path.abspath("install") +gpr_install_dir = os.path.join(install_dir, "share", "gpr") +installed_mylib_gpr = os.path.join(gpr_install_dir, "mylib.gpr") +os.mkdir(install_dir) +env.add_search_path("GPR_PROJECT_PATH", gpr_install_dir) + +# Build and install the library project +if thistest.options.trace_mode == "src": + xcov_instrument( + gprsw=GPRswitches(root_project=mylib_gpr), + covlevel="stmt", + gpr_obj_dir=mylib_obj_dir, + ) +gprbuild(mylib_gpr) + +if thistest.options.trace_mode == "src": + gprinstall( + mylib_gpr, + [ + f"--prefix={install_dir}", + "--src-subdirs=gnatcov-instr", + "--implicit-with=gnatcov_rts", + ], + ) +else: + gprinstall(mylib_gpr, f"--prefix={install_dir}") + +# Run the coverage workflow for each dump trigger +for dump_trigger in dump_triggers: + check_one(dump_trigger, installed_mylib_gpr) + +thistest.result() diff --git a/testsuite/tests/S621-026-mcdc-ckpt/main1.adb b/testsuite/tests/S621-026-mcdc-ckpt/main1.adb new file mode 100644 index 000000000..2a5e24e04 --- /dev/null +++ b/testsuite/tests/S621-026-mcdc-ckpt/main1.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Main1 is +begin + Ada.Text_IO.Put_Line ("Hello, world!"); +end Main1; diff --git a/testsuite/tests/S621-026-mcdc-ckpt/main2.adb b/testsuite/tests/S621-026-mcdc-ckpt/main2.adb new file mode 100644 index 000000000..5f6babf84 --- /dev/null +++ b/testsuite/tests/S621-026-mcdc-ckpt/main2.adb @@ -0,0 +1,16 @@ +procedure Main2 is + function And_Then (X, Y : Boolean) return Boolean is + begin + if X and then Y then + return True; + else + return False; + end if; + end And_Then; + + Dummy : array (Positive range <>) of Boolean := + (And_Then (False, False), + And_Then (True, True)); +begin + null; +end Main2; diff --git a/testsuite/tests/S621-026-mcdc-ckpt/test.py b/testsuite/tests/S621-026-mcdc-ckpt/test.py new file mode 100644 index 000000000..1158379d6 --- /dev/null +++ b/testsuite/tests/S621-026-mcdc-ckpt/test.py @@ -0,0 +1,45 @@ +"""Regression testcase for the use of checkpoints and MC/DC coverage.""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +gpr = gprfor(["main1.adb", "main2.adb"], srcdirs="..") + +# Create a checkpoint for the execution of "main1" and another for "main2" +for i in (1, 2): + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt+mcdc", + mains=["main{}".format(i)], + extra_coverage_args=["--save-checkpoint=c{}.ckpt".format(i)], + scos=["obj/main{}".format(i)], + ) + +# Now consolidate both. c1.ckpt comes first in order to check that, when +# c2.ckpt is loaded, all SCOs in it, and in particular the ones in evaluation +# vectors for MC/DC, are properly remapped. +xcov( + [ + "coverage", + "--annotate=xcov", + "--level=stmt+mcdc", + "--checkpoint=c1.ckpt", + "--checkpoint=c2.ckpt", + ] +) + +check_xcov_reports( + ".", + { + "main1.adb.xcov": {"+": {5}}, + "main2.adb.xcov": {"+": {5, 7, 11, 12, 13, 15}, "!": {4}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/bar.h b/testsuite/tests/S820-013-ckpt-dup-scos/bar.h new file mode 100644 index 000000000..20dba0330 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/bar.h @@ -0,0 +1,8 @@ +static inline int +fact (int n) +{ + if (n > 1) + return n * fact (n - 1); + else + return n; +} diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/foo.c b/testsuite/tests/S820-013-ckpt-dup-scos/foo.c new file mode 100644 index 000000000..7f3505691 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/foo.c @@ -0,0 +1,7 @@ +#include "bar.h" + +int +foo (int n) +{ + return n + fact (n); +} diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/main.c b/testsuite/tests/S820-013-ckpt-dup-scos/main.c new file mode 100644 index 000000000..2d4164717 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/main.c @@ -0,0 +1,11 @@ +#include "bar.h" + +extern int foo (int); + +int +main (void) +{ + int n = fact (3); + foo (fact (3)); + return 0; +} diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/test.opt b/testsuite/tests/S820-013-ckpt-dup-scos/test.opt new file mode 100644 index 000000000..7ba7cedac --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test involves C units diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/test.py b/testsuite/tests/S820-013-ckpt-dup-scos/test.py new file mode 100644 index 000000000..7f129b313 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/test.py @@ -0,0 +1,47 @@ +""" +Test that checkpoints consolidation does not crash in the presence of "null" +SCOs, i.e. duplicated SCOs removed from the SCO vector in +Process_Low_Level_SCOs. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +wd = Wdir("tmp_") + +exe = exepath_to("main") +trace = tracename_for("main") +gpr = gprfor(["main.c"], srcdirs="..") + +# Build the test program and generate a trace file +gprbuild(gpr) +xrun([exe]) + +# Load the duplicated ALIs and create a checkpoint +ckpt = "c.ckpt" +xcov( + [ + "coverage", + "-c", + "stmt", + "--save-checkpoint", + ckpt, + "--scos=obj/main.c.gli", + "--scos=obj/foo.c.gli", + trace, + ] +) + +# Now try to generate a report from this checkpoint +xcov(["coverage", "-a", "xcov", "-c", "stmt", "--checkpoint", ckpt]) + +thistest.result() diff --git a/testsuite/tests/SB06-033-homonyms/.gitignore b/testsuite/tests/SB06-033-homonyms/.gitignore new file mode 100644 index 000000000..ca5215678 --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/.gitignore @@ -0,0 +1,2 @@ +*.trace +install diff --git a/testsuite/tests/SB06-033-homonyms/app/main.adb b/testsuite/tests/SB06-033-homonyms/app/main.adb new file mode 100644 index 000000000..e7f57c6ce --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/app/main.adb @@ -0,0 +1,7 @@ +with Lib; + +procedure Main is + Dummy : constant Integer := Lib.Next (Lib.First); +begin + null; +end; diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb b/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb new file mode 100644 index 000000000..27321e3d5 --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package body Lib is + function First return Integer is (1); + function Next (I : Integer) return Integer is (I + 1); +end; diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads b/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads new file mode 100644 index 000000000..29e7795cd --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Lib is + function First return Integer; + function Next (I : Integer) return Integer + with Inline_Always; + -- Always inlining this function is necessary to introduce code that + -- references installed source files (i.e. stub files from gnatcov's point + -- of view) for lib.adb into the _ada_main symbol (i.e. a routine analyzed + -- for source coverage, from main.adb). + -- + -- This makes "gnatcov coverage" try to get line info for this inlined + -- code, i.e. get line info on a stub file, which used to make gnatcov fail + -- on a precondition. +end; diff --git a/testsuite/tests/SB06-033-homonyms/test.opt b/testsuite/tests/SB06-033-homonyms/test.opt new file mode 100644 index 000000000..54c050461 --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/test.opt @@ -0,0 +1 @@ +src-traces DEAD S918-031: src-traces and externally built projects diff --git a/testsuite/tests/SB06-033-homonyms/test.py b/testsuite/tests/SB06-033-homonyms/test.py new file mode 100644 index 000000000..aa275f16b --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/test.py @@ -0,0 +1,84 @@ +""" +Check that "gnatcov coverage" does not crash when processing a program that +exposes two paths for the same source (once before and one after installation). + +Note that in this testcase, both absolute paths come from debug info line +mapping (.debug_lines). +""" + +import os.path +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprbuild, gprfor, gprinstall, xcov, xrun + + +# Build libfoo and install it in some prefix, then make the installed project +# available through the GPR_PROJECT_PATH environment variable. +tmp = Wdir("tmp_libfoo") +install_dir = os.path.abspath("install") +libfoo_gpr = gprfor( + prjid="libfoo", + mains=[], + srcdirs=["../libfoo"], + langs=["Ada"], + extra=""" + for Library_Kind use "static"; + for Library_Name use "foo"; + for Library_Dir use "lib"; + """, +) +gprbuild(libfoo_gpr) +gprinstall(libfoo_gpr, gargs=[f"--prefix={install_dir}"]) +os.environ["GPR_PROJECT_PATH"] = os.path.join(install_dir, "share", "gpr") +tmp.to_homedir() + +# Now, in another directory (so that we are sure it is the installed libfoo +# that is used), build the main application, then generate a binary trace for +# it. +tmp = Wdir("tmp_app") +app_gpr = gprfor( + prjid="app", mains=["main.adb"], srcdirs=["../app"], deps=["libfoo"] +) +gprbuild(app_gpr) +xrun("./main") + +# The very goal of this testcase is to compute code coverage for a unit that +# belongs to a project installed with gprinstall, so we need to enable the +# processing of externally built projects. +log_file = "gnatcov-coverage.txt" +xcov( + [ + "coverage", + "--annotate=xcov", + "--level=stmt", + "-P", + app_gpr, + "--projects=app", + "--externally-built-projects", + "main.trace", + ], + out=log_file, +) +thistest.fail_if_no_match( + '"gnatcov output" ({})'.format(log_file), + "warning: same base name for files:" + "\r?\n [^\n]+{}" + "\r?\n [^\n]+{}".format( + re.escape( + os.path.join( + "SB06-033-homonyms", + "tmp_libfoo", + "install", + "include", + "libfoo", + "lib.adb", + ) + ), + re.escape(os.path.join("SB06-033-homonyms", "libfoo", "lib.adb")), + ), + contents_of(log_file), +) + +thistest.result() diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/engines.adb b/testsuite/tests/SanityCheck/decision/Engines/src/engines.adb new file mode 100644 index 000000000..5ef8c9cad --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/engines.adb @@ -0,0 +1,33 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + if E.P < Stable_P and then E.T < Stable_T then -- # eval + return True; -- # true + end if; + return False; -- # false + end Stable; +end Engines; diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/engines.ads b/testsuite/tests/SanityCheck/decision/Engines/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb new file mode 100644 index 000000000..36970e5de --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb @@ -0,0 +1,38 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Both is + E : Engine; +begin + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); +end Test_Engines_Both; + +--# engines.adb +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb new file mode 100644 index 000000000..11b135a3b --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb @@ -0,0 +1,33 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Null is + E : Engine; + pragma Unreferenced (E); +begin + Assert (True); +end Test_Engines_Null; + +--# engines.adb +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb new file mode 100644 index 000000000..5e35e3d3d --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Stable is + E : Engine; +begin + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); +end Test_Engines_Stable; + +--# engines.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb new file mode 100644 index 000000000..fb6d2e924 --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 2, or (at your option) any later -- +-- version. Couverture is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Unstable is + E : Engine; +begin + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); +end Test_Engines_Unstable; + +--# engines.adb +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /false/ l+ ## 0 diff --git a/testsuite/tests/SanityCheck/decision/Engines/test.py b/testsuite/tests/SanityCheck/decision/Engines/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/T117-007-intf-thunks/src/action.ads b/testsuite/tests/T117-007-intf-thunks/src/action.ads new file mode 100644 index 000000000..39411d52a --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/action.ads @@ -0,0 +1,14 @@ +package Action is + + type T_Action is abstract tagged private; + + type T_NA_Action_Class is not null access all T_Action'Class; + + procedure Init (Obj : in out T_Action) is abstract; + + procedure Run (Obj : in out T_Action) is abstract; + +private + type T_Action is abstract tagged null record; + +end Action; diff --git a/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads b/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads new file mode 100644 index 000000000..b91fc2584 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads @@ -0,0 +1,9 @@ +package Interface_A is + + type T_Interface_A is interface; + + function Get_Variable (This : in T_Interface_A) return Integer is abstract; + + type T_A_Interface_A_Class is access all T_Interface_A'Class; + +end Interface_A; diff --git a/testsuite/tests/T117-007-intf-thunks/src/package_a.adb b/testsuite/tests/T117-007-intf-thunks/src/package_a.adb new file mode 100644 index 000000000..9352c3393 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/package_a.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; +package body Package_A is + + The_Instance : aliased T_A; + + NA_Intance : T_NA_A := The_Instance'Access; + + function NA_A return T_NA_A is (NA_Intance); + + overriding procedure Init (Obj : in out T_A) + is + begin + Obj.Variable := 15; + end Init; + + overriding procedure Run (Obj : in out T_A) + is + begin + Obj.Enumeration := DEF; + end Run; + + overriding function Get_Variable (Obj : in T_A) return Integer is (1); + +end Package_A; diff --git a/testsuite/tests/T117-007-intf-thunks/src/package_a.ads b/testsuite/tests/T117-007-intf-thunks/src/package_a.ads new file mode 100644 index 000000000..c7a43d209 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/package_a.ads @@ -0,0 +1,33 @@ +pragma Ada_2012; +with Action; +with Interface_A; + + +package Package_A is + + type T_A is new Action.T_Action + and Interface_A.T_Interface_A + with private; -- Statement on the line was not executed + + type T_NA_A is not null access all T_A; -- Statement on the line was not executed + + function NA_A return T_NA_A; + + overriding procedure Init (Obj : in out T_A); + + overriding procedure Run (Obj : in out T_A); + + overriding function Get_Variable (Obj : in T_A) return Integer; + + type Enum is (ABC, DEF); -- Statement on the line was not executed + +private + + type T_A is new Action.T_Action -- Statement on the line was not executed + and Interface_A.T_Interface_A + with record + Variable : Integer; + Enumeration : Enum; + end record; + +end Package_A; diff --git a/testsuite/tests/T117-007-intf-thunks/src/ut_main.adb b/testsuite/tests/T117-007-intf-thunks/src/ut_main.adb new file mode 100644 index 000000000..73c843c6a --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/ut_main.adb @@ -0,0 +1,18 @@ + +with Package_A; + +procedure Ut_Main is + + Instance : aliased Package_A.T_A; + + A_Instance : Package_A.T_NA_A := Package_A.NA_A; + + returnValue : Integer; + +begin + + Instance.Init; + Instance.Run; + returnValue := Instance.Get_Variable; + +end Ut_Main; diff --git a/testsuite/tests/T117-007-intf-thunks/test.opt b/testsuite/tests/T117-007-intf-thunks/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/T117-007-intf-thunks/test.py b/testsuite/tests/T117-007-intf-thunks/test.py new file mode 100644 index 000000000..670ab2bcb --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/test.py @@ -0,0 +1,29 @@ +import re + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +tmp_ = Wdir("tmp_") + +gpr = gprfor(srcdirs="../src", mains=["ut_main.adb"]) +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["ut_main"], + extra_coverage_args=["--annotate=xcov"], +) + +# We do not expect uncovered lines in package_a, as the code generated +# for the interface type declaration is thunk code, which is to be +# ignored for coverage purposes. + +report_package_a = contents_of("obj/package_a.ads.xcov") +thistest.fail_if( + re.search(string=report_package_a, pattern=r"-:"), + "unexpected uncovered code", +) + +thistest.result() diff --git a/testsuite/tests/T319-018-if-expr/src/pkg.adb b/testsuite/tests/T319-018-if-expr/src/pkg.adb new file mode 100644 index 000000000..595e445f3 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/pkg.adb @@ -0,0 +1,26 @@ +package body Pkg is + + function Null_Out_Data_Port return Out_Data_Port'Class is + begin + return Out_Data_Port'Class (Simple_Out_Data_Port'(null record)); + end Null_Out_Data_Port; + + overriding function Image (Out_P : Simple_Out_Data_Port) return String is + begin + return "foo"; + end Image; + + overriding function Incoming_Signal + (I : Simple_In_Data_Port) return Signal'Class + is + begin + return Signal'Class + (Simple_Signal'(Is_Null => I.Incoming_Signal_Is_Null)); + end Incoming_Signal; + + function Src_Port (S : Simple_Signal) return Out_Port'Class is + begin + return Out_Port'Class (Simple_Out_Data_Port'(null record)); + end Src_Port; + +end Pkg; diff --git a/testsuite/tests/T319-018-if-expr/src/pkg.ads b/testsuite/tests/T319-018-if-expr/src/pkg.ads new file mode 100644 index 000000000..46593d9fa --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/pkg.ads @@ -0,0 +1,44 @@ +pragma Ada_2012; + +package Pkg is + + ----------------- + -- Interfaces -- + ----------------- + + type Signal; + + type Out_Port is interface; + type Out_Data_Port is interface and Out_Port; + function Image (Out_P : Out_Data_Port) return String is abstract; + + type In_Port is interface; + function Incoming_Signal (I : In_Port) return Signal'Class is abstract; + + type In_Data_Port is interface and In_Port; + + type Signal is interface; + function Is_Not_Null (S : Signal) return Boolean is abstract; + function Src_Port (S : Signal) return Out_Port'Class is abstract; + + function Null_Out_Data_Port return Out_Data_Port'Class; + + --------------------- + -- Implementations -- + --------------------- + + type Simple_Out_Data_Port is new Out_Data_Port with null record; + overriding function Image (Out_P : Simple_Out_Data_Port) return String; + + type Simple_In_Data_Port is new In_Data_Port with record + Incoming_Signal_Is_Null : Boolean; + end record; + overriding function Incoming_Signal + (I : Simple_In_Data_Port) return Signal'Class; + + type Simple_Signal is new Signal with record + Is_Null : Boolean; + end record; + function Is_Not_Null (S : Simple_Signal) return Boolean is (not S.Is_Null); + function Src_Port (S : Simple_Signal) return Out_Port'Class; +end Pkg; diff --git a/testsuite/tests/T319-018-if-expr/src/proc.adb b/testsuite/tests/T319-018-if-expr/src/proc.adb new file mode 100644 index 000000000..3ff792f97 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/proc.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Proc (In_P : In_Data_Port'Class) +is + Orig_Out_P : constant Out_Data_Port'Class := -- # uncond + (if In_P.Incoming_Signal.Is_Not_Null -- # decision + then Out_Data_Port'Class (In_P.Incoming_Signal.Src_Port) -- # out-true + else Null_Out_Data_Port); -- # out-false +begin + Put_Line (Orig_Out_P.Image); -- # uncond +end Proc; diff --git a/testsuite/tests/T319-018-if-expr/src/test_all.adb b/testsuite/tests/T319-018-if-expr/src/test_all.adb new file mode 100644 index 000000000..5041edc19 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_all.adb @@ -0,0 +1,14 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_All is +begin + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => False)); + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => True)); +end Test_All; + +--# proc.adb +-- /uncond/ l+ ## 0 +-- /decision/ l+ ## 0 +-- /out-true/ l+ ## 0 +-- /out-false/ l+ ## 0 diff --git a/testsuite/tests/T319-018-if-expr/src/test_false.adb b/testsuite/tests/T319-018-if-expr/src/test_false.adb new file mode 100644 index 000000000..660214eaa --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_false.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_False is +begin + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => False)); +end Test_False; + +--# proc.adb +-- /uncond/ l+ ## 0 +-- /decision/ l! ## d! +-- /out-true/ l+ ## 0 +-- /out-false/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- =/decision/ l! ## dF- diff --git a/testsuite/tests/T319-018-if-expr/src/test_no.adb b/testsuite/tests/T319-018-if-expr/src/test_no.adb new file mode 100644 index 000000000..e04a61546 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_no.adb @@ -0,0 +1,15 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_No is +begin + if Null_Out_Data_Port.Image = "" then + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => False)); + end if; +end Test_No; + +--# proc.adb +-- /uncond/ l- ## s- +-- /decision/ l- ## 0 +-- /out-true/ l- ## 0 +-- /out-false/ l- ## 0 diff --git a/testsuite/tests/T319-018-if-expr/src/test_true.adb b/testsuite/tests/T319-018-if-expr/src/test_true.adb new file mode 100644 index 000000000..ba491cc03 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_true.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_True is +begin + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => True)); +end Test_True; + +--# proc.adb +-- /uncond/ l+ ## 0 +-- /decision/ l! ## d! +-- /out-true/ l+ ## 0 +-- /out-false/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- =/decision/ l! ## dT- diff --git a/testsuite/tests/T319-018-if-expr/test.opt b/testsuite/tests/T319-018-if-expr/test.opt new file mode 100644 index 000000000..e0ed9ce5c --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD Test requires dynamic interface conversions +RTS_LIGHT_TASKING DEAD Test requires dynamic interface conversions +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/T319-018-if-expr/test.py b/testsuite/tests/T319-018-if-expr/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/T331-043-native-warn/main.adb b/testsuite/tests/T331-043-native-warn/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/T331-043-native-warn/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/T331-043-native-warn/test.py b/testsuite/tests/T331-043-native-warn/test.py new file mode 100644 index 000000000..7340a5bd7 --- /dev/null +++ b/testsuite/tests/T331-043-native-warn/test.py @@ -0,0 +1,58 @@ +"""Check that "gnatcov run" warns when running a native program.""" + +import os + +from e3.env import Env + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + + +tmp = Wdir("tmp") + + +# The testsuite automatically disables the warning we want to test: override +# this decision just for this testcase. +os.environ.pop("GNATCOV_NO_NATIVE_WARNING", None) + +is_native = not Env().is_cross +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + + +warning_exceprt = ( + "Support for coverage of non-instrumented native programs is deprecated" +) + + +def check_warning_absent(logfile): + thistest.fail_if( + warning_exceprt in contents_of(logfile), + "unexpected warning in {}".format(logfile), + ) + + +def check_warning_present(logfile): + thistest.fail_if( + warning_exceprt not in contents_of(logfile), + "missing warning in {}".format(logfile), + ) + + +# Depending on the trace mode and the target, check the presence/absence of the +# warning. +if thistest.options.trace_mode == "src": + check_warning_absent("instrument.log") +elif is_native: + check_warning_present("main_output.txt") +else: + check_warning_absent("main_output.txt") +check_warning_absent("coverage.log") + +thistest.result() diff --git a/testsuite/tests/T520-035-exit-when/src/parser.adb b/testsuite/tests/T520-035-exit-when/src/parser.adb new file mode 100644 index 000000000..206338c1a --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/parser.adb @@ -0,0 +1,29 @@ +package body Parser is + + procedure Skip_Line_Sep is null; + procedure Append is null; -- # append + + procedure Parse_Array (T : Toks) is + TI : Natural := T'First; + + function Scan_Tok return Tok is + Result : Tok := T (TI); + begin + TI := TI + 1; + return Result; + end Scan_Tok; + + begin + loop + -- Skip ';' or EOL + Skip_Line_Sep; -- # stmt + + -- If ']' is alone on its line + exit when Scan_Tok = Tok_Close_Bracket; -- # ex1 + + Append; -- # append + exit when Scan_Tok /= Tok_Semicolon and then Scan_Tok /= Tok_EOL; -- # ex2 + end loop; + end Parse_Array; + +end Parser; diff --git a/testsuite/tests/T520-035-exit-when/src/parser.ads b/testsuite/tests/T520-035-exit-when/src/parser.ads new file mode 100644 index 000000000..4f20fcd83 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/parser.ads @@ -0,0 +1,6 @@ +package Parser is + type Tok is (Tok_Close_Bracket, Tok_Semicolon, Tok_EOL, Tok_Stuff); + type Toks is array (Natural range <>) of Tok; + + procedure Parse_Array (T : Toks); +end Parser; diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_0.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_0.adb new file mode 100644 index 000000000..fe32bd332 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_0.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_0 is +begin + Parser.Parse_Array ((0 => Tok_Close_Bracket)); +end Test_Parser_0; + +--# parser.adb +-- /append/ l- ## s- +-- /ex1/ l! ## dF- +-- /ex2/ l- ## s- diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_full.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_full.adb new file mode 100644 index 000000000..8d04d3481 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_full.adb @@ -0,0 +1,11 @@ +with Parser; use Parser; +procedure Test_Parser_Full is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Stuff, Tok_Stuff, Tok_Close_Bracket)); + Parser.Parse_Array ((Tok_Stuff, Tok_Semicolon, Tok_Close_Bracket)); +end Test_Parser_Full; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l+ ## 0 +-- /ex2/ l+ ## 0 diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb new file mode 100644 index 000000000..183c2a967 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_FX is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Semicolon, Tok_Close_Bracket)); +end Test_Parser_FX; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l+ ## 0 +-- /ex2/ l! ## dT- diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb new file mode 100644 index 000000000..cfa1b5577 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_TF is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Stuff, Tok_EOL, Tok_Close_Bracket)); +end Test_Parser_TF; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l+ ## 0 +-- /ex2/ l! ## dT- diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb new file mode 100644 index 000000000..18fa6df83 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_TT is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Stuff, Tok_Stuff, Tok_Close_Bracket)); +end Test_Parser_TT; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l! ## dT- +-- /ex2/ l! ## dF- diff --git a/testsuite/tests/T520-035-exit-when/test.py b/testsuite/tests/T520-035-exit-when/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb new file mode 100644 index 000000000..993018799 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb @@ -0,0 +1,12 @@ +package body P1 is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end P1; diff --git a/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads new file mode 100644 index 000000000..cd9d6a897 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads @@ -0,0 +1,5 @@ +package P1 is + + function Next (I : Integer) return Integer; + +end P1; diff --git a/testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb b/testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb new file mode 100644 index 000000000..23b6dcf98 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb @@ -0,0 +1,7 @@ +with P1; + +procedure P2 is + Dummy : constant Integer := P1.Next (1); +begin + null; +end P2; diff --git a/testsuite/tests/T528-018-dup-proj-crash/test.py b/testsuite/tests/T528-018-dup-proj-crash/test.py new file mode 100644 index 000000000..6d5c56229 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/test.py @@ -0,0 +1,34 @@ +""" +Regression test: gnatcov used to crash when the same project was processed +multiple times. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") +p1 = gprfor( + prjid="p1", srcdirs=["../src-p1"], objdir="obj-p1", mains=[], langs=["Ada"] +) +p2 = gprfor( + prjid="p2", + srcdirs=["../src-p2"], + objdir="obj-p2", + deps=["p1"], + mains=["p2.adb"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p2, projects=["p1", "p2"]), + covlevel="stmt", + mains=["p2"], + gpr_obj_dir="obj-p2", + extra_coverage_args=["-axcov"], +) + + +thistest.result() diff --git a/testsuite/tests/T611-027-dump-units-to/main.adb b/testsuite/tests/T611-027-dump-units-to/main.adb new file mode 100644 index 000000000..9771e014c --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Say_Hello; +end Main; diff --git a/testsuite/tests/T611-027-dump-units-to/pkg.adb b/testsuite/tests/T611-027-dump-units-to/pkg.adb new file mode 100644 index 000000000..dcf5ce77e --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/pkg.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Say_Hello is + begin + Put_Line ("Hello, world!"); + end Say_Hello; +end Pkg; diff --git a/testsuite/tests/T611-027-dump-units-to/pkg.ads b/testsuite/tests/T611-027-dump-units-to/pkg.ads new file mode 100644 index 000000000..0728a72dd --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Say_Hello; +end Pkg; diff --git a/testsuite/tests/T611-027-dump-units-to/test.py b/testsuite/tests/T611-027-dump-units-to/test.py new file mode 100644 index 000000000..9c1fdb1b9 --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/test.py @@ -0,0 +1,221 @@ +""" +Check that --dump-units-at works as expected. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Generate a project, instrument it and run it +p = gprfor(mains=["main.adb"], srcdirs=[".."]) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) +xcov_args_no_trace = xcov_args[:-1] +trace_file = xcov_args[-1] + + +def check_output(output_file, expected_content, regexp=False): + """ + Check that the content of the "output_file" text file matches + "expected_content". Check for equality if "regexp" is False and consider + that "expected_content" is a regexp otherwise. + + :param str output_file: Name of the text file whose content needs to be + checked. + :param str expected_content: Expected content for this file. + :param bool regexp: Whether to match as a regexp (by default, check + content equality). + """ + checker = ( + thistest.fail_if_no_match if regexp else thistest.fail_if_not_equal + ) + checker( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace("\r\n", "\n"), + ) + + +def run_and_check( + args, output_file, expected_content, regexp=False, success_expected=True +): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_content: See the corresponding argument in "check". + :param bool regexp: See the corresponding argument in "check". + :param bool success_expected: If true, the test fails if gnatcov exits with + an error code. If false, the test fails if gnatcov exits with the zero + status code. + """ + p = xcov(args, out=output_file, register_failure=success_expected) + if not success_expected: + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + " succeeded (see {})".format(output_file), + ) + check_output(output_file, expected_content, regexp) + + +# Check that --dump-units-to is rejected when used in object coverage mode +run_and_check( + ["coverage", "-cinsn", "-aasm", trace_file, "-P", p, "--dump-units-to=-"], + "objcov.txt", + ".*gnatcov.*: --dump-units-to works in source coverage only", + regexp=True, + success_expected=False, +) + +# Check that nothing is dumped without --dump-units-to +run_and_check(xcov_args + ["-axcov"], "xcov-nodump.txt", "") + +# Check that when *not* using the "report" format, the list is printed on +# stdout with --dump-units-to=-. +run_and_check( + xcov_args + ["-axcov", "--dump-units-to=-"], + "xcov-stdout1.txt", + "main\npkg\n", +) +run_and_check( + xcov_args + ["-axcov", "--units=main", "--dump-units-to=-"], + "xcov-stdout2.txt", + "main\n", +) + +# Check that the list is written to the designated file (foo1.txt) and not on +# the standard output with --dump-units-to=foo1.txt. +run_and_check( + xcov_args + ["-axcov", "--dump-units-to=foo1.txt"], "xcov-foo.txt", "" +) +check_output("foo1.txt", "main\npkg\n") + +# Check that with --dump-units-to=-, the list is included in the "report" +# annotation format... + +REPORT_PATTERN = ( + "(.|\n)*=+" + "\n== 4\\. UNITS OF INTEREST ==" + "\n=+" + "\n" + "\nmain" + "\npkg" + "\n" + "\n\\*\\* END OF REPORT \\*\\*" + "\n(.|\n)*" +) + +# ... on the standard output... +run_and_check( + xcov_args + ["-areport", "--dump-units-to=-"], + "report-stdout.txt", + REPORT_PATTERN, + regexp=True, +) + +# ... or in the designated report file +run_and_check( + xcov_args + ["-areport", "--dump-units-to=-", "--output=report1.txt"], + "report-stdout.txt", + "", +) +check_output("report1.txt", REPORT_PATTERN, regexp=True) + +# Check that even with "-a report", the list is put in the designated file +# (foo2.txt) with --dump-units-to=foo2.txt. Check also that the report does +# *not* contain the list of units of interest. +run_and_check( + xcov_args + + ["-areport", "--dump-units-to=foo2.txt", "--output=report2.txt"], + "report-redirected.txt", + "", +) +check_output( + "report2.txt", + "(.|\n)*=+" + "\n== 3\\. ANALYSIS SUMMARY ==" + "\n=+" + "\n" + "\nNo STMT violation." + "\n" + "\n\\*\\* END OF REPORT \\*\\*" + "\n(.|\n)*", + regexp=True, +) +check_output("foo2.txt", "main\npkg\n") + +# Now check that gnatcov refuses to dump the list of units of interest when +# --scos or --sid is involved. +if thistest.options.trace_mode == "bin": + scos_optname = "--scos" + scos_ext = "ali" +else: + scos_optname = "--sid" + scos_ext = "sid" +scos_arg = "{}=obj/main.{}".format(scos_optname, scos_ext) +run_and_check( + xcov_args + ["-axcov", "--dump-units-to=.", scos_arg], + "xcov-scos.txt", + "We will not be able to dump the list of units of interest: {} is" + " present\n" + ".*gnatcov.*: Cannot dump the list of names for units of interest: see" + " above.".format(scos_optname), + regexp=True, + success_expected=False, +) + +# Check that the list of units of interest is written when just creating a +# checkpoint and --dump-units-to is passed. +run_and_check( + xcov_args + + ["--units=main", "--dump-units-to=-", "--save-checkpoint=c1.ckpt"], + "ckpt-1.txt", + "main\n", +) +run_and_check( + xcov_args + ["--units=pkg", "--save-checkpoint=c2.ckpt"], "ckpt-2.txt", "" +) + +# Now check that it is properly reconstitued during checkpoint consolidation +run_and_check( + [ + "coverage", + "-cstmt", + "-axcov", + "--dump-units-to=-", + "-Cc1.ckpt", + "-Cc2.ckpt", + ], + "ckpt-cons.txt", + "main\npkg\n", +) + +# Finally, check that trying to dump units after loading a checkpoint which +# was created using --scos/--sid is rejected. +run_and_check( + xcov_args + ["--save-checkpoint=c3.ckpt", scos_arg], "ckpt-3.txt", "" +) +run_and_check( + xcov_args_no_trace + ["-axcov", "--dump-units-to=.", "-Cc3.ckpt"], + "ckpt-cons-invalid.txt", + "We will not be able to dump the list of units of interest: c3.ckpt does" + " not contain the list of units \\(produced with --scos or --sid\\)\n" + ".*gnatcov.*: Cannot dump the list of names for units of interest: see" + " above.", + regexp=True, + success_expected=False, +) + +thistest.result() diff --git a/testsuite/tests/T629-012-pragmas/test.py b/testsuite/tests/T629-012-pragmas/test.py new file mode 100644 index 000000000..c18e8ea8d --- /dev/null +++ b/testsuite/tests/T629-012-pragmas/test.py @@ -0,0 +1,28 @@ +""" +Check that GNATcoverage knows about all pragmas listed in GNAT. +""" + +from SUITE.context import thistest +from SUITE.tutils import xcov +from SUITE.cutils import Wdir, lines_of + + +wd = Wdir("tmp_") + +# Get the list of pragmas that gnatcov knows +xcov(["dump-pragmas"], out="gnatcov.txt") +gnatcov_names = {line.strip() for line in lines_of("gnatcov.txt")} + +# Get the list of pragmas that GNAT knows +xcov(["dump-pragmas", "--gnat-pragmas"], out="gnat.txt") +gnat_names = {line.strip() for line in lines_of("gnat.txt")} + +# Check that gnatcov knows about all pragmas from gnat_util +missing_names = "\n".join(sorted(gnat_names - gnatcov_names)) +thistest.fail_if( + missing_names, + "gnatcov does not know about the following pragmas:\n" + missing_names, +) + + +thistest.result() diff --git a/testsuite/tests/T731-036-ckpt-bdd/test.opt b/testsuite/tests/T731-036-ckpt-bdd/test.opt new file mode 100644 index 000000000..c811f2f27 --- /dev/null +++ b/testsuite/tests/T731-036-ckpt-bdd/test.opt @@ -0,0 +1 @@ +arm-elf,src-traces DEAD The test program and its src-cov buffers are too big for this board diff --git a/testsuite/tests/T731-036-ckpt-bdd/test.py b/testsuite/tests/T731-036-ckpt-bdd/test.py new file mode 100644 index 000000000..b59c345e6 --- /dev/null +++ b/testsuite/tests/T731-036-ckpt-bdd/test.py @@ -0,0 +1,150 @@ +""" +Regression testcase for the loading of BDD nodes from checkpoints. + +When loading a checkpoint, gnatcov used to load the whole BDD table once per +loaded CU (whereas the BDD table contains all BDDs for all CUs). For some usage +patterns, this could even trigger a memory exhaustion in gnatcov. This testcase +checks that the BDD table does not grow when we load/save the same checkpoint +over and over. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_file, text_to_file +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Generate sources for the test program. The point of this program is to have +# one unit (DC_Unit) that generates lots of BDD nodes (i.e. lots of decisions), +# several other units (Simple_Unit_*), and a main that uses all these units. + +# First emit a helper for DC_Unit +helper_ads_text = """ +package Helper is + function A return Boolean; + function B return Boolean; + function C return Boolean; +end Helper; +""" +helper_adb_text = """ +package body Helper is + function A return Boolean is + begin + return False; + end A; + function B return Boolean is + begin + return True; + end B; + function C return Boolean is + begin + return False; + end C; +end Helper; +""" +text_to_file(helper_ads_text, "helper.ads") +text_to_file(helper_adb_text, "helper.adb") + +# Emit DC_Unit itself, with 1000 decisions (3 BDD nodes each) +dc_unit_ads_text = """ +package DC_Unit is + procedure Run; +end DC_Unit; +""" +dc_unit_adb_text = [ + "with Helper; use Helper;", + "package body DC_Unit is", + " procedure Run is", + " begin", +] +for _ in range(1000): + dc_unit_adb_text.extend( + [ + " if (A and then B) or C then", + " raise Program_Error;", + " end if;", + ] + ) +dc_unit_adb_text.extend([" end Run;", "end DC_Unit;"]) +text_to_file(dc_unit_ads_text, "dc_unit.ads") +list_to_file(dc_unit_adb_text, "dc_unit.adb") + +# Start the preparation of source excerpts for the Main unit +main_adb_context_clauses = ["with DC_Unit;"] +main_adb_statements = ["DC_Unit.Run;"] + +# Generate sources for the Simple_Unit_* units +simple_unit_ads = """ +package Simple_Unit_{n} is + procedure Run; +end Simple_Unit_{n}; +""" +simple_unit_adb = """ +package body Simple_Unit_{n} is + procedure Run is + begin + null; + end Run; +end Simple_Unit_{n}; +""" +for n in range(1, 11): + text_to_file(simple_unit_ads.format(n=n), "simple_unit_{}.ads".format(n)) + text_to_file(simple_unit_adb.format(n=n), "simple_unit_{}.adb".format(n)) + main_adb_context_clauses.append("with Simple_Unit_{};".format(n)) + main_adb_statements.append("Simple_Unit_{}.Run;".format(n)) + +# Finally, generate the Main unit +main_adb_sources = ( + main_adb_context_clauses + + ["procedure Main is", "begin"] + + main_adb_statements + + ["end Main;"] +) +list_to_file(main_adb_sources, "main.adb") + +# Generate the project file, run the instrumenter, run the program and produce +# a checkpoint. +p = gprfor(mains=["main.adb"], srcdirs=["."]) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint=c0.ckpt"], + extra_gprbuild_args=["-j128"], +) + +# Load the same checkpoint multiple times. This used to create redundant BDDs, +# making the checkpoint grow over time. Checking that each loading/saving cycle +# does not make the checkpoint grow verifies that this bug is gone. +expected_size = None +for n in range(5): + prev_checkpoint = "c{}.ckpt".format(n) + next_checkpoint = "c{}.ckpt".format(n + 1) + ckpt_list = "ckpt_list_{}.txt".format(n) + list_to_file([prev_checkpoint] * 50, ckpt_list) + xcov( + [ + "coverage", + "-cstmt", + "-C@{}".format(ckpt_list), + "--save-checkpoint", + next_checkpoint, + ] + ) + + size = os.path.getsize(next_checkpoint) + if expected_size is None: + expected_size = size + else: + thistest.fail_if_not_equal( + f"Unexpected size for {next_checkpoint}", + expected_size, + size, + ) + +thistest.result() diff --git a/testsuite/tests/T807-011-externally-built-objdir/.gitignore b/testsuite/tests/T807-011-externally-built-objdir/.gitignore new file mode 100644 index 000000000..255b407b1 --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/.gitignore @@ -0,0 +1,2 @@ +opslib/obj-opslib +opslib/lib-opslib diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb new file mode 100644 index 000000000..55ef999ad --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb @@ -0,0 +1,9 @@ + package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end Apply; + end Ops; diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads new file mode 100644 index 000000000..50271fc3d --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads @@ -0,0 +1,4 @@ +package Ops is + type Op_Kind is (Increment, Decrement); + procedure Apply (Op : Op_Kind; X : in out Integer); +end Ops; diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr b/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr new file mode 100644 index 000000000..e2e643a1b --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr @@ -0,0 +1,14 @@ +library project Opslib is + + for Library_Name use "opslib"; + for Library_Kind use "static"; + + for Library_Dir use "lib-" & Project'Library_Name; + for Object_Dir use "obj-" & Project'Library_Name; + + for Source_Dirs use ("."); + + type Boolean is ("false", "true"); + for Externally_Built use external ("OPSLIB_EXTERNALLY_BUILT", "false"); + +end Opslib; diff --git a/testsuite/tests/T807-011-externally-built-objdir/test.py b/testsuite/tests/T807-011-externally-built-objdir/test.py new file mode 100644 index 000000000..67dbbea2f --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/test.py @@ -0,0 +1,70 @@ +""" +Check that "gnatcov instrument" does not remove instrumented sources in the +object directory of externally built projects. +""" + +import os.path + +from e3.fs import ls, rm + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +opslib_gpr = os.path.join("..", "opslib", "opslib.gpr") +tests_gpr = os.path.join("..", "tests.gpr") +tests_obj_dir = os.path.join("..", "obj") +sid_pattern = os.path.join("..", "opslib", "obj-opslib", "*.sid") + +tests_gprsw = GPRswitches( + root_project=tests_gpr, + xvars=[("OPSLIB_EXTERNALLY_BUILT", "true")], + externally_built_projects=True, +) + +# First, instrument and build the opslib library project +xcov_instrument( + gprsw=GPRswitches(root_project=opslib_gpr), covlevel="stmt+decision" +) +gprbuild(opslib_gpr, trace_mode="src", out="gprbuild-opslib.out") + +# Now instrument, build and run the test driver. When run on this test project, +# the instrumenter used to remove the instrumented sources in the opslib +# directory, which is invalid since opslib is externally built during this +# step, and as a result, building the instrumented main (from tests.gpr) failed +# because of the missing buffer units in opslib. +build_run_and_coverage( + gprsw=tests_gprsw, + covlevel="stmt+decision", + mains=["test_inc"], + extra_coverage_args=["-axcov", "--output-dir=report"], + gpr_obj_dir=tests_obj_dir, + gpr_exe_dir=tests_obj_dir, + trace_mode="src", +) + +check_xcov_reports( + "report", + {"ops.ads.xcov": {}, "ops.adb.xcov": {"+": {4, 5}, "-": {6}}}, + discard_empty=False, +) + +# Re-run the instrumenter on the main, to check that it does not re-create a +# SID file for the opslib externall built project. +rm(sid_pattern) +xcov_instrument(gprsw=tests_gprsw, covlevel="stmt+decision") +sids = ls(sid_pattern) +thistest.fail_if( + sids, + '"gnatcov instrument" wrongly re-created SID files: {}'.format( + sorted(sids) + ), +) + +thistest.result() diff --git a/testsuite/tests/T807-011-externally-built-objdir/tests.gpr b/testsuite/tests/T807-011-externally-built-objdir/tests.gpr new file mode 100644 index 000000000..93222dd5c --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/tests.gpr @@ -0,0 +1,12 @@ +with "opslib/opslib.gpr"; + +project Tests is + for Source_Dirs use ("tests"); + for Object_Dir use "obj"; + + for Main use ("test_inc.adb"); + + package Coverage is + for Units use (); + end Coverage; +end Tests; diff --git a/testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb b/testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb new file mode 100644 index 000000000..2213c45c9 --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb @@ -0,0 +1,7 @@ +with Ops; +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end Test_Inc; diff --git a/testsuite/tests/T825-010-naming-scheme/main.adb b/testsuite/tests/T825-010-naming-scheme/main.adb new file mode 100644 index 000000000..5a9eb3e67 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/main.adb @@ -0,0 +1,6 @@ +with Pkg.Child; + +procedure Main is +begin + Pkg.Child.Proc (1); +end Main; diff --git a/testsuite/tests/T825-010-naming-scheme/pkg.1.ada b/testsuite/tests/T825-010-naming-scheme/pkg.1.ada new file mode 100644 index 000000000..4b917c5d4 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/pkg.1.ada @@ -0,0 +1,4 @@ +package Pkg is + type Int is new Integer; + function Identity (Value : Int) return Int; +end Pkg; diff --git a/testsuite/tests/T825-010-naming-scheme/pkg.2.ada b/testsuite/tests/T825-010-naming-scheme/pkg.2.ada new file mode 100644 index 000000000..a9963c839 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/pkg.2.ada @@ -0,0 +1,6 @@ +package body Pkg is + function Identity (Value : Int) return Int is + begin + return Value; + end Identity; +end Pkg; diff --git a/testsuite/tests/T825-010-naming-scheme/pkg__child.1.ada b/testsuite/tests/T825-010-naming-scheme/pkg__child.1.ada new file mode 100644 index 000000000..93791744a --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/pkg__child.1.ada @@ -0,0 +1,4 @@ +package Pkg.Child is + procedure Proc (I : Int); + V : constant Int := Identity (2); +end Pkg.Child; diff --git a/testsuite/tests/T825-010-naming-scheme/pkg__child.2.ada b/testsuite/tests/T825-010-naming-scheme/pkg__child.2.ada new file mode 100644 index 000000000..9cac4e4cf --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/pkg__child.2.ada @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg.Child is + procedure Proc (I : Int) is + begin + Put_Line (Int'Image (I)); + end Proc; +end Pkg.Child; diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py new file mode 100644 index 000000000..96ff3a2ed --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -0,0 +1,70 @@ +""" +Check that gnatcov works fine on projects using non-standard naming schemes. +""" + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +spec_suffix = ".1.ada" +body_suffix = ".2.ada" + +for casing, converter in [ + ("lowercase", str.lower), + ("uppercase", str.upper), + ("mixedcase", str), +]: + tmp = Wdir(f"tmp_{casing}") + + pkg_spec = converter("Pkg") + spec_suffix + pkg_body = converter("Pkg") + body_suffix + child_spec = converter("Pkg__Child") + spec_suffix + child_body = converter("Pkg__Child") + body_suffix + + cp("../main.adb", "main.adb") + cp("../pkg.1.ada", pkg_spec) + cp("../pkg.2.ada", pkg_body) + cp("../pkg__child.1.ada", child_spec) + cp("../pkg__child.2.ada", child_body) + + p = gprfor( + mains=["main.adb"], + prjid="p", + srcdirs=["."], + extra=f""" + package Naming is + for Spec_Suffix ("Ada") use "{spec_suffix}"; + for Body_Suffix ("Ada") use "{body_suffix}"; + for Dot_Replacement use "__"; + for Body ("main") use "main.adb"; + for Casing use "{casing}"; + end Naming; + """, + ) + build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=report"], + ) + + check_xcov_reports( + "report", + { + "main.adb.xcov": {"+": {5}}, + f"{pkg_spec}.xcov": {}, + f"{pkg_body}.xcov": {"+": {4}}, + f"{child_spec}.xcov": {"+": {3}}, + f"{child_body}.xcov": {"+": {6}}, + }, + discard_empty=False, + ) + + tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/T828-018-tagged-aggr/src/pkg.adb b/testsuite/tests/T828-018-tagged-aggr/src/pkg.adb new file mode 100644 index 000000000..5adf673a6 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/pkg.adb @@ -0,0 +1,11 @@ +package body Pkg is + function Create (I : Integer) return T is + begin + return (I => I); -- # create + end Create; + + procedure Foo is + begin + null; -- # foo + end Foo; +end Pkg; diff --git a/testsuite/tests/T828-018-tagged-aggr/src/pkg.ads b/testsuite/tests/T828-018-tagged-aggr/src/pkg.ads new file mode 100644 index 000000000..575125068 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + type T is tagged record + I : Integer; + end record; + + function Create (I : Integer) return T; + procedure Foo; -- # foo +end Pkg; diff --git a/testsuite/tests/T828-018-tagged-aggr/src/test_full.adb b/testsuite/tests/T828-018-tagged-aggr/src/test_full.adb new file mode 100644 index 000000000..c781e8fa0 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/test_full.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Full is + V : constant Pkg.T := Pkg.Create (1); +begin + Pkg.Foo; +end Test_Full; + +--# pkg.ads +-- /foo/ l. ## 0 +-- +--# pkg.adb +-- /create/ l+ ## 0 +-- /foo/ l+ ## 0 diff --git a/testsuite/tests/T828-018-tagged-aggr/src/test_no.adb b/testsuite/tests/T828-018-tagged-aggr/src/test_no.adb new file mode 100644 index 000000000..1b504c0a0 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/test_no.adb @@ -0,0 +1,13 @@ +with Pkg; + +procedure Test_No is +begin + Pkg.Foo; +end Test_No; + +--# pkg.ads +-- /foo/ l. ## 0 +-- +--# pkg.adb +-- /create/ l- ## s- +-- /foo/ l+ ## 0 diff --git a/testsuite/tests/T828-018-tagged-aggr/test.py b/testsuite/tests/T828-018-tagged-aggr/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/T916-046-bdd-remapping/main.adb b/testsuite/tests/T916-046-bdd-remapping/main.adb new file mode 100644 index 000000000..1f627c209 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is + Dummy : Integer := + Pkg.Compute (True, False) + Pkg.Compute_In_Stub (False, True); +begin + null; +end Main; diff --git a/testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb b/testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb new file mode 100644 index 000000000..4179c26d6 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb @@ -0,0 +1,9 @@ +separate (Pkg) +function Compute_In_Stub (A, B : Boolean) return Integer is +begin + if A and then B then + return 2; + else + return 3; + end if; +end Compute_In_Stub; diff --git a/testsuite/tests/T916-046-bdd-remapping/pkg.adb b/testsuite/tests/T916-046-bdd-remapping/pkg.adb new file mode 100644 index 000000000..96543fe86 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + function Compute (A, B : Boolean) return Integer is + begin + if A and then B then + return 2; + else + return 3; + end if; + end Compute; + + function Compute_In_Stub (A, B : Boolean) return Integer is separate; +end Pkg; diff --git a/testsuite/tests/T916-046-bdd-remapping/pkg.ads b/testsuite/tests/T916-046-bdd-remapping/pkg.ads new file mode 100644 index 000000000..00946638c --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function Compute (A, B : Boolean) return Integer; + function Compute_In_Stub (A, B : Boolean) return Integer; +end Pkg; diff --git a/testsuite/tests/T916-046-bdd-remapping/test.py b/testsuite/tests/T916-046-bdd-remapping/test.py new file mode 100644 index 000000000..9f98f208a --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/test.py @@ -0,0 +1,26 @@ +""" +Check that "gnatcov coverage" is able to process BDD data for the decisions to +cover. This used to crash in source trace mode when a single compilation unit +(in the GCC sense: the unit for pkg.ads, pkg.adb and pkg-compute_in_stub.adb) +contains multiple "CU" (pkg.ads, pkg.adb and pkg-compute_in_stub.adb are 3 CUs +for gnatcov), with multiple CUs containing decisions. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +p = gprfor(srcdirs=[".."], mains=["main.adb"]) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--save-checkpoint=partial.ckpt"], +) + +thistest.result() diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/foo.c b/testsuite/tests/TA12-013-dump-ignore-src-files/foo.c new file mode 100644 index 000000000..cba07c41a --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/foo.c @@ -0,0 +1,7 @@ +#include "identity.h" + +int +foo (int i) +{ + return identity (2 * i); +} diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/identity.h b/testsuite/tests/TA12-013-dump-ignore-src-files/identity.h new file mode 100644 index 000000000..a9a41fc1c --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/identity.h @@ -0,0 +1,5 @@ +static int +identity (int i) +{ + return i; +} diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/main.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/main.adb new file mode 100644 index 000000000..0ce6b0c64 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/main.adb @@ -0,0 +1,14 @@ +with Pkg; +with Pkh; + +procedure Main is + function C_Foo (I : Integer) return Integer; + pragma Import (C, C_Foo, "foo"); + + Dummy : Integer := C_Foo (1); +begin + Pkg.Say_Hello; + Pkg.Test; + Pkh.Say_Hello; + Pkh.Test; +end Main; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb new file mode 100644 index 000000000..8dfff4a05 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (pkg.test) procedure Sep is +begin + Put_Line("This double separate is super useless!"); +end Sep; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb new file mode 100644 index 000000000..0da377c2c --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (pkg) procedure Test is + procedure Sep; + procedure Sep is separate; +begin + Put_Line ("This test procedure is useless!"); + Sep; +end Test; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb new file mode 100644 index 000000000..d1e7159b5 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Say_Hello is + begin + Put_Line ("Hello, world!"); + end Say_Hello; + procedure Test is separate; +end Pkg; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads new file mode 100644 index 000000000..ab3cad927 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Say_Hello; + procedure Test; +end Pkg; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb new file mode 100644 index 000000000..d4cb21592 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (pkh) procedure Test is +begin + Put_Line ("This test procedure is useless!"); +end Test; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb new file mode 100644 index 000000000..9445b60f7 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkh is + procedure Say_Hello is + begin + Put_Line ("Hello, world!"); + end Say_Hello; + procedure Test is separate; +end Pkh; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads new file mode 100644 index 000000000..1674205ed --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads @@ -0,0 +1,4 @@ +package Pkh is + procedure Say_Hello; + procedure Test; +end Pkh; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/test.py b/testsuite/tests/TA12-013-dump-ignore-src-files/test.py new file mode 100644 index 000000000..7a758661c --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/test.py @@ -0,0 +1,259 @@ +""" +Check that --dump-units-to shows the individually ignored source files. +This extends test T611-027-dump-units-to. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Generate a project, instrument it and run it +p = gprfor(mains=["main.adb"], srcdirs=[".."], langs=["Ada", "C"]) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) +xcov_args_no_trace = xcov_args[:-1] +trace_file = xcov_args[-1] + + +def check_output(output_file, expected_content, regexp=False): + """ + Check that the content of the "output_file" text file matches + "expected_content". Check for equality if "regexp" is False and consider + that "expected_content" is a regexp otherwise. + + :param str output_file: Name of the text file whose content needs to be + checked. + :param str expected_content: Expected content for this file. + :param bool regexp: Whether to match as a regexp (by default, check + content equality). + """ + checker = ( + thistest.fail_if_no_match if regexp else thistest.fail_if_not_equal + ) + checker( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace("\r\n", "\n"), + ) + + +def run_and_check( + args, output_file, expected_content, regexp=False, success_expected=True +): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_content: See the corresponding argument in "check". + :param bool regexp: See the corresponding argument in "check". + :param bool success_expected: If true, the test fails if gnatcov exits with + an error code. If false, the test fails if gnatcov exits with the zero + status code. + """ + p = xcov(args, out=output_file, register_failure=success_expected) + if not success_expected: + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + " succeeded (see {})".format(output_file), + ) + check_output(output_file, expected_content, regexp) + + +# Check that nothing is dumped without --dump-units-to +run_and_check(xcov_args + ["-axcov"], "xcov-nodump.txt", "") + +# Check that when *not* using the "--ignored-source-files" option, the list of +# units is still printed. +run_and_check( + xcov_args + + ["-axcov", "--dump-units-to=-", "--save-checkpoint=all_files.ckpt"], + "xcov-stdout1.txt", + expected_content=("foo.c\n" "identity.h\n" "main\n" "pkg\n" "pkh\n"), +) +run_and_check( + xcov_args + ["-axcov", "--units=main", "--dump-units-to=-"], + "xcov-stdout2.txt", + expected_content="main\n", +) + +# Check that dumping the list of units with ignored source files works on the +# "report" output. +REPORT_PATTERN = ( + "(.|\n)*=+" + "\n== 4\\. UNITS OF INTEREST ==" + "\n=+" + "\n" + "\nfoo.c" + "\nidentity.h" + "\n identity.h always ignored" + "\nmain" + "\npkg" + "\n pkg-test.adb always ignored" + "\npkh" + "\n pkh-test.adb always ignored" + "\n" + "\n\\*\\* END OF REPORT \\*\\*" + "\n(.|\n)*" +) +run_and_check( + xcov_args + + [ + "-areport", + "--dump-units-to=-", + "--ignore-source-files=*-test.adb", + "--ignore-source-files=identity.h", + ], + "report-stdout.txt", + REPORT_PATTERN, + regexp=True, +) + +# Check that the units of separates of level deeper than one is listed under +# the correct unit. +run_and_check( + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--ignore-source-files=pkg-test-sep.adb", + ], + "xcov-stdout3.txt", + expected_content=( + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + " pkg-test-sep.adb always ignored\n" + "pkh\n" + ), +) + +# Check that a file ignored but that isn't part of a unit of interest +# is not listed. +run_and_check( + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--units=pkg", + "--ignore-source-files=*-test.adb", + "--ignore-source-files=identity.h", + "--save-checkpoint=pkg.ckpt", + ], + "xcov-stdout4.txt", + expected_content=("pkg\n" " pkg-test.adb always ignored\n"), +) + +# Check that a file ignored that is part of a unit of interest is listed +run_and_check( + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--units=pkh", + "--ignore-source-files=pkh-test.adb", + "--save-checkpoint=pkh.ckpt", + ], + "xcov-stdout5.txt", + expected_content=("pkh\n" " pkh-test.adb always ignored\n"), +) + +# Check that loading results from a checkpoint shows files that were ignored +# when creating the checkpoint. +run_and_check( + xcov_args_no_trace + ["-axcov", "--dump-units-to=-", "-Cpkh.ckpt"], + "xcov-stdout6.txt", + expected_content=( + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + "pkh\n" + " pkh-test.adb always ignored\n" + ), +) + +run_and_check( + xcov_args_no_trace + + ["-axcov", "--dump-units-to=-", "-Cpkg.ckpt", "-Cpkh.ckpt"], + "xcov-stdout7.txt", + expected_content=( + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + " pkg-test.adb always ignored\n" + "pkh\n" + " pkh-test.adb always ignored\n" + ), +) + +# Check that combining results from runs were a file was ignored in some +# of them but not all displays the files as 'sometimes ignored'. +run_and_check( + xcov_args_no_trace + + [ + "-axcov", + "--dump-units-to=-", + "-Cpkg.ckpt", + "-Call_files.ckpt", + ], + "xcov-stdout8.txt", + expected_content=( + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + " pkg-test.adb sometimes ignored\n" + "pkh\n" + ), +) + +# Check that --ignore-source-files filters trace analysis but not checkpoints, +# and that if a file is ignored when analyzing a trace but is present in a +# checkpoint, then it is marked as 'sometimes ignored'. +run_and_check( + xcov_args + + [ + "-axcov", + "--ignore-source-files=pkh-test.adb", + "--save-checkpoint=pkh_not_pkg.ckpt", + ], + "xcov-sdtout9.txt", + "", +) +run_and_check( + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--ignore-source-files=*test.adb", + "--ignore-source-files=identity.h", + "-Cpkh_not_pkg.ckpt", + ], + "xcov-stdout9.txt", + expected_content=( + "foo.c\n" + "identity.h\n" + " identity.h sometimes ignored\n" + "main\n" + "pkg\n" + " pkg-test.adb sometimes ignored\n" + "pkh\n" + " pkh-test.adb always ignored\n" + ), +) + +thistest.result() diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb b/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb new file mode 100644 index 000000000..801b5e835 --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb @@ -0,0 +1,10 @@ +with Pkg; use Pkg; +procedure Main is +begin + Mystery (False, True, True); + Mystery (False, False, False); + Mystery (True, True, True); + Mystery (True, True, False); + Other_Proc (True, True); + Other_Proc (False, True); +end Main; diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb new file mode 100644 index 000000000..4febbe7fe --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb @@ -0,0 +1,26 @@ +with Ada.Text_IO; use Ada.Text_IO; +package body Pkg is + + procedure Mystery (A, B, C : Boolean) is + begin + if (A and then B and then C) or else A then + Put_Line ("Great success!"); + else + Put_Line ("Failed"); + end if; + if A then + Put_Line ("A is True"); + else + Put_Line ("A is False"); + end if; + end Mystery; + + procedure Other_Proc (A, B : Boolean) is + begin + if A and then B then + Put_Line ("Stuff"); + else + Put_Line ("not Stuff"); + end if; + end Other_Proc; +end Pkg; diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads new file mode 100644 index 000000000..c5528490a --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads @@ -0,0 +1,6 @@ +package Pkg is + + procedure Mystery (A, B, C : Boolean); + + procedure Other_Proc (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/test.py b/testsuite/tests/TA14-011-show-mcdc-vectors/test.py new file mode 100644 index 000000000..948a72571 --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/test.py @@ -0,0 +1,180 @@ +""" +Check that --show-mcdc-vectors works as expected. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Generate a project, instrument it if necessary and run it, +p = gprfor(mains=["main.adb"], srcdirs=[".."]) +xcov_args_mcdc = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=[], +) + + +def check_output(output_file, expected_content, regexp=False): + """ + Check that the content of the "output_file" text file matches + "expected_content". Check for equality if "regexp" is False and consider + that "expected_content" is a regexp otherwise. + + :param str output_file: Name of the text file whose content needs to be + checked. + :param str expected_content: Expected content for this file. + :param bool regexp: Whether to match as a regexp (by default, check + content equality). + """ + checker = ( + thistest.fail_if_no_match if regexp else thistest.fail_if_not_equal + ) + checker( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace("\r\n", "\n"), + ) + + +def run_and_check( + args, output_file, expected_content, regexp=False, success_expected=True +): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_content: See the corresponding argument in "check". + :param bool regexp: See the corresponding argument in "check". + :param bool success_expected: If true, the test fails if gnatcov exits with + an error code. If false, the test fails if gnatcov exits with the zero + status code. + """ + p = xcov(args, out=output_file, register_failure=success_expected) + if not success_expected: + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + " succeeded (see {})".format(output_file), + ) + check_output(output_file, expected_content, regexp) + + +# Check that no vector information is dumped without the option +# --show-mcdc-vectors + +REPORT_PATTERN_NO_VECTORS = ( + "(.|\n)*" + "\n" + r"\n2\.3\. MCDC COVERAGE" + "\n-+" + "\n" + r"\npkg\.adb:6:22: condition has no independent influence pair" + ", MC/DC not achieved" + r"\npkg\.adb:6:33: condition has no independent influence pair" + ", MC/DC not achieved" + r"\npkg\.adb:20:21: condition has no independent influence pair" + ", MC/DC not achieved" + "\n" + r"\n3 violations\." +) + +run_and_check( + xcov_args_mcdc + ["-areport"], + "report-stdout.txt", + REPORT_PATTERN_NO_VECTORS, + regexp=True, +) + +# Check that mcdc vectors are displayed under the corresponding +# condition violations, and show the conditions indexes in violation messages. + +REPORT_PATTERN_MCDC = ( + "(.|\n)*" + "\n" + r"\n2\.3\. MCDC COVERAGE" + "\n-+" + "\n" + r'\npkg\.adb:6:22: condition 1 \("B"\) has no independent influence pair' + ", MC/DC not achieved" + r'\npkg\.adb:6:33: condition 2 \("C"\) has no independent influence pair' + ", MC/DC not achieved" + r"\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)" + r" and then C2\) or else C3\)" + "\nEvaluation vectors found:" + "\n F - - F -> FALSE In a pair for C0, C3" + "\n T T F T -> TRUE In a pair for C3" + "\n T T T - -> TRUE In a pair for C0" + "\n" + r'\npkg\.adb:20:21: condition 1 \("B"\) has no independent influence pair' + ", MC/DC not achieved" + r"\npkg.adb:20:10: Decision of the form \(C0 and then C1\)" + "\nEvaluation vectors found:" + "\n F - -> FALSE In a pair for C0" + "\n T T -> TRUE In a pair for C0" + "\n" + "\n" + r"\n3 violations\." +) + +run_and_check( + xcov_args_mcdc + ["-areport", "--show-mcdc-vectors"], + "report-stdout.txt", + REPORT_PATTERN_MCDC, + regexp=True, +) + + +# Check that evaluation vectors not part of any pair are displayed +# below the other vectors. + +# No need to re-run since we only change the coverage from "stmt+mcdc" to +# "stmt+uc_mcdc". +xcov_args_uc_mcdc = xcov_args_mcdc + ["--level=stmt+uc_mcdc"] + +REPORT_PATTERN_UC_MCDC = ( + "(.|\n)*" + "\n" + r"\n2\.3\. UC_MCDC COVERAGE" + "\n-+" + "\n" + r'\npkg\.adb:6:22: condition 1 \("B"\) has no independent influence pair' + ", MC/DC not achieved" + r'\npkg\.adb:6:33: condition 2 \("C"\) has no independent influence pair' + ", MC/DC not achieved" + r'\npkg\.adb:6:44: condition 3 \("A"\) has no independent influence pair' + ", MC/DC not achieved" + r"\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)" + r" and then C2\) or else C3\)" + "\nEvaluation vectors found:" + "\n F - - F -> FALSE In a pair for C0" + "\n T T T - -> TRUE In a pair for C0" + "\n T T F T -> TRUE Not part of any pair" + "\n" + r'\npkg\.adb:20:21: condition 1 \("B"\) has no independent influence pair' + ", MC/DC not achieved" + r"\npkg.adb:20:10: Decision of the form \(C0 and then C1\)" + "\nEvaluation vectors found:" + "\n F - -> FALSE In a pair for C0" + "\n T T -> TRUE In a pair for C0" + "\n" + "\n" + r"\n4 violations\." +) + +run_and_check( + xcov_args_uc_mcdc + ["-areport", "--show-mcdc-vectors"], + "report-stdout.txt", + REPORT_PATTERN_UC_MCDC, + regexp=True, +) + +thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb new file mode 100644 index 000000000..ea86ea180 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Test; +end Main; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb new file mode 100644 index 000000000..2d801bc89 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) +procedure Test is +begin + Put_Line ("Test 1"); +end Test; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb new file mode 100644 index 000000000..10e85a255 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Do_Things; +end Main; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb new file mode 100644 index 000000000..60cc4a6e8 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb @@ -0,0 +1,10 @@ +-- Tests override this unit to implement testcases + +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) +procedure Test is +begin + Put_Line ("!!! Test stub called in production setup"); + raise Program_Error; +end Test; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb new file mode 100644 index 000000000..8802e8cc3 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb @@ -0,0 +1,4 @@ +package body Pkg is + procedure Do_Things is null; + procedure Test is separate; +end Pkg; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads new file mode 100644 index 000000000..4b9eed974 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Do_Things; + procedure Test; +end Pkg; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test.py b/testsuite/tests/TA15-063-ignore-fingerprint/test.py new file mode 100644 index 000000000..df0e65d92 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test.py @@ -0,0 +1,86 @@ +""" +Check that the consolidation of two checkpoints produced with different +--ignore-source-files options on the same set of sources works as expected. A +warning used to be emitted in that case, because of a low level SCO tables +fingerprint mismatch. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def check_empty(filename): + content = contents_of(filename) + thistest.fail_if( + content, + f'Output of "gnatcov coverage" not empty ({filename}):\n\n{content}', + ) + + +tmp = Wdir("tmp_") + +p = gprfor(prjid="p", srcdirs=["../src"], mains=["main.adb"]) +test1 = os.path.abspath("test1.gpr") +cp("../test1.gpr", test1) + +# Build and run p.gpr's main.adb, then compute a partial coverage report +# (c1.ckpt), ignoring no source file. +build_run_and_coverage( + gprsw=GPRswitches(root_project=p, projects=["p"]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint=c1.ckpt"], + out="log-cov1.txt", +) +check_empty("log-cov1.txt") + +# Build and run test1.gpr's main.adb, then compute a partial coverage report +# (c2.ckpt) on p.gpr's source files, however, ignore pkg-test.adb this time. +build_run_and_coverage( + gprsw=GPRswitches(root_project=test1, projects=["p"], units=["pkg"]), + covlevel="stmt", + gpr_obj_dir="obj-test1", + gpr_exe_dir="obj-test1", + mains=["main"], + ignored_source_files=["pkg-test.adb"], + extra_coverage_args=["--save-checkpoint=c2.ckpt"], + out="log-cov2.txt", +) +check_empty("log-cov2.txt") + +# Consolidate both partial reports and produce an XCOV report +xcov( + [ + "coverage", + "-P", + p, + "--projects", + "p", + "-cstmt", + "-axcov", + "--output-dir=report", + "--quiet", + "-Cc1.ckpt", + "-Cc2.ckpt", + ], + out="log-cons.txt", +) +check_empty("log-cons.txt") +check_xcov_reports( + "report", + { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {2}}, + "pkg-test.adb.xcov": {"-": {8, 9}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr b/testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr new file mode 100644 index 000000000..436bcd7fb --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr @@ -0,0 +1,4 @@ +project Test1 extends "p.gpr" is + for Source_Dirs use ("../src-test1"); + for Object_Dir use "obj-test1"; +end Test1; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb new file mode 100644 index 000000000..08d358367 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Say_Hello; + Pkg.Say_Goodbye; +end Main; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb new file mode 100644 index 000000000..d3c34f2a1 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) +procedure Say_Goodbye is +begin + if True then + Put_Line ("Goodbye!"); + else + Put_Line ("But not really!"); + end if; +end Say_Goodbye; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb new file mode 100644 index 000000000..7934788a7 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Say_Hello is + begin + if False then + Put_Line ("Hello, world!"); + else + Put_Line ("Not Hello World!"); + end if; + end Say_Hello; + procedure Say_Goodbye is separate; +end Pkg; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads new file mode 100644 index 000000000..b59060210 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Say_Hello; + procedure Say_Goodbye; +end Pkg; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py new file mode 100644 index 000000000..64675a87f --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py @@ -0,0 +1,111 @@ +""" +Check that, in source instrumentation mode, --ignore-source-files can be used +when loading SID files, and that it does not interfere with the loading of +checkpoints otherwise. +""" + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches +import os + + +tmp = Wdir("tmp_") + +# Generate a project, instrument it and run it +p = gprfor(mains=["main.adb"], srcdirs=[".."]) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + trace_mode="src", + extra_coverage_args=[], +) +xcov_args_no_trace = xcov_args[:-1] +trace_file = xcov_args[-1] + +expected_res_dict = { + "pkg.adb.xcov": {"-": {7}}, + "pkg-say_goodbye.adb.xcov": {"-": {9}}, + "pkg.ads.xcov": {}, +} + + +def check(report_name, args, expected_files): + """ + Run gnatcov coverage with the given set of arguments in xcov mode, + and store the results in directory 'report_name'. Check that a report is + generated exactly for the files listed in 'expected_files', given the + fact that the results for a file should be the same accross all runs + and than coverage results match corresponding ones in expected_res_dict. + """ + thistest.log(f"== {report_name} ==") + + # Create report dir to avoid warning message + os.mkdir(report_name) + checked_xcov( + args + ["-axcov", "--output-dir=" + report_name], + f"{report_name}_out.txt", + ) + expected = { + filename: expected_res_dict[filename] for filename in expected_files + } + expected["main.adb.xcov"] = {"+": {5, 6}} + check_xcov_reports(report_name, expected, discard_empty=False) + + +# Check that not passing the option has no effect +check( + "report0", + xcov_args + ["--save-checkpoint=full.ckpt"], + ["pkg.adb.xcov", "pkg-say_goodbye.adb.xcov", "pkg.ads.xcov"], +) + +# Check that --ignore-source-files has the expected effect on the 'coverage' +# command. +check( + "report1", + xcov_args + ["--ignore-source-files=pkg-say_goodbye.adb"], + ["pkg.adb.xcov", "pkg.ads.xcov"], +) + +# Check that --ignore-source-files does not filter checkpoint loading +check( + "report2", + xcov_args_no_trace + + ["--ignore-source-files=pkg-say_goodbye.adb", "-Cfull.ckpt"], + ["pkg.adb.xcov", "pkg-say_goodbye.adb.xcov", "pkg.ads.xcov"], +) + +# Check that in presence of bot a checkpoint and a SID file, +# --ignore-source-files filters the SID file but not the checkpoint. +checked_xcov( + xcov_args + + [ + "--ignore-source-files=pkg-say_goodbye.adb", + "--save-checkpoint=pkg.ckpt", + ], + "report3_out.txt", +) +check( + "report3", + xcov_args + ["--ignore-source-files=pkg*.adb", "-Cpkg.ckpt"], + ["pkg.adb.xcov", "pkg.ads.xcov"], +) + +# Check that if a file is ignored when creating the checkpoint, then it is not +# present when loading that checkpoint. +checked_xcov( + xcov_args + + ["--save-checkpoint=pkg_goodbye.ckpt", "--ignore-source-files=pkg.adb"], + "report4_out.txt", +) +check( + "report4", + xcov_args_no_trace + ["-Cpkg_goodbye.ckpt"], + ["pkg-say_goodbye.adb.xcov", "pkg.ads.xcov"], +) + +thistest.result() diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/main.adb b/testsuite/tests/TB13-020-expr-func-mcdc/main.adb new file mode 100644 index 000000000..597273750 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/main.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; + +with Pkg; + +procedure Main is + Dummy : Integer := (if Pkg.Flag then 1 else 2); + pragma Volatile (Dummy); + + function Is_Null (Self : Pkg.Point) return Boolean is + (Pkg.Is_Null (Self.X) and then Pkg.Is_Null (Self.Y)); + + P1 : constant Pkg.Point := (0, 0); + P2 : constant Pkg.Point := (0, 1); +begin + + if not Is_Null (P1) then + raise Program_Error; + end if; + + if Is_Null (P2) then + raise Program_Error; + end if; + +end Main; diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb new file mode 100644 index 000000000..fee4b7187 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + ------------- + -- Is_Null -- + ------------- + + function Is_Null (I : Integer) return Boolean is + begin + return I = 0; + end Is_Null; + +end Pkg; diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads new file mode 100644 index 000000000..71e6109e4 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + Flag : Boolean := True; + type Point is record + X, Y : Integer; + end record; + + function Is_Null (I : Integer) return Boolean; +end Pkg; diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.opt b/testsuite/tests/TB13-020-expr-func-mcdc/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py new file mode 100644 index 000000000..bcba8e97a --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -0,0 +1,36 @@ +""" +Regression testcase for the instrumentation of expression functions that +trigger MC/DC obligations. + +(No reason not to also run it with binary traces.) +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +p = gprfor(prjid="p", srcdirs=[".."], mains=["main.adb"]) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=report"], +) + +check_xcov_reports( + "report", + { + "main.adb.xcov": {"!": {6, 10, 16, 20}, "+": {12, 13}, "-": {17, 21}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {9}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb new file mode 100644 index 000000000..993018799 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb @@ -0,0 +1,12 @@ +package body P1 is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end P1; diff --git a/testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads new file mode 100644 index 000000000..cd9d6a897 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads @@ -0,0 +1,5 @@ +package P1 is + + function Next (I : Integer) return Integer; + +end P1; diff --git a/testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb b/testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb new file mode 100644 index 000000000..23b6dcf98 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb @@ -0,0 +1,7 @@ +with P1; + +procedure P2 is + Dummy : constant Integer := P1.Next (1); +begin + null; +end P2; diff --git a/testsuite/tests/TB24-022-missing-sid/test.py b/testsuite/tests/TB24-022-missing-sid/test.py new file mode 100644 index 000000000..74c123fd8 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/test.py @@ -0,0 +1,45 @@ +""" +Check that gnatcov correctly detects missing SID. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +gprfor(prjid="p1", srcdirs=["../src-p1"], mains=None, langs="Ada") + +p2 = gprfor( + prjid="p2", + srcdirs=["../src-p2"], + mains=["p2.adb"], + deps=["p1"], + extra='for Origin_Project use "p1";', +) + +# Build the projects and produce a trace for the main +build_run_and_coverage( + gprsw=GPRswitches(root_project=p2), + covlevel="stmt", + mains=["p2"], + extra_coverage_args=[ + "-a", + "xcov", + "--no-subprojects", + "--projects=p2", + "-v", + ], + trace_mode="src", + tolerate_coverage_messages="no SID file found for unit p2", +) + +thistest.fail_if( + "warning: no SID file found for unit p2" + not in contents_of("coverage.log"), + "No warning for missing SID file (for p2)", +) + +thistest.result() diff --git a/testsuite/tests/TC03-012-objcov-line-state/fact.c b/testsuite/tests/TC03-012-objcov-line-state/fact.c new file mode 100644 index 000000000..c1df045dd --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/fact.c @@ -0,0 +1,10 @@ +int +fact (int n) +{ + if (n == 0) + return 1; + else if (n < 2) + return 1; + else + return n * fact (n - 1); +} diff --git a/testsuite/tests/TC03-012-objcov-line-state/fact.s b/testsuite/tests/TC03-012-objcov-line-state/fact.s new file mode 100644 index 000000000..c44665a57 --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/fact.s @@ -0,0 +1,206 @@ + .arch armv8-a+crc + .file "fact.c" + .text +.Ltext0: + .cfi_sections .debug_frame + .align 2 + .global fact + .type fact, %function +fact: +.LFB0: + .file 1 "fact.c" + .loc 1 3 1 + .cfi_startproc + stp x29, x30, [sp, -32]! + .cfi_def_cfa_offset 32 + .cfi_offset 29, -32 + .cfi_offset 30, -24 + mov x29, sp + str w0, [sp, 28] + .loc 1 4 9 + ldr w0, [sp, 28] + cmp w0, 0 + bne .L2 +# The following instruction (mov w0, 1) was manually inserted so that we have +# an instruction that is assigned the same sloc as the conditional branch above +# (bne, line 4), but that will not be executed even though the branch is +# executed. Because of this, the coverage report is expected to report line 4 +# as partially covered (it used to wrongly report it as fully covered). + mov w0, 1 + .loc 1 5 12 + mov w0, 1 + b .L3 +.L2: + .loc 1 6 14 + ldr w0, [sp, 28] + cmp w0, 1 + bgt .L4 + .loc 1 7 12 + mov w0, 1 + b .L3 +.L4: + .loc 1 9 16 + ldr w0, [sp, 28] + sub w0, w0, #1 + bl fact + mov w1, w0 + .loc 1 9 14 discriminator 1 + ldr w0, [sp, 28] + mul w0, w1, w0 +.L3: + .loc 1 10 1 + nop + ldp x29, x30, [sp], 32 + .cfi_restore 30 + .cfi_restore 29 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc +.LFE0: + .size fact, .-fact +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .4byte 0x62 + .2byte 0x5 + .byte 0x1 + .byte 0x8 + .4byte .Ldebug_abbrev0 + .uleb128 0x1 + .4byte .LASF2 + .byte 0x1d + .4byte .LASF0 + .4byte .LASF1 + .8byte .Ltext0 + .8byte .Letext0-.Ltext0 + .4byte .Ldebug_line0 + .uleb128 0x2 + .4byte .LASF3 + .byte 0x1 + .byte 0x2 + .byte 0x1 + .4byte 0x5e + .8byte .LFB0 + .8byte .LFE0-.LFB0 + .uleb128 0x1 + .byte 0x9c + .4byte 0x5e + .uleb128 0x3 + .string "n" + .byte 0x1 + .byte 0x2 + .byte 0xb + .4byte 0x5e + .uleb128 0x2 + .byte 0x91 + .sleb128 -4 + .byte 0 + .uleb128 0x4 + .byte 0x4 + .byte 0x5 + .string "int" + .byte 0 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x1f + .uleb128 0x1b + .uleb128 0x1f + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x10 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x7c + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .4byte 0x2c + .2byte 0x2 + .4byte .Ldebug_info0 + .byte 0x8 + .byte 0 + .2byte 0 + .2byte 0 + .8byte .Ltext0 + .8byte .Letext0-.Ltext0 + .8byte 0 + .8byte 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF3: + .string "fact" +.LASF2: + .string "GNU C17 14.3.1 20250720 (for GNAT Pro 26.0w 20250720) -mcpu=cortex-a53 -mlittle-endian -mabi=lp64 -g -fno-tree-loop-distribute-patterns -fpreserve-control-flow -fpreserve-decisions-generic" + .section .debug_line_str,"MS",@progbits,1 +.LASF0: + .string "fact.c" +.LASF1: + .string ".." + .ident "GCC: (GNU) 14.3.1 20250720 (for GNAT Pro 26.0w 20250720)" diff --git a/testsuite/tests/TC03-012-objcov-line-state/main.c b/testsuite/tests/TC03-012-objcov-line-state/main.c new file mode 100644 index 000000000..bfb3dcc6d --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/main.c @@ -0,0 +1,7 @@ +extern int fact (int n); + +int +main (void) +{ + return fact (2); +} diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.opt b/testsuite/tests/TC03-012-objcov-line-state/test.opt new file mode 100644 index 000000000..cffec28fb --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/test.opt @@ -0,0 +1 @@ +!aarch64-elf DEAD Embeds x86_64 assembly sources for Linux diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.py b/testsuite/tests/TC03-012-objcov-line-state/test.py new file mode 100644 index 000000000..9992b0ea1 --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/test.py @@ -0,0 +1,69 @@ +""" +Testcase for TC03-012: check that gnatcov reports as uncovered an instruction +that is not executed, but that follows an executed instruction and has the same +sloc. +""" + +from e3.fs import cp, mkdir + +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + xcov, + xrun, + tracename_for, +) + +Wdir("tmp_") + +# Compile all C sources +original_prj = gprfor( + srcdirs=[".."], + mains=["main.c"], + objdir="obj-original", + prjid="original", + langs=["C"], +) +gprbuild(original_prj, extracargs=["-save-temps"]) + +# Use our custom assembly source for fact.c. Explicitly ask for debug info so +# that "gnatcov covearge" can generate XCOV reports. +mkdir("src") +cp("../main.c", "src/main.c") +cp("../fact.s", "src/fact.s") +prj = gprfor(srcdirs=["src"], mains=["main.c"], prjid="gen") +gprbuild(prj, extracargs=["-g"]) + +# Run and compute the XCOV coverage report. Restrict the set of routines +# considered for object coverage so that gnatcov does not try to look for the +# source files used to implement the RTS. +routines = ["--routines=main", "--routines=fact"] +xrun(["-cinsn", exepath_to("main"), *routines]) +xcov( + [ + "coverage", + "-cinsn", + "-axcov", + "-Pgen", + *routines, + "--source-search=..", + tracename_for("main"), + ] +) + +# Check that line 4 is correctly marked as partially covered, as it contains +# an uncovered instruction that follows an (always taken) branch (see the +# comment in fact.s). +check_xcov_reports( + "obj", + { + "fact.c.xcov": {"+": {6, 7, 9}, "-": {5}, "!": {4}}, + "main.c.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/TC11-052-internal-error/main.adb b/testsuite/tests/TC11-052-internal-error/main.adb new file mode 100644 index 000000000..782870a93 --- /dev/null +++ b/testsuite/tests/TC11-052-internal-error/main.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + type T is null record; + procedure Do_Nothing is null; +begin + Put_Line ("Hello World!"); + Do_Nothing; +end Main; diff --git a/testsuite/tests/TC11-052-internal-error/test.py b/testsuite/tests/TC11-052-internal-error/test.py new file mode 100644 index 000000000..cb89be2b8 --- /dev/null +++ b/testsuite/tests/TC11-052-internal-error/test.py @@ -0,0 +1,112 @@ +""" +Check that gnatcov reports internal errors as expected. +""" + +import re +import os + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def check(args, trigger, info): + # Run gnatcov with the given arguments and trigger + out = f"{trigger}.log" + env = dict(os.environ) + env["GNATCOV_INTERNAL_ERROR_TRIGGER"] = trigger + p = xcov(args + ["-q"], out=out, env=env, register_failure=False) + thistest.fail_if( + p.status == 0, "gnatcov returned success exit code, error expected" + ) + + trigger_msg = trigger.upper().replace("-", "_") + expected_output = re.compile( + "\n".join( + [ + ".*", + "== gnatcov bug detected ==", + "", + "gnatcov just encountered an internal error:", + f"raised CONSTRAINT_ERROR : {trigger_msg}", + # Depending on how gnatcov is built, exception info may contain + # stack traces. + "((Load address: [x0-9a-f]+\n)?Call stack traceback" + " locations:", + "[x0-9a-f ]+", + ")?", + "", + "(?P.*)", + "", + "This is gnatcov version .*", + ] + ), + re.MULTILINE, + ) + + # The difference between expected and actual output generally is + # specifically in the "info" part. To make error messages easier to read, + # first match the global structure of the output. If that succeeds, compare + # the "info" part separately. + output = contents_of(out) + thistest.fail_if_no_match( + what=f"[{trigger}] gnatcov output", + regexp=expected_output, + actual=output, + ) + + m = expected_output.match(output) + if m: + thistest.fail_if_no_match( + what=f"[{trigger}] context info in gnatcov output", + regexp=re.compile(info, re.MULTILINE), + actual=m.group("info"), + ) + + +tmp = Wdir("tmp_") +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) +os.mkdir("obj") + +check( + args=["coverage"], + trigger="arguments-loading", + info=r"No coverage processing context information available\.", +) + +check( + args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-start-file", + info=r"Instrumenting [^\n]*main\.adb", +) + +check( + args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-null-proc", + info=r"Instrumenting NullSubpDecl at [^\n]*main\.adb:7:4-7:33", +) + +check( + args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-insert-stmt-witness", + info=r"Instrumenting ConcreteTypeDecl at [^\n]*main\.adb:6:4-6:26", +) + +# Instrument the example project, run its main to produce a source trace and +# then trigger an internal error while loading the SID file. +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + trace_mode="src", +) +check( + args=xcov_args, + trigger="load-checkpoint", + info=r"Loading [^\n]*main\.sid", +) + +thistest.result() diff --git a/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb b/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb new file mode 100644 index 000000000..715aa8861 --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb @@ -0,0 +1,26 @@ +procedure Exemptions (X : in out Positive) is +begin + if X = 1 then -- # if_1 + X := X + 1; -- # inc_1 + end if; + + if X = 3 then -- # if_2 + X := X + 1; -- # inc_2 + end if; + + pragma Annotate (Xcov, Exempt_On, "Exempt 1"); -- # exempt1 + if X = 3 then -- # exempt1_if1 + X := X + 1; -- # exempt1_inc1 + X := X + 1; -- # exempt1_inc2 + end if; -- # exempt1 + pragma Annotate (Xcov, Exempt_Off); -- # exempt1 + + pragma Annotate (Xcov, Exempt_On, "Exempt 2"); -- # exempt2 + if X = 3 then -- # exempt2_if2 + X := X + 1; -- # exempt2_inc3 + X := X + 1; -- # exempt2_inc4 + X := X + 1; -- # exempt2_inc5 + X := X + 1; -- # exempt2_inc6 + end if; -- # exempt2 + pragma Annotate (Xcov, Exempt_Off); -- # exempt2 +end Exemptions; diff --git a/testsuite/tests/TC31-001-show-exempted/src/test_1.adb b/testsuite/tests/TC31-001-show-exempted/src/test_1.adb new file mode 100644 index 000000000..96eae62f0 --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/src/test_1.adb @@ -0,0 +1,24 @@ +with Exemptions; + +procedure Test_1 is + X : Positive := 1; +begin + Exemptions (X); + Exemptions (X); +end Test_1; + +--# exemptions.adb +-- /if_1/ l+ ## 0 +-- /inc_1/ l+ ## 0 +-- /if_2/ l! ## dT- +-- /inc_2/ l- ## s- +-- /exempt1/ l* ## x+ +-- /exempt1_if1/ l= ## XoT- +-- /exempt1_inc1/ l= ## Xs- +-- /exempt1_inc2/ l= ## Xs- +-- /exempt2/ l* ## x+ +-- /exempt2_if2/ l= ## XoT- +-- /exempt2_inc3/ l= ## Xs- +-- /exempt2_inc4/ l= ## Xs- +-- /exempt2_inc5/ l= ## Xs- +-- /exempt2_inc6/ l= ## Xs- diff --git a/testsuite/tests/TC31-001-show-exempted/test.opt b/testsuite/tests/TC31-001-show-exempted/test.opt new file mode 100644 index 000000000..d53c552fd --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Cannot compile pragmas marking begin and end of exempted regions diff --git a/testsuite/tests/TC31-001-show-exempted/test.py b/testsuite/tests/TC31-001-show-exempted/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/U128-004-displayed-percentages/main1.adb b/testsuite/tests/U128-004-displayed-percentages/main1.adb new file mode 100644 index 000000000..877836be8 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/main1.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main1 is +begin + Pkg.Process (True); +end Main1; diff --git a/testsuite/tests/U128-004-displayed-percentages/main99.adb b/testsuite/tests/U128-004-displayed-percentages/main99.adb new file mode 100644 index 000000000..ecb470e56 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/main99.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main99 is +begin + Pkg.Process (False); +end Main99; diff --git a/testsuite/tests/U128-004-displayed-percentages/pkg.adb b/testsuite/tests/U128-004-displayed-percentages/pkg.adb new file mode 100644 index 000000000..333babbc1 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/pkg.adb @@ -0,0 +1,250 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Process (B : Boolean) is + begin + if B then + Put_Line("Hello World!"); + else + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + end if; + end Process; +end Pkg; diff --git a/testsuite/tests/U128-004-displayed-percentages/pkg.ads b/testsuite/tests/U128-004-displayed-percentages/pkg.ads new file mode 100644 index 000000000..cea167fa1 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Process (B : Boolean); +end Pkg; diff --git a/testsuite/tests/U128-004-displayed-percentages/test.py b/testsuite/tests/U128-004-displayed-percentages/test.py new file mode 100644 index 000000000..e094d0de3 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/test.py @@ -0,0 +1,33 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +prj = gprfor(srcdirs=[".."], mains=["main1.adb", "main99.adb"]) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main99"], + extra_coverage_args=["-a", "xcov"], +) +# For percentages > 99%, GNATcoverage should always round down +thistest.fail_if( + "99% of 241 lines covered" not in contents_of("obj/pkg.adb.xcov") +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main1"], + extra_coverage_args=["-a", "xcov"], +) +# Symetrically, for percentages < 1%, GNATcoverage should round up +thistest.fail_if( + "1% of 241 lines covered" not in contents_of("obj/pkg.adb.xcov") +) + +thistest.result() diff --git a/testsuite/tests/U128-029-missing-dump-trigger/main.adb b/testsuite/tests/U128-029-missing-dump-trigger/main.adb new file mode 100644 index 000000000..2d5ca66b2 --- /dev/null +++ b/testsuite/tests/U128-029-missing-dump-trigger/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello World!"); +end Main; diff --git a/testsuite/tests/U128-029-missing-dump-trigger/test.py b/testsuite/tests/U128-029-missing-dump-trigger/test.py new file mode 100644 index 000000000..3073b4d3e --- /dev/null +++ b/testsuite/tests/U128-029-missing-dump-trigger/test.py @@ -0,0 +1,13 @@ +""" +Regression testcase for a gnatcov crash when gnatcov instrument is called +without the dump-trigger option. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov + +tmp = Wdir("tmp_") +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) +xcov(["instrument", "-P", prj, "--level=stmt"]) +thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/README.md b/testsuite/tests/U204-026-arch-mix/README.md new file mode 100644 index 000000000..e3e2f1dd5 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/README.md @@ -0,0 +1,25 @@ +This test checks that "gnatcov coverage" can deal with SID and checkpoint files +produced in various cross-configuration scenarios. + +Since we can't run the test on multiple hosts, we store compilation and trace +artifacts for each host instead of generating them every time the test is rerun. +If the format of these artifacts (traces, checkpoints) changes, the previously +stored format may become incompatible with the newer version of 'gnatcov.' In +such cases, we need to update the test to use artifacts in the newer format. + +Updating the artifacts is necessary for both Windows (native) and Linux (native, +as well as the aarch64-elf and arm-elf targets). To do this, you'll need a +native toolchain for both hosts and a cross toolchain for arm-eabi and +aarch64-elf for Linux, with the instrumentation runtime setup. + +In addition, also install the sshpass utility, available through apt: + +``` +apt install -y sshpass +``` + +In order for the update to work on windows, push the contents of your branch to +the eng/das/cov/gnatcoverage origin remote. + +Then, to update instrumentation and trace artifacts for all hosts / targets, +run the `update.sh` script. diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace new file mode 100644 index 000000000..601c5f5e5 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace differ diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace new file mode 100644 index 000000000..86180e65a Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace differ diff --git a/testsuite/tests/U204-026-arch-mix/foo.gpr b/testsuite/tests/U204-026-arch-mix/foo.gpr new file mode 100644 index 000000000..5d6ea4e09 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/foo.gpr @@ -0,0 +1,4 @@ +project Foo is + for Object_Dir use "obj"; + for Main use ("main_1.adb", "main_2.adb"); +end Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen.sh b/testsuite/tests/U204-026-arch-mix/gen.sh new file mode 100755 index 000000000..c16a448a3 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen.sh @@ -0,0 +1,124 @@ +#! /bin/sh + +# Script to generate instrumented sources, SID, traces and checkpoint files to +# be used in this test. +# +# Since our testsuite infrastructure does not allow us to run several hosts and +# toolchains at the same time, we pre-generate these files manually and add +# them as material to the testsuite. + +set -ex + +os="$1" +case "$os" in + linux) + expected_cwd="/tmp/U204-026-arch-mix" + ;; + windows) + expected_cwd="/cygdrive/c/tmp/U204-026-arch-mix" + ;; + *) + echo "Invalid OS: $os" + exit 1 + ;; +esac +if [ "$expected_cwd" != "$PWD" ] +then + echo "Please run this script from the $expected_cwd directory" + exit 1 +fi + +XCOV_INSTR="gnatcov instrument -Pfoo -cstmt+mcdc \ + --dump-trigger=main-end --dump-channel=base64-stdout" +XCOV_COV="gnatcov coverage -Pfoo -cstmt+mcdc" +CROSS32_OPTS="--target=arm-eabi --RTS=light-stm32f4" +CROSS64_OPTS="--target=aarch64-elf --RTS=light-zynqmp" +SRC_BUILD_OPTS="--src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts" +SRC_BUILD_CROSS_OPTS="--src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts" +BIN_BUILD_OPTS="-cargs -g -fdump-scos -fpreserve-control-flow" + +rm -rf gen +mkdir gen + +# +# 1. Check that we can instrument on one host and build+run+coverage on another +# + +# On Windows, instrument the "foo" project for the native target. "test.py" +# will find the SIDs and the instrumented sources in "gen/x86_64-windows". +# +# On Linux, instrument the "foo" project for ARM ELF. "test.py" will find the +# SIDs and the instrumented sources in "gen/arm-elf-linux" + +case $os in + windows) + $XCOV_INSTR + dest=x86_64-windows + ;; + linux) + $XCOV_INSTR $CROSS32_OPTS + dest=arm-elf-linux + ;; +esac +mkdir gen/$dest +cp obj/*.sid obj/foo-gnatcov-instr/* gen/$dest + +# +# 2. Check that we can mix checkpoints created from source traces even when +# these source traces were produced for different targets, possibly from +# different hosts. +# + +# On Windows, build the "foo" instrumented project (previously for the native +# target) and run main_1 to produce a source trace. +# +# On Linux, do the same for ARM ELF/main_2. +# +# In both cases, create a checkpoint from the trace. + +case $os in + windows) + gprbuild -Pfoo $SRC_BUILD_OPTS + obj/main_1 > main_1-out.txt + gnatcov extract-base64-trace main_1-out.txt gen/main_1.srctrace + $XCOV_COV --save-checkpoint=gen/src-main_1.ckpt gen/main_1.srctrace + ;; + linux) + gprbuild $CROSS32_OPTS -Pfoo $SRC_BUILD_CROSS_OPTS + arm-eabi-gnatemu --board=stm32f4 obj/main_2 > main_2-out.txt + gnatcov extract-base64-trace main_2-out.txt gen/main_2.srctrace + $XCOV_COV --save-checkpoint=gen/src-main_2.ckpt gen/main_2.srctrace + ;; +esac + +# +# 3. Reject mix of checkpoints created with binary traces for different +# "bits-target" (32 vs 64-bit). +# + +# On Linux, build+run+create checkpoints (with binary traces) for both 32 and +# 64-bit targets. + +case $os in + linux) + gprbuild -Pfoo $CROSS32_OPTS $BIN_BUILD_OPTS + gnatcov run --target=arm-eabi,stm32f4 -o bin-main_1.trace obj/main_1 + $XCOV_COV $CROSS32_OPTS --save-checkpoint=gen/bin-main_1.ckpt \ + bin-main_1.trace + + gprbuild -Pfoo $CROSS64_OPTS $BIN_BUILD_OPTS + gnatcov run --target=aarch64-elf -o bin-main_2.trace obj/main_2 + $XCOV_COV $CROSS64_OPTS --save-checkpoint=gen/bin-main_2.ckpt \ + bin-main_2.trace + ;; +esac + +# +# 4. Check that we can use source traces produced on a different host +# + +# Nothing to do here: step 2 already added source traces to the "gen" +# directory. + +# Clean up permissions (i.e. remove execution bits on Windows) +find gen -type f | xargs chmod 644 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads new file mode 100644 index 000000000..4f8fb6567 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads @@ -0,0 +1,75 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bz3791e32c is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_z3791e32c_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_z3791e32c_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_z3791e32c_1"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z3791e32c_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z3791e32c_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z3791e32c_2"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (31, 7, 116, 68, 128, 108, 109, 251, 97, 162, 61, 255, 238, 251, 162, 56, 7, 34, 238, 156), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); +end Buffers_2; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access, +2 => Buffers_2.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z3791e32c_buffers"); + +end GCVRT.Bz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads new file mode 100644 index 000000000..98a55c9bb --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads @@ -0,0 +1,44 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bz794ac68b is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68b_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68b_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68b_1"); + + Unit_Name : constant String := "main_1"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68b_buffers"); + +end GCVRT.Bz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads new file mode 100644 index 000000000..4bc122bc6 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads @@ -0,0 +1,44 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bz794ac68c is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68c_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68c_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68c_1"); + + Unit_Name : constant String := "main_2"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68c_buffers"); + +end GCVRT.Bz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb new file mode 100644 index 000000000..7f9e91472 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb @@ -0,0 +1,15 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with GNATcov_RTS.Buffers.Lists; +with GCVRT.Foo; +package body GCVRT.DB_z794ac68b is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", + Exec_Date => 0); + end Dump_Buffers; + +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads new file mode 100644 index 000000000..59172a575 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads @@ -0,0 +1,12 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +package GCVRT.DB_z794ac68b is + + pragma Preelaborate; + + pragma No_Tagged_Streams; + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb new file mode 100644 index 000000000..7daa5a71a --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb @@ -0,0 +1,15 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with GNATcov_RTS.Buffers.Lists; +with GCVRT.Foo; +package body GCVRT.DB_z794ac68c is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", + Exec_Date => 0); + end Dump_Buffers; + +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads new file mode 100644 index 000000000..34440e9db --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads @@ -0,0 +1,12 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +package GCVRT.DB_z794ac68c is + + pragma Preelaborate; + + pragma No_Tagged_Streams; + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.adb new file mode 100644 index 000000000..d42ac97c7 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.adb @@ -0,0 +1,16 @@ +with Interfaces; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; + +package body GCVRT.Foo.Observe is + function Sum_Buffer_Bits return Natural is + function Sum_Buffer_Bits_C + (C_List : GNATcov_RTS_Coverage_Buffers_Group_Array) + return Interfaces.Unsigned_64; +pragma Import (C, Sum_Buffer_Bits_C, "gnatcov_rts_sum_buffer_bits"); + begin + return Natural + (Interfaces.Unsigned_64'Min + (Sum_Buffer_Bits_C (GCVRT.Foo.C_List), + Interfaces.Unsigned_64 (Natural'Last))); + end; +end GCVRT.Foo.Observe; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.ads new file mode 100644 index 000000000..a3321385e --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.ads @@ -0,0 +1,3 @@ +package GCVRT.Foo.Observe is + function Sum_Buffer_Bits return Natural; +end GCVRT.Foo.Observe; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads new file mode 100644 index 000000000..414d9af4f --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GCVRT.Bz794ac68b; +with GCVRT.Bz794ac68c; +with GCVRT.Bz3791e32c; + +package GCVRT.Foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_z794ac68b_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68b_buffers,"gnatcov_rts_buffers_z794ac68b_buffers"); + gnatcov_rts_buffers_z794ac68c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68c_buffers,"gnatcov_rts_buffers_z794ac68c_buffers"); + gnatcov_rts_buffers_z3791e32c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z3791e32c_buffers,"gnatcov_rts_buffers_z3791e32c_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_z794ac68b_buffers'Access, + 2 => gnatcov_rts_buffers_z794ac68c_buffers'Access, + 3 => gnatcov_rts_buffers_z3791e32c_buffers'Access); + C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := + ( 3, List'Address); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_foo"); + +end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads new file mode 100644 index 000000000..1c808ade0 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -0,0 +1,35 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pz3791e32c is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_z3791e32c_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_z3791e32c_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_z3791e32c_1"); + +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z3791e32c_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z3791e32c_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z3791e32c_2"); + +end Buffers_2; + +end GCVRT.Pz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads new file mode 100644 index 000000000..927e8b086 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -0,0 +1,23 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pz794ac68b is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68b_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68b_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68b_1"); + +end Buffers_1; + +end GCVRT.Pz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads new file mode 100644 index 000000000..870f9ae12 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -0,0 +1,23 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pz794ac68c is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68c_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68c_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68c_1"); + +end Buffers_1; + +end GCVRT.Pz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb new file mode 100644 index 000000000..656f51403 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid new file mode 100644 index 000000000..96f6c5407 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb new file mode 100644 index 000000000..285a40eb7 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); +GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid new file mode 100644 index 000000000..7323a92fe Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb new file mode 100644 index 000000000..09519828e --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb @@ -0,0 +1,18 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with Ada.Text_IO; use Ada.Text_IO; + +with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is + + ------------- + -- Compute -- + ------------- + + procedure Compute (A, B : Boolean) is + MCDC_State_2_Var:GNATcov_RTS.Buffers.MCDC_State_Type:=0;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Decision_Buffer,0,1,GCVRT.Pz3791e32c.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,1);Put_Line ("true"); + else + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,2);Put_Line ("false"); + end if; + end Compute; + +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads new file mode 100644 index 000000000..1373d53c2 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads @@ -0,0 +1,3 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is + procedure Compute (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid new file mode 100644 index 000000000..49d156be4 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt new file mode 100644 index 000000000..b615e6a13 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt new file mode 100644 index 000000000..a13c938c3 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace new file mode 100644 index 000000000..a6bdcb7b9 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace new file mode 100644 index 000000000..7dd13a1b7 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt new file mode 100644 index 000000000..1128b0dcb Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt new file mode 100644 index 000000000..12b59f154 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads new file mode 100644 index 000000000..fb65743cc --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads @@ -0,0 +1,75 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bz3791e32c is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_z3791e32c_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_z3791e32c_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_z3791e32c_1"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z3791e32c_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z3791e32c_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z3791e32c_2"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (31, 7, 116, 68, 128, 108, 109, 251, 97, 162, 61, 255, 238, 251, 162, 56, 7, 34, 238, 156), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); +end Buffers_2; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access, +2 => Buffers_2.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z3791e32c_buffers"); + +end GCVRT.Bz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads new file mode 100644 index 000000000..f18b67c82 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads @@ -0,0 +1,44 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bz794ac68b is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68b_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68b_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68b_1"); + + Unit_Name : constant String := "main_1"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68b_buffers"); + +end GCVRT.Bz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads new file mode 100644 index 000000000..16970adcb --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads @@ -0,0 +1,44 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bz794ac68c is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68c_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68c_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68c_1"); + + Unit_Name : constant String := "main_2"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68c_buffers"); + +end GCVRT.Bz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb new file mode 100644 index 000000000..845ba4ae7 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb @@ -0,0 +1,20 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with GNATcov_RTS.Buffers.Lists; +with GCVRT.Foo; +package body GCVRT.DB_z794ac68b is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", + Exec_Date => 0); + end Dump_Buffers; + + overriding procedure Finalize (Self : in out Dump_Controlled_Type) is + begin + Dump_Buffers; + end Finalize; + +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads new file mode 100644 index 000000000..75cfad832 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads @@ -0,0 +1,18 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +with Ada.Finalization; +package GCVRT.DB_z794ac68b is + + pragma Preelaborate; + + pragma No_Tagged_Streams; + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + + type Dump_Controlled_Type is new + Ada.Finalization.Limited_Controlled + with null record; + overriding procedure Finalize (Self : in out Dump_Controlled_Type); + +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb new file mode 100644 index 000000000..b05673245 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb @@ -0,0 +1,20 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with GNATcov_RTS.Buffers.Lists; +with GCVRT.Foo; +package body GCVRT.DB_z794ac68c is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", + Exec_Date => 0); + end Dump_Buffers; + + overriding procedure Finalize (Self : in out Dump_Controlled_Type) is + begin + Dump_Buffers; + end Finalize; + +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads new file mode 100644 index 000000000..693788978 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads @@ -0,0 +1,18 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +with Ada.Finalization; +package GCVRT.DB_z794ac68c is + + pragma Preelaborate; + + pragma No_Tagged_Streams; + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + + type Dump_Controlled_Type is new + Ada.Finalization.Limited_Controlled + with null record; + overriding procedure Finalize (Self : in out Dump_Controlled_Type); + +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.adb new file mode 100644 index 000000000..768025281 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.adb @@ -0,0 +1,16 @@ +with Interfaces; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; + +package body GCVRT.Foo.Observe is + function Sum_Buffer_Bits return Natural is + function Sum_Buffer_Bits_C + (C_List : GNATcov_RTS_Coverage_Buffers_Group_Array) + return Interfaces.Unsigned_64; +pragma Import (C, Sum_Buffer_Bits_C, "gnatcov_rts_sum_buffer_bits"); + begin + return Natural + (Interfaces.Unsigned_64'Min + (Sum_Buffer_Bits_C (GCVRT.Foo.C_List), + Interfaces.Unsigned_64 (Natural'Last))); + end; +end GCVRT.Foo.Observe; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.ads new file mode 100644 index 000000000..81aa283b7 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.ads @@ -0,0 +1,3 @@ +package GCVRT.Foo.Observe is + function Sum_Buffer_Bits return Natural; +end GCVRT.Foo.Observe; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads new file mode 100644 index 000000000..f0c30210d --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GCVRT.Bz794ac68b; +with GCVRT.Bz794ac68c; +with GCVRT.Bz3791e32c; + +package GCVRT.Foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_z794ac68b_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68b_buffers,"gnatcov_rts_buffers_z794ac68b_buffers"); + gnatcov_rts_buffers_z794ac68c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68c_buffers,"gnatcov_rts_buffers_z794ac68c_buffers"); + gnatcov_rts_buffers_z3791e32c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z3791e32c_buffers,"gnatcov_rts_buffers_z3791e32c_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_z794ac68b_buffers'Access, + 2 => gnatcov_rts_buffers_z794ac68c_buffers'Access, + 3 => gnatcov_rts_buffers_z3791e32c_buffers'Access); + C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := + ( 3, List'Address); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_foo"); + +end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads new file mode 100644 index 000000000..03f085d72 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads @@ -0,0 +1,35 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pz3791e32c is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_z3791e32c_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_z3791e32c_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_z3791e32c_1"); + +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z3791e32c_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z3791e32c_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z3791e32c_2"); + +end Buffers_2; + +end GCVRT.Pz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads new file mode 100644 index 000000000..08e30c044 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads @@ -0,0 +1,23 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pz794ac68b is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68b_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68b_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68b_1"); + +end Buffers_1; + +end GCVRT.Pz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads new file mode 100644 index 000000000..235f1a41a --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads @@ -0,0 +1,23 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pz794ac68c is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68c_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68c_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68c_1"); + +end Buffers_1; + +end GCVRT.Pz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb new file mode 100644 index 000000000..2506d1b0c --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +GNATcov_Dump_Object:GCVRT.DB_z794ac68b.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid new file mode 100644 index 000000000..c15c782f1 Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb new file mode 100644 index 000000000..7feb3b7a6 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); +end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid new file mode 100644 index 000000000..4d89b525b Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid differ diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb new file mode 100644 index 000000000..09519828e --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb @@ -0,0 +1,18 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with Ada.Text_IO; use Ada.Text_IO; + +with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is + + ------------- + -- Compute -- + ------------- + + procedure Compute (A, B : Boolean) is + MCDC_State_2_Var:GNATcov_RTS.Buffers.MCDC_State_Type:=0;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Decision_Buffer,0,1,GCVRT.Pz3791e32c.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,1);Put_Line ("true"); + else + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,2);Put_Line ("false"); + end if; + end Compute; + +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads new file mode 100644 index 000000000..1373d53c2 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads @@ -0,0 +1,3 @@ +pragma Style_Checks (Off); pragma Warnings (Off);with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is + procedure Compute (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid new file mode 100644 index 000000000..0ef87464e Binary files /dev/null and b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid differ diff --git a/testsuite/tests/U204-026-arch-mix/main_1.adb b/testsuite/tests/U204-026-arch-mix/main_1.adb new file mode 100644 index 000000000..d60a8b539 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/main_1.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_1 is +begin + Pkg.Compute (True, False); +end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/main_2-out.txt b/testsuite/tests/U204-026-arch-mix/main_2-out.txt new file mode 100644 index 000000000..bef2cf381 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/main_2-out.txt @@ -0,0 +1,12 @@ +true + +== GNATcoverage source trace file == +R05BVGNvdiBzb3VyY2UgdHJhY2UgZmlsZQAAAAAAAAAEAAAABAAAAAEAAAADAAAARm9vAAIAAAAIAAAA +AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAABgAAAAEAAAAAAAAAAAAAAAABAH0bAHG8jOubvn207otfbMbl +SN4LDtCqT9bM78Zpgrb6QsBvakZqvIcAAAAAAAAAAAAAAAAAAAAAAAAAAABtYWluXzEAAAAAAAAGAAAA +AQAAAAAAAAAAAAAAAAEA8u0hD3mvaqCR4eIKrxDP3xobG5QO0KpP1szvxmmCtvpCwG9qRmq8hwAAAAAA +AAAAAAAAAAAAAAAAAAAAAG1haW5fMgAAAQAAAAMAAAAAAAAAAAAAAAAAAAAAAgCsh3iDUUGq2pxXmh4j +R2CmDqF92BK87zZvnC568Fpn4hd6I1ecuY3CAAAAAAAAAAAAAAAAAAAAAAAAAAAAcGtnAAMAAAADAAAA +AgAAAAMAAAAAAQCpSGO3og9c8i7R8zewUhE+/kyZMB8HdESAbG37YaI9/+77ojgHIu6cAAAAAAAAAAAA +AAAAAAAAAAAAAAAAcGtnAAMAAAACAAAABAAAAA== +== End == diff --git a/testsuite/tests/U204-026-arch-mix/main_2.adb b/testsuite/tests/U204-026-arch-mix/main_2.adb new file mode 100644 index 000000000..ec8ec5d02 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/main_2.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_2 is +begin + Pkg.Compute (True, True); +end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/pkg.adb b/testsuite/tests/U204-026-arch-mix/pkg.adb new file mode 100644 index 000000000..92d16a2a2 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/pkg.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + ------------- + -- Compute -- + ------------- + + procedure Compute (A, B : Boolean) is + begin + if A and then B then + Put_Line ("true"); + else + Put_Line ("false"); + end if; + end Compute; + +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/pkg.ads b/testsuite/tests/U204-026-arch-mix/pkg.ads new file mode 100644 index 000000000..b7f30c150 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Compute (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/test.opt b/testsuite/tests/U204-026-arch-mix/test.opt new file mode 100644 index 000000000..29bdb5343 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD Native instrumentation not compatible with cross light profiles +RTS_LIGHT_TASKING DEAD Native instr not compatible with cross light-tasking profiles +block DEAD Hard-coded instrumented files and SIDs diff --git a/testsuite/tests/U204-026-arch-mix/test.py b/testsuite/tests/U204-026-arch-mix/test.py new file mode 100644 index 000000000..e0f77735e --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/test.py @@ -0,0 +1,190 @@ +""" +Check that "gnatcov coverage" can deal with SID and checkpoint files produced +in various cross-configuration scenarios. +""" + +import glob +import os.path + +from e3.env import Env +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_convert_base64 +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exename_for, gprbuild, gprfor, run_cov_program, xcov + + +src_dir = os.getcwd() +env = Env() +tmp = Wdir("tmp_") + + +def gen_project(name): + """ + Generate in the current directory a project file with the given name for + this testcases' sources. Return its filename as well as its object/exec + directory (computed from the given name). + """ + obj_dir = f"obj-{name}" + p = gprfor( + mains=["main_1.adb", "main_2.adb"], + prjid=name, + srcdirs=[".."], + objdir=obj_dir, + exedir=obj_dir, + ) + return (p, obj_dir) + + +def check_reports(xcov_dir): + """ + Check that the "*.xcov" coverage reports in the given directory have the + expected content. This assumes coverage data from the execution of both + mains. + """ + check_xcov_reports( + xcov_dir, + { + "main_1.adb.xcov": {"+": {5}}, + "main_2.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {"+": {12, 14}, "!": {11}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, + ) + + +# Checkpoints were produced in a specific location both on Windows and Linux. +# Use the appropriate source rebasing arguments so that gnatcov can find all +# source files in the testcase's directory. +src_rebase_args = [ + f"--source-rebase=c:\\tmp\\u204-026-arch-mix={src_dir}", + f"--source-rebase=/tmp/U204-026-arch-mix={src_dir}", +] +cov_args = ["coverage", "-cstmt+mcdc", "-axcov"] + src_rebase_args + + +# +# 1. Check that we can instrument on one host and build+run+coverage on another +# + +# The instrumentation part was done in "gen.sh". Restore SIDs and instrumented +# sources for the two cases to test and do the build+run+coverage. +for name, gen_dir_name in [ + ("win", "x86_64-windows"), + ("linux", "arm-elf-linux"), +]: + thistest.log(f"== 1. {name} ==") + + # Generate a dedicated project for this + p, obj_dir = gen_project(name) + + instr_dir = os.path.join(obj_dir, f"{name}-gnatcov-instr") + mkdir(obj_dir) + mkdir(instr_dir) + + # Copy SIDs and instrumented sources where expected in its object directory + gen_dir = os.path.join("..", "gen", gen_dir_name) + cp(os.path.join(gen_dir, "*.sid"), obj_dir) + cp(os.path.join(gen_dir, "*.ad*"), instr_dir) + + # Build and run the instrumented program, collecting source traces + traces = [] + gprbuild(p, trace_mode="src") + for main in ["main_1", "main_2"]: + out_file = f"{name}-{main}-out.txt" + run_cov_program( + executable=exename_for(os.path.join(obj_dir, main)), out=out_file + ) + + trace_file = f"{name}-{main}.srctrace" + xcov_convert_base64(out_file, trace_file) + traces.append(trace_file) + + # Finally, generate and check the coverage report from these traces + xcov(cov_args + ["-P", p] + traces) + check_reports(obj_dir) + + +# +# 2. Check that we can mix checkpoints created from source traces even when +# these source traces were produced for different targets, possibly from +# different hosts. +# + +thistest.log("== 2. src-checkpoints mix ==") +mkdir("2-xcov") +xcov( + cov_args + + ["--output-dir=2-xcov"] + + [ + f"--checkpoint={os.path.join('..', 'gen', ckpt)}" + for ckpt in ["src-main_1.ckpt", "src-main_2.ckpt"] + ] +) +check_reports("2-xcov") + + +# +# 3. Reject mix of checkpoints created with binary traces for different +# "bits-target" (32 vs 64-bit). +# + +thistest.log("== 3. bin-checkpoints mix ==") +mkdir("3-xcov") +p = xcov( + cov_args + + ["--output-dir=3-xcov"] + + [ + f"--checkpoint={os.path.join('..', 'gen', ckpt)}" + for ckpt in ["bin-main_1.ckpt", "bin-main_2.ckpt"] + ], + out="3-coverage-out.txt", + register_failure=False, +) +thistest.fail_if( + p.status == 0, + "'gnatcov coverage' exited with status code 0 while an error was expected", +) + +# Since the checkpoint for main_1 was created for 32-bits while the checkpoint +# for main_2 was created for 64-bits, the error message depends on the target +# platform for which we run the testsuite. +if env.target.cpu.bits == 32: + ckpt = "bin-main_2.ckpt" + ckpt_bits = "64-bit" + req_bits = "32-bit" +else: + assert env.target.cpu.bits == 64 + ckpt = "bin-main_1.ckpt" + ckpt_bits = "32-bit" + req_bits = "64-bit" +thistest.fail_if_no_match( + "'gnatcov coverage' output", + f".*gnatcov.*: .*{ckpt} was created with {ckpt_bits} traces whereas the" + f" selected target requires {req_bits} traces", + contents_of("3-coverage-out.txt"), +) + +# +# 4. Check that we can use source traces produced on a different host +# + +thistest.log("== 4. src-traces mix ==") +mkdir("4-xcov") +sid_list = "sids.txt" +with open(sid_list, "w") as f: + for sid in sorted(glob.glob(os.path.join("..", "gen", "*", "*.sid"))): + f.write(os.path.abspath(sid)) + f.write("\n") +xcov( + cov_args + + ["--output-dir=4-xcov", f"--sid=@{sid_list}"] + + [os.path.join("..", "gen", f"main_{i}.srctrace") for i in range(1, 3)], + out="4-coverage-out.txt", +) +check_reports("4-xcov") + +thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh new file mode 100755 index 000000000..916101bdf --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -0,0 +1,39 @@ +#! /bin/bash + +set -ex + +cwd=$PWD +unamestr=$(uname) +if [ "$unamestr" != "Linux" ] +then + echo "Please run this script from a linux OS" + exit 1 +fi + +# Update the linux artifacts +cd .. +rsync -ar U204-026-arch-mix/ /tmp/U204-026-arch-mix +cd /tmp/U204-026-arch-mix +./gen.sh linux +cd $cwd +rsync -ar /tmp/U204-026-arch-mix/ . + +# Then update the Windows artifacts using an IOD machine. Do not create the IOD +# instance if one already exists +IOD_DEV_DIR=/tmp/iod-dev +INSTANCES_FILE="$IOD_DEV_DIR/instances.txt" +if ! [ -d "$IOD_DEV_DIR" ] +then + git clone git-adacore:eng/shared/iod-dev "$IOD_DEV_DIR" +fi +iod list --instances > "$INSTANCES_FILE" 2>&1 +if ! grep "You have some running instance" "$INSTANCES_FILE" \ + > /dev/null +then + "$IOD_DEV_DIR/create-base.py" --base-image x86_64-windows-2019 +fi + +ssh iod 'bash -s' < update_win_setup_git.sh +git push -f iod:gnatcoverage HEAD:wip +ssh iod 'bash -s' < update_arch_mix_windows.sh +rsync -av iod:/cygdrive/c/tmp/U204-026-arch-mix/gen/* gen/ diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh new file mode 100755 index 000000000..003a1e126 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -0,0 +1,36 @@ +# Update windows artifacts for U204-026-arch-mix + +set -ex + +# Create a sandbox +cd /Users/itmgr +if ! [ -d wave ] +then + anod init wave +fi + +# Checkout the right gnatcov branch +cd /Users/itmgr/gnatcoverage +git reset --hard wip + +# Build gnatcov +cd /Users/itmgr/wave +anod vcs --reset +anod vcs --add-repo gnatcoverage /Users/itmgr/gnatcoverage +anod build gnatcov --smart +anod install gnatall -Qstable +eval $(anod printenv gnatcov) +eval $(anod printenv gnatall -Qstable) + +# Then, retrieve the sources of the arch-mix test +SRC_DIR=/Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix +BUILD_DIR=/cygdrive/c/tmp/U204-026-arch-mix +rm -rf "$SRC_DIR/gen/x86_64-windows" +rsync -ar "$SRC_DIR/" "$BUILD_DIR" +cd "$BUILD_DIR" +chmod +x gen.sh +gnatcov setup +./gen.sh windows + +# Copy back the generated sources +rsync -ar "$BUILD_DIR/gen/" "$SRC_DIR/gen" diff --git a/testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh b/testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh new file mode 100644 index 000000000..5ccb3cadf --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh @@ -0,0 +1,9 @@ +# Set up the gnatcoverage repositoy on the Windows IOD machie + +set -ex + +cd /Users/itmgr +if ! [ -d gnatcoverage ] +then + git clone git-adacore:eng/cov/gnatcoverage +fi diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb new file mode 100644 index 000000000..28d252535 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg1; + +procedure Disjoint_Main_1 is +begin + Put_Line ("Pkg1.Fn1 (True) :" & Integer'Image (Pkg1.Fn1 (True))); + Put_Line ("Pkg1.Fn1 (False):" & Integer'Image (Pkg1.Fn1 (False))); +end Disjoint_Main_1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb new file mode 100644 index 000000000..aafdcb2c7 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg2; + +procedure Disjoint_Main_2 is +begin + Put_Line ("Pkg2.Fn2 (True) :" & Integer'Image (Pkg2.Fn2 (True))); + Put_Line ("Pkg2.Fn2 (False):" & Integer'Image (Pkg2.Fn2 (False))); +end Disjoint_Main_2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb new file mode 100644 index 000000000..e1dc8d141 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg1; +with Pkg2; + +procedure Intersecting_Main_1 is +begin + Put_Line ("Pkg1.Fn1 (True):" & Integer'Image (Pkg1.Fn1 (True))); + Put_Line ("Pkg2.Fn2 (True):" & Integer'Image (Pkg2.Fn2 (True))); +end Intersecting_Main_1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb new file mode 100644 index 000000000..41dc08b6f --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg1; +with Pkg2; + +procedure Intersecting_Main_2 is +begin + Put_Line ("Pkg1.Fn1 (False):" & Integer'Image (Pkg1.Fn1 (False))); + Put_Line ("Pkg2.Fn2 (False):" & Integer'Image (Pkg2.Fn2 (False))); +end Intersecting_Main_2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb new file mode 100644 index 000000000..b7e0017f6 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb @@ -0,0 +1,15 @@ +package body Pkg1 is + + X : Integer := 0; + pragma Volatile(X); + + function Fn1 (B : Boolean) return Integer is + begin + if B then + return X - 1; + else + return x + 1; + end if; + end Fn1; + +end Pkg1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads new file mode 100644 index 000000000..783fd6d06 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads @@ -0,0 +1,5 @@ +package Pkg1 is + + function Fn1 (B : Boolean) return Integer; + +end Pkg1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb new file mode 100644 index 000000000..ee78667d7 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb @@ -0,0 +1,15 @@ +package body Pkg2 is + + Y : Integer := 42; + pragma Volatile (Y); + + function Fn2 (B : Boolean) return Integer is + begin + if B then + return Y - 1; + else + return Y + 1; + end if; + end Fn2; + +end Pkg2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads new file mode 100644 index 000000000..e4be9ad20 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads @@ -0,0 +1,5 @@ +package Pkg2 is + + function Fn2 (B : Boolean) return Integer; + +end Pkg2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/test.py b/testsuite/tests/U204-029-source-rebase/Ada/test.py new file mode 100644 index 000000000..896c87b7d --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/test.py @@ -0,0 +1,90 @@ +""" +Test the behaviour of the --source-rebase option under various configurations +for Ada projects. +""" + +from SUITE.context import thistest +from test_support import run_variant + +# Test that specifiying a wrong rebase prefix still outputs warnings about +# files not found. +run_variant( + variant_basename="no_src", + mains_list=["disjoint_main_1.adb"], + units_lists=[["Pkg1"]], + origin_src_dir="src", + expected_xcov_results={}, + rebase_dir="/some/random/dir", + expect_failure=True, + suppress_src_dir=True, +) + +# Test that specifying a wrong rebase prefix outputs no warning if the original +# sources are still on the disk. +run_variant( + variant_basename="no_coverage_src", + mains_list=["disjoint_main_1.adb"], + units_lists=[["Pkg1"]], + origin_src_dir="src", + expected_xcov_results={ + "pkg1.ads.xcov": {}, + "pkg1.adb.xcov": {"+": {8, 9, 11}}, + }, + rebase_dir="/some/random/dir", +) + +# Check the absence of warnings when the source rebase does redirect to +# existing sources. +run_variant( + variant_basename="simple", + mains_list=["disjoint_main_1.adb"], + units_lists=[["Pkg1"]], + origin_src_dir="src", + expected_xcov_results={ + "pkg1.ads.xcov": {}, + "pkg1.adb.xcov": {"+": {8, 9, 11}}, + }, + suppress_src_dir=True, +) + +# Check that source rebase is done correctly when rebasing sources from two +# checkpoints, concerning disjoint set of sources for each checkpoint. +run_variant( + variant_basename="disjoint", + mains_list=["disjoint_main_1.adb", "disjoint_main_2.adb"], + units_lists=[["Pkg1"], ["Pkg2"]], + origin_src_dir="src", + expected_xcov_results={ + "pkg1.ads.xcov": {}, + "pkg1.adb.xcov": {"+": {8, 9, 11}}, + "pkg2.ads.xcov": {}, + "pkg2.adb.xcov": {"+": {8, 9, 11}}, + }, + suppress_src_dir=True, +) + +# Check that source rebase is done correctly when rebasing sources from two +# checkpoints, where the set of sources from each checkpoint is overlapping. +# In particular, check that gnatcov doesn't consider that a same file coming +# from two different checkpoints is two separate files. +# +# This is also useful to check that source-rebase actually rebases when both +# the original and the rebase source files exist. Indeed, if GNATcoverage did +# not rebase, we would get ``Warning: same base name for files`` as both +# checkpoints would hold the same units, with the same base name but with a +# different full name. As by default, warnings are registered as errors in a +# test execution, this would fail. +run_variant( + variant_basename="intersecting", + mains_list=["intersecting_main_1.adb", "intersecting_main_2.adb"], + units_lists=[["Pkg1", "Pkg2"]] * 2, + origin_src_dir="src", + expected_xcov_results={ + "pkg1.ads.xcov": {}, + "pkg1.adb.xcov": {"+": {8, 9, 11}}, + "pkg2.ads.xcov": {}, + "pkg2.adb.xcov": {"+": {8, 9, 11}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h b/testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h new file mode 100644 index 000000000..ef1db960f --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h @@ -0,0 +1,13 @@ + +static int +return_a_number (int x) +{ + if (x < 0) + { + return x - 3; + } + else + { + return x + 2; + } +} diff --git a/testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h b/testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h new file mode 100644 index 000000000..316e0af4b --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h @@ -0,0 +1,13 @@ + +static int +return_some_number (int x) +{ + if (x < 0) + { + return x - 1; + } + else + { + return x + 1; + } +} diff --git a/testsuite/tests/U204-029-source-rebase/C/src/main1.c b/testsuite/tests/U204-029-source-rebase/C/src/main1.c new file mode 100644 index 000000000..e67ea1dac --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/main1.c @@ -0,0 +1,10 @@ +#include "a/pkg.h" +#include "b/pkg.h" + +int +main () +{ + volatile int dummy = return_a_number (2); + dummy = return_some_number (2); + return 0; +} diff --git a/testsuite/tests/U204-029-source-rebase/C/src/main2.c b/testsuite/tests/U204-029-source-rebase/C/src/main2.c new file mode 100644 index 000000000..cfb93caea --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/main2.c @@ -0,0 +1,10 @@ +#include "a/pkg.h" +#include "b/pkg.h" + +int +main () +{ + volatile int dummy = return_a_number (-3); + dummy = return_some_number (-1); + return 0; +} diff --git a/testsuite/tests/U204-029-source-rebase/C/test.opt b/testsuite/tests/U204-029-source-rebase/C/test.opt new file mode 100644 index 000000000..41ff4f9fb --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/test.opt @@ -0,0 +1 @@ +src-traces XFAIL C instrumentation does not yet support header analysis. diff --git a/testsuite/tests/U204-029-source-rebase/C/test.py b/testsuite/tests/U204-029-source-rebase/C/test.py new file mode 100644 index 000000000..661fe9596 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/test.py @@ -0,0 +1,33 @@ +""" +Test the behaviour of the --source-rebase option under various configurations +for C projects. +""" + +from SUITE.context import thistest +from test_support import run_variant + + +# Check that source rebase is done correctly when rebasing sources from two +# checkpoints, where the set of sources from each checkpoint is overlapping. +# In particular, check that gnatcov doesn't consider that a same file comming +# from two different checkpoints is two separate files. +run_variant( + variant_basename="intersecting", + mains_list=["main1.c", "main2.c"], + units_lists=[ + [ + "main1.c", + ], + ["main2.c"], + ], + origin_src_dir="src", + expected_xcov_results={ + "main1.c.xcov": {"+": {7, 8, 9}}, + "main2.c.xcov": {"+": {7, 8, 9}}, + "a-pkg.h.xcov": {"+": {5, 7, 11}}, + "b-pkg.h.xcov": {"+": {5, 7, 11}}, + }, +) + + +thistest.result() diff --git a/testsuite/tests/U204-029-source-rebase/test_support.py b/testsuite/tests/U204-029-source-rebase/test_support.py new file mode 100644 index 000000000..15c0995a1 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/test_support.py @@ -0,0 +1,172 @@ +import os +import shutil + +from e3.fs import cp, mkdir + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir, contents_of, empty +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def out_of_source_checkpoint( + variant_name, main, units, origin_src_dir, suppress_src_dir +): + """ + Create a checkpoint with a copy of the sources in origin_src_dir, using + main as the main program and units as the list of units of interest. + + This operates on a copy of the given sources, the copies are deleted after + the checkpoint creation if suppress_src_dir is True, so that gnatcov cannot + find the source in their original location when producing a report. + + Returns the name of the created checkpoint and the absolute path to the + directory where the sources were when creating the checkpoint. + """ + local_src_dir = f"src_{variant_name}" + cp(origin_src_dir, local_src_dir, recursive=True) + checkpoint_name = f"{main}.ckpt" + + build_run_and_coverage( + gprsw=GPRswitches( + gprfor(mains=[main], srcdirs=local_src_dir, objdir="obj"), + units=units, + ), + covlevel="stmt", + mains=[os.path.splitext(main)[0]], + extra_coverage_args=[f"--save-checkpoint={checkpoint_name}"], + ) + + if suppress_src_dir: + shutil.rmtree(local_src_dir) + + return (checkpoint_name, os.path.abspath(local_src_dir)) + + +def consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts, + output_dir_name, +): + """ + Consolidate the given set of checkpoints and create xcov reports. + The xcov reports are checked against expected_xcov_results, and if + expect_failure is True, check that gnatcov emits warnings concerning files + not found. Otherwise check that gnatcov does not emmit any warnings. + """ + log_filename = f"coverage-{output_dir_name}.log" + mkdir(output_dir_name) + xcov( + ["coverage", "-cstmt", "-axcov", f"--output-dir={output_dir_name}"] + + [f"-C{checkpoint}" for checkpoint in checkpoints] + + rebase_opts, + out=log_filename, + tolerate_messages=".", + ) + + if expect_failure: + thistest.fail_if_no_match( + "'gnatcov coverage' output" + f" ({variant_basename}-{output_dir_name})", + r"^(warning: can't open .*\n)+$", + contents_of(log_filename), + ) + else: + thistest.fail_if( + not empty(log_filename), + f"'gnatcov coverage' output ({variant_basename}-{output_dir_name})" + " not empty:\n " + contents_of(log_filename), + ) + + check_xcov_reports(output_dir_name, expected_xcov_results) + + +def run_variant( + variant_basename, + mains_list, + units_lists, + origin_src_dir, + expected_xcov_results, + rebase_dir=None, + expect_failure=False, + suppress_src_dir=False, +): + """ + Create a set of checkpoints using, for checkpoint i, the sources in + origin_src_dir, the main in mains_list[i] and the units in units_lists[i]. + If suppress_src_dir is True, remove the created source directory that is a + copy of origin_src_dir. + + Try to rebase the source to rebase_dir if specified, or to origin_src_dir + otherwise. + """ + origin_src_dir = os.path.abspath(origin_src_dir) + + wd = Wdir(f"tmp_{variant_basename}") + # If no rebase_dir is specified, use origin_src_dir as the place to search + # for sources after rebase. + if rebase_dir is None: + rebase_dir = origin_src_dir + else: + rebase_dir = os.path.abspath(rebase_dir) + + # Create a checkpoint for each set of main/units_of_interest and retrieve + # the checkpoint's name, as well as the path to the source directory used + # to create said checkpoint. + checkpoints, prefixes = zip( + *[ + out_of_source_checkpoint( + f"{variant_basename}_{i}", + main, + units, + origin_src_dir, + suppress_src_dir, + ) + for i, (main, units) in enumerate(zip(mains_list, units_lists)) + ] + ) + + # Test individual options passed to gnatcov for each checkpoint + consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts=[ + f"--source-rebase={prefix}={rebase_dir}" for prefix in prefixes + ], + output_dir_name="simple", + ) + + # Test using one globbing pattern to specify source rebase for all + # checkpoints. + glob_pattern = os.path.join(wd.homedir, "*", "src_*") + consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts=[f"--source-rebase={glob_pattern}={rebase_dir}"], + output_dir_name="globbing_pattern", + ) + + # Test using a response file to specify source rebase for all checkpoints + response_file_name = "src-rebase.txt" + + with open(response_file_name, "w") as f: + f.writelines([f"{prefix}={rebase_dir}\n" for prefix in prefixes]) + + consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts=[f"--source-rebase=@{response_file_name}"], + output_dir_name="response_file", + ) + + wd.to_homedir() diff --git a/testsuite/tests/U208-020-child-project/p-child-src/main.adb b/testsuite/tests/U208-020-child-project/p-child-src/main.adb new file mode 100644 index 000000000..13844d0f9 --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-child-src/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is +begin + if Pkg.Foo (True) then + null; + end if; +end; diff --git a/testsuite/tests/U208-020-child-project/p-child.gpr b/testsuite/tests/U208-020-child-project/p-child.gpr new file mode 100644 index 000000000..7bb2061ed --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-child.gpr @@ -0,0 +1,7 @@ +with "p"; + +project P.Child is + for Source_Dirs use ("p-child-src"); + for Main use ("main.adb"); + for Object_Dir use "obj/p-child"; +end P.Child; diff --git a/testsuite/tests/U208-020-child-project/p-src/pkg.adb b/testsuite/tests/U208-020-child-project/p-src/pkg.adb new file mode 100644 index 000000000..46672538f --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-src/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Foo (B : Boolean) return Boolean is + begin + return B; + end Foo; + +end Pkg; diff --git a/testsuite/tests/U208-020-child-project/p-src/pkg.ads b/testsuite/tests/U208-020-child-project/p-src/pkg.ads new file mode 100644 index 000000000..9ffbd4f6b --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function Foo (B : Boolean) return Boolean; +end Pkg; diff --git a/testsuite/tests/U208-020-child-project/p.gpr b/testsuite/tests/U208-020-child-project/p.gpr new file mode 100644 index 000000000..6ef24db5d --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p.gpr @@ -0,0 +1,4 @@ +project P is + for Source_Dirs use ("p-src"); + for Object_Dir use "obj/p"; +end P; diff --git a/testsuite/tests/U208-020-child-project/test.opt b/testsuite/tests/U208-020-child-project/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/U208-020-child-project/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/U208-020-child-project/test.py b/testsuite/tests/U208-020-child-project/test.py new file mode 100644 index 000000000..e07adb00e --- /dev/null +++ b/testsuite/tests/U208-020-child-project/test.py @@ -0,0 +1,36 @@ +""" +This test checks that the instrumentation of a child project produces valid +instrumented sources. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +p_gpr = os.path.abspath("p-child.gpr") +obj_dir = os.path.abspath("obj/p-child") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 6}}, + "pkg.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/U208-020-error-call/main.c b/testsuite/tests/U208-020-error-call/main.c new file mode 100644 index 000000000..b919edf78 --- /dev/null +++ b/testsuite/tests/U208-020-error-call/main.c @@ -0,0 +1,8 @@ +#include + +int +main () +{ + errno = ENOENT; + return 0; +} diff --git a/testsuite/tests/U208-020-error-call/test.opt b/testsuite/tests/U208-020-error-call/test.opt new file mode 100644 index 000000000..6aa810fbc --- /dev/null +++ b/testsuite/tests/U208-020-error-call/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD Uses errno, which is not defined in embedded / light runtimes diff --git a/testsuite/tests/U208-020-error-call/test.py b/testsuite/tests/U208-020-error-call/test.py new file mode 100644 index 000000000..839693bc2 --- /dev/null +++ b/testsuite/tests/U208-020-error-call/test.py @@ -0,0 +1,28 @@ +""" +This test checks that dumping traces with errno set to a non-zero value +works. It can be the case in user code if a system call fails. + +The source traces dump used to crash as we were checking the errno value +to check for an I/O error when writing the trace file (instead of checking +that we had a valid file descriptor for instance). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="p", srcdirs=[".."], mains=["main.c"], langs=["C"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports("obj", {"main.c.xcov": {"+": {6, 7}}}) +thistest.result() diff --git a/testsuite/tests/U208-020-unique-language-project/main.adb b/testsuite/tests/U208-020-unique-language-project/main.adb new file mode 100644 index 000000000..4fe1236da --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end; diff --git a/testsuite/tests/U208-020-unique-language-project/main.c b/testsuite/tests/U208-020-unique-language-project/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/U208-020-unique-language-project/test.opt b/testsuite/tests/U208-020-unique-language-project/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/U208-020-unique-language-project/test.py b/testsuite/tests/U208-020-unique-language-project/test.py new file mode 100644 index 000000000..4b40528d9 --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/test.py @@ -0,0 +1,56 @@ +""" +This test checks that the instrumentation of an Ada project produces +only Ada files. Likewise for C. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import LANGINFO +from SUITE.cutils import ext, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="ada_prj", srcdirs=[".."], mains=["main.adb"], langs=["Ada"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +for f in os.listdir("obj/ada_prj-gnatcov-instr"): + if ext(f) not in LANGINFO["Ada"].src_ext: + thistest.failed( + f"{f} is not an Ada source. Instrumentation " + "of an Ada project should only produce Ada files." + ) + break + +check_xcov_reports("obj", {"main.adb.xcov": {"+": {3}}}) + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="c_prj", srcdirs=[".."], mains=["main.c"], langs=["C"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +for f in os.listdir("obj/c_prj-gnatcov-instr"): + if ext(f) not in LANGINFO["C"].src_ext: + thistest.failed( + f"{f} is not a C source. Instrumentation " + "of a C project should only produce C files." + ) + break + +check_xcov_reports("obj", {"main.c.xcov": {"+": {4}}}) +thistest.result() diff --git a/testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr b/testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr new file mode 100644 index 000000000..f5b9ed954 --- /dev/null +++ b/testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr @@ -0,0 +1,4 @@ +project Ext_RT extends "gnatcov_rts" is + for Object_Dir use "obj" & GNATcov_RTS'Object_Dir; + for Library_Dir use "obj" & GNATcov_RTS'Library_Dir; +end Ext_RT; diff --git a/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb b/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb new file mode 100644 index 000000000..5991c02cd --- /dev/null +++ b/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb @@ -0,0 +1,49 @@ +with GNAT.IO; + +package body GNATcov_RTS.Base_Io is + + Printed_Tag : Boolean := False; + + function Dummy_Predicate return Boolean; + procedure Print_Tag; + + --------------------- + -- Dummy_Predicate -- + --------------------- + + function Dummy_Predicate return Boolean is + begin + GNAT.IO.Put_Line (""); + GNAT.IO.New_Line; + return True; + end Dummy_Predicate; + + --------------- + -- Print_Tag -- + --------------- + + procedure Print_Tag is + begin + if not Printed_Tag then + Printed_Tag := True; + pragma Assert (Dummy_Predicate); + GNAT.IO.Put_Line (""); + GNAT.IO.New_Line; + end if; + end Print_Tag; + + --------- + -- Put -- + --------- + + procedure Put (S : GNATcov_RTS_String) is + pragma Warnings (Off); + Str : String (1 .. Integer (S.Length)); + for Str'Address use S.Str; + pragma Warning (On); + begin + Print_Tag; + GNAT.IO.Put_Line (Str); + end Put; + +end GNATcov_RTS.Base_Io; diff --git a/testsuite/tests/U211-014-setup/src-ada/foo.adb b/testsuite/tests/U211-014-setup/src-ada/foo.adb new file mode 100644 index 000000000..3072b68a4 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-ada/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello world!"); +end Foo; diff --git a/testsuite/tests/U211-014-setup/src-c/foo.c b/testsuite/tests/U211-014-setup/src-c/foo.c new file mode 100644 index 000000000..ef8f6dc90 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-c/foo.c @@ -0,0 +1,8 @@ +#include + +int +main (void) +{ + puts ("Hello, world!"); + return 0; +} diff --git a/testsuite/tests/U211-014-setup/src-mixed/bar.c b/testsuite/tests/U211-014-setup/src-mixed/bar.c new file mode 100644 index 000000000..c55b18592 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/bar.c @@ -0,0 +1,13 @@ +typedef void (*put_char_ptr) (char c); + +void +bar (put_char_ptr put_char) +{ + const char *message = "Hello, world!"; + int i; + + for (i = 0; message[i]; ++i) + { + put_char (message[i]); + } +} diff --git a/testsuite/tests/U211-014-setup/src-mixed/foo.adb b/testsuite/tests/U211-014-setup/src-mixed/foo.adb new file mode 100644 index 000000000..86c85ce33 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/foo.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Foo is + + procedure Bar (Put_Char : Pkg.Put_Char_Access); + pragma Import (C, Bar, "bar"); + +begin + Bar (Pkg.Put_Char'Access); +end; diff --git a/testsuite/tests/U211-014-setup/src-mixed/pkg.adb b/testsuite/tests/U211-014-setup/src-mixed/pkg.adb new file mode 100644 index 000000000..4c3ac6781 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Put_Char (C : Character) is + begin + Put (C); + end Put_Char; + +end Pkg; diff --git a/testsuite/tests/U211-014-setup/src-mixed/pkg.ads b/testsuite/tests/U211-014-setup/src-mixed/pkg.ads new file mode 100644 index 000000000..e2c00043b --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/pkg.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Pkg is + + type Put_Char_Access is + access procedure (C : Character); + pragma Convention (C, Put_Char_Access); + + procedure Put_Char (C : Character); + pragma Export (C, Put_Char, "pkg_put_char"); + +end Pkg; diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py new file mode 100644 index 000000000..217c1fe90 --- /dev/null +++ b/testsuite/tests/U211-014-setup/test.py @@ -0,0 +1,286 @@ +""" +Check that the "gnatcov setup" command works as expected. + +Note that all tests use a non-standard project name for the installed +instrumentation runtime project, as a way to avoid checks working just because +they actually use the runtime project already present in the testsuite +environment. + +Also note that, due to the testsuite infrastructure, we cannot test the +"default prefix", i.e. letting gprinstall put the instrumentation runtime +project in the toolchain prefix, as the testsuite is not allowed to modify it. +""" + +from dataclasses import dataclass +import os.path +from typing import List, Dict, Set + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprbuild, gprfor, xcov +from SUITE.gprutils import GPRswitches + + +# Project file for an extended runtime +rt_ext_file = os.path.join(os.path.abspath("ext_rt"), "ext_rt.gpr") + + +tmp = Wdir("tmp_") + +# Name of the installed instrumentation runtime project +rt_prj = "rt_prj" + +# Installation directory for the instrumentation runtime project and directory +# for the project path. +rt_install_dir = os.path.abspath("install") +rt_path_dir = os.path.join(rt_install_dir, "share", "gpr") + +# Make this install available to GPR tools +env.add_search_path("GPR_PROJECT_PATH", rt_path_dir) + +ExpectedCov = Dict[str, Dict[str, Set[int]]] + + +@dataclass +class PrjConfig: + """ + Project file, executable name and expected coverage report. + """ + + project_file: str + objdir: str + expected_cov: ExpectedCov + + @classmethod + def create( + cls, tag: str, langs: List[str], main: str, expected_cov: ExpectedCov + ): + objdir = f"obj-{tag}" + return cls( + project_file=gprfor( + prjid=f"{tag}_prj", + langs=langs, + mains=[main], + srcdirs=[f"../src-{tag}"], + objdir=objdir, + ), + objdir=objdir, + expected_cov=expected_cov, + ) + + @property + def gprsw(self): + return GPRswitches(root_project=self.project_file) + + +# Create simple projects to host our experiments +ada_prj = PrjConfig.create( + tag="ada", + langs=["Ada"], + main="foo.adb", + expected_cov={"foo.adb.xcov": {"+": {5}}}, +) +c_prj = PrjConfig.create( + tag="c", + langs=["C"], + main="foo.c", + expected_cov={"foo.c.xcov": {"+": {6, 7}}}, +) +mixed_prj = PrjConfig.create( + tag="mixed", + langs=["Ada", "C"], + main="foo.adb", + expected_cov={ + "foo.adb.xcov": {"+": {11}}, + "pkg.ads.xcov": {"+": {5, 6}}, + "pkg.adb.xcov": {"+": {7}}, + "bar.c.xcov": {"+": {6}}, + }, +) + + +def xsetup(args, out, register_failure=True, auto_config_args=True): + """ + "xcov" wrapper to run "gnatcov setup". + + This wrapper just automatically pass --install-name and --prefix + arguments. + """ + return xcov( + [ + "setup", + f"--install-name={rt_prj}", + f"--prefix={rt_install_dir}", + "-v", + ] + + args, + out=out, + register_failure=register_failure, + auto_config_args=auto_config_args, + force_project_args=True, + ) + + +def check_full( + label, + setup_args, + prj_config, + runtime_project=rt_prj, + dump_channel="auto", + auto_config_args=True, +): + """ + Run "gnatcov setup" with the arguments (setup_args), then compute code + coverage and check the report for the given project (prj_config). + + Also check that `gnatcov instrument` successfully loaded the setup + configuration file. + """ + thistest.log(f"== {label} ==") + xsetup(setup_args, f"setup-{label}.txt", auto_config_args=auto_config_args) + build_run_and_coverage( + gprsw=prj_config.gprsw, + covlevel="stmt", + mains=["foo"], + gpr_obj_dir=prj_config.objdir, + extra_coverage_args=["-axcov", f"--output-dir=xcov-{label}"], + trace_mode="src", + runtime_project=runtime_project, + dump_channel=dump_channel, + extra_instr_args=["-v"], + ) + thistest.fail_if( + "Successfully loaded the setup configuration file" + not in contents_of("instrument.log"), + "Failed to load the setup config file in `gnatcov instrument`", + ) + check_xcov_reports(f"xcov-{label}", prj_config.expected_cov) + + +# "gnatcov setup" (+ relevant target options) is supposed to work out of the +# box and use most of the RTS capabilities. +check_full("basic-mixed", [], mixed_prj) + +# Check that --restricted-to-languages works as expected +check_full("basic-ada", ["--restricted-to-languages=Ada,C"], ada_prj) + +# Our current testsuite runs use Ada runtimes, which do not provide fwrite and +# other similar routines on embedded targets. This means that we cannot test +# our C-only instrumentation runtime on these targets. +# +# Do not pass the testsuite project configuration file to gnatcov setup as it +# was generated for Ada, C and C++, and thus defines Ada specific attributes +# (such as the runtime directory) which would not normally be present in a C +# only project. +if not env.is_cross: + check_full( + "basic-c", + ["--restricted-to-languages=C"], + c_prj, + auto_config_args=False, + ) + +# The core runtime is implemented in C, so C must be enabled +thistest.log("== ada-only ==") +log_file = "setup-ada-only.txt" +p = xsetup(["--restricted-to-languages=Ada"], log_file, register_failure=False) +thistest.fail_if( + p.status == 0, "gnatcov setup succeeded when we expected it to fail" +) +thistest.fail_if_no_match( + log_file, + "(.|\n)*The C language must be enabled(.\n)*", + contents_of(log_file), +) + +# ... so also check that misusing it fails, as expected too: the previous tests +# could fail because --restricted-to-languages is actually ignored (and thus +# the installed runtime always support both Ada and C). Here, we check that +# actually have an error when trying to build instrumented Ada code while the +# runtime has support for C only. +# +# Same remark as above concerning the configuration file. +thistest.log("== basic-bad-lang ==") +log_file = "gprbuild-basic-bad-lang.txt" +xsetup( + ["--restricted-to-languages=C"], + "setup-basic-bad-lang.txt", + auto_config_args=False, +) +xcov_instrument( + gprsw=mixed_prj.gprsw, + covlevel="stmt", + runtime_project=rt_prj, + out="instr-basic-bad-lang.txt", + # Since "gnatcov setup" excluded Ada from the coverage runtime languages, + # no runtime was used to compile it, and thus it is expected that we get a + # discrepancy between "rt_prj" (no runtime) and "mixed_prj" (current + # testsuite runtime). + tolerate_messages="Current runtime is", +) +p = gprbuild( + mixed_prj.project_file, + gargs=["--src-subdirs=gnatcov-instr", "-q"], + trace_mode="src", + runtime_project=rt_prj, + out=log_file, + register_failure=False, +) +thistest.fail_if( + p.status == 0, "gprbuild succeeded when we expected it to fail" +) +thistest.fail_if_no_match( + log_file, + '.*foo.adb:.*"gnatcov_rts.ads" not found.*', + contents_of(log_file), +) + +# Check the installation of an alternative runtime project. Our modified +# runtime (designed for base64-stdout only) just prints a "Hello, world", so we +# can check that our modified runtime is correctly used looking at the main +# output. +# +# Accept just the hello world message or more, as the output may contain a +# base64 trace depending on the testsuite mode. +check_full("ext_rt", [rt_ext_file], ada_prj, dump_channel="base64-stdout") +thistest.fail_if( + "" not in contents_of("foo_output.txt"), + " not in the program output", +) + +# Now, check that -gargs arguments are passed to gprbuild. To do this, build +# the instrumentation runtime with -gnata. This will make GNAT compile with +# assertions enabled (they are disabled by default), and will thus trigger the +# execution of a Put_Line that is otherwise disabled. +check_full( + "ext_rt", + [rt_ext_file, "-gargs", "-cargs:Ada", "-gnata"], + ada_prj, + dump_channel="base64-stdout", +) +thistest.fail_if( + "" not in contents_of("foo_output.txt"), + " not in the program output", +) + +# Check C89 backward-compatibility, as we want to support instrumentation +# with older toolchains. +check_full( + "ext_rt", + [rt_ext_file, "-gargs", "-cargs:C", "-std=c89"], + ada_prj, + dump_channel="base64-stdout", +) + +# Check that passing a full path to --runtime-project works +check_full( + "full_path", + [], + ada_prj, + runtime_project=os.path.join(rt_path_dir, rt_prj), +) + +thistest.result() diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb b/testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb new file mode 100644 index 000000000..eadb48f5c --- /dev/null +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb @@ -0,0 +1,29 @@ +procedure Main is + + task type My_Task is + entry P1; + entry P2; + entry P3; + end My_Task; + + task body My_Task is + begin + select + accept P1 do + null; + end P1; + or when (not True) => + accept P2 do + null; + end P2; + or + accept P3 do + null; + end P3; + end select; + end My_Task; + + T : My_Task; +begin + T.P1; +end Main; diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt new file mode 100644 index 000000000..1a80636a9 --- /dev/null +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt @@ -0,0 +1,2 @@ +!native DEAD Uses full runtime only constructs +RTS_ZFP DEAD Uses full runtime only constructs diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py new file mode 100644 index 000000000..0d0865fbb --- /dev/null +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py @@ -0,0 +1,32 @@ +""" +Regression test for source location of dominance markers referencing +decisions in entry guards. It used to be wrong in ali files. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports, checked_xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +# Check that there is no warning + +checked_xcov(xcov_args, "coverage.log") + +check_xcov_reports( + "obj", + { + "main.adb.xcov": {"+": {11, 12, 13}, "-": {16, 17, 20, 21}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb new file mode 100644 index 000000000..ba8b55b4c --- /dev/null +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + if True then + Put_Line ("Hello World"); + end if; +end Main; diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt new file mode 100644 index 000000000..0a73d5eda --- /dev/null +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt @@ -0,0 +1 @@ +src-traces DEAD Test SCOs in ALI files diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py new file mode 100644 index 000000000..cc4edcb50 --- /dev/null +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py @@ -0,0 +1,45 @@ +""" +Check that gnatcov does not crash on wrong source location for dominance +information. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +# Artificially create wrong source locations to check that gnatcov does +# not crash on these. + +with open("obj/main.ali", "r") as f: + content = f.read() + assert "CS >T5:4 6:7-6:17" in content + content = content.replace(">T5:4", ">T5:5") + +with open("obj/main.ali", "w") as f: + f.write(content) + +xcov(xcov_args, out="coverage.log") + +# Check that a warning is issued + +thistest.fail_if_not_equal( + "gnatcov coverage output", + "!!! main.adb:6:7: dominant decision of statement SCO #4: STATEMENT " + "at main.adb:6:7-17 has no associated SCO, discarding dominance " + "information\n", + contents_of("coverage.log"), +) + +thistest.result() diff --git a/testsuite/tests/U317-004-xml-report/main.adb b/testsuite/tests/U317-004-xml-report/main.adb new file mode 100644 index 000000000..78cf5e255 --- /dev/null +++ b/testsuite/tests/U317-004-xml-report/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello"); +end Main; diff --git a/testsuite/tests/U317-004-xml-report/test.py b/testsuite/tests/U317-004-xml-report/test.py new file mode 100644 index 000000000..bbdd49e46 --- /dev/null +++ b/testsuite/tests/U317-004-xml-report/test.py @@ -0,0 +1,33 @@ +""" +Check that the right column numbers are output for a statement coverage +obligation in the XML report. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains="main.adb")), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-a", "xml"], +) + +if thistest.options.trace_mode == "src": + expected_match = ( + '' + ) +else: + expected_match = ( + '' + ) + +thistest.fail_if(expected_match not in contents_of("obj/main.adb.xml")) +thistest.result() diff --git a/testsuite/tests/U416-006-big-bdd/src/compute.c b/testsuite/tests/U416-006-big-bdd/src/compute.c new file mode 100644 index 000000000..82101e1a3 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/compute.c @@ -0,0 +1,7 @@ +int +c_compute (int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8) +{ + return ((((((((c1 || c2) && c3) || c4) && c5) || c6) && c7) || c8) + && (((((((c1 || c2) && c3) || c4) && c5) || c6) && c7) || c8) + && (((((((c1 || c2) && c3) || c4) && c5) || c6) && c7) || c8)); +} diff --git a/testsuite/tests/U416-006-big-bdd/src/test_eval.adb b/testsuite/tests/U416-006-big-bdd/src/test_eval.adb new file mode 100644 index 000000000..760da21af --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/test_eval.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; + +with Interfaces.C; use Interfaces.C; + +with TestConditions; + +procedure Test_Eval is + function C_Compute (C1, C2, C3, C4, C5, C6, C7, C8 : int) return int; + pragma Import (C, C_Compute); + + Dummy : int; +begin + Ada.Text_IO.Put_Line ("Hello_World"); + TestConditions.Run; + + -- Exercize both outcomes so that conditions are labeled with undetermined + -- coverage. + + Dummy := C_Compute (0, 0, 0, 0, 0, 0, 0, 0); + Dummy := C_Compute (0, 0, 0, 0, 0, 0, 0, 1); +end Test_Eval; diff --git a/testsuite/tests/U416-006-big-bdd/src/testconditions.adb b/testsuite/tests/U416-006-big-bdd/src/testconditions.adb new file mode 100644 index 000000000..4fb4c9f44 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/testconditions.adb @@ -0,0 +1,31 @@ +with Ada.Text_IO; + +package body TestConditions is + + C1 : Boolean := False; + C2 : Boolean := False; + C3 : Boolean := True; + C4 : Boolean := False; + C5 : Boolean := True; + C6 : Boolean := False; + C7 : Boolean := False; + C8 : Boolean := True; + + function Is_Activated return Boolean is + begin + return + ((((((((((((((( C1 or else C2 ) and then C3 ) or else (( C1 or else C2 ) and then C3 )) or else ((( C4 or else C1 ) or else C2 ) and then C3 )) or else ((( C4 or else C1 ) or else C2 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else (( C7 or else C1 ) and then C3 )) or else (( C7 or else C1 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else (( C1 or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else (( C5 or else C8 ) and then C3 ); + end Is_Activated; + + procedure Run is + begin + if Is_Activated then + Ada.Text_IO.Put_Line ("Is Activated"); + C3 := False; + C5 := False; + C8 := False; + Run; + end if; + end Run; + +end TestConditions; diff --git a/testsuite/tests/U416-006-big-bdd/src/testconditions.ads b/testsuite/tests/U416-006-big-bdd/src/testconditions.ads new file mode 100644 index 000000000..485fe0e62 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/testconditions.ads @@ -0,0 +1,5 @@ +package TestConditions is + + procedure Run; + +end TestConditions; diff --git a/testsuite/tests/U416-006-big-bdd/test.py b/testsuite/tests/U416-006-big-bdd/test.py new file mode 100644 index 000000000..b2f024fbc --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/test.py @@ -0,0 +1,101 @@ +""" +Check that gnatcov (instrument/run/coverage) successfully handles very big +decisions in MC/DC. For such decisions with an overly large BDD path count, the +tool is simply expected not to instrument the decision and thus report +undetermined MC/DC coverage for it. +""" + +import re + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir() + + +def warning_re_for(filename, sloc): + """ + Return a regexp for the warning expected for the given file name and source + location. + """ + return ( + r"\*\*\* {filename}:{sloc}: warning: Number of distinct paths in the" + r" decision exceeds the limit \(\d+\)\. MC/DC coverage for this" + r" decision will be left undetermined in coverage reports\. Use option" + r" --path-count-limit to adjust the limit if the default value is too" + r" low\." + ).format(filename=re.escape(filename), sloc=re.escape(sloc)) + + +def do_one_level(level): + tmp.to_subdir(f"tmp_{level}") + thistest.log(f"===== {level} =====") + + gpr = gprfor( + mains=["test_eval.adb"], srcdirs=["../src"], langs=["Ada", "C"] + ) + + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=xcov"], + covlevel=level, + mains=["test_eval"], + trace_mode="src", + tolerate_instrument_messages=( + "Number of distinct paths .* exceeds the limit" + if level == "stmt+mcdc" + else None + ), + ) + + expected_cov = { + "test_eval.adb.xcov": {"+": {11, 13, 19, 20}}, + "testconditions.adb.xcov": {"+": {22, 23, 24, 25, 26, 27}}, + "testconditions.ads.xcov": {}, + "compute.c.xcov": {"+": {5, 6}}, + } + + # For stmt+decision, the BDD is still computed, but the non-instrumentation + # of the conditions has no impact on stmt+decision coverage reports. + # As such, we expect no warnings or errors in the log and no undetermined + # coverage items in the report. + + if level == "stmt+mcdc": + expected_cov["testconditions.adb.xcov"]["?"] = {17} + expected_cov["compute.c.xcov"]["?"] = {4} + else: + expected_cov["testconditions.adb.xcov"]["+"].add(17) + expected_cov["compute.c.xcov"]["+"].add(4) + + check_xcov_reports("obj", expected_cov, discard_empty=False) + + if level == "stmt+mcdc": + # The order in which sources are instrumented is not specified, so sort + # lines in the output of "gnatcov instrument" to get deterministic test + # execution. + log = "\n".join(sorted(contents_of("instrument.log").splitlines())) + + thistest.fail_if_no_match( + what="Unexpected/missing warnings for MC/DC path limit", + regexp="^" + + "\n".join( + [ + warning_re_for("compute.c", "4:11"), + warning_re_for("testconditions.adb", "17:9"), + ] + ), + actual=log, + ) + + +# Run the mcdc case +do_one_level("stmt+mcdc") + +# Then the decision case +do_one_level("stmt+decision") + +thistest.result() diff --git a/testsuite/tests/U429-016-gnatcov-misuse/main.adb b/testsuite/tests/U429-016-gnatcov-misuse/main.adb new file mode 100644 index 000000000..4fe1236da --- /dev/null +++ b/testsuite/tests/U429-016-gnatcov-misuse/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end; diff --git a/testsuite/tests/U429-016-gnatcov-misuse/test.py b/testsuite/tests/U429-016-gnatcov-misuse/test.py new file mode 100644 index 000000000..675a9937e --- /dev/null +++ b/testsuite/tests/U429-016-gnatcov-misuse/test.py @@ -0,0 +1,69 @@ +""" +Check error messages upon incorrectly providing SCOs to gnatcov. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Generate a project, instrument it and run it +p = gprfor(mains=["main.adb"], srcdirs=[".."]) + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) + +trace_file = xcov_args[-1] + + +def check_output(output_file, expected_content): + """ + Check that the content of the "output_file" text file matches + "expected_content". + """ + thistest.fail_if_no_match( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + contents_of(output_file), + ) + + +def run_and_check(args, output_file, expected_content): + """ + Run gnatcov with the given command line arguments "args", latch the output + in "output_file" and check that this output matches the provided + "expected_content". + """ + p = xcov(args, out=output_file, register_failure=False) + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + " succeeded (see {})".format(output_file), + ) + check_output(output_file, expected_content) + + +# Check that an error is emitted when using --units without -P +run_and_check( + ["coverage", "--level=stmt", "--units=main", trace_file], + "missing_project.txt", + ".*gnatcov.*: --units requires -P", +) + +# Check the error message when not attempting to provide any SCOs +run_and_check( + ["coverage", "--level=stmt", trace_file], + "missing_scos.txt", + ".*gnatcov.*: Please specify SCOs on the command line, specifying Units " + "in project or using \\[--units and -P\\]\\|--scos\\|--sid\\..*", +) + +thistest.result() diff --git a/testsuite/tests/U527-020-dc-from-mcdc/main.adb b/testsuite/tests/U527-020-dc-from-mcdc/main.adb new file mode 100644 index 000000000..c3064790a --- /dev/null +++ b/testsuite/tests/U527-020-dc-from-mcdc/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/U527-020-dc-from-mcdc/test.py b/testsuite/tests/U527-020-dc-from-mcdc/test.py new file mode 100644 index 000000000..737b8d2db --- /dev/null +++ b/testsuite/tests/U527-020-dc-from-mcdc/test.py @@ -0,0 +1,42 @@ +""" +Test that stmt+decision analysis is allowed and functional +on top of stmt+mcdc instrumentation. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov, gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Instrument, build and produce a trace for stmt+mcdc on a very simple +# program. Retrieve the base arguments that we would need to pass to gnatcov +# coverage for an analysis of the same SCOs at that --level: + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=[], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", +) + +# Switch to --level=stmt+decision, add the arguments for the +# output format/location then check that we can produce a report: + +xcov_args = [ + "--level=stmt+decision" if arg.startswith("--level") else arg + for arg in xcov_args +] + +xcov_args.extend(["--annotate=xcov", "--output-dir=xcov"]) + +xcov(xcov_args) + +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {2}, "!": {5}, "-": {6}}}) + +thistest.result() diff --git a/testsuite/tests/U630-040-static-decision/src/p.ads b/testsuite/tests/U630-040-static-decision/src/p.ads new file mode 100644 index 000000000..61bc4dfee --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/src/p.ads @@ -0,0 +1,30 @@ +pragma Ada_2012; + +package P is + subtype Priority is Integer range 10 .. 20; + + FUNNY_PRIO : constant Integer := 999; + + USE_FUNNY_PRIO : constant Boolean := False; + -- constant boolean to guard out of range computation + + Base_Prio : Priority := + (if USE_FUNNY_PRIO then FUNNY_PRIO - 1 else Priority'First); -- # eval + + -- When instrumenting, the tool needs to prevent a Witness call on + -- the static USE_FUNNY_PRIO. Such a call would make the if-expr control + -- non-static, which would get the compiler to evaluate both possible + -- values and error out on FUNNY_PRIO - 1 with: + -- + -- error: value not in range of type "Priority" defined at line 4 + -- error: static expression fails Constraint_Check + + -- And likewise for mcdc conditions: + + FORCE_BASE_PRIO : constant Boolean := False; + + function Prio_Val return Priority is + (if USE_FUNNY_PRIO and then not FORCE_BASE_PRIO -- # complex + then FUNNY_PRIO + else Base_Prio); +end P; diff --git a/testsuite/tests/U630-040-static-decision/src/test_p.adb b/testsuite/tests/U630-040-static-decision/src/test_p.adb new file mode 100644 index 000000000..2ef0dff68 --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/src/test_p.adb @@ -0,0 +1,27 @@ +with P; + +procedure Test_P is + Prio : P.Priority := P.Prio_Val; + pragma Volatile (Prio); +begin + if Prio /= P.Priority'First then + raise Program_Error; + end if; +end; + +-- The "complex" decision case, even though involving a +-- static expression as well, is provided through an expression +-- function for which the compiler generates code. +-- +-- The simpler "eval" case boils down to a static constant, +-- for which no code at all is visible to binary traces. + +--# p.ads +-- +-- /complex/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /eval/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/U630-040-static-decision/test.opt b/testsuite/tests/U630-040-static-decision/test.opt new file mode 100644 index 000000000..677ea7107 --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Missing feature (if expression) in GNAT 5.04 +7.1.2 DEAD expression functions support weak in GNAT 7.1.2 diff --git a/testsuite/tests/U630-040-static-decision/test.py b/testsuite/tests/U630-040-static-decision/test.py new file mode 100644 index 000000000..d0218cecf --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/test.py @@ -0,0 +1,17 @@ +""" +This test checks that gnatcov correctly deals with static decisions. The +instrumenter used to produce code triggering constraint violations as it +made such decisions not static anymore by wrapping them in witness calls. + +Also check that the inner conditions are not wrapped in witness calls, as +this too renders the expression non-static. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/U811-028-suppress-output/main.adb b/testsuite/tests/U811-028-suppress-output/main.adb new file mode 100644 index 000000000..d9f3b70c2 --- /dev/null +++ b/testsuite/tests/U811-028-suppress-output/main.adb @@ -0,0 +1,14 @@ +procedure Main is + + Bool1 : Boolean := False; + pragma Volatile (Bool1); + + Bool2 : Boolean := True; + pragma Volatile (Bool2); + + Res : Boolean; + pragma Volatile (Res); + +begin + Res := Bool1 or else Bool2; +end Main; diff --git a/testsuite/tests/U811-028-suppress-output/test.py b/testsuite/tests/U811-028-suppress-output/test.py new file mode 100644 index 000000000..2a805ddf2 --- /dev/null +++ b/testsuite/tests/U811-028-suppress-output/test.py @@ -0,0 +1,125 @@ +""" +Check that --cancel-annotate prevents the emmission of a coverage +report. +""" + +import os +from os import listdir +from os.path import exists + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, empty +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +p = gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra="package Coverage is" + '\n for Switches ("Coverage") use ("--annotate=report");' + "\nend Coverage;\n", +) + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + gpr_obj_dir="obj", + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=[], +) + +# check that specifying --cancel-annotate without specifying +# --save-checkpoint is not allowed. + +# As the gnatcov command is a full path by default on windows, we will +# explicitely specify it to avoid spurious diffs. +env = dict(os.environ) +env.update({"GNATCOV_CMD": "gnatcov"}) + +process = xcov( + args=xcov_args + ["--cancel-annotate"], + register_failure=False, + out="no-save-checkpoint.txt", + env=env, +) + +thistest.fail_if( + process.status == 0, + comment="Gnatcov returned 0 with --cancel-annotate" + " and no --save-checkpoint option specified", +) +thistest.fail_if_not_equal( + what="Unexpected error message from gnatcov", + expected="gnatcov: Please specify --save-checkpoint on the command line" + " when --cancel-annotate is also specified.\n" + "Usage: gnatcov coverage [OPTIONS] TRACE_FILEs\n" + "Run 'gnatcov coverage --help' for more information.\n", + actual=contents_of("no-save-checkpoint.txt"), +) + +# Check that specifying --cancel-annotate suppresses the emission +# of a coverage report specified in the project file but a checkpoint +# is still emitted. + +xcov( + xcov_args + ["--cancel-annotate", "--save-checkpoint=prj_attr.ckpt"], + out="suppress-report-project-file.txt", +) +thistest.fail_if( + not empty("suppress-report-project-file.txt"), + comment="report output not suppressed (from project file)", +) +thistest.fail_if( + not exists("prj_attr.ckpt"), + comment="Checkpoint file does not exist (project attribute)", +) + + +# Check that specifying --cancel-annotate with --annotate=report on the command +# line does suppress the report output. + +xcov( + args=xcov_args + + [ + "--annotate=report", + "--cancel-annotate", + "--save-checkpoint=cmd_line_report.ckpt", + ], + out="suppress-report.txt", +) + +thistest.fail_if( + not empty("suppress-report.txt"), + comment="report output not suppressed (from command line)", +) +thistest.fail_if( + not exists("cmd_line_report.ckpt"), + comment="Checkpoint file does not exists (--annotate=report)", +) + +# Check that specifying --annotate=supress-output with --annotate=xcov on the +# command line does prevent the creation of .xcov files. + +xcov( + xcov_args + + [ + "--annotate=xcov", + "--output-dir=xcov", + "--cancel-annotate", + "--save-checkpoint=cmd_line_xcov.ckpt", + ] +) + +thistest.fail_if( + len(listdir("xcov")) > 0, + comment="xcov report produced with --cancel-annotate", +) +thistest.fail_if( + not exists("cmd_line_xcov.ckpt"), + comment="Checkpoint file does not exist (--annotate=xcov)", +) + +thistest.result() diff --git a/testsuite/tests/U901-029-estamps/main.adb b/testsuite/tests/U901-029-estamps/main.adb new file mode 100644 index 000000000..c3064790a --- /dev/null +++ b/testsuite/tests/U901-029-estamps/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/U901-029-estamps/test.opt b/testsuite/tests/U901-029-estamps/test.opt new file mode 100644 index 000000000..2b60383b6 --- /dev/null +++ b/testsuite/tests/U901-029-estamps/test.opt @@ -0,0 +1,2 @@ +src-traces,!native DEAD checking trace stamp, no way to get from BB programs +native,RTS_ZFP DEAD checking trace stamp, no way to get it from light runtime diff --git a/testsuite/tests/U901-029-estamps/test.py b/testsuite/tests/U901-029-estamps/test.py new file mode 100644 index 000000000..a4ba405ca --- /dev/null +++ b/testsuite/tests/U901-029-estamps/test.py @@ -0,0 +1,67 @@ +""" +Check that the command execution and trace creation dates +advertised in reports look reasonable. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +import re +from datetime import date + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Build, run, and analyze to produce a "report" output, then verify that the +# dates advertised in the report are consistent with what we perceive is the +# current date. + +report = "report" + +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=report", "-o", report], + covlevel="stmt", + mains=["main"], +) + +# We expect to find two items mentioning the date: +# +# Date and time of execution: 2021-09-15 20:20:50 +02:00 +# +# Then: +# +# Trace files: +# +# main.trace +# ... +# date : 2021-09-15 20:20:50 +02:00 +# +# Fetch the date components and check: + +today = date.today().isoformat() + +report = contents_of(report) + +date_re = r"\d{4}-\d{2}-\d{2}" + +for pattern in ( + r"Date.*execution: (?P%s)" % date_re, + r"date *: (?P%s)" % date_re, +): + m = re.search(pattern=pattern, string=report) + + thistest.fail_if( + not m, "couldn't find a match for pattern '%s' in report" % pattern + ) + + thistest.fail_if( + m.group("date") != today, + "date found (%s) doesn't match today (%s)" % (m.group("date"), today), + ) + +thistest.result() diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb new file mode 100644 index 000000000..a04188dff --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb @@ -0,0 +1,13 @@ +package body Pkg is + + Ret_Val : Boolean; -- # decl + pragma Volatile (Ret_Val); + + function Foo return Boolean is + begin + return Ret_Val; -- # fun + end Foo; + +begin + Ret_Val := A or else C; -- # elab_body +end Pkg; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads new file mode 100644 index 000000000..2eb2d106e --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads @@ -0,0 +1,13 @@ +package Pkg is + + A : Boolean := False; -- # decl + pragma Volatile (A); + B : Boolean := True; -- # decl + pragma Volatile (B); + + function Foo return Boolean; + + C : Boolean := A and then B; -- # elab_spec + pragma Volatile (C); + +end Pkg; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb new file mode 100644 index 000000000..29a585e49 --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb @@ -0,0 +1,12 @@ +package body Pkh is + + function Bar (X : Boolean) return Boolean is + + package Inner_Bar is + Res_Val : Boolean := X and then C; -- # elab_fun + end Inner_Bar; + + begin + return Inner_Bar.Res_Val; + end Bar; +end Pkh; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads new file mode 100644 index 000000000..b26bb2526 --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads @@ -0,0 +1,11 @@ +package Pkh is + A : constant Boolean := True; + + B : constant Boolean := False; + + C : Boolean := A and then B; -- elab_spec + + function Bar (X : Boolean) return Boolean; + +end Pkh; +pragma Preelaborate (Pkh); diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb new file mode 100644 index 000000000..29a516ce3 --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb @@ -0,0 +1,28 @@ +with Pkg; use Pkg; +with Pkh; use Pkh; + +procedure Test_Elab is + Dummy : Boolean; + pragma Volatile (Dummy); +begin + Dummy := Bar (Foo); +end Test_Elab; + +--# pkg.ads +-- +-- /decl/ l+ ## 0 +-- /elab_spec/ l! ## eT- + +--# pkg.adb +-- +-- /decl/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /elab_body/ l! ## eT- + +--# pkh.adb +-- +-- /elab_spec/ l. ## 0 + +--# pkh.adb +-- +-- /elab_fun/ l! ## eT- diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/test.py b/testsuite/tests/UA21-030-elab_mcdc_state/test.py new file mode 100644 index 000000000..b4572a02e --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/test.py @@ -0,0 +1,11 @@ +""" +Test that decisions in elaboration code (both declarations and package body +statments) are proprely instrumented for MCDC. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest +from SCOV.tctl import CAT + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb b/testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb new file mode 100644 index 000000000..6d9c9e0c6 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb @@ -0,0 +1,6 @@ +with B; + +procedure Main is +begin + B.Plop; +end Main; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb new file mode 100644 index 000000000..e44832103 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb @@ -0,0 +1,8 @@ +with C; + +package body B is + procedure Plop is + begin + C.Plop; + end Plop; +end B; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads new file mode 100644 index 000000000..7306088a1 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads @@ -0,0 +1,3 @@ +package B is + procedure Plop; +end B; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb new file mode 100644 index 000000000..ba627c0fb --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; + +package body C is + procedure Plop is + begin + Ada.Text_IO.Put_Line ("Plop"); + end Plop; +end C; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads new file mode 100644 index 000000000..834e07b09 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads @@ -0,0 +1,3 @@ +package C is + procedure Plop; +end C; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/test.py b/testsuite/tests/UB18-055-switches-in-gprfile/test.py new file mode 100644 index 000000000..313309cb1 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/test.py @@ -0,0 +1,61 @@ +""" +This regression test checks that we consider the --projects / --no-subproject +switches when they are given in a project file Coverage.Switches attribute. +""" + +import os + +from SUITE.tutils import gprfor +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports + +tmp = Wdir("tmp_") + +gpr_coverage_package = """ + package Coverage is + for Switches ("coverage") use ("--level=stmt+decision", + "--projects", "b", + "--no-subprojects"); + end Coverage; +""" + +a_gpr = gprfor( + mains=["main.adb"], + prjid="a", + srcdirs=os.path.join("..", "a"), + objdir="obj-a", + deps=["b"], + extra=gpr_coverage_package, +) +b_gpr = gprfor( + mains=[], + prjid="b", + srcdirs=os.path.join("..", "b"), + langs=["Ada"], + objdir="obj-b", + deps=["c"], +) +c_gpr = gprfor( + mains=[], + prjid="c", + srcdirs=os.path.join("..", "c"), + langs=["Ada"], + objdir="obj-c", +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=a_gpr), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-a", + extra_coverage_args=["-axcov", "--output-dir=."], +) + +# Check that we have coverage result only for the project of interest, as +# specified in the gpr file. + +check_xcov_reports(".", {"b.ads.xcov": {}, "b.adb.xcov": {"+": {6}}}) + +thistest.result() diff --git a/testsuite/tests/V120-034-dup-langs/main.adb b/testsuite/tests/V120-034-dup-langs/main.adb new file mode 100644 index 000000000..c3064790a --- /dev/null +++ b/testsuite/tests/V120-034-dup-langs/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/V120-034-dup-langs/test.py b/testsuite/tests/V120-034-dup-langs/test.py new file mode 100644 index 000000000..6c7198c59 --- /dev/null +++ b/testsuite/tests/V120-034-dup-langs/test.py @@ -0,0 +1,28 @@ +""" +Check that we handle duplication and casing differences for language names in +--restricted-to-languages. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=xcov"], + extra_instr_args=["--restricted-to-languages=Ada,ada"], + covlevel="stmt", + mains=["main"], + trace_mode="src", +) + +check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5}, "-": {6}}}) + +thistest.result() diff --git a/testsuite/tests/V201-010-multi-report/main.adb b/testsuite/tests/V201-010-multi-report/main.adb new file mode 100644 index 000000000..83fcc87e6 --- /dev/null +++ b/testsuite/tests/V201-010-multi-report/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end Main; diff --git a/testsuite/tests/V201-010-multi-report/test.py b/testsuite/tests/V201-010-multi-report/test.py new file mode 100644 index 000000000..4ebcc44ad --- /dev/null +++ b/testsuite/tests/V201-010-multi-report/test.py @@ -0,0 +1,50 @@ +""" +Check that gnatcov correctly produces multiple reports when requested +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +import os + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=report,xcov,dhtml", "--annotate=xml"], + covlevel="stmt", + mains=["main"], + out="coverage.log", +) + +# For the xcov report kind we can check the actual content +check_xcov_reports("obj/xcov", {"main.adb.xcov": {"+": {2, 5}, "-": {6}}}) + +# Check that there is a report in the log of the coverage command +thistest.fail_if_no_match( + what="did not find report in the coverage output", + regexp=r"(.|\n)*" + r"\*\* COVERAGE REPORT \*\*" + r"(.|\n)*" + r"\n\*\* END OF REPORT \*\*", + actual=contents_of("coverage.log"), +) + +# For the others, we'll fall back to checking that there are files produced +# in the expected directories + +thistest.fail_if( + not os.path.exists("obj/html/main.adb.hunk.js"), "no html report produced" +) + +thistest.fail_if( + not os.path.exists("obj/xml/main.adb.xml"), "no xml report produced" +) + +thistest.result() diff --git a/testsuite/tests/V304-007-missing-files/baz.adb b/testsuite/tests/V304-007-missing-files/baz.adb new file mode 100644 index 000000000..a44560963 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/baz.adb @@ -0,0 +1,6 @@ +with Bar; + +procedure Baz is +begin + Bar.Do_Things; +end Baz; diff --git a/testsuite/tests/V304-007-missing-files/foo.adb b/testsuite/tests/V304-007-missing-files/foo.adb new file mode 100644 index 000000000..973507ac2 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/foo.adb @@ -0,0 +1,7 @@ +with Bar, Baz; + +procedure Foo is +begin + Baz; + Bar.Do_Things; +end Foo; diff --git a/testsuite/tests/V304-007-missing-files/test.opt b/testsuite/tests/V304-007-missing-files/test.opt new file mode 100644 index 000000000..46bf1b3c9 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/test.opt @@ -0,0 +1,3 @@ +-- This test intentionally misses source files, so the instrumenter gets +-- errors from Libadalang (turned into noisy warnings). +all-warnings DEAD diff --git a/testsuite/tests/V304-007-missing-files/test.py b/testsuite/tests/V304-007-missing-files/test.py new file mode 100644 index 000000000..38a95ddc7 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/test.py @@ -0,0 +1,34 @@ +""" +Check that "gnatcov instrument" warns about missing files. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) +mkdir("obj") + +xcov_instrument( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + out="instrument.log", + tolerate_messages=".", +) + +thistest.fail_if_not_equal( + what="'gnatcov instrument' output", + expected=( + "warning: While instrumenting baz.adb...\n" + "warning: Cannot find required source file: bar.ads\n" + ), + actual=contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/V309-017-setup-config/foo.adb b/testsuite/tests/V309-017-setup-config/foo.adb new file mode 100644 index 000000000..3072b68a4 --- /dev/null +++ b/testsuite/tests/V309-017-setup-config/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello world!"); +end Foo; diff --git a/testsuite/tests/V309-017-setup-config/test.opt b/testsuite/tests/V309-017-setup-config/test.opt new file mode 100644 index 000000000..d39effadc --- /dev/null +++ b/testsuite/tests/V309-017-setup-config/test.opt @@ -0,0 +1,6 @@ +-- This test needs to check that --dump-channel is properly handled in a +-- typical gnatcov usage workflow. To do this, it needs multiple dump channels +-- to be supported, i.e. a native platform (bin-file and base64-stdout), and +-- a full runtime. +!native DEAD +RTS_ZFP DEAD diff --git a/testsuite/tests/V309-017-setup-config/test.py b/testsuite/tests/V309-017-setup-config/test.py new file mode 100644 index 000000000..3edd12cb9 --- /dev/null +++ b/testsuite/tests/V309-017-setup-config/test.py @@ -0,0 +1,112 @@ +""" +Check that dump options passed to "gnatcov setup" are used as defaults for the +subsequent "gnatcov instrument" using the installed instrumentation runtime. + +Note that for test simplicity, here we only check this for --dump-channel: dump +config code being shared in gnatcov, in principle it should work for all other +--dump-* options (there are lots of such options and checking that they are +used is not trivial). +""" + +import json +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Installation directory for the instrumentation runtime projects and directory +# for the project path. +rt_install_dir = os.path.abspath("install") +rt_path_dir = os.path.join(rt_install_dir, "share", "gpr") + +# Make this install available to GPR tools +env.add_search_path("GPR_PROJECT_PATH", rt_path_dir) + + +def xsetup(install_name, args): + """ + "xcov" wrapper to run "gnatcov setup". + + This wrapper just automatically passes --install-name and --prefix + arguments. + """ + xcov( + [ + "setup", + f"--install-name={install_name}", + f"--prefix={rt_install_dir}", + ] + + args, + force_project_args=True, + ) + + +# Test project to instrument +prj = gprfor(srcdirs=[".."], mains=["foo.adb"]) + +# Install two runtime projects, each with different dump-channel defaults. The +# default is --dump-channel=bin-file. +for rt_name, dump_args in [ + ("rt_def", []), + ("rt_b64", ["--dump-channel=base64-stdout"]), +]: + xsetup(rt_name, dump_args) + +# Now instrument and build the test program in various scenarios. For each +# case, we just call build_run_and_coverage, which relies on the metadata that +# "gnatcov instrument" writes to the object directory in order to know how to +# read traces ("*.srctrace" binary file or decode base64 trace from the +# stdout). +# +# We expect the dump channel to be the first parameter in the following list +# (when passed): +# +# * --dump-channel passed to "gnatcov instrument"; +# * --dump-channel passed to "gnatcov setup"; +# * bin-file (the ultimate default for native targets). +for label, rt_name, dump_args, expected_dump_channel in [ + ("def_def", "rt_def", [], "bin-file"), + ( + "def_base64", + "rt_def", + ["--dump-channel=base64-stdout"], + "base64-stdout", + ), + ("b64_def", "rt_b64", [], "base64-stdout"), + ("b64_binfile", "rt_b64", ["--dump-channel=bin-file"], "bin-file"), +]: + thistest.log(f"== {label} ==") + build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["foo"], + extra_instr_args=dump_args + ["--runtime-project", rt_name], + runtime_project=rt_name, + extra_coverage_args=["-axcov", "--output-dir=."], + dump_channel=None, + trace_mode="src", + ) + check_xcov_reports(".", {"foo.adb.xcov": {"+": {5}}}) + + # Make sure that the metadata contains the expected dump channel + with open("obj/gnatcov-instr.json") as f: + params = json.load(f) + thistest.fail_if_not_equal( + "actual dump trigger", + "atexit", + params["dump-trigger"], + ) + thistest.fail_if_not_equal( + "actual dump channel", + expected_dump_channel, + params["dump-channel"], + ) + +thistest.result() diff --git a/testsuite/tests/V520-019-duplicate-messages/main.adb b/testsuite/tests/V520-019-duplicate-messages/main.adb new file mode 100644 index 000000000..dadf3e517 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is + X : Integer := Pkg.Foo; + pragma Volatile (X); +begin + null; +end Main; diff --git a/testsuite/tests/V520-019-duplicate-messages/pkg.adb b/testsuite/tests/V520-019-duplicate-messages/pkg.adb new file mode 100644 index 000000000..2959d2732 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/pkg.adb @@ -0,0 +1,13 @@ +package body Pkg is + + function Foo return Integer is + begin + return 1; + end Foo; + + function Bar return Integer is + begin + return 2; + end Bar; + +end Pkg; diff --git a/testsuite/tests/V520-019-duplicate-messages/pkg.ads b/testsuite/tests/V520-019-duplicate-messages/pkg.ads new file mode 100644 index 000000000..93de195e9 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + function Foo return Integer; + + function Bar return Integer; + +end Pkg; diff --git a/testsuite/tests/V520-019-duplicate-messages/test.py b/testsuite/tests/V520-019-duplicate-messages/test.py new file mode 100644 index 000000000..16a342704 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/test.py @@ -0,0 +1,45 @@ +""" +Check that when producing multiple reports in one "gnatcov coverage" +execution messages are not emitted multiple times. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Test project to instrument +prj = gprfor(srcdirs=[".."], mains=["main.adb"], objdir="obj") + +# Generate multiple reports for prj in a single "gnatcov coverage" execution +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-areport,xcov", "--output-dir=obj"], + out="coverage.log", +) + +# Check the expected results +expected_cov = {"main.adb.xcov": {}, "pkg.adb.xcov": {"-": {10}}} +if thistest.options.trace_mode == "src": + expected_cov["pkg.ads.xcov"] = {} +check_xcov_reports("obj", expected_cov, discard_empty=False) + +# Check that we do not have any duplicate messages. In this case, we only +# expect a single statment violation. +thistest.fail_if_no_match( + "More than one violation detected", + r"(.|\n)*2.1. STMT COVERAGE" + r"\n------------------" + r"\n" + r"\npkg.adb:10:7: statement not executed" + r"\n" + r"\n1 violation.(.|\n)*", + contents_of("coverage.log"), +) + +thistest.result() diff --git a/testsuite/tests/V616-028-xsd-check/lib.c b/testsuite/tests/V616-028-xsd-check/lib.c new file mode 100644 index 000000000..c1524eef2 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/lib.c @@ -0,0 +1,5 @@ +int +and_then (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/V616-028-xsd-check/pkg.adb b/testsuite/tests/V616-028-xsd-check/pkg.adb new file mode 100644 index 000000000..1f3b12e57 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + function Id (A : Boolean) return Boolean is + begin + return A; + end Id; +end Pkg; diff --git a/testsuite/tests/V616-028-xsd-check/pkg.ads b/testsuite/tests/V616-028-xsd-check/pkg.ads new file mode 100644 index 000000000..4c73d86df --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/pkg.ads @@ -0,0 +1,9 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + function And_Then (A, B : int) return int; + pragma Import + (Convention => C, Entity => And_Then, External_Name => "and_then"); + + function Id (A : Boolean) return Boolean; +end Pkg; diff --git a/testsuite/tests/V616-028-xsd-check/test.adb b/testsuite/tests/V616-028-xsd-check/test.adb new file mode 100644 index 000000000..7d416f467 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/test.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Interfaces.C; use Interfaces.C; + +with Pkg; + +procedure Test is + function And_Then (A, B : Boolean) return Boolean; + + function And_Then (A, B : Boolean) return Boolean is + begin + return A and then B; + end And_Then; + +begin + Put_Line (int'Image (Pkg.And_Then (0, 1))); + Put_Line (Boolean'Image (And_Then (Pkg.Id (True), False))); +end Test; diff --git a/testsuite/tests/V616-028-xsd-check/test.py b/testsuite/tests/V616-028-xsd-check/test.py new file mode 100644 index 000000000..bc8861f01 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/test.py @@ -0,0 +1,60 @@ +""" +Check that the distributed XSD validates different kinds of XML reports +produced by gnatcov. +""" + +import os + +from lxml import etree + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + + +def check_xml(xsd_file, xml_file): + xsd_doc = etree.parse(xsd_file) + xsd = etree.XMLSchema(xsd_doc) + xml = etree.parse(xml_file) + xml.xinclude() + try: + xsd.assertValid(xml) + except Exception as exc: + thistest.failed( + "The XSD does not validate {}: \n {}".format( + os.path.abspath(xml_file), exc + ) + ) + + +# The XML Schema is generated in the output directory with the XML report +def xsd_file(output_dir): + return os.path.join(output_dir, "gnatcov-xml-report.xsd") + + +def xml_file(output_dir): + return os.path.join(output_dir, "index.xml") + + +def build_run_coverage_and_check(covlevel): + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test.adb"]) + ), + covlevel=covlevel, + mains=["test"], + extra_coverage_args=["--annotate=xml"], + ) + check_xml(xsd_file("obj"), xml_file("obj")) + + +build_run_coverage_and_check("stmt+mcdc") + +if thistest.options.trace_mode == "bin": + build_run_coverage_and_check("insn") + build_run_coverage_and_check("branch") + +thistest.result() diff --git a/testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr b/testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr new file mode 100644 index 000000000..511b46e91 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr @@ -0,0 +1,6 @@ +project Ext_Pkg extends "pkg.gpr" is + for Source_Dirs use ("src-ext_pkg"); + for Main use ("main.adb"); + for Exec_Dir use "."; + for Object_Dir use "obj-ext_pkg"; +end Ext_Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/pkg.gpr b/testsuite/tests/V824-005-sid-ext-prj/pkg.gpr new file mode 100644 index 000000000..6227043a4 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/pkg.gpr @@ -0,0 +1,4 @@ +project Pkg is + for Source_Dirs use ("src-pkg"); + for Object_Dir use "obj-pkg"; +end Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb b/testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb new file mode 100644 index 000000000..69661642e --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + --------- + -- Foo -- + --------- + + procedure Foo is + begin + Put_Line ("Hello, world!"); + end Foo; + +end Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads new file mode 100644 index 000000000..d91f3ae51 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Foo; +end Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/test.py b/testsuite/tests/V824-005-sid-ext-prj/test.py new file mode 100644 index 000000000..765b0f9cd --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/test.py @@ -0,0 +1,58 @@ +""" +Test that SID files are created in the object directory of the extending +project (i.e. not in the extended project's object directory). +""" + +import os.path + +from e3.fs import mkdir, sync_tree + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +wd = Wdir("tmp_") + +# Copy the projec tree in the temporary directory +for filename in ["src-pkg", "src-ext_pkg", "pkg.gpr", "ext_pkg.gpr"]: + sync_tree(os.path.join("..", filename), filename) + +# Go through the instrument/build/run cycle +xcov_args = build_and_run( + gprsw=GPRswitches(root_project="ext_pkg.gpr", units=["pkg"]), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-ext_pkg", + extra_coverage_args=["--annotate=xcov", "--output-dir=output"], + trace_mode="src", +) + +# Make sure that SID files were created in the extending project tree, not in +# the extended project tree. +orig_sid = os.path.join("obj-pkg", "pkg.sid") +ext_sid = os.path.join("obj-ext_pkg", "pkg.sid") +thistest.fail_if(os.path.exists(orig_sid), f"Spurious {orig_sid} found") +thistest.fail_if(not os.path.exists(ext_sid), f"Missing expected {ext_sid}") + +# Before running "gnatcov coverage", create a dummy SID file in the extended +# project. "gnatcov coverage" should not try to use it, as there is a SID file +# in the extending project. +# +# Note that gprbuild may not create the object directory for the extended +# project, so do it manually. +mkdir("obj-pkg") +with open(orig_sid, "w") as f: + f.write("dummy SID file\n") + +# Compute the coverage report and check its contents (sanity check) +xcov(xcov_args, out="coverage.log") +check_xcov_reports( + "output", + {"pkg.adb.xcov": {"+": {11}}, "pkg.ads.xcov": {}}, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c new file mode 100644 index 000000000..a1b61ceef --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c @@ -0,0 +1,5 @@ +int +foo (void) +{ + return 0; +} diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h new file mode 100644 index 000000000..2fe431a4f --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h @@ -0,0 +1 @@ +extern int foo (void); diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c new file mode 100644 index 000000000..acdc74a63 --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c @@ -0,0 +1,11 @@ +#include "foo.h" + +int +main () +{ + int volatile a = 1, b = 0; + if (a && b) + return 0; + else + return foo (); +} diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py new file mode 100644 index 000000000..81d023d93 --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py @@ -0,0 +1,27 @@ +""" +Check that gnatcov --dump-trigger=main-end produces valid code when the main +is not a unit of interest and thus when the main code was not curlified. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["test.c"], srcdirs=[".."]), units=["foo.c"] + ), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", +) + +check_xcov_reports("xcov", {"foo.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c new file mode 100644 index 000000000..118ce390d --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c @@ -0,0 +1,6 @@ +int +main () +{ + int volatile a = 1, b = 0; + return a && b; +} diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py new file mode 100644 index 000000000..cb2547056 --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py @@ -0,0 +1,27 @@ +""" +Check that gnatcov --dump-trigger=main-end actually dump coverage buffers after +the return expression has been executed. +TODO: add a lambda expression and turn this into a C++ test when C++ support +lands in master. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.c"], srcdirs=[".."])), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", +) + +check_xcov_reports("xcov", {"test.c.xcov": {"+": {4}, "!": {5}}}) + +thistest.result() diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb b/testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb new file mode 100644 index 000000000..24f762c65 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb @@ -0,0 +1,10 @@ +with Pkg_1; +with Pkg_2; + +procedure Main is + function Incr is new Pkg_1.Generic_Incr; + function Decr is new Pkg_2.Generic_Decr; + Dummy : constant Integer := Decr (Incr (1)); +begin + null; +end Main; diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads new file mode 100644 index 000000000..a19ed1ecd --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pkg_1 is + + generic + Incr : Natural := 1; + function Generic_Incr (Value : Integer) return Integer; + + function Generic_Incr (Value : Integer) return Integer + is (Value + Incr); + + I : Integer := 0; + +end Pkg_1; diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads new file mode 100644 index 000000000..9c72502b9 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pkg_2 is + + generic + Decr : Natural := 1; + function Generic_Decr (Value : Integer) return Integer; + + function Generic_Decr (Value : Integer) return Integer + is (Value - Decr); + + I : Integer := 0; + +end Pkg_2; diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt new file mode 100644 index 000000000..4d7631d98 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Bug reproducer requires expression functions diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py new file mode 100644 index 000000000..eedd88380 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py @@ -0,0 +1,44 @@ +""" +Regression test: the relocation logic for non instrumented SCOs when loading +SCOs/checkpoints used to be buggy and some non-instrumented SCOs ended up being +instrumented during "gnatcov coverage". +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Instrument the pkg_1 and pkg_2 units. Both contain unsupported constructs +# (generic expression functions), so both will create non-instrumented SCO +# statements. +# +# The coverage step will load SID files for both units, and this step used to +# discard the non-instrumented info for the second SID file loaded because of a +# bug in the SCO_Id relocation mechanism for non-instrumented SCOs. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr, units=["pkg_1", "pkg_2"]), + extra_coverage_args=["--annotate=xcov"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + tolerate_instrument_messages=( + "cannot instrument generic expression function" + ), +) + +check_xcov_reports( + "obj", + expected_cov={ + "pkg_1.ads.xcov": {"?": {10}, "+": {12}}, + "pkg_2.ads.xcov": {"?": {10}, "+": {12}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/VB07-015-clean-output-dir/main.adb b/testsuite/tests/VB07-015-clean-output-dir/main.adb new file mode 100644 index 000000000..1f2932234 --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +procedure Main is + X : Integer := 4; + pragma Volatile (X); +begin + X := Ident (X); +end Main; diff --git a/testsuite/tests/VB07-015-clean-output-dir/pkg.adb b/testsuite/tests/VB07-015-clean-output-dir/pkg.adb new file mode 100644 index 000000000..7a73f74bb --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Ident (X : Integer) return Integer is + begin + return X; + end Ident; + +end Pkg; diff --git a/testsuite/tests/VB07-015-clean-output-dir/pkg.ads b/testsuite/tests/VB07-015-clean-output-dir/pkg.ads new file mode 100644 index 000000000..9ff0e430a --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Ident (X : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py new file mode 100644 index 000000000..4d33ac815 --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -0,0 +1,80 @@ +""" +Check that gnatcov correctly cleans any previously existing xcov report before +producing a new one. +""" + +from SCOV.minicheck import build_and_run, xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +from e3.fs import mkdir + +import os + +tmp = Wdir("tmp_") + +expected_cov = { + "main.adb": {"+": {4, 7}}, + "pkg.adb": {"+": {5}}, + "pkg.ads": {}, +} + +possible_output_dirs = ["obj", os.path.join("obj", "xcov")] + + +def check_one(units, output_dir, xcov_args): + """ + Run gnatcov coverage with the specified xcov_args and check that we only + get a coverage report for units in output_dir. Also check that all + directories that are not output_dir contain no .xcov files. + """ + xcov(xcov_args) + for dirname in possible_output_dirs: + thistest.log(f"inspecting {dirname}") + check_xcov_reports( + dirname, + ( + {f"{unit}.xcov": expected_cov[unit] for unit in units} + if dirname == output_dir + else {} + ), + ) + + +# Create the traces +xcov_args = build_and_run( + gprsw=GPRswitches(gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) + +# Create the possible output dirs +for dirname in possible_output_dirs: + mkdir(os.path.join(os.getcwd(), dirname)) + +# First, produce a report for all units, with a single report format specified +thistest.log("=== Step 1: all units in obj ===") +check_one(["main.adb", "pkg.adb", "pkg.ads"], "obj", xcov_args + ["-axcov"]) + +# Then only create a report for pkg, still a single report format +thistest.log("=== Step 2: pkg in obj ===") +check_one(["pkg.adb", "pkg.ads"], "obj", xcov_args + ["-axcov", "--units=pkg"]) + +# Now create a report for both units, but specifying two output formats +# (thus creating a subdir). +thistest.log("=== Step 3: all units in obj/xcov ===") +check_one( + ["main.adb", "pkg.adb", "pkg.ads"], + os.path.join("obj", "xcov"), + xcov_args + ["-axcov,html"], +) + +# An finally check that the subdir is also cleaned when once again generating +# report with a single report format. +thistest.log("=== Step 4: pkg in obj ===") +check_one(["pkg.adb", "pkg.ads"], "obj", xcov_args + ["-axcov", "--units=pkg"]) + +thistest.result() diff --git a/testsuite/tests/VB18-035-default-opts/main.adb b/testsuite/tests/VB18-035-default-opts/main.adb new file mode 100644 index 000000000..55db5185b --- /dev/null +++ b/testsuite/tests/VB18-035-default-opts/main.adb @@ -0,0 +1,10 @@ +procedure Main is + Val : Boolean := True; + pragma Volatile (Val); +begin + if Val then + Val := False; + else + Val := True; + end if; +end Main; diff --git a/testsuite/tests/VB18-035-default-opts/test.py b/testsuite/tests/VB18-035-default-opts/test.py new file mode 100644 index 000000000..a7ebddb4b --- /dev/null +++ b/testsuite/tests/VB18-035-default-opts/test.py @@ -0,0 +1,64 @@ +""" +Test that gnatcov chooses the correct defaults for the level and the +annotation format, and that it emits a warning concerning the level default +value. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def check_log(command, log_file): + thistest.fail_if_no_match( + what=f"Missing warning about default level for command {command}", + regexp=r"warning: Coverage level not specified on the command line or" + r' in the project file \(--level=.*\), defaulting to "stmt"\.', + actual=contents_of(log_file), + ) + + +tmp = Wdir("tmp_") + +# 1. Check the instrument command by not specifying a coverage level to +# build_and_run. Tolerate any warning, we'll check the log. +cov_args = build_and_run( + GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel=None, + mains=["main"], + tolerate_instrument_messages="Coverage level not specified", + extra_coverage_args=[], +) + +if thistest.options.trace_mode == "src": + check_log("instrument", "instrument.log") + +# We do not check the output of gnatcov run as it was already possible +# not to specify a coverage level for that command. + +# 2. Check the output of the coverage command while specifying an annotation +# format, and check that the coverage report corresponds to a stmt level. +cov_log = "coverage_no_level.log" +xcov( + cov_args + ["-axcov"], + out=cov_log, + tolerate_messages="Coverage level not specified", +) + +check_log("coverage", cov_log) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5, 6}, "-": {8}}}) + +# 3. Run the coverage command without specifying an annotation format and +# check if there is a report on the standard output. + +cov_log = "coverage_no_annotate.log" +xcov(cov_args + ["-cstmt"], out=cov_log) +thistest.fail_if_no_match( + what="Missing report on the standard output without annotation format", + regexp=r"\*\* COVERAGE REPORT \*\*", + actual=contents_of(cov_log), +) + +thistest.result() diff --git a/testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb b/testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb new file mode 100644 index 000000000..6e42d1bc2 --- /dev/null +++ b/testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb @@ -0,0 +1,15 @@ +procedure Main is + function F (A, B : Boolean) return Boolean is + begin + if A and then B then + return True; + else + return False; + end if; + end F; + + C : Boolean := F (False, True); + D : Boolean := F (True, True); +begin + null; +end Main; diff --git a/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py new file mode 100644 index 000000000..f2b176db9 --- /dev/null +++ b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py @@ -0,0 +1,46 @@ +""" +Check that "gnatcov coverage" properly rejects mismatching SID files and source +trace files (i.e. source traces generated by an instrumented program, and SID +files created by an incompatible instrumentation of this program). +""" + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +wd = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) +gprsw = GPRswitches(root_project=gpr) + +# Go through the instrument/build/run cycle in stmt+mcdc mode +xcov_args = build_and_run( + gprsw=gprsw, + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", +) + +# Re-instrument in stmt mode +xcov_instrument(gprsw=gprsw, covlevel="stmt") + +# Now compute code coverage using 1) the old trace 2) the new SIDs. We expect a +# warning about inconsistent Source Instrumentation Data and discarded coverage +# info (i.e. code not covered). +level_arg = xcov_args.index("--level=stmt+mcdc") +xcov_args[level_arg] = "--level=stmt" +xcov(xcov_args, out="coverage.log", tolerate_messages=".") +thistest.fail_if_no_match( + "'gnatcov coverage' output", + r"warning: traces for body of main \(from main.*\.srctrace\) are" + " inconsistent with the corresponding Source Instrumentation Data", + contents_of("coverage.log").strip(), +) +check_xcov_reports("obj", {"main.adb.xcov": {"-": {4, 5, 7, 11, 12, 14}}}) + +thistest.result() diff --git a/testsuite/tests/VC19-001-origin-prj/src_code/code.adb b/testsuite/tests/VC19-001-origin-prj/src_code/code.adb new file mode 100644 index 000000000..bbea9e083 --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/src_code/code.adb @@ -0,0 +1,6 @@ +package body Code is + function Compute (X : Boolean; Y : Boolean) return Boolean is + begin + return X and then Y; + end Compute; +end Code; diff --git a/testsuite/tests/VC19-001-origin-prj/src_code/code.ads b/testsuite/tests/VC19-001-origin-prj/src_code/code.ads new file mode 100644 index 000000000..22be3a035 --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/src_code/code.ads @@ -0,0 +1,3 @@ +package Code is + function Compute (X : Boolean; Y : Boolean) return Boolean; +end Code; diff --git a/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb b/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb new file mode 100644 index 000000000..afd28330d --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb @@ -0,0 +1,12 @@ +with Code; + +procedure Test_Main is + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + Assert (Code.Compute (True, False) = Code.Compute (False, True)); +end Test_Main; diff --git a/testsuite/tests/VC19-001-origin-prj/test.py b/testsuite/tests/VC19-001-origin-prj/test.py new file mode 100644 index 000000000..ce9230429 --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/test.py @@ -0,0 +1,50 @@ +""" +Check that gnatcov correctly uses the Switches attributes from the +project designated by the Origin_Project attribute in the root project. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Generate a project file for our code, containing all the relevant +# coverage switches in the Coverage package Switches attributes. +code_prj = gprfor( + mains=[], + prjid="code", + srcdirs=[os.path.join("..", "src_code")], + extra="package Coverage is" + '\n for Switches ("*") use ("--level=stmt+mcdc");' + '\n for Switches ("coverage") use ("-axcov", "--output-dir=xcov");' + "\nend Coverage;", +) + +# Generate a project for the test driver, "withing" the code project and +# referencing it through the Origin_Project attribute +test_prj = gprfor( + mains=["test_main.adb"], + prjid="test", + srcdirs=[os.path.join("..", "src_test")], + deps=[code_prj], + extra=f'for Origin_Project use "{code_prj}";', +) + +# No level or annotation format provided, everything should be loaded from +# the Origin_Project (code.gpr). +build_run_and_coverage( + gprsw=GPRswitches(root_project=test_prj), + covlevel=None, + extra_coverage_args=[], + mains=["test_main"], +) + +check_xcov_reports("xcov", {"code.ads.xcov": {}, "code.adb.xcov": {"!": {4}}}) + +thistest.result() diff --git a/testsuite/tests/W315-021-generic-preelab/pkg.adb b/testsuite/tests/W315-021-generic-preelab/pkg.adb new file mode 100644 index 000000000..a25d2cf21 --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/pkg.adb @@ -0,0 +1,5 @@ +package body Pkg is + Var : constant Integer := 2; + + procedure Foo is null; +end Pkg; diff --git a/testsuite/tests/W315-021-generic-preelab/pkg.ads b/testsuite/tests/W315-021-generic-preelab/pkg.ads new file mode 100644 index 000000000..0e87851ab --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/pkg.ads @@ -0,0 +1,6 @@ +generic + A : Integer; +package Pkg is + pragma Preelaborate; + procedure Foo; +end Pkg; diff --git a/testsuite/tests/W315-021-generic-preelab/test.adb b/testsuite/tests/W315-021-generic-preelab/test.adb new file mode 100644 index 000000000..427fe2daf --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/test.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Test is + package Pkg_Inst is new Pkg (2); +begin + Pkg_Inst.Foo; +end Test; diff --git a/testsuite/tests/W315-021-generic-preelab/test.py b/testsuite/tests/W315-021-generic-preelab/test.py new file mode 100644 index 000000000..65107c97d --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/test.py @@ -0,0 +1,30 @@ +""" +Check that declarations of a generic preelaborate Ada unit are not +instrumented, as it would otherwise result in uncompilable code. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports( + "obj", + { + "test.adb.xcov": {"+": {4, 6}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {4}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/Z999-999/test.opt b/testsuite/tests/Z999-999/test.opt new file mode 100644 index 000000000..e01fc68f8 --- /dev/null +++ b/testsuite/tests/Z999-999/test.opt @@ -0,0 +1 @@ +ALL XFAIL [should always fail] diff --git a/testsuite/tests/Z999-999/test.py b/testsuite/tests/Z999-999/test.py new file mode 100644 index 000000000..49fdfa77e --- /dev/null +++ b/testsuite/tests/Z999-999/test.py @@ -0,0 +1,9 @@ +from SUITE.tutils import maybe_valgrind + +print("tool versions are now emitted as comments attached to this run") + +print("valgrind control: " + str(maybe_valgrind([]))) + +print("End of Z999-999") + +# This test will fail by not calling thistest.result() diff --git a/testsuite/tests/asm-consolidate/src/lib.adb b/testsuite/tests/asm-consolidate/src/lib.adb new file mode 100644 index 000000000..ad617e158 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/lib.adb @@ -0,0 +1,18 @@ +package body Lib is + + -- We will be checking full object coverage by just exercising the source + -- condition True and False. Possible overflow checks are not part of the + -- goal. + + pragma Suppress (All_Checks); + + procedure Adjust (X : in out Integer) is + begin + if X > 0 then + X := X - 1; + else + X := X + 1; + end if; + end; + +end; diff --git a/testsuite/tests/asm-consolidate/src/lib.ads b/testsuite/tests/asm-consolidate/src/lib.ads new file mode 100644 index 000000000..b1937e167 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/lib.ads @@ -0,0 +1,5 @@ +package Lib is + + procedure Adjust (X : in out Integer); + +end; diff --git a/testsuite/tests/asm-consolidate/src/p1.adb b/testsuite/tests/asm-consolidate/src/p1.adb new file mode 100644 index 000000000..ed9b0a062 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/p1.adb @@ -0,0 +1,9 @@ +with Stuff1, Lib; + +procedure P1 is + X : Integer := 7; + pragma Volatile (X); +begin + Stuff1.Run; + Lib.Adjust (X); +end; diff --git a/testsuite/tests/asm-consolidate/src/p2.adb b/testsuite/tests/asm-consolidate/src/p2.adb new file mode 100644 index 000000000..029ffe337 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/p2.adb @@ -0,0 +1,7 @@ +with Lib; +procedure P2 is + X : Integer := -12; + pragma Volatile (X); +begin + Lib.Adjust (X); +end; diff --git a/testsuite/tests/asm-consolidate/src/stuff1.adb b/testsuite/tests/asm-consolidate/src/stuff1.adb new file mode 100644 index 000000000..42dc976f7 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/stuff1.adb @@ -0,0 +1,7 @@ + +package body Stuff1 is + procedure Run is + begin + Counter := Counter + 1; + end; +end; diff --git a/testsuite/tests/asm-consolidate/src/stuff1.ads b/testsuite/tests/asm-consolidate/src/stuff1.ads new file mode 100644 index 000000000..5b01d0bb7 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/stuff1.ads @@ -0,0 +1,4 @@ +package Stuff1 is + Counter : Integer := 0; + procedure Run; +end; diff --git a/testsuite/tests/asm-consolidate/test.opt b/testsuite/tests/asm-consolidate/test.opt new file mode 100644 index 000000000..99b5b4ca1 --- /dev/null +++ b/testsuite/tests/asm-consolidate/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage-specific test diff --git a/testsuite/tests/asm-consolidate/test.py b/testsuite/tests/asm-consolidate/test.py new file mode 100644 index 000000000..d9f010201 --- /dev/null +++ b/testsuite/tests/asm-consolidate/test.py @@ -0,0 +1,75 @@ +""" +Verify that consolidation works for object-coverage with asm outputs. +""" + +import re + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.tutils import ( + exename_for, + exepath_to, + gprbuild, + gprfor, + xcov, + xrun, + tracename_for, +) +from SUITE.cutils import Wdir + + +Wdir("tmp_") + +# Build two programs using a common "lib" unit, organized so the unit object +# code is placed at different addresses in the two executables. +gpr = gprfor(srcdirs=["../src"], mains=["p1.adb", "p2.adb"]) +gprbuild(gpr) + +# Check that the lib subprograms are at different addresses +libsym = target_info().to_platform_specific_symbol("lib__adjust") + + +def address_range_for(symname, binfile): + m = re.search( + pattern=r"(?P\S*-\S*) symbol for %s" % symname, + string=xcov(["dump-symbols", binfile]).out, + ) + + return m.group("address_range") + + +thistest.fail_if( + address_range_for(libsym, exename_for("p1")) + == address_range_for(libsym, exename_for("p2")), + "address ranges for %s are identical" % libsym, +) + +# Execute both programs: +xrun(exepath_to("p1")) +xrun(exepath_to("p2")) + +# Do object level coverage analysis. We expect each program to cover the +# lib symbol only partially, and the two combined to cover the lib symbol +# complete. + + +def check(pgmlist): + covnote = "!" if len(pgmlist) == 1 else "+" + + out = xcov( + "coverage --level=branch --annotate=asm %s --routines=%s" + % (" ".join(tracename_for(pgm) for pgm in pgmlist), libsym) + ).out + + results = re.findall(string=out, pattern="%s \\%c:" % (libsym, covnote)) + thistest.fail_if( + len(results) != 1, + "unexpected #matches for %s:\n%s" % (pgmlist, results), + ) + + +check(pgmlist=["p1"]) +check(pgmlist=["p2"]) +check(pgmlist=["p1", "p2"]) + +thistest.result() diff --git a/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb b/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb new file mode 100644 index 000000000..0a3c7b965 --- /dev/null +++ b/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb @@ -0,0 +1,4 @@ +function Inrange (L, H, X : Float) return Boolean is +begin + return X >= L and then X <= H; +end; diff --git a/testsuite/tests/branch-cond/IB11-006-compare-floats/test.py b/testsuite/tests/branch-cond/IB11-006-compare-floats/test.py new file mode 100644 index 000000000..80d3b242a --- /dev/null +++ b/testsuite/tests/branch-cond/IB11-006-compare-floats/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("inrange.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb b/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb new file mode 100644 index 000000000..fe16c8920 --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb @@ -0,0 +1,5 @@ +procedure CheckX (X : Integer) is + pragma Postcondition (X > 0); +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB12-008-postcond/test.py b/testsuite/tests/branch-cond/IB12-008-postcond/test.py new file mode 100644 index 000000000..27c761be3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-008-postcond/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb b/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb new file mode 100644 index 000000000..95f7ef86e --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb @@ -0,0 +1,6 @@ +procedure Eval_Not (A : Boolean; E : out Boolean) is + Ain : Boolean; +begin + Ain := A; + E := not A; +end; diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb b/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb new file mode 100644 index 000000000..ee25e03ef --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb @@ -0,0 +1,8 @@ +function Not_If (A, B : Boolean) return Boolean is +begin + if B then + return A; + else + return not A; + end if; +end; diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/test.py b/testsuite/tests/branch-cond/IB12-016-lone-not/test.py new file mode 100644 index 000000000..1a7a134de --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker(["eval_not.adb", "not_if.adb"], ensure_dcscos=False).run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-019-fncalls/services.adb b/testsuite/tests/branch-cond/IB12-019-fncalls/services.adb new file mode 100644 index 000000000..a0f93410e --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-019-fncalls/services.adb @@ -0,0 +1,14 @@ +package body Services is + function GT (X, Y : Int) return Boolean is + begin + return X.Value > Y.Value; + end; + function EQ (X, Y : Int) return Boolean is + begin + return X.Value = Y.Value; + end; + function GE (X, Y : Int) return Boolean is + begin + return GT (X, Y) or else EQ (X, Y); + end; +end; diff --git a/testsuite/tests/branch-cond/IB12-019-fncalls/services.ads b/testsuite/tests/branch-cond/IB12-019-fncalls/services.ads new file mode 100644 index 000000000..a0466607b --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-019-fncalls/services.ads @@ -0,0 +1,9 @@ +package Services is + type Int is record + Value : Integer; + end record; + + function GT (X, Y : Int) return Boolean; + function EQ (X, Y : Int) return Boolean; + function GE (X, Y : Int) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IB12-019-fncalls/test.py b/testsuite/tests/branch-cond/IB12-019-fncalls/test.py new file mode 100644 index 000000000..9c13267dd --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-019-fncalls/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("services.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-028-length/empty.adb b/testsuite/tests/branch-cond/IB12-028-length/empty.adb new file mode 100644 index 000000000..edd5badbb --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-028-length/empty.adb @@ -0,0 +1,8 @@ +function Empty (S : String) return Boolean is +begin + if S'Length > 0 then + return True; + else + return False; + end if; +end; diff --git a/testsuite/tests/branch-cond/IB12-028-length/test.py b/testsuite/tests/branch-cond/IB12-028-length/test.py new file mode 100644 index 000000000..198c452ed --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-028-length/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("empty.adb", options="-fverbose-asm -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb new file mode 100644 index 000000000..760b49109 --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb @@ -0,0 +1,4 @@ +procedure Checkx (X : Float) is +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads new file mode 100644 index 000000000..617940e5a --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads @@ -0,0 +1,2 @@ +procedure Checkx (X : Float); +pragma Precondition (X > 1.0); diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb new file mode 100644 index 000000000..7c84972c2 --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb @@ -0,0 +1,6 @@ +package body Services is + procedure Checkn (N : T) is + begin + null; + end; +end; diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads new file mode 100644 index 000000000..f93c45232 --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads @@ -0,0 +1,6 @@ +generic + type T is digits <>; +package Services is + procedure CheckN (N : T); + pragma Precondition (N > 1.0); +end; diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py b/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py new file mode 100644 index 000000000..66ae79677 --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py @@ -0,0 +1,13 @@ +from SUITE.context import thistest +from SUITE.tutils import exename_for +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +MapChecker( + sources=["services.adb", "test_services.ads"], + options="-gnata", + execs=[exename_for("test_services")], + alis=["obj/services.ali"], +).run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads new file mode 100644 index 000000000..57c9bef6b --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads @@ -0,0 +1,2 @@ +with Services; +package Test_Services is new Services (Float); diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb new file mode 100644 index 000000000..f8157270f --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb @@ -0,0 +1,4 @@ +procedure CheckI (I, Lb, Hb : Integer) is +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads new file mode 100644 index 000000000..c0e421574 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads @@ -0,0 +1,2 @@ +procedure CheckI (I, Lb, Hb : Integer); +pragma Precondition (Lb > 0 and then I >= Lb and then I <= Hb); diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb new file mode 100644 index 000000000..1a9012ed3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb @@ -0,0 +1,4 @@ +procedure CheckX (X, Lb, Hb : Float) is +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads new file mode 100644 index 000000000..b89f68542 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads @@ -0,0 +1,2 @@ +procedure CheckX (X, Lb, Hb : Float); +pragma Precondition (Lb > 0.0 and then X >= Lb and then X <= Hb); diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/test.py b/testsuite/tests/branch-cond/IB18-024-float-precond/test.py new file mode 100644 index 000000000..64ba0b4d9 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/test.py @@ -0,0 +1,7 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +MapChecker("checki.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb b/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb new file mode 100644 index 000000000..1572eabf1 --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb @@ -0,0 +1,5 @@ +function Starts (S : String; Key : String) return Boolean is +begin + return Key'Length = 3 + and then S (S'First .. S'First + Key'Length) = "abc"; -- # contents +end; diff --git a/testsuite/tests/branch-cond/IB20-015-length-check/test.py b/testsuite/tests/branch-cond/IB20-015-length-check/test.py new file mode 100644 index 000000000..2a61d3df4 --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-015-length-check/test.py @@ -0,0 +1,7 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("starts.adb", options="-gnata").run() +MapChecker("starts.adb", options="-gnata -gnatp").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb new file mode 100644 index 000000000..2d4aac61a --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb @@ -0,0 +1,11 @@ +with System; use System; + +package body Regions is + procedure Check (R : Region) is + pragma Precondition + (R'Address /= System.Null_Address + and then R.Data'Address /= System.Null_Address); + begin + null; + end; +end; diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads new file mode 100644 index 000000000..de21623a7 --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads @@ -0,0 +1,9 @@ + +package Regions is + type Region (Size : Natural) is record + Data : String (1 .. Size); + end record; + pragma Suppress_Initialization (Region); + + procedure Check (R : Region); +end; diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/test.py b/testsuite/tests/branch-cond/IB20-027-addr-compare/test.py new file mode 100644 index 000000000..44f5ddcde --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("regions.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb b/testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb new file mode 100644 index 000000000..1e9da635c --- /dev/null +++ b/testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb @@ -0,0 +1,4 @@ +function CheckX (X, Lb, Hb : Integer; Docheck : Boolean) return Boolean is +begin + return Docheck and then X in Lb .. Hb; +end; diff --git a/testsuite/tests/branch-cond/IB23-016-range-test/test.py b/testsuite/tests/branch-cond/IB23-016-range-test/test.py new file mode 100644 index 000000000..27c761be3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB23-016-range-test/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb new file mode 100644 index 000000000..53416b9b3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb @@ -0,0 +1,33 @@ +with System; use System; + +package body Services is + procedure Validate (T : Boolean) is + begin + if not T then + raise Program_Error; + end if; + end; + + procedure Check_Value_And (This : in out Str_Type) is + begin + Validate (This.Size = 0 or else This.Value (1) = 'X'); + end; + + procedure Check_Value_Or (This : in out Str_Type) is + begin + Validate (This.Size = 0 or else This.Value (1) = 'X'); + end; + + procedure Check_Addr_And (This : Str_Type) is + begin + Validate (This'Address /= System.Null_Address + and then This.Value'Address /= System.Null_Address); + end; + + procedure Check_Addr_Or (This : Str_Type) is + begin + Validate (This'Address /= System.Null_Address + or else This.Value'Address /= System.Null_Address); + end; + +end; diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads new file mode 100644 index 000000000..7b32564f9 --- /dev/null +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads @@ -0,0 +1,10 @@ +package Services is + type Str_Type (Size : Integer) is record + Value : String (1 .. Size); + end record; + + procedure Check_Value_And (This : in out Str_Type); + procedure Check_Value_Or (This : in out Str_Type); + procedure Check_Addr_And (This : Str_Type); + procedure Check_Addr_Or (This : Str_Type); +end; diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py new file mode 100644 index 000000000..9c13267dd --- /dev/null +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("services.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb new file mode 100644 index 000000000..757384f4c --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb @@ -0,0 +1,10 @@ +package body Fatp is + function Is_Null (S : String_Access) return Boolean is + begin + if S = null then + return True; + else + return False; + end if; + end; +end; diff --git a/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads new file mode 100644 index 000000000..361d50f54 --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads @@ -0,0 +1,4 @@ +package Fatp is + type String_Access is access all String; + function Is_Null (S : String_Access) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IC01-011-null-fatp/test.py b/testsuite/tests/branch-cond/IC01-011-null-fatp/test.py new file mode 100644 index 000000000..6524cef06 --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-011-null-fatp/test.py @@ -0,0 +1,6 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("fatp.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb new file mode 100644 index 000000000..179a728d3 --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb @@ -0,0 +1,5 @@ +function Starts (S : String; Key : String) return Boolean is +begin + return Key'Length <= S'Length -- # startsLength + and then S (S'First .. S'First + Key'Length - 1) = Key; -- # startsKey +end; diff --git a/testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py new file mode 100644 index 000000000..dcdaf0dcd --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py @@ -0,0 +1,5 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + +MapChecker("starts.adb", options="-gnata -save-temps -gnatp").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb new file mode 100644 index 000000000..91e33c9e4 --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb @@ -0,0 +1,13 @@ +with System; use System; +package body Check is + + function Valid (S : T_Str; X, Y : Integer) return Boolean is + begin + return (X > 10 + and then + (Y = 0 + or else + (Y = 1 + and then S.Value'Address /= System.Null_address))); + end; +end; diff --git a/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads new file mode 100644 index 000000000..0ba52afe3 --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads @@ -0,0 +1,8 @@ +package Check is + + type T_Str (Size : Integer) is record + Value : String (1 .. Size); + end record; + + function Valid (S : T_Str; X, Y : Integer) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py new file mode 100644 index 000000000..3f4ab4a0f --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py @@ -0,0 +1,7 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("check.adb", options="-gnatp").run() +MapChecker("check.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb new file mode 100644 index 000000000..b652ea895 --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb @@ -0,0 +1,16 @@ +package body Check is + + K_Nul : constant Character := '0'; + + function Validate (This : T_Str; Str : String) return Boolean is + begin + pragma Warnings (Off, "index for * may assume lower bound of 1"); + return + (This.Len <= This.Size + and then ((This.Len = 0 and then Str (1) = K_Nul) + or else (Str (1) = This.Tab (1) + and then Str (This.Len) = This.Tab (This.Len) + and then Str (This.Len + 1) = K_Nul))); + pragma Warnings (On, "index for * may assume lower bound of 1"); + end; +end; diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads new file mode 100644 index 000000000..d9175a09a --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads @@ -0,0 +1,9 @@ +package Check is + + type T_Str (Size : Integer) is record + Len : Integer; + Tab : String (1 .. Size); + end record; + + function Validate (This : T_Str; Str : String) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py b/testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py new file mode 100644 index 000000000..3f4ab4a0f --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py @@ -0,0 +1,7 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("check.adb", options="-gnatp").run() +MapChecker("check.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/J205-019-and-not/check.adb b/testsuite/tests/branch-cond/J205-019-and-not/check.adb new file mode 100644 index 000000000..0cf355595 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/check.adb @@ -0,0 +1,4 @@ +function Check (A, B, C : Boolean) return Boolean is +begin + return A and then not (B and then C); +end; diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo.adb new file mode 100644 index 000000000..c7bdd5990 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo.adb @@ -0,0 +1,4 @@ +function Foo (A, B, C, D : Boolean) return Boolean is +begin + return A and then B and then (not C and then not D); +end; diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb new file mode 100644 index 000000000..428cb42ab --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb @@ -0,0 +1,4 @@ +function Foo2 (A, B, C : Boolean) return Boolean is +begin + return not A and then (B or else C); +end; diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb new file mode 100644 index 000000000..aca4292fc --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb @@ -0,0 +1,4 @@ +function Foo3 (A, B, C : Boolean) return Boolean is +begin + return A and then not B and then not C; +end; diff --git a/testsuite/tests/branch-cond/J205-019-and-not/test.py b/testsuite/tests/branch-cond/J205-019-and-not/test.py new file mode 100644 index 000000000..1afe9f1e7 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/test.py @@ -0,0 +1,9 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("check.adb").run() +MapChecker("foo.adb").run() +MapChecker("foo2.adb").run() +MapChecker("foo3.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/J205-021-slice-compare/p.adb b/testsuite/tests/branch-cond/J205-021-slice-compare/p.adb new file mode 100644 index 000000000..1b6955d73 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-021-slice-compare/p.adb @@ -0,0 +1,10 @@ +function P (S1, S2 : String; L : Integer) return Boolean is +begin + pragma Warnings (Off, "index for * may assume lower bound of 1"); + if S1 (1 .. L) = S2 (1 .. L) then + return True; + else + return False; + end if; + pragma Warnings (On, "index for * may assume lower bound of 1"); +end; diff --git a/testsuite/tests/branch-cond/J205-021-slice-compare/test.py b/testsuite/tests/branch-cond/J205-021-slice-compare/test.py new file mode 100644 index 000000000..8e39094e5 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-021-slice-compare/test.py @@ -0,0 +1,7 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("p.adb", options="-gnatp").run() +MapChecker("p.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/extra.opt b/testsuite/tests/branch-cond/extra.opt new file mode 100644 index 000000000..a29228f15 --- /dev/null +++ b/testsuite/tests/branch-cond/extra.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise map-routines, specific to binary trace mode diff --git a/testsuite/tests/build_run-assert-failure/p.adb b/testsuite/tests/build_run-assert-failure/p.adb new file mode 100644 index 000000000..d62d54a67 --- /dev/null +++ b/testsuite/tests/build_run-assert-failure/p.adb @@ -0,0 +1,6 @@ +with Support; + +procedure P is +begin + Support.Assert (False); +end; diff --git a/testsuite/tests/build_run-assert-failure/test.py b/testsuite/tests/build_run-assert-failure/test.py new file mode 100644 index 000000000..f012a22dc --- /dev/null +++ b/testsuite/tests/build_run-assert-failure/test.py @@ -0,0 +1,43 @@ +""" +Verify that the testsuite detects tests resulting in assertion +failures through build_and_run. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest, Test +from SUITE.cutils import Wdir, FatalError +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["p.adb"], srcdirs=[".."]) + +# build_and_run with register_failure True and check +# the program's output for an exception indication. + +try: + build_and_run( + gprsw=GPRswitches(root_project=gpr, units=["p"]), + mains=["p"], + covlevel="stmt", + extra_coverage_args=[], + register_failure=True, + ) +except FatalError: + pass +else: + thistest.stop( + FatalError( + "expected FatalError from build_and_run, got different exception" + ) + ) + +# If we reach here, the test is PASSED. The failure registration +# closes the test logs though, so we need to reinstantiate to be able +# to report. Note that this brings us back at the test's home dir. + +thistest = Test() + +thistest.result() diff --git a/testsuite/tests/cobertura_validation/src/lib.c b/testsuite/tests/cobertura_validation/src/lib.c new file mode 100644 index 000000000..c1524eef2 --- /dev/null +++ b/testsuite/tests/cobertura_validation/src/lib.c @@ -0,0 +1,5 @@ +int +and_then (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/cobertura_validation/src/pkg.adb b/testsuite/tests/cobertura_validation/src/pkg.adb new file mode 100644 index 000000000..1f3b12e57 --- /dev/null +++ b/testsuite/tests/cobertura_validation/src/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + function Id (A : Boolean) return Boolean is + begin + return A; + end Id; +end Pkg; diff --git a/testsuite/tests/cobertura_validation/src/pkg.ads b/testsuite/tests/cobertura_validation/src/pkg.ads new file mode 100644 index 000000000..4c73d86df --- /dev/null +++ b/testsuite/tests/cobertura_validation/src/pkg.ads @@ -0,0 +1,9 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + function And_Then (A, B : int) return int; + pragma Import + (Convention => C, Entity => And_Then, External_Name => "and_then"); + + function Id (A : Boolean) return Boolean; +end Pkg; diff --git a/testsuite/tests/cobertura_validation/src/test.adb b/testsuite/tests/cobertura_validation/src/test.adb new file mode 100644 index 000000000..7d416f467 --- /dev/null +++ b/testsuite/tests/cobertura_validation/src/test.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Interfaces.C; use Interfaces.C; + +with Pkg; + +procedure Test is + function And_Then (A, B : Boolean) return Boolean; + + function And_Then (A, B : Boolean) return Boolean is + begin + return A and then B; + end And_Then; + +begin + Put_Line (int'Image (Pkg.And_Then (0, 1))); + Put_Line (Boolean'Image (And_Then (Pkg.Id (True), False))); +end Test; diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py new file mode 100644 index 000000000..20873cfb2 --- /dev/null +++ b/testsuite/tests/cobertura_validation/test.py @@ -0,0 +1,114 @@ +""" +Check that creating Cobertura coverage reports works as expected. +""" + +import os + +from e3.fs import sync_tree, mv + +from lxml import etree + +from SCOV.minicheck import build_and_run, xcov +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + + +tmp = Wdir("tmp_") + +sync_tree(os.path.join("..", "src"), "src") + +gprsw = gprsw = GPRswitches( + root_project=gprfor(srcdirs=["src"], mains=["test.adb"]) +) + +scos_list = ["obj/lib.c", "obj/pkg", "obj/test"] + + +def build_run_coverage_and_check( + covlevel, + output_opt=None, + source_root=None, + hide_src=False, + expected_filenames=None, +): + # We need to use manually designated SCOs if we are to remove the sources + # from the project. + # + # Passing explicit SCOs does not work in bin traces for C files, so do not + # run cases with explicit SCOs if this is a bin-traces run. + if thistest.options.trace_mode == "bin" and hide_src: + return + extra_args = ["--annotate=cobertura"] + if source_root: + extra_args += ["--source-root", source_root] + + filename = output_opt if output_opt else "cobertura.xml" + if output_opt: + extra_args += ["-o", output_opt] + # Using explicit SCOs instead of a project changes the default output dir, + # so set it manually to keep everything consistent. + if hide_src: + extra_args += ["--output-dir=obj"] + + xcov_args = build_and_run( + gprsw=gprsw, + covlevel=covlevel, + scos=scos_list if hide_src else None, + mains=["test"], + extra_coverage_args=extra_args, + ) + if hide_src: + mv("src", "src_hidden") + xcov(xcov_args, out="coverage.log") + if hide_src: + mv("src_hidden", "src") + parser = etree.XMLParser(dtd_validation=True) + report = etree.parse(os.path.join("obj", filename), parser) + if expected_filenames: + filenames = set() + for elt in report.getroot().iter(): + if elt.tag == "class": + filenames.add(elt.get("filename")) + + thistest.fail_if_not_equal( + "list of filenames in cobertura.xml", + "\n".join(sorted(expected_filenames)), + "\n".join(sorted(filenames)), + ) + + +# For both source and object coverage, check that the output "cobertura.xml" +# file is valid according to the cobertura.dtd standard. +build_run_coverage_and_check("stmt+mcdc") +if thistest.options.trace_mode == "bin": + build_run_coverage_and_check("insn", "cobertura-insn.xml") + build_run_coverage_and_check("branch", "cobertura-branch.xml") + + +# Check that the --source-root option works as expected +expected_filenames = {"lib.c", "pkg.adb", "pkg.ads", "test.adb"} +for prefix in ["src", "src/"]: + thistest.log(f"== Prefix: {prefix} ==") + + build_run_coverage_and_check( + "stmt", + source_root=os.path.join(os.getcwd(), prefix), + expected_filenames=expected_filenames, + ) + +# Check that the report can be emitted in the absence of the project sources. +# We have to rely on sid files to convey the coverage obligations +thistest.log("== Report with no sources ==") +# No pkg.ads in the report as there are no coverage obligations for it +expected_filenames = {"lib.c", "pkg.adb", "test.adb"} + +build_run_coverage_and_check( + "stmt", + "cobertura-no_src.xml", + source_root=os.path.join(os.getcwd(), "src"), + hide_src=True, + expected_filenames=expected_filenames, +) + +thistest.result() diff --git a/testsuite/tests/duplicate_postprocess/lib.c b/testsuite/tests/duplicate_postprocess/lib.c new file mode 100644 index 000000000..4d81d8d52 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/lib.c @@ -0,0 +1,19 @@ +extern void dummy_puts (const char *msg); + +#define PRINT_HW dummy_puts ("Hello world!\n"); + +/* Thanks to macro_stmts_enabled returning 0, macro_stmts is never executed, + and thus we get coverage violations inside macro expansion. */ + +int +macro_stmts_enabled (void) +{ + return 0; +} + +void +macro_stmts (void) +{ + PRINT_HW; + PRINT_HW; +} diff --git a/testsuite/tests/duplicate_postprocess/test.opt b/testsuite/tests/duplicate_postprocess/test.opt new file mode 100644 index 000000000..ae9029965 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to instrumentation diff --git a/testsuite/tests/duplicate_postprocess/test.py b/testsuite/tests/duplicate_postprocess/test.py new file mode 100644 index 000000000..64d033e78 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/test.py @@ -0,0 +1,35 @@ +""" +Regression test: check that we do not preprocess multiple times a file at +coverage time. +""" + +import re + +from SCOV.minicheck import build_run_and_coverage +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test_macros.c"]) + ), + covlevel="stmt+mcdc", + mains=["test_macros"], + extra_coverage_args=["--annotate=xcov+", "-v"], +) + +thistest.fail_if( + len( + re.findall( + f"gcc{env.build.os.exeext}' '-E'", contents_of("coverage.log") + ) + ) + != 1, + "source file was preprocessed multiple times", +) + +thistest.result() diff --git a/testsuite/tests/duplicate_postprocess/test_macros.c b/testsuite/tests/duplicate_postprocess/test_macros.c new file mode 100644 index 000000000..be45e319b --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/test_macros.c @@ -0,0 +1,16 @@ +extern int macro_stmts_enabled (void); +extern void macro_stmts (void); + +void +dummy_puts (const char *msg) +{ + return; +} + +int +main (void) +{ + if (macro_stmts_enabled ()) + macro_stmts (); + return 0; +} diff --git a/testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c b/testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c new file mode 100644 index 000000000..f939f7693 --- /dev/null +++ b/testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c @@ -0,0 +1,5 @@ +int +foo (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/excluded_unit_imported_prj/test.c b/testsuite/tests/excluded_unit_imported_prj/test.c new file mode 100644 index 000000000..19740b019 --- /dev/null +++ b/testsuite/tests/excluded_unit_imported_prj/test.c @@ -0,0 +1,8 @@ +extern int foo (int a, int b); + +int +main () +{ + foo (0, 1); + return 0; +} diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py new file mode 100644 index 000000000..7a007f7cf --- /dev/null +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -0,0 +1,51 @@ +""" +This test checks that units of interest project attributes only apply to the +project in which they are defined, and not to recursive project dependencies. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +prj1 = gprfor(mains=[], prjid="prj1", srcdirs=["../prj1"], objdir="obj-prj1") + +# Check that ignoring pkg.c in the main project yields a warning, as the pkg.c +# unit is in the prj1 dependency and not in the root project. +extra_p = """ +package Coverage is + for Excluded_Units use ("pkg.c"); +end Coverage; +""" +p = gprfor(mains=["test.c"], deps=["prj1"], srcdirs=[".."], extra=extra_p) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["--annotate=xcov"], + tolerate_instrument_messages="no unit .* in project", + tolerate_coverage_messages="no unit .* in project", +) +warning_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) + +thistest.fail_if_not_equal( + warning_file, + "warning: no unit pkg.c in project gen" + " (coverage.excluded_units attribute)\n", + contents_of(warning_file), +) + +# Check that pkg.c is not ignored by checking the report contents +check_xcov_reports( + "obj", + {"pkg.c.xcov": {"!": {4}}, "test.c.xcov": {"+": {6, 7}}}, +) + +thistest.result() diff --git a/testsuite/tests/exemptions-check/expected b/testsuite/tests/exemptions-check/expected new file mode 100644 index 000000000..3e3f709cc --- /dev/null +++ b/testsuite/tests/exemptions-check/expected @@ -0,0 +1,8 @@ +!!! hello.adb:4:4: unexpected EXEMPT_OFF BAD lone at start (expected EXEMPT_ON) +!!! hello.adb:15:4: empty message for EXEMPT_ON +!!! hello.adb:19:4: unexpected EXEMPT_OFF BAD1 mismatch (expected BAD1) +!!! hello.adb:22:4: unexpected EXEMPT_ON BAD2 nested (expected EXEMPT_OFF) +!!! hello.adb:24:4: unexpected EXEMPT_OFF BAD2 (expected EXEMPT_ON) +!!! hello.adb:29:4: bad annotation exempt_bad1 +!!! hello.adb:30:4: bad annotation exempt_bad2 +!!! hello.adb:26:4: missing Exempt_Off BAD lone at end diff --git a/testsuite/tests/exemptions-check/src/hello.adb b/testsuite/tests/exemptions-check/src/hello.adb new file mode 100644 index 000000000..3dabe6eb0 --- /dev/null +++ b/testsuite/tests/exemptions-check/src/hello.adb @@ -0,0 +1,31 @@ +procedure Hello is +begin + null; + pragma Annotate (Xcov, Exempt_Off, "BAD lone at start"); + + pragma Annotate (Xcov, Exempt_On, "OK"); + pragma Annotate (Xcov, Exempt_Off, "OK"); + + pragma Annotate (Xcov, Exempt_On, "OK2"); + pragma Annotate (Xcov, Exempt_Off, ""); + + pragma Annotate (Xcov, Exempt_On, "OK3"); + pragma Annotate (Xcov, Exempt_Off); + + pragma Annotate (Xcov, Exempt_On); + pragma Annotate (Xcov, Exempt_Off); + + pragma Annotate (Xcov, Exempt_On, "BAD1"); + pragma Annotate (Xcov, Exempt_Off, "BAD1 mismatch"); + + pragma Annotate (Xcov, Exempt_On, "BAD2"); + pragma Annotate (Xcov, Exempt_On, "BAD2 nested"); + pragma Annotate (Xcov, Exempt_Off, "BAD2 nested"); + pragma Annotate (Xcov, Exempt_Off, "BAD2"); + + pragma Annotate (Xcov, Exempt_On, "BAD lone at end"); + + pragma Annotate (Xcov); + pragma Annotate (Xcov, Exempt_Bad1); + pragma Annotate (Xcov, Exempt_Bad2, "foo"); +end Hello; diff --git a/testsuite/tests/exemptions-check/test.opt b/testsuite/tests/exemptions-check/test.opt new file mode 100644 index 000000000..aea7bfc5c --- /dev/null +++ b/testsuite/tests/exemptions-check/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Check map-routines, specific to binary traces mode diff --git a/testsuite/tests/exemptions-check/test.py b/testsuite/tests/exemptions-check/test.py new file mode 100644 index 000000000..e5758222f --- /dev/null +++ b/testsuite/tests/exemptions-check/test.py @@ -0,0 +1,23 @@ +""" +Check that a simple decision SCO is correctly loaded and interpreted by xcov. +""" + +from e3.diff import diff + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +tmp = Wdir("tmp_") + +gprbuild(gprfor(["hello.adb"], srcdirs="../src")) + +xcov(["map-routines", "--scos=obj/hello.ali", "obj/hello.o"], "out") + +dif = diff("../expected", "out") +thistest.fail_if( + dif, "out != expected on exemption pragma placement rules:\n" + dif +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb new file mode 100644 index 000000000..8593db67b --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; + +package body Pkg is + + procedure Check_Ok is + Val : Boolean := False; -- # ok_st + begin + if Val then -- # ex_dc + raise Program_Error; -- # ex_st + else + Ada.Text_IO.Put_Line ("All ok"); -- # ok_st + end if; + end Check_Ok; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads new file mode 100644 index 000000000..c18de71e3 --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Check_Ok; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb new file mode 100644 index 000000000..806be74bd --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Pkg is +begin + Pkg.Check_Ok; +end Test_Pkg; + + +--# pkg.adb +-- +-- /ok_st/ l+ ## 0 +-- /ex/ l* ## x+ +-- /ex_dc/ l= ## XoT- +-- /ex_st/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt new file mode 100644 index 000000000..1572a45d8 --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt @@ -0,0 +1 @@ +bin-traces DEAD test uses constructions that are optimized out diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/test.py b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.py new file mode 100644 index 000000000..fc9c575cc --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.py @@ -0,0 +1,21 @@ +""" +Check that gnatcov add-annotation does not crash when the designated region +has columns that are smaller than the starting column of the enclosing named +declaration. This used to make stable_sloc (and thus gnatcov) crash. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest +from SUITE.tutils import Exempt_Region, generate_annotations + +annotations = [ + Exempt_Region("src/pkg.adb", "8:1", "9:30", "Unreachable"), +] + +annot_file = generate_annotations(annotations) + +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=f"--external-annotations={annot_file}") +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/buffers/ada_no_unit.toml b/testsuite/tests/ext_annotations/buffers/ada_no_unit.toml new file mode 100644 index 000000000..4ecdf0459 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/ada_no_unit.toml @@ -0,0 +1,25 @@ +# These two entries will reset the buffers before the first statement in +# do_dump then dump them before the end of the procedure. + +[dump_buffs] +kind="absolute" +file="pkh.adb" +[dump_buffs.matcher] +start_line=5 +start_col=11 +end_line=5 +end_col=11 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" +insert_after=true + +[dump_reset] +kind="absolute" +file="pkh.adb" +[dump_reset.matcher] +start_line=5 +start_col=7 +end_line=5 +end_col=7 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/ada_unit.toml b/testsuite/tests/ext_annotations/buffers/ada_unit.toml new file mode 100644 index 000000000..7e8b6af99 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/ada_unit.toml @@ -0,0 +1,27 @@ +# These two entries will reset the buffers before the first statement in +# do_dump then dump them before the end of the procedure. + +[dump_buffs] +kind="absolute" +file="pkg.adb" +[dump_buffs.matcher] +start_line=5 +start_col=11 +end_line=5 +end_col=11 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" +# Use the same trace prefix as the project name to simply test code +trace_prefix='"prj_ada_unit"' +insert_after=true + +[dump_reset] +kind="absolute" +file="pkg.adb" +[dump_reset.matcher] +start_line=5 +start_col=7 +end_line=5 +end_col=7 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/c.toml b/testsuite/tests/ext_annotations/buffers/c.toml new file mode 100644 index 000000000..e2389e19e --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/c.toml @@ -0,0 +1,27 @@ +# These two entries will reset the buffers before the first statement in +# do_c_dump then dump them before the end of the function. +# +# The end_* fields do not really matter for buffer annotations, they are +# just set to something valid. + +[dump_buffs] +kind="absolute" +file="c_unit.c" +[dump_buffs.matcher] +start_line=4 +start_col=13 +end_line=4 +end_col=13 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" + +[dump_reset] +kind="absolute" +file="c_unit.c" +[dump_reset.matcher] +start_line=4 +start_col=3 +end_line=4 +end_col=3 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/c_unit.c b/testsuite/tests/ext_annotations/buffers/c_unit.c new file mode 100644 index 000000000..dbcdac133 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/c_unit.c @@ -0,0 +1,5 @@ +void +do_c_dump () +{ + int x = 0; // Generate an obligation +} diff --git a/testsuite/tests/ext_annotations/buffers/cpp.toml b/testsuite/tests/ext_annotations/buffers/cpp.toml new file mode 100644 index 000000000..27709dda4 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/cpp.toml @@ -0,0 +1,26 @@ +# These two entries will reset the buffers before the first statement in +# do_cpp_dump then dump them before the end of the function. + +[dump_buffs] +kind="absolute" +file="cpp_unit.cpp" +[dump_buffs.matcher] +start_line=6 +start_col=16 +end_line=6 +end_col=16 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" +# Use the same trace prefix as the project name to simply test code +trace_prefix='"prj_cpp"' + +[dump_reset] +kind="absolute" +file="cpp_unit.cpp" +[dump_reset.matcher] +start_line=6 +start_col=5 +end_line=6 +end_col=5 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/cpp_unit.cpp b/testsuite/tests/ext_annotations/buffers/cpp_unit.cpp new file mode 100644 index 000000000..ae71de2da --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/cpp_unit.cpp @@ -0,0 +1,8 @@ +extern "C" +{ + void + do_cpp_dump () + { + int x = 0; // generate a SCO to check reports + } +} diff --git a/testsuite/tests/ext_annotations/buffers/main.adb b/testsuite/tests/ext_annotations/buffers/main.adb new file mode 100644 index 000000000..2e82f736a --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/main.adb @@ -0,0 +1,15 @@ +with Pkg; +with Pkh; + +procedure Main is + procedure Do_CPP_Dump; + pragma Import (C, Do_CPP_Dump, "do_cpp_dump"); + + procedure Do_C_Dump; + pragma Import (C, Do_C_Dump, "do_c_dump"); +begin + Do_C_Dump; + Do_CPP_Dump; + Pkg.Do_Dump; + Pkh.Do_Dump; +end Main; diff --git a/testsuite/tests/ext_annotations/buffers/pkg.adb b/testsuite/tests/ext_annotations/buffers/pkg.adb new file mode 100644 index 000000000..09f301c93 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkg.adb @@ -0,0 +1,7 @@ +package body Pkg is + + procedure Do_Dump is + begin + null; + end Do_Dump; +end Pkg; diff --git a/testsuite/tests/ext_annotations/buffers/pkg.ads b/testsuite/tests/ext_annotations/buffers/pkg.ads new file mode 100644 index 000000000..3969881df --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkg.ads @@ -0,0 +1,7 @@ +-- This unit is part of the set of units of interest + +package Pkg is + + procedure Do_Dump; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/buffers/pkh.adb b/testsuite/tests/ext_annotations/buffers/pkh.adb new file mode 100644 index 000000000..54b1a7f0f --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkh.adb @@ -0,0 +1,7 @@ +package body Pkh is + + procedure Do_Dump is + begin + null; + end Do_Dump; +end Pkh; diff --git a/testsuite/tests/ext_annotations/buffers/pkh.ads b/testsuite/tests/ext_annotations/buffers/pkh.ads new file mode 100644 index 000000000..603cc7f99 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkh.ads @@ -0,0 +1,7 @@ +-- This unit is not part of the set of units of interest + +package Pkh is + + procedure Do_Dump; + +end Pkh; diff --git a/testsuite/tests/ext_annotations/buffers/test.opt b/testsuite/tests/ext_annotations/buffers/test.opt new file mode 100644 index 000000000..2427c8fc1 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/test.opt @@ -0,0 +1,2 @@ +!C++ DEAD Requires C++ compiler +bin-traces DEAD Test requires support for C++ source coverage diff --git a/testsuite/tests/ext_annotations/buffers/test.py b/testsuite/tests/ext_annotations/buffers/test.py new file mode 100644 index 000000000..5ef7d4744 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/test.py @@ -0,0 +1,87 @@ +""" +Test simple external annotations for buffer management, both for +buffer dump and buffer reset. +""" + +from copy import deepcopy + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir() + + +def run_one(tc_id, annotation_file, expected_results): + """ + Run a whole gnatcov source trace workflow, passing the + given annotation_file to the --external-annotation switch + and checking the expected_results. + + tc_id is used to identify the test case (temporary work dir) + """ + thistest.log(f"====== Running test {tc_id} ======") + tmp.to_subdir(f"tmp_{tc_id}") + prjid = f"prj_{tc_id}" + prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + langs=["Ada", "C", "C++"], + prjid=prjid, + ) + build_run_and_coverage( + gprsw=GPRswitches(prj), + extra_instr_args=[ + f"--external-annotations={annotation_file}", + ], + extra_args=[ + "--units=Pkg", + "--units=c_unit.c", + "--units=cpp_unit.cpp", + ], + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name=prjid, + extra_coverage_args=["-axcov"], + ) + check_xcov_reports( + "obj", + expected_results, + ) + + +default_cov = { + "cpp_unit.cpp.xcov": {"-": {6}}, + "c_unit.c.xcov": {"-": {4}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"-": {5}}, +} + +# CPP first, we expect full coverage for the CPP unit as buffers are cleared +# when entering do_cpp_dump, and dumped at the end of that function +expected_cov = deepcopy(default_cov) +expected_cov["cpp_unit.cpp.xcov"] = {"+": {6}} +run_one("cpp", "../cpp.toml", expected_cov) + +# C then, we expect full coverage for the C unit as buffers are cleared +# when entering do_c_dump, and dumped at the end of that function +expected_cov = deepcopy(default_cov) +expected_cov["c_unit.c.xcov"] = {"+": {4}} +run_one("c", "../c.toml", expected_cov) + +# For Ada, first check the annotations when the file is part of the set of +# units of interest. As above, buffers are cleared entering the Do_Dump +# procedure, then dumped at the end. +expected_cov = deepcopy(default_cov) +expected_cov["pkg.adb.xcov"] = {"+": {5}} +run_one("ada_unit", "../ada_unit.toml", expected_cov) + +# Test when the annotations are not part of a unit of interest. As the buffers +# are handled in the same fashion, no code in a unit of interest should be +# executed. +run_one("ada_no_unit", "../ada_no_unit.toml", default_cov) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/diagnostics/buffers.toml b/testsuite/tests/ext_annotations/diagnostics/buffers.toml new file mode 100644 index 000000000..76813540d --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/buffers.toml @@ -0,0 +1,36 @@ +# All these annotations should load fine, but generate a warning + +[unknown_kind_buffers] +kind="absolute" +file="main.adb" +[unknown_kind_buffers.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[unknown_kind_buffers.annotations]] +purpose="xcov.buffers.foo_bar" + +[duplicate_1] +kind="absolute" +file="main.adb" +[duplicate_1.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_1.annotations]] +purpose="xcov.buffers.dump" +justification="this entry is duplicated (same sloc)" + +[duplicate_2] +kind="absolute" +file="main.adb" +[duplicate_2.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_2.annotations]] +purpose="xcov.buffers.reset" +justification="this entry is duplicated (same sloc)" diff --git a/testsuite/tests/ext_annotations/diagnostics/cov_off.toml b/testsuite/tests/ext_annotations/diagnostics/cov_off.toml new file mode 100644 index 000000000..cbfb3ba66 --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/cov_off.toml @@ -0,0 +1,53 @@ +# All these entries should either fail to load or produce a warning + +# Fail due to unknown annotation kind +[unknown_kind_cov] +kind="absolute" +file="main.adb" +[unknown_kind_cov.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[unknown_kind_cov.annotations]] +purpose="xcov.cov.foo_bar" + +# Rejected because a cov_on annotation cannot appear first +[cov_on_first] +kind="absolute" +file="main.adb" +[cov_on_first.matcher] +start_line=2 +start_col=4 +end_line=3 +end_col=4 +[[cov_on_first.annotations]] +purpose="xcov.cov.on" + +# Ultimately rejected as the next annotation will be ignored, +# and a cov_off annotation cannot be the last one of a file +[duplicate_cov_1] +kind="absolute" +file="main.adb" +[duplicate_cov_1.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_cov_1.annotations]] +purpose="xcov.cov.off" +justification="this entry is duplicated (same sloc)" + +# Rejected as this annotates the same location +[duplicate_cov_2] +kind="absolute" +file="main.adb" +[duplicate_cov_2.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_cov_2.annotations]] +purpose="xcov.cov.on" + + diff --git a/testsuite/tests/ext_annotations/diagnostics/exemptions.toml b/testsuite/tests/ext_annotations/diagnostics/exemptions.toml new file mode 100644 index 000000000..51714021d --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/exemptions.toml @@ -0,0 +1,47 @@ +# All these annotations should load fine, but generate a warning + +[unknown_kind_exempt] +kind="absolute" +file="main.adb" +[unknown_kind_exempt.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[unknown_kind_exempt.annotations]] +purpose="xcov.exempt.foo_bar" + +[missing_justif] +kind="absolute" +file="main.adb" +[missing_justif.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[missing_justif.annotations]] +purpose="xcov.exempt.on" + +[duplicate_3] +kind="absolute" +file="main.adb" +[duplicate_3.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_3.annotations]] +purpose="xcov.exempt.on" +justification="this entry is duplicated (same sloc)" + +[duplicate_4] +kind="absolute" +file="main.adb" +[duplicate_4.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_4.annotations]] +purpose="xcov.exempt.off" +justification="this entry is duplicated (same sloc)" diff --git a/testsuite/tests/ext_annotations/diagnostics/expected.txt b/testsuite/tests/ext_annotations/diagnostics/expected.txt new file mode 100644 index 000000000..9d347412a --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/expected.txt @@ -0,0 +1,11 @@ +warning: ../load_fail.toml:15:1: Error while parsing entry "missing_field": Missing "annotations" field +warning: ../load_fail.toml:18:1: Error while parsing entry "missing_justif": Missing "kind" field +warning: Entry "unknown_kind_exempt" has an unknown annotation kind, it will be ignored. +warning: Entry "unknown_kind_cov" has an unknown annotation kind, it will be ignored. +warning: Entry "unknown_kind_buffers" has an unknown annotation kind, it will be ignored. +warning: Missing or empty justification for external exemption annotation "missing_justif", it will be ignored. +warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_2" +warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_cov_2" +warning: main.adb: 2:4: external Cov_On annotation with no previous Cov_Off annotation, ignoring it. +warning: main.adb: 3:4: external COV_OFF annotation with no subsequent COV_ON annotation, ignoring it. +warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_4" diff --git a/testsuite/tests/ext_annotations/diagnostics/load_fail.toml b/testsuite/tests/ext_annotations/diagnostics/load_fail.toml new file mode 100644 index 000000000..d1916e41d --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/load_fail.toml @@ -0,0 +1,22 @@ +# A couple of entries that should fail to load, to ensure we properly +# report them. + +[unknown_kind] +kind="no such kind" +file="main.adb" +[unknown_kind.matcher] +start_line=1 +start_col=1 +end_line=1 +end_col=1 +[[unknown_kind.annotations]] +purpose="xcov.exempt.on" + +[missing_field] +kind="absolute" +file="main.adb" +[missing_justif.matcher] +start_line=1 +start_col=1 +[[missing_justif.annotations]] +purpose="xcov.exempt.on" diff --git a/testsuite/tests/ext_annotations/diagnostics/main.adb b/testsuite/tests/ext_annotations/diagnostics/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/ext_annotations/diagnostics/test.opt b/testsuite/tests/ext_annotations/diagnostics/test.opt new file mode 100644 index 000000000..e3ab1b655 --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/test.opt @@ -0,0 +1 @@ +bin-traces DEAD requires gnatcov instrumentation for some diagnostics diff --git a/testsuite/tests/ext_annotations/diagnostics/test.py b/testsuite/tests/ext_annotations/diagnostics/test.py new file mode 100644 index 000000000..6aaaef7b2 --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/test.py @@ -0,0 +1,45 @@ +""" +Test that gnatcov emits the expected diagnostics when loading external +annotations, for unknown annotations kinds or ill-formed annotation +payloads. +""" + +from e3.testsuite.driver.diff import Substitute + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +prj = gprfor(mains=["main.adb"], srcdirs=[".."]) + +log = "instr.log" + +# Instrument the project with all the external exemptions +xcov_instrument( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + dump_trigger="manual", + extra_args=[ + "--external-annotations=../buffers.toml", + "--external-annotations=../exemptions.toml", + "--external-annotations=../load_fail.toml", + "--external-annotations=../cov_off.toml", + ], + tolerate_messages=".*", + out=log, +) + +refiners = thistest.report_output_refiners() + [Substitute("\\", "/")] + +thistest.fail_if_diff( + "../expected.txt", + log, + "Unexpected messages for 'gnatcov instrument' output", + refiners, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/exemptions/exemptions.toml b/testsuite/tests/ext_annotations/exemptions/exemptions.toml new file mode 100644 index 000000000..7bc7fa519 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/exemptions.toml @@ -0,0 +1,81 @@ +# Basic exemptions for pkg.adb + +[on] +file="pkg.adb" +kind="absolute" +[on.matcher] +start_line=6 +start_col=7 +# End line annotations does not matter for exempt_on +end_line=6 +end_col=7 +[[on.annotations]] +purpose="xcov.exempt.on" +justification="defensive code, not to be triggered (on)" + + +[off] +file="pkg.adb" +kind="absolute" +[off.matcher] +start_line=8 +start_col=14 +# End line annotations does not matter for exempt_off +end_line=8 +end_col=14 +[[off.annotations]] +purpose="xcov.exempt.off" + + +[region] +file="pkg.adb" +kind="absolute" +[region.matcher] +start_line=10 +start_col=7 +end_line=12 +end_col=14 +[[region.annotations]] +purpose="xcov.exempt.region" +justification="defensive code, not to be triggered (region)" + +# Basic exemption for foo.h + +[region_c] +file="foo.h" +kind="absolute" +[region_c.matcher] +start_line=4 +start_col=1 +end_line=5 +end_col=16 +[[region_c.annotations]] +purpose="xcov.exempt.region" +justification="defensive code, not to be triggered (region)" + +# Basic exemption for foo.c + +[on_c] +file="foo.c" +kind="absolute" +[on_c.matcher] +start_line=6 +start_col=1 +# End line annotations does not matter for exempt_on +end_line=6 +end_col=1 +[[on_c.annotations]] +purpose="xcov.exempt.on" +justification="garbage code, not to be triggered (on)" + +[off_c] +file="foo.c" +kind="absolute" +[off_c.matcher] +start_line=7 +start_col=17 +# End line annotations does not matter for exempt_off +end_line=7 +end_col=17 +[[off_c.annotations]] +purpose="xcov.exempt.off" diff --git a/testsuite/tests/ext_annotations/exemptions/src/foo.c b/testsuite/tests/ext_annotations/exemptions/src/foo.c new file mode 100644 index 000000000..6ed0c4700 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/foo.c @@ -0,0 +1,9 @@ +#include "foo.h" + +int +ident (int x) +{ + if (x == 0) // # exempt_c_d + return -1; // # exempt_c_s + return static_helper (&x); // # ok +} diff --git a/testsuite/tests/ext_annotations/exemptions/src/foo.h b/testsuite/tests/ext_annotations/exemptions/src/foo.h new file mode 100644 index 000000000..91d414838 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/foo.h @@ -0,0 +1,7 @@ +static int +static_helper (int *x) +{ + if (!x) // # exempt_h_d + return 0; // # exempt_h_s + return *x; // # ok +} diff --git a/testsuite/tests/ext_annotations/exemptions/src/pkg.adb b/testsuite/tests/ext_annotations/exemptions/src/pkg.adb new file mode 100644 index 000000000..9270d2cf7 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/pkg.adb @@ -0,0 +1,18 @@ +package body Pkg is + + procedure Swap (X, Y : Bool_Acc) is + Tmp : Boolean; + begin + if X = null then -- # exempt_1_d + raise Program_Error; -- # exempt_1_s + end if; -- # exempt_1 + + if Y = null then -- # exempt_2_d + raise Program_Error; -- # exempt_2_s + end if; -- # exempt_2 + Tmp := X.all; -- # ok + X.all := Y.all; -- # ok + Y.all := Tmp; -- # ok + end Swap; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/exemptions/src/pkg.ads b/testsuite/tests/ext_annotations/exemptions/src/pkg.ads new file mode 100644 index 000000000..4db6d0bf0 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + type Bool_Acc is access all Boolean; + + procedure Swap (X, Y : Bool_Acc); + +end Pkg; diff --git a/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb b/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb new file mode 100644 index 000000000..98597a3f1 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb @@ -0,0 +1,43 @@ +with Pkg; + +with Support; + +with Interfaces.C; + +procedure Test_Exempt is + use type Interfaces.C.int; + X : aliased Boolean := True; + Y : aliased Boolean := False; + X_Acc : Pkg.Bool_Acc := X'Unchecked_Access; + Y_Acc : Pkg.Bool_Acc := Y'Unchecked_Access; + function Ident (X : Interfaces.C.int) return Interfaces.C.int; + pragma Import (C, Ident, "ident"); +begin + Pkg.Swap (X_Acc, Y_Acc); + Support.Assert (Y and then not X); + Support.Assert (Ident (1) = 1); +end Test_Exempt; + +--# pkg.adb +-- +-- /exempt_1/ l* ## x+ +-- /exempt_1_d/ l= ## XoT- +-- /exempt_1_s/ l= ## Xs- +-- /exempt_2/ l* ## x+ +-- /exempt_2_d/ l= ## XoT- +-- /exempt_2_s/ l= ## Xs- +-- /ok/ l+ ## 0 + +--# foo.h +-- +-- /exempt_h/ l* ## x+ +-- /exempt_h_d/ l= ## XoT- +-- /exempt_h_s/ l= ## Xs- +-- /ok/ l+ ## 0 + +--# foo.c +-- +-- /exempt_c/ l* ## x+ +-- /exempt_c_d/ l= ## XoT- +-- /exempt_c_s/ l= ## Xs- +-- /ok/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/exemptions/test.opt b/testsuite/tests/ext_annotations/exemptions/test.opt new file mode 100644 index 000000000..a3d0e79c1 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1 XFAIL Issues with optimization, see #324 diff --git a/testsuite/tests/ext_annotations/exemptions/test.py b/testsuite/tests/ext_annotations/exemptions/test.py new file mode 100644 index 000000000..d2299206f --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/test.py @@ -0,0 +1,28 @@ +""" +Basic test to ensure exemptions are properly imported by gnatcov +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +# Run the same test but passing the annotations either at instrumentation time +# or at coverage time. This should yield the same results. + +TestCase(category=CAT.decision).run( + CovControl( + covoptions="--external-annotations=../exemptions.toml", + instroptions="", + ), + subdirhint="cov_", +) + +if thistest.options.trace_mode == "src": + TestCase(category=CAT.decision).run( + CovControl( + instroptions="--external-annotations=../exemptions.toml", + ), + subdirhint="instr_", + ) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb new file mode 100644 index 000000000..0288bde90 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb @@ -0,0 +1,5 @@ +procedure Main is + Some_Var : Boolean := True; +begin + Some_Var := False; +end Main; diff --git a/testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py new file mode 100644 index 000000000..4b5bd3c1e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py @@ -0,0 +1,71 @@ +""" +Test that gnatcov does not crash when the source locations passed to the +--start-location or --end-location options, and instead exit in an error. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov, contents_of + +tmp = Wdir("tmp_") + + +def check_one(arg_name, invalid_line): + """ + Run gnatcov add-annotation to generate an annotation for main.adb, with + either a line or a column set to 0 in the value passed to arg_name, and + check that gnatcov correctly rejects the argument with an expected error + message. + + arg_name must be one of location, start-location or end-location. + """ + log_filename = arg_name + ("_line" if invalid_line else "_col") + ".log" + + sloc = "0:1" if invalid_line else "1:0" + + # Pass the requested argument to gnatcov. For start/end location arguments, + # also add the complementary argument. + sloc_args = [f"--{arg_name}={sloc}"] + if arg_name != "location": + sloc_args += [ + ( + "--end-location" + if arg_name == "start-location" + else "--start-location" + ), + "1:1", + ] + + p = xcov( + [ + "add-annotation", + "--kind", + "exempt_on" if arg_name == "location" else "exempt_region", + "--justification=dummy", + "--output=dummy.toml", + ] + + sloc_args + + ["../main.adb"], + out=log_filename, + register_failure=False, + ) + thistest.fail_if(p.status == 0, "zero return status not expected") + + expected_err = ( + r".*gnatcov(\.exe)?: " + + ("Line" if invalid_line else "Column") + + f" number in argument to --{arg_name} should not be 0" + ) + + thistest.fail_if_no_match( + what="wrong 'gnatcov add-annotation' error message", + regexp=expected_err, + actual=contents_of(log_filename), + ) + + +for arg_name in ["location", "start-location", "end-location"]: + for invalid_line in [True, False]: + check_one(arg_name, invalid_line) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb new file mode 100755 index 000000000..9c6c26779 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb @@ -0,0 +1,79 @@ +package body Exemptions is + + procedure Swap (I, J : in out Integer) is + + -- Exemption for a local declaration + + pragma Annotate -- # xswap + (Xxxx, Exempt_On, "exemption on declarations"); -- # xswap + Tmp : Integer := J; -- # xswap_vio + pragma Annotate (Xxxx, Exempt_Off); -- # xswap + begin + J := I; -- # swap_stmt + I := Tmp; -- # swap_stmt + end Swap; + + function Factorial (X : Natural) return Positive is + begin + if X = 1 then -- # factorial + return 1; -- # 1_factorial + elsif X >= Positive'Last / 1000 then -- # elsif_factorial + + -- Exemption for a conditioned set of statements + + pragma Annotate -- # xfactorial + (Xxxx, Exempt_On, -- # xfactorial + "exemption on statements in function"); -- # xfactorial + return Positive'Last; -- # xfactorial_vio + pragma Annotate (Xxxx, Exempt_Off); -- # xfactorial + else + return X * Factorial (X - 1); -- # rec_factorial + end if; + end Factorial; + + -- No exemption in the couple of subprograms below + + procedure Another_Swap (I, J : in out Integer) is + Tmp : Integer := J; -- # another_swap + begin + J := I; -- # another_swap + I := Tmp; -- # another_swap + end Another_Swap; + + function Another_Factorial (X : Natural) return Positive is + Result : Positive := 1; -- # another_factorial + begin + for J in 1 .. X loop -- # another_factorial + if Result > Positive'Last / J then -- # in_loop_a_f + raise Constraint_Error; -- # in_if_a_f + end if; + + Result := Result * J; -- # in_loop_a_f + end loop; + + return Result; -- # another_factorial + exception + when Constraint_Error => + return Positive'Last; -- # handler_a_f + end Another_Factorial; + + +begin + + -- Mix of exempted and non-exempted statements in the package + -- elaboration sequence + + pragma Annotate -- # xelab_1 + (Xxxx, Exempt_On, -- # xelab_1 + "exemption on elaboration code - 1"); -- # xelab_1 + Z := Identity (3); -- # xelab_1_vio + pragma Annotate (Xxxx, Exempt_Off); -- # xelab_1 + + Another_Swap (X, Y); -- # elab + + pragma Annotate -- # xelab_2 + (Xxxx, Exempt_On, -- # xelab_2 + "exemption on elaboration code - 2"); -- # xelab_2_vio + Another_Swap (Z, X); -- # xelab_2 + pragma Annotate (Xxxx, Exempt_Off); -- # xelab_2 +end Exemptions; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads new file mode 100755 index 000000000..300ed769a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads @@ -0,0 +1,26 @@ +with Support; use Support; +package Exemptions is + + procedure Swap (I, J : in out Integer); + -- Body contains exemption section for a declaration + + function Factorial (X : Natural) return Positive; + -- Body contains exemption section for a statement + + procedure Another_Swap (I, J : in out Integer) ; + -- No exemption section in the body + + function Another_Factorial (X : Natural) return Positive; + -- No exemption section in the body + + -- Mix of exempted and non-exempted declarations + + X : Integer := Identity (1); -- # decl + + pragma Annotate -- # xdecl + (No_Such_Tool, No); -- # xdecl + Y : Integer := Identity (2); -- # xdecl_vio + pragma Annotate (No_Such_Tool, No); -- # xdecl + + Z : Integer := 1; +end Exemptions; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb new file mode 100755 index 000000000..a6ecbe190 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb @@ -0,0 +1,48 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, and it executes all the code in all the exempted sections. + +with Exemptions; +with Support; use Support; + +procedure Test_All_Exempted is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Exemptions.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); + -- Code in exemption section is executed + +end Test_All_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l# ## x0 +-- /swap_stmt/ l+ ## 0 + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /xfactorial/ l# ## x0 +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb new file mode 100755 index 000000000..ea83b13b3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb @@ -0,0 +1,54 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, but these calls do not execute/elaborate exempted code. So the only +-- exempted construct that are expected to be reported as covered are those +-- that are executed/elaborated when the spec and body of the package +-- Exemptions are elaborated +-- +-- This driver executes all the non-exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_All_Non_Exempted is + I, J, K : Integer := 1; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Assert (Exemptions.Factorial (3) = 6); + -- No exempted code is executed + + Assert (Exemptions.Another_Factorial (3) = 6); + Assert (Exemptions.Another_Factorial (Positive'Last) = Positive'Last); + -- No exempted code in this function + +end Test_All_Non_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l+ ## 0 +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l+ ## 0 + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l+ ## 0 +-- /in_loop_a_f/ l+ ## 0 +-- /in_if_a_f/ l+ ## 0 +-- /handler_a_f/ l+ ## 0 + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb new file mode 100755 index 000000000..424491b5a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb @@ -0,0 +1,51 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, and it executes a part of the code in a part of the exempted +-- sections. +-- +-- This driver executes not all but only a part of exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_Exempted is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Exemptions.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); + -- Code in exemption section is executed + +end Test_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l# ## x0 +-- /swap_stmt/ l+ ## 0 + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /xfactorial/ l# ## x0 +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb new file mode 100755 index 000000000..06125fd6b --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb @@ -0,0 +1,42 @@ +-- Test driver for exemptions. It only "withes" the functional code, so the +-- only constructs that are expected to be reported as covered are those that +-- are executed/elaborated when the spec and body of the package Exemptions +-- are elaborated + +with Exemptions; +with Support; use Support; + +procedure Test_No is +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); +end Test_No; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l- ## s- +-- /1_factorial/ l- ## s- +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l- ## s- +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb new file mode 100755 index 000000000..0f7bc7b5e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb @@ -0,0 +1,53 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, but these calls do not execute/elaborate exempted code. So the only +-- exempted construct that are expected to be reported as covered are those +-- that are executed/elaborated when the spec and body of the package +-- Exemptions are elaborated +-- +-- This driver executes not all but only a part of non-exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_Non_Exempted is + I, J, K : Integer := 1; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Assert (Exemptions.Factorial (3) = 6); + -- No exempted code is executed + + Assert (Exemptions.Another_Factorial (3) = 6); + -- No exempted code in this function + +end Test_Non_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l+ ## 0 +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l+ ## 0 + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l+ ## 0 +-- /in_loop_a_f/ l+ ## 0 +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst new file mode 100644 index 000000000..5a1985437 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst @@ -0,0 +1,6 @@ +**Exercise exemptions over a mix of statements and declarations in several units** + +Exercise a package that contains non-exempted code and several exemption +regions, for a combination of statements and declarations in subprogram bodies, +in the package specification, and in the package body. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py new file mode 100755 index 000000000..9ba9845bd --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py @@ -0,0 +1,50 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region( + "src/exemptions.adb", "7:7", "10:42", "exemption on declarations" + ), + Exempt_Region( + "src/exemptions.adb", + "24:10", + "28:45", + "exemption on statements in function", + ), + Exempt_On( + "src/exemptions.adb", + "66:4", + None, + "exemption on elaboration code - 1", + ), + Exempt_Off("src/exemptions.adb", "70:39", None), + Exempt_Region( + "src/exemptions.adb", + "74:4", + "78:39", + "exemption on elaboration code - 2", + ), + Exempt_Region( + "src/exemptions.ads", + "20:4", + "23:39", + "exemption on global declaration", + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb new file mode 100644 index 000000000..9be392893 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb @@ -0,0 +1,51 @@ +package body Stacks is + + procedure On (S : in out Stack; Op : Op_Kind; V : in out Integer) is + begin + case Op is -- # op_case + when Push => + pragma Annotate -- # op_oflow + (Xxxx, Exempt_On, "no overflow"); -- # op_oflow + if S.Vcount = S.Size then -- # op_oflow_v1 + raise Constraint_Error; -- # op_oflow_v2 + end if; -- # op_oflow + pragma Annotate (Xxxx, Exempt_Off); -- # op_oflow + + S.Vcount := S.Vcount + 1; -- # op_push + S.Values (S.Vcount) := V; -- # op_push + + when Pop => + pragma Annotate -- # op_uflow + (Xxxx, Exempt_On, "no underflow"); -- # op_uflow + if S.Vcount = 0 then -- # op_uflow_v1 + raise Constraint_Error; -- # op_uflow_v2 + end if; -- # op_uflow + pragma Annotate (Xxxx, Exempt_Off); -- # op_uflow + + V := S.Values (S.Vcount); -- # op_pop + S.Vcount := S.Vcount - 1; -- # op_pop + end case; + exception + when Constraint_Error => + S.Ecount := S.Ecount + 1; -- # op_handler + end; + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + + function Errcount (S : in Stack) return Natural is + begin + return S.Ecount; -- # err_body + end; + +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb new file mode 100644 index 000000000..9867b0aca --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Call nothing, no overflow, no underflow - Both exempted. + +procedure Test_0 is +begin + null; +end; + +--# stacks.adb +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb new file mode 100644 index 000000000..c77127091 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb @@ -0,0 +1,27 @@ +with Stacks, Support; use Stacks, Support; + +-- Pop only, immediate underflow. Overflow uncovered/exempted only. +-- No pop operation performed. + +procedure Test_Pop_U is + S : Stack (Size => 2); + V : Integer; +begin + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb new file mode 100644 index 000000000..353642beb --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb @@ -0,0 +1,27 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, no overflow. Underflow & overflow both uncovered/exempted. + +procedure Test_Push_0 is + S : Stack (Size => 5); + +begin + Push (S, 3); + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb new file mode 100644 index 000000000..8bb76caf7 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb @@ -0,0 +1,30 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, until overflow. Underflow uncovered/exempted only. + +procedure Test_Push_O is + S : Stack (Size => 2); + +begin + Push (S, 1); + Push (S, 3); + Assert (Errcount (S) = 0); + + Push (S, 4); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb new file mode 100644 index 000000000..249586671 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb @@ -0,0 +1,34 @@ +with Stacks, Support; use Stacks, Support; + +-- Push and Pop, no overflow, no underflow - Both exempted. + +procedure Test_PushPop_0 is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb new file mode 100644 index 000000000..373cceb08 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb @@ -0,0 +1,32 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop. Underflow uncovered/exempted only. + +procedure Test_PushPop_O is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb new file mode 100644 index 000000000..5469640b3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb @@ -0,0 +1,37 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop until underflow. Nothing exempted. + +procedure Test_PushPop_OU is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Pop (S, V); + Assert (Errcount (S) = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb new file mode 100644 index 000000000..9c50e1bab --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb @@ -0,0 +1,30 @@ +with Stacks, Support; use Stacks, Support; + +-- Push, then Pop until underflow. Overflow uncovered/exempted only. + +procedure Test_PushPop_U is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Pop (S, V); + Assert (V = 1); + Assert (Errcount (S) = 0); + + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst new file mode 100644 index 000000000..1b6c991f6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst @@ -0,0 +1,5 @@ +**Exercise exemptions over groups of statements within a subprogram body** + +Exercise non-exempted code and several exemption regions within a +subprogram body, all protected by a local exception handler. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py new file mode 100644 index 000000000..af8a189ae --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py @@ -0,0 +1,29 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region("src/stacks.adb", "7:13", "12:48", "no overflow"), + Exempt_On("src/stacks.adb", "18:13", None, "no underflow"), + Exempt_Off( + "src/stacks.adb", + "23:38", + None, + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb new file mode 100644 index 000000000..4ced376ed --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb @@ -0,0 +1,24 @@ + +package body Com is + + -- Non-exempted subprogram body + + procedure Initialize is + begin + Current_State := Idle; -- # init_body + Initialized := True; -- # init_body + end; + +begin + + if Auto_Initialize then + + -- Exempted sequence nested within a conditional, part of + -- a non-generic package body elaboration sequence + + pragma Annotate -- # init_call + (Xxxx, Exempt_On, "auto init off"); -- # init_call + Initialize; -- # init_call_violation + pragma Annotate (Xxxx, Exempt_Off); -- # init_call + end if; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads new file mode 100644 index 000000000..825492be4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads @@ -0,0 +1,16 @@ +package Com is + pragma Elaborate_Body; + + type State is (RX, TX, Idle); + Current_State : State; + + Initialized : Boolean := False; + procedure Initialize; + + Auto_Initialize : Boolean := False; + -- Variable to prevent obvious constant folding and absence of + -- code in conditioned sequences, which we test for coverage + + -- The package elaboration body calls Initialize if Auto_Initialize + -- is True, which can never happen. +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads new file mode 100644 index 000000000..23125d760 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads @@ -0,0 +1,6 @@ +-- Instantiate Gcom with auto-init True. Identity prevents variations in +-- results from possible constant folding otherwise, irrelevant for the test +-- purposes. + +with Support, Gcom; use Support; +package Comi_Init is new Gcom (Auto_Init => Identity(True)); diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads new file mode 100644 index 000000000..6ec75025a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads @@ -0,0 +1,6 @@ +-- Instantiate Gcom with auto-init False. Identity prevents variations in +-- results from possible constant folding otherwise, irrelevant for the test +-- purposes. + +with Support, Gcom; use Support; +package Comi_NoInit is new Gcom (Auto_Init => Identity(False)); diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb new file mode 100644 index 000000000..a396faae4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb @@ -0,0 +1,21 @@ +package body Gcom is + + -- Non-exempted subprogram body + + procedure Initialize is + begin + Initialized := True; -- # init_body + end; + +begin + if Auto_Init then + + -- Exempted sequence nested within a conditional, part of + -- a generic package body elaboration sequence + + pragma Annotate -- # init_call + (Xxxx, Exempt_On, "auto init off"); -- # init_call + Initialize; -- # init_call_violation + pragma Annotate (Xxxx, Exempt_Off); -- # init_call + end if; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads new file mode 100644 index 000000000..1e068af1e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads @@ -0,0 +1,6 @@ +generic + Auto_Init : Boolean; +package Gcom is + Initialized : Boolean := False; + procedure Initialize; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb new file mode 100644 index 000000000..d1c453f5d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb @@ -0,0 +1,15 @@ +with Support, Com; use Support, Com; + +-- The functional package is withed - it's elaboration body is covered with +-- auto_init off, so the init body is not executed and the call to init gets +-- exempted. + +procedure Test_Com is +begin + Assert (Com.Initialized = False); +end; + +--# com.adb +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb new file mode 100644 index 000000000..eaaed1e0a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb @@ -0,0 +1,13 @@ +with Support, Comi_Noinit; use Support; + +-- Reach gcom with auto-init False - call not covered => exempted. + +procedure Test_Gcom_F is +begin + Assert (Comi_Noinit.Initialized = False); +end; + +--# gcom.adb +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb new file mode 100644 index 000000000..df4a78f3d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb @@ -0,0 +1,12 @@ +with Support, Comi_Init; use Support; + +-- Reach gcom with auto-init True - call covered => no exemption + +procedure Test_Gcom_T is +begin + Assert (Comi_Init.Initialized = True); +end; + +--# gcom.adb +-- /init_body/ l+ ## 0 +-- /init_call/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb new file mode 100644 index 000000000..69267c79f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb @@ -0,0 +1,13 @@ +with Support, Comi_Init, Comi_Noinit; use Support; + +-- Reach gcom with auto-init both False and True - call covered => exempted + +procedure Test_Gcom_TF is +begin + Assert (Comi_Init.Initialized = True); + Assert (Comi_Noinit.Initialized = False); +end; + +--# gcom.adb +-- /init_body/ l+ ## 0 +-- /init_call/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst new file mode 100644 index 000000000..62165ecd6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst @@ -0,0 +1,7 @@ +**Exercise exemptions over groups of statements within a package body elaboration sequence** + +Exercise a regular package and a generic package instance +containing a non-exempted subprogram and an exemption region +for a conditional set of statements within the package body +elaboration sequence. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py new file mode 100644 index 000000000..7de0c0f89 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py @@ -0,0 +1,29 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region("src/com.adb", "19:7", "22:42", "auto init off"), + Exempt_On("src/gcom.adb", "16:7", None, "auto init off"), + Exempt_Off( + "src/gcom.adb", + "19:42", + None, + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb new file mode 100644 index 000000000..414b3ee20 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb @@ -0,0 +1,51 @@ +package body Stacks is + + procedure On (S : in out Stack; Op : Op_Kind; V : in out Integer) is + begin + case Op is -- # op_case + when Push => + if S.Vcount = S.Size then -- # test_oflow + raise Constraint_Error; -- # op_oflow + end if; + + S.Vcount := S.Vcount + 1; -- # op_push + S.Values (S.Vcount) := V; -- # op_push + + when Pop => + if S.Vcount = 0 then -- # test_uflow + raise Constraint_Error; -- # op_uflow + end if; + + V := S.Values (S.Vcount); -- # op_pop + S.Vcount := S.Vcount - 1; -- # op_pop + end case; + exception + when Constraint_Error => + + -- Exemption region in local handler here + + pragma Annotate -- # op_handler + (Xxxx, Exempt_On, "exception handler"); -- # op_handler + S.Ecount := S.Ecount + 1; -- # op_handler_stmt + pragma Annotate (Xxxx, Exempt_Off); -- # op_handler + end; + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + + function Errcount (S : in Stack) return Natural is + begin + return S.Ecount; -- # err_body + end; + +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb new file mode 100644 index 000000000..50faca385 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb @@ -0,0 +1,25 @@ +with Stacks, Support; use Stacks, Support; + +-- Call nothing, no overflow, no underflow - handler exempted. + +procedure Test_0 is +begin + null; +end; + +--# stacks.adb +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /test_oflow/ l- ## s- +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb new file mode 100644 index 000000000..23cc089d8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Pop only, immediate underflow. Handler covered. + +procedure Test_Pop_U is + S : Stack (Size => 2); + V : Integer; +begin + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /test_oflow/ l- ## s- +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l+ ## 0 +-- /op_handler/ l# ## x0 + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb new file mode 100644 index 000000000..347eee539 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb @@ -0,0 +1,27 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, no overflow, no underflow. Handler exempted. + +procedure Test_Push_0 is + S : Stack (Size => 5); + +begin + Push (S, 3); + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb new file mode 100644 index 000000000..b81f4a95e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb @@ -0,0 +1,30 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, until overflow. Handler covered. + +procedure Test_Push_O is + S : Stack (Size => 2); + +begin + Push (S, 1); + Push (S, 3); + Assert (Errcount (S) = 0); + + Push (S, 4); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l+ ## 0 +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb new file mode 100644 index 000000000..2a09c98fa --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb @@ -0,0 +1,35 @@ +with Stacks, Support; use Stacks, Support; + +-- Push and Pop, no overflow, no underflow. Handler exempted. + +procedure Test_PushPop_0 is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb new file mode 100644 index 000000000..4f41dc49a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb @@ -0,0 +1,33 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop. Handler covered. + +procedure Test_PushPop_O is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l+ ## 0 +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l- ## s- +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb new file mode 100644 index 000000000..5012ce38d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb @@ -0,0 +1,39 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop until underflow. Handler covered. + +procedure Test_PushPop_OU is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Pop (S, V); + Assert (Errcount (S) = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l+ ## 0 +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l+ ## 0 +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb new file mode 100644 index 000000000..3d31e2be3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb @@ -0,0 +1,31 @@ +with Stacks, Support; use Stacks, Support; + +-- Push, then Pop until underflow. Handler covered. + +procedure Test_PushPop_U is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Pop (S, V); + Assert (V = 1); + Assert (Errcount (S) = 0); + + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l+ ## 0 +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst new file mode 100644 index 000000000..104c89499 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst @@ -0,0 +1,5 @@ +**Exercise exemptions over groups of statements within local exception handlers** + +Exercise non-exempted code and an exemption region for a short sequence of +statements within a local exception handler. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py new file mode 100644 index 000000000..4a726f9fe --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py @@ -0,0 +1,18 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import Exempt_Region, generate_annotations + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region("src/stacks.adb", "27:10", "30:45", "exception handler"), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb new file mode 100755 index 000000000..2f9229d02 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb @@ -0,0 +1,69 @@ +-- This procedure performs completely meaningless computations, its goal is +-- to create a natural context for several exemption sections + +with MX; use MX; + +-- I, J, and K are functional parameters. Xf.(X1, X2, X3) tell if we went +-- into the exempted regions 1, 2, and 3 respectively. Xf.Xh tells if we went +-- into the exempted handler. + +procedure Multiple_Exemptions + (I, J, K : in out Integer; Xf : access Xflags) +is + Tmp : Integer := I; -- # dcl +begin + + Xf.X1 := False; -- # stmt + Xf.X2 := False; -- # stmt + Xf.X3 := False; -- # stmt + Xf.Xh := False; -- # stmt + + -- A few exemption regions within conditionals in a sequence. Getting + -- into the first one raises an exception, caught by a local handler. + + if I = 0 and then J = 0 and then K = 0 then -- # 1_if + Xf.X1 := True; -- # 1_flag + pragma Annotate -- # 1_exem + (Xxxx, Exempt_On, "exemption section #1"); -- # 1_exem + raise Constraint_Error; -- # 1_exem_v1 + pragma Annotate (Xxxx, Exempt_Off); -- # 1_exem + end if; + + I := (I + J + K) / 3; -- # stmt + if I > 0 then -- # stmt + if J < 0 then -- # 2_if + Xf.X2 := True; -- # 2_flag + pragma Annotate -- # 2_exem + (Xxxx, Exempt_On, "exemption section #2"); -- # 2_exem + J := -J; -- # 2_exem_v1 + pragma Annotate (Xxxx, Exempt_Off); -- # 2_exem + end if; + I := Tmp; -- # 2_if + end if; + + J := J + K; -- # stmt + if K < 0 then -- # stmt + if J = 0 then -- # 3_if + Xf.X3 := True; -- # 3_flag + pragma Annotate -- # 3_exem + (Xxxx, Exempt_On, "exemption section #3"); -- # 3_exem + J := 1; -- # 3_exem_v1 + pragma Annotate (Xxxx, Exempt_Off); -- # 3_exem + end if; + K := K + I; -- # 3_if + end if; + +exception + when Constraint_Error => + Xf.Xh := True; -- # h_flag + + -- Here, an exemption region within an exception handler + + pragma Annotate -- # h_exem + (Xxxx, Exempt_On, "exemption section in handler"); -- # h_exem + Tmp := I + J + K; -- # h_exem_v1 + I := Tmp; -- # h_exem_v2 + J := Tmp + 1; -- # h_exem_v3 + K := Tmp + 2; -- # h_exem_v4 + pragma Annotate (Xxxx, Exempt_Off); -- # h_exem +end Multiple_Exemptions; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb new file mode 100644 index 000000000..8b94c8feb --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb @@ -0,0 +1,38 @@ +with Multiple_Exemptions, Support; use Support; + +package body MX is + I, J, K : Integer; + Xf : aliased Xflags; + + procedure Trigger_0XR is + begin + I := 1; J := 1; K := 1; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (not Xf.X1 and then not Xf.X2 + and then not Xf.X3 and then not Xf.Xh); + end; + + procedure Trigger_XR1 is + begin + I := 0; J := 0; K := 0; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (Xf.X1 and then not Xf.X2 + and then not Xf.X3 and then Xf.Xh); + end; + + procedure Trigger_XR2 is + begin + I := 3; J := -1; K := 1; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (not Xf.X1 and then Xf.X2 + and then not Xf.X3 and then not Xf.Xh); + end; + + procedure Trigger_XR3 is + begin + I := 10; J := 1; K := -1; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (not Xf.X1 and then not Xf.X2 + and then Xf.X3 and then not Xf.Xh); + end; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads new file mode 100644 index 000000000..193d6e2d1 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads @@ -0,0 +1,20 @@ +package MX is + + type Xflags is record + X1, X2, X3, Xh : Boolean; + end record; + + procedure Trigger_0XR; + -- Call into the functional code, arranging to get into none of the + -- exempted regions + + procedure Trigger_XR1; + procedure Trigger_XR2; + procedure Trigger_XR3; + -- Call into the functional code, arranging to get into the exempted + -- region 1, 2 or 3 only + + -- This unit is a helper to trigger some pieces of the functional code by + -- calling into it with well chosen set of arguments. It is not subject to + -- coverage expectations. +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb new file mode 100644 index 000000000..d40658d42 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb @@ -0,0 +1,31 @@ +with MX; + +-- Do nothing, so statement gets covered at all, and all the exemption +-- regions do exempt their statements. + +procedure Test_0 is +begin + null; +end Test_0; + +--# multiple_exemptions.adb +-- /dcl/ l- ## s- +-- /1_if/ l- ## s- +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l- ## s- +-- /2_if/ l- ## s- +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb new file mode 100644 index 000000000..08e0e68c1 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb @@ -0,0 +1,26 @@ +-- Call into the functional code, arranging to execute all the code in all +-- the exempted sections, so no violation gets exempted. + +with MX, Support; use MX, Support; + +procedure Test_Exempt_0 is +begin + Trigger_XR1; + Trigger_XR2; + Trigger_XR3; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l+ ## 0 +-- /1_exem/ l# ## x0 +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l+ ## 0 +-- /2_exem/ l# ## x0 +-- /3_if/ l+ ## 0 +-- /3_flag/ l+ ## 0 +-- /3_exem/ l# ## x0 +-- /h_flag/ l+ ## 0 +-- /h_exem/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb new file mode 100644 index 000000000..632346ad6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb @@ -0,0 +1,31 @@ +-- Call into the functional code, arranging not to execute any exempted +-- region, so all the regions do exempt statements. + +with MX; use MX; + +procedure Test_Exempt_All is +begin + Trigger_0XR; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb new file mode 100644 index 000000000..a6088e071 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb @@ -0,0 +1,30 @@ +with MX; use MX; + +-- Call functional code arranging to get into exempted region 3 only, +-- hence exempt violations from regions 1 and 2. + +procedure Test_Exempt_XR12 is +begin + Trigger_XR3; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l+ ## 0 +-- /3_flag/ l+ ## 0 +-- /3_exem/ l# ## x0 +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb new file mode 100644 index 000000000..174224dba --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb @@ -0,0 +1,30 @@ +with MX; use MX; + +-- Call functional code arranging to get into exempted region 2 only, +-- hence exempt violations from regions 1 and 3. + +procedure Test_Exempt_XR13 is +begin + Trigger_XR2; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l+ ## 0 +-- /2_exem/ l# ## x0 +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb new file mode 100644 index 000000000..72be78090 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb @@ -0,0 +1,31 @@ +with MX; use MX; + +-- Call functional code arranging to get into exempted region 1 only, +-- hence exempt violations from regions 2 and 3. + +procedure Test_Exempt_XR23 is +begin + Trigger_XR1; + + -- Region 1 raises an exception, force running the other blocks + -- without the exempted regions. + + Trigger_0XR; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l+ ## 0 +-- /1_exem/ l# ## x0 +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l+ ## 0 +-- /h_exem/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst new file mode 100644 index 000000000..18a80a776 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst @@ -0,0 +1,6 @@ +**Exercise exemptions over a mix of statements and declarations in several regions of a subprogram body** + +Exercise a subprogram containing non-exempted code and several disjoint +exemption regions, in both the top-level sequence of statements and a local +exception handler. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py new file mode 100644 index 000000000..8522e7bea --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py @@ -0,0 +1,36 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region( + "src/multiple_exemptions.adb", "26:7", "29:42", "exemption section #1" + ), + Exempt_Region( + "src/multiple_exemptions.adb", "36:10", "39:45", "exemption section #2" + ), + Exempt_On( + "src/multiple_exemptions.adb", "48:10", None, "exemption section #3" + ), + Exempt_Off("src/multiple_exemptions.adb", "51:45", None), + Exempt_On( + "src/multiple_exemptions.adb", "62:7", None, "exemption section #4" + ), + Exempt_Off("src/multiple_exemptions.adb", "68:42", None), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb new file mode 100644 index 000000000..852466775 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb @@ -0,0 +1,56 @@ +package body Stacks is + + -- Single exemption region for a couple of entire subprogram definitions + + pragma Annotate -- # xregion + (Xxxx, Exempt_On, "we only care about push and pop"); -- # xregion + -- # xregion + procedure On -- # xregion + (S : in out Stack; Op : Op_Kind; V : in out Integer) -- # xregion + is -- # xregion + begin -- # xregion + case Op is -- # xregion_01 + when Push => -- # xregion + if S.Vcount = S.Size then -- # xregion_02 + raise Constraint_Error; -- # xregion_03 + end if; -- # xregion + -- # xregion + S.Vcount := S.Vcount + 1; -- # xregion_04 + S.Values (S.Vcount) := V; -- # xregion_05 + -- # xregion + when Pop => -- # xregion + if S.Vcount = 0 then -- # xregion_06 + raise Constraint_Error; -- # xregion_07 + end if; -- # xregion + -- # xregion + V := S.Values (S.Vcount); -- # xregion_08 + S.Vcount := S.Vcount - 1; -- # xregion_09 + end case; -- # xregion + exception -- # xregion + when Constraint_Error => -- # xregion + S.Ecount := S.Ecount + 1; -- # xregion_10 + end; -- # xregion + -- # xregion + function Errcount (S : in Stack) return Natural is -- # xregion + begin -- # xregion + return S.Ecount; -- # xregion_11 + end; -- # xregion + -- # xregion + pragma Annotate (Xxxx, Exempt_Off); -- # xregion + + -- Then a couple of subprograms without any exemption + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb new file mode 100644 index 000000000..3186da809 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb @@ -0,0 +1,28 @@ +with Stacks, Support; use Stacks, Support; + +-- Call nothing, no overflow, no underflow - region exempted. + +procedure Test_0 is +begin + null; +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_01/ l= ## Xs- +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- +-- /xregion_11/ l= ## Xs- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb new file mode 100644 index 000000000..02a4911e0 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Pop only, immediate underflow. Region exempted. + +procedure Test_Pop_U is + S : Stack (Size => 2); + V : Integer; +begin + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb new file mode 100644 index 000000000..54f9fed66 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, no overflow, no underflow. Region exempted. + +procedure Test_Push_0 is + S : Stack (Size => 5); + +begin + Push (S, 3); + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb new file mode 100644 index 000000000..6d871a716 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb @@ -0,0 +1,28 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, until overflow. Region exempted. + +procedure Test_Push_O is + S : Stack (Size => 2); + +begin + Push (S, 1); + Push (S, 3); + Assert (Errcount (S) = 0); + + Push (S, 4); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb new file mode 100644 index 000000000..af94531be --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb @@ -0,0 +1,31 @@ +with Stacks, Support; use Stacks, Support; + +-- Push and Pop, no overflow, no underflow. Region exempted. + +procedure Test_PushPop_0 is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_10/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb new file mode 100644 index 000000000..9f37a886d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb @@ -0,0 +1,28 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop. Region exempted. + +procedure Test_PushPop_O is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_07/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb new file mode 100644 index 000000000..93c23ba23 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb @@ -0,0 +1,33 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop until underflow. Region covered. + +procedure Test_PushPop_OU is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Pop (S, V); + Assert (Errcount (S) = 2); +end; + +--# stacks.adb +-- /xregion/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb new file mode 100644 index 000000000..0d0c5cef3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Push, then Pop until underflow. Region exempted. + +procedure Test_PushPop_U is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Pop (S, V); + Assert (V = 1); + Assert (Errcount (S) = 0); + + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst new file mode 100644 index 000000000..7dde4dc8e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst @@ -0,0 +1,6 @@ +**Exercise exemptions over groups of entire subprograms** + +Exercise a package that declares some non-exempted subprogram bodies as +well as an exemption region encompassing several other subprograms. + + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py new file mode 100644 index 000000000..2b87406ba --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py @@ -0,0 +1,19 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import Exempt_Region, generate_annotations + +annotations = [ + Exempt_Region( + "src/stacks.adb", "5:4", "39:40", "we only care about push and pop" + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb new file mode 100644 index 000000000..c4c40190a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb @@ -0,0 +1,12 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_0 is +begin + null; +end; + +--# tipos.adb +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_if/ l= ## Xs- +-- /xblock_r1/ l= ## Xs- +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb new file mode 100644 index 000000000..dea643efc --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb @@ -0,0 +1,10 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_All is +begin + Assert (Tipos (5) = 10); + Assert (Tipos (-2) = -2); +end; + +--# tipos.adb +-- /xblock/ l# ## x0:"test exempting all" diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb new file mode 100644 index 000000000..7e377b1f7 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb @@ -0,0 +1,10 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_Other is +begin + Assert (Tipos (-2) = -2); +end; + +--# tipos.adb +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r1/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb new file mode 100644 index 000000000..c3b785427 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb @@ -0,0 +1,10 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_Pos is +begin + Assert (Tipos (5) = 10); +end; + +--# tipos.adb +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb new file mode 100644 index 000000000..8ee02dfa0 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb @@ -0,0 +1,13 @@ +function Tipos (X : Integer) return Integer is +begin + -- Full sequence exempted below + + pragma Annotate (Xxxx, Exempt_On, -- # xblock + "test exempting all"); -- # xblock + if X > 0 then -- # xblock_if + return X * 2; -- # xblock_r1 + else -- # xblock + return X; -- # xblock_r2 + end if; -- # xblock + pragma Annotate (Xxxx, Exempt_Off); -- # xblock +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads new file mode 100644 index 000000000..68d462531 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads @@ -0,0 +1,2 @@ +function Tipos (X : Integer) return Integer; +-- Twice_If_Pos: x * 2 if x positive, x otherwise. diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst new file mode 100644 index 000000000..2fd022a0f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst @@ -0,0 +1,5 @@ +**Exercise exemptions over entire subprogram bodies** + +Exercise a subprogram in which all the statements are part of a single +exemption region. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py new file mode 100644 index 000000000..1b95170f6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py @@ -0,0 +1,17 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import Exempt_Region, generate_annotations + +annotations = [ + Exempt_Region("src/tipos.adb", "5:4", "12:39", "test exempting all"), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/extra.opt b/testsuite/tests/ext_annotations/gen/ada_ex/extra.opt new file mode 100644 index 000000000..596c843db --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test uses pragma not recognized by compiler diff --git a/testsuite/tests/ext_annotations/gen/basic/foo.c b/testsuite/tests/ext_annotations/gen/basic/foo.c new file mode 100644 index 000000000..2f8ce7b14 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/foo.c @@ -0,0 +1,5 @@ +int +ident (int x) +{ + return x; +} diff --git a/testsuite/tests/ext_annotations/gen/basic/main.adb b/testsuite/tests/ext_annotations/gen/basic/main.adb new file mode 100644 index 000000000..c8d6cadd6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/main.adb @@ -0,0 +1,16 @@ +with Interfaces.C; use Interfaces.C; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + function Ident (X : int) return int; + pragma Import(Convention => C, Entity => Ident, External_Name => "ident"); + + X : int := 5; + Res : int := Ident (X); +begin + if X /= Res then + Put_Line ("C really does weird things with their integers"); + end if; +end Main; diff --git a/testsuite/tests/ext_annotations/gen/basic/show_expected.txt b/testsuite/tests/ext_annotations/gen/basic/show_expected.txt new file mode 100644 index 000000000..ac3096f35 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/show_expected.txt @@ -0,0 +1,4 @@ + +main.adb: +- 13:4 - 13:4; id: exempt_on_1; kind: Exempt_On; Justification: unexpected C failure +- 15:11 - 15:11; id: exempt_off_1; kind: Exempt_Off diff --git a/testsuite/tests/ext_annotations/gen/basic/test.py b/testsuite/tests/ext_annotations/gen/basic/test.py new file mode 100644 index 000000000..33343a259 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/test.py @@ -0,0 +1,143 @@ +""" +Simple sanity checking test for the add-annotation, delete-annotation and +show-annotation commands. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +annotation_file = "annotations.toml" + +# Create a simple project to work on +gprsw = GPRswitches( + root_project=gprfor( + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada", "C"], + ) +) + +# Instrument, build and run +cov_args = build_and_run( + gprsw=gprsw, + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=[ + "-axcov", + f"--external-annotations={annotation_file}", + ], +) + +# Generate some annotations. Only use exemption annotations as they can be +# interpreted at coverage time and do not require a full coverage cycle when +# modified. +# Pass the project file as argument to ensure the annotations only contain the +# required +xcov( + [ + "add-annotation", + "--kind=Exempt_On", + "--justification", + "unexpected C failure", + "--location=13:4", + f"--output={annotation_file}", + "--annotation-id=exempt_on_1", + "../main.adb", + ] + + gprsw.cov_switches, + force_project_args=True, +) +xcov( + [ + "add-annotation", + "--kind=Exempt_Off", + "--location=15:11", + f"--external-annotations={annotation_file}", + f"--output={annotation_file}", + "--annotation-id=exempt_off_1", + "../main.adb", + ] + + gprsw.cov_switches, + force_project_args=True, +) + +# Check we get the intended coverage result +cov_1 = "cov_1" +xcov(cov_args + [f"--output-dir={cov_1}"], out="cov_1.log") +check_xcov_reports( + cov_1, + expected_cov={ + "main.adb.xcov": {"+": {10, 11}, "*": {13, 14, 15}}, + "foo.c.xcov": {"+": {4}}, + }, +) + +show_log = "show.log" + +# Show the annotations and check against a baseline +xcov( + [ + "show-annotations", + f"--external-annotations={annotation_file}", + ] + + gprsw.cov_switches, + out=show_log, +) + +thistest.fail_if_diff( + baseline_file="../show_expected.txt", + actual_file=show_log, + failure_message='Unexpected "gnatcov show-annotations" output', +) + +# Delete the annotations and add a new one +xcov( + [ + "delete-annotation", + f"--external-annotations={annotation_file}", + "--annotation-id=exempt_on_1", + f"--output={annotation_file}", + ], +) +xcov( + [ + "delete-annotation", + f"--external-annotations={annotation_file}", + "--annotation-id=exempt_off_1", + f"--output={annotation_file}", + ], +) +xcov( + [ + "add-annotation", + "--kind=Exempt_Region", + "--justification", + "Useless exemption", + "--start-location=4:3", + "--end-location=4:12", + f"--output={annotation_file}", + "--annotation-id=exempt_region_1", + "../foo.c", + ] + + gprsw.cov_switches, + force_project_args=True, +) + +# Re-compute report to ensure the annotations have indeed been modified +# Check we get the intended coverage result +cov_2 = "cov_2" +xcov(cov_args + [f"--output-dir={cov_2}"]) +check_xcov_reports( + cov_2, + expected_cov={ + "main.adb.xcov": {"+": {10, 11}, "!": {13}, "-": {14}}, + "foo.c.xcov": {"#": {4}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb new file mode 100644 index 000000000..4c46e1ef0 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb @@ -0,0 +1,9 @@ +package body Lib1 is + function Foo return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xxxx, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb new file mode 100644 index 000000000..3aea37455 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb @@ -0,0 +1,9 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xxxx, Dump_Buffers); + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb new file mode 100644 index 000000000..6242717d5 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb @@ -0,0 +1,30 @@ +pragma Ada_2012; + +with Lib1; +with Lib2; +with Manual_Dump; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + -- The only call that should not count as a violation when never executed + -- is that of the dump buffers procedure. + if 1 = I + 1 then + pragma Annotate (Xcov, Dump_Buffers); + I := I+ 1; + end if; + + Increment (I); + pragma Annotate (Xcov, Dump_Buffers); + I := I + Lib1.Foo; + I := I + Lib2.Bar; + Manual_Dump.Dump; + Increment (I); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb new file mode 100644 index 000000000..cde653702 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb @@ -0,0 +1,6 @@ +package body Manual_Dump is + procedure Dump is + begin + pragma Annotate (Xxxx, Dump_Buffers); + end Dump; +end Manual_Dump; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads new file mode 100644 index 000000000..898439fa6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads @@ -0,0 +1,3 @@ +package Manual_Dump is + procedure Dump; +end Manual_Dump; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt new file mode 100644 index 000000000..da87b2710 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt @@ -0,0 +1,2 @@ +block DEAD Manual dump wrapped in procedure call (unsupported when using block coverage) +5.04a1 DEAD Uses pragma unknown to compiler diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py new file mode 100644 index 000000000..16298244e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py @@ -0,0 +1,103 @@ +""" +Test that when using manual dump trigger in Ada with a specific pragma +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + Dump_Buffers, + generate_annotations, + gprfor, + srctrace_pattern_for, +) + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("src/manual_dump.adb", "4:7", None, insert_after=True), + Dump_Buffers("src-lib1/lib1.adb", "6:9", None, insert_after=True), + Dump_Buffers("src-lib2/lib2.adb", "6:9", None, insert_after=True), + ] +) + +tmp = Wdir("tmp_") + +lib1_p = gprfor( + mains=[], + prjid="lib1", + srcdirs="../src-lib1", + objdir="obj-lib1", + langs=["Ada"], +) + +lib2_p = gprfor( + mains=[], + prjid="lib2", + srcdirs="../src-lib2", + objdir="obj-lib2", + langs=["Ada"], +) + +p = gprfor( + prjid="gen", + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], +) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="gen", + tolerate_instrument_messages=instr_warning, +) + +# Check that gnatcov inserted the call to the dump buffers procedure in the +# lib2.adb which is not a unit of interest + + +def check_call(file): + thistest.fail_if_no_match( + "missing dump buffers procedure call", + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers(.*);" "(\n|.)*", + contents_of(file), + ) + + +check_call("obj-lib2/lib2-gnatcov-instr/lib2.adb") + +# Generate and check coverage reports, using the last trace generated for the +# root project. +trace_file = sorted( + glob.glob(srctrace_pattern_for("main", manual=True, manual_prj_name="gen")) +)[-1] + +xcov(cov_args + [trace_file], out="coverage.log") +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {12, 15, 19, 24, 26, 27, 28}, "-": {21, 29}}, + "lib1.adb.xcov": {"+": {4, 7}}, + "lib1.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb new file mode 100644 index 000000000..83adfaee4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb @@ -0,0 +1,12 @@ +with Lib2; + +package body Lib1 is + function Foo return Integer + is + Res : Integer := 1; + begin + Res := Res + Lib2.Bar; + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb new file mode 100644 index 000000000..dac52ea6c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb @@ -0,0 +1,8 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb new file mode 100644 index 000000000..d52e99f7a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Lib1; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + Increment (I); + I := I + Lib1.Foo; + Increment (I); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py new file mode 100644 index 000000000..2c3f42e1f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py @@ -0,0 +1,98 @@ +""" +Test that when using manual dump trigger in Ada with the appropriate buffers +dump pragma only in a subproject itself dependent on another subproject +gnatcov is able to provide the correct coverage analysis. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import Dump_Buffers, generate_annotations, gprfor + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [Dump_Buffers("src-lib1/lib1.adb", "9:9", None, insert_after=True)] +) + + +def make_lib_gpr(name, srcdirs, deps): + return gprfor( + mains=[], + prjid=name, + srcdirs=srcdirs, + objdir="obj-" + name, + langs=["Ada"], + deps=deps, + ) + + +def check_one(with_units): + """ + Do a build, run, coverage, and report-check workflow, ensuring we get the + expected warnings and coverage results. + + with_units controls wether the --units option is passed + to gnatcov instrument to restrict analysis to the units in the projects + where the manual dump indication has visibility. + """ + + suffix = "units" if with_units else "no_units" + tmp = Wdir("tmp_" + suffix) + + make_lib_gpr("lib1", "../src-lib1", ["lib2"]) + make_lib_gpr("lib2", "../src-lib1/src-lib2", None) + + p = gprfor( + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], + ) + + # Check that we get the expected coverage reports + + # Running gnatcov natively allows to have one source trace file per + # project. + instr_warning = ( + r"warning: Manual buffer dump/reset indications were" r" found in.*" + ) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=p, units=["lib1", "lib2"] if with_units else None + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov", "--output-dir=xcov_" + suffix], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="lib1", + tolerate_instrument_messages=instr_warning, + ) + + # If with_units is False, we expect coverage violations for main.adb + check_xcov_reports( + "xcov_" + suffix, + { + "lib1.adb.xcov": {"+": {6, 8}, "-": {10}}, + "lib1.ads.xcov": {}, + "lib2.adb.xcov": {"+": {4, 6}}, + "lib2.ads.xcov": {}, + } + | ( + {} + if with_units + else {"main.adb.xcov": {"-": {10, 13, 15, 16, 17}}} + ), + ) + tmp.to_homedir() + + +check_one(with_units=False) +check_one(with_units=True) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c new file mode 100644 index 000000000..d51660a01 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* *******_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c new file mode 100644 index 000000000..abbbb22c8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* *******_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* *******_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py new file mode 100644 index 000000000..61b6d3260 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py @@ -0,0 +1,92 @@ +""" +Test that when using manual dump trigger in C with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import Dump_Buffers, generate_annotations, gprfor +from SUITE.gprutils import GPRswitches + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("src/main.c", "17:7", None), + Dump_Buffers("src/main.c", "24:3", None), + Dump_Buffers("src-lib/foo.c", "6:3", None), + ] +) + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.c" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.c.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp new file mode 100644 index 000000000..d51660a01 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* *******_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp new file mode 100644 index 000000000..abbbb22c8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* *******_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* *******_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt new file mode 100644 index 000000000..5a8819395 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt @@ -0,0 +1 @@ +!C++ DEAD test specific to C++ handling diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py new file mode 100644 index 000000000..a84bbcd44 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py @@ -0,0 +1,94 @@ +""" +Test that when using manual dump trigger in C++ with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import Dump_Buffers, generate_annotations, gprfor +from SUITE.gprutils import GPRswitches + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("src/main.cpp", "17:7", None), + Dump_Buffers("src/main.cpp", "24:3", None), + Dump_Buffers("src-lib/foo.cpp", "6:3", None), + ] +) + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.cpp"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C++"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C++"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +# Ensure we get no compilation warnings, this used to be the case without the +# proper dump function declaration. +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.cpp" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.cpp.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.cpp.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/extra.opt b/testsuite/tests/ext_annotations/gen/buf_dump/extra.opt new file mode 100644 index 000000000..ff4943776 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD src-trace only feature tests diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb new file mode 100644 index 000000000..837c15a87 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xxxx, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c new file mode 100644 index 000000000..c12408cbb --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* *******_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp new file mode 100644 index 000000000..3086d2ec2 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + std::cout << "hello C++ world!" << std::endl; + /* *******_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt new file mode 100644 index 000000000..ab2120f34 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test uses stdio +!C++ DEAD test requires C++ compiler +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py new file mode 100644 index 000000000..696e636e8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py @@ -0,0 +1,79 @@ +""" +Check that using --dump-trigger=manual works correctly in projects where a +manual dump indication is present in an Ada source and in all supported C-like +sources. + +This is a regression test, gnatcov used to emit helper units with colliding +object filenames, resulting in the instrumented sources failing to build. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + Dump_Buffers, + generate_annotations, + gprfor, + run_cov_program, + exepath_to, +) + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("main_ada.adb", "6:5", None, insert_after=True), + Dump_Buffers("main_c.c", "7:3", None), + Dump_Buffers("main_cpp.cpp", "7:3", None), + ] +) + +Wdir("tmp_") + +# Name for the main_c and main_cpp executable traces +c_trace_name = "main_c.srctrace" +cpp_trace_name = "main_cpp.srctrace" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so all mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the other mains manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c", "main_cpp.cpp"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + dump_trigger="manual", + manual_prj_name="p", + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov", c_trace_name, cpp_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) + +env["GNATCOV_TRACE_FILE"] = cpp_trace_name +run_cov_program(exepath_to("main_cpp"), env=env) + +xcov(cov_args) +check_xcov_reports( + "obj", + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + "main_cpp.cpp.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format b/testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format new file mode 100644 index 000000000..74b68f75d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: GNU +ColumnLimit: 80 +ContinuationIndentWidth: 2 +IndentWidth: 2 +ReflowComments: true +SortIncludes: Never +UseTab: Never diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb b/testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb new file mode 100644 index 000000000..68f88cd34 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb @@ -0,0 +1,15 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Main_Ada is +begin + Assert (not Or_Else (False, False)); + pragma Annotate (Xxxx, Dump_Buffers, "ada-0"); + pragma Annotate (Xxxx, Reset_Buffers); + Assert (Or_Else (True, False)); + pragma Annotate (Xxxx, Dump_Buffers, "ada-1"); + pragma Annotate (Xxxx, Reset_Buffers); + Assert (Or_Else (False, True)); + pragma Annotate (Xxxx, Dump_Buffers, "ada-2"); +end Main_Ada; diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c b/testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c new file mode 100644 index 000000000..88c95920c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c @@ -0,0 +1,17 @@ +#include + +extern bool and_then (bool left, bool right); + +int +main (void) +{ + and_then (true, true); + /* *******_DUMP_BUFFERS ("c-0") */ + /* *******_RESET_BUFFERS */ + and_then (true, false); + /* *******_DUMP_BUFFERS ("c-1") */ + /* *******_RESET_BUFFERS */ + and_then (false, true); + /* *******_DUMP_BUFFERS ("c-2") */ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb new file mode 100644 index 000000000..de46c9e85 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Or_Else (L, R : Boolean) return Boolean is + begin + return L or else R; + end Or_Else; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads new file mode 100644 index 000000000..2bedb4461 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Or_Else (L, R : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c b/testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c new file mode 100644 index 000000000..016dfffad --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c @@ -0,0 +1,7 @@ +#include + +bool +and_then (bool left, bool right) +{ + return left && right; +} diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/test.opt b/testsuite/tests/ext_annotations/gen/buffer_reset/test.opt new file mode 100644 index 000000000..4f6c15e13 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD Test specific to src trace feature +!native DEAD Test requires bin-file dump channel +5.04a1 DEAD Uses pragmas unknown to the compiler diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/test.py b/testsuite/tests/ext_annotations/gen/buffer_reset/test.py new file mode 100644 index 000000000..af8324cb8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/test.py @@ -0,0 +1,174 @@ +""" +Test basic functionality of the buffer reset mechanism, in both C and Ada +source files. +""" + +import glob +import re + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + Dump_Buffers, + generate_annotations, + gprfor, + Reset_Buffers, +) + +annotations = generate_annotations( + [ + Dump_Buffers("main_c.c", "9:3", None, trace_prefix='"c-0"'), + Reset_Buffers("main_c.c", "10:3", None), + Dump_Buffers("main_c.c", "12:3", None, trace_prefix='"c-1"'), + Reset_Buffers("main_c.c", "13:3", None), + Dump_Buffers("main_c.c", "15:3", None, trace_prefix='"c-2"'), + Dump_Buffers("main_ada.adb", "8:5", None, trace_prefix='"ada-0"'), + Reset_Buffers("main_ada.adb", "9:5", None, insert_after=True), + Dump_Buffers("main_ada.adb", "11:5", None, trace_prefix='"ada-1"'), + Reset_Buffers("main_ada.adb", "12:5", None, insert_after=True), + Dump_Buffers("main_ada.adb", "14:5", None, trace_prefix='"ada-2"'), + ] +) + +tmp = Wdir("tmp_") + +# Map from language to the corresponding main report name, and lines with +# coverage obligations. +main_lines = { + "ada": ("main_ada.adb.xcov", [7, 10, 13]), + "c": ("main_c.c.xcov", [8, 11, 14, 16]), +} + +# Units which will only have a partial coverage result in them, regardless of +# the trace. +default_part_cov = { + "ada": {"pkg.adb.xcov": {"!": {5}}, "pkg.ads.xcov": {}}, + "c": {"pkh.c.xcov": {"!": {6}}}, +} + +# Default "nothing executed" expected result for each unit +default_no_cov = { + "ada": { + "main_ada.adb.xcov": {"-": {7, 10, 13}}, + "pkg.adb.xcov": {"-": {5}}, + "pkg.ads.xcov": {}, + }, + "c": { + "main_c.c.xcov": {"-": {8, 11, 14, 16}}, + "pkh.c.xcov": {"-": {6}}, + }, +} + + +def get_expected_cov(trace_name): + """ + Generate an expected coverage results based on the prefix of the trace + indicating which main was executed, and its index. + """ + match = re.match(pattern=r"(.*)-(\d)\.srctrace", string=trace_name) + thistest.fail_if( + not match, comment="trace name not in expected format: " + trace_name + ) + trace_lang = match.group(1) + idx = int(match.group(2)) + expected_cov = {} + + lines = main_lines[trace_lang][1] + for lang in ("ada", "c"): + if lang == trace_lang: + expected_cov.update( + { + main_lines[lang][0]: { + "+": {lines[idx]}, + "-": {lines[i] for i in range(len(lines)) if i != idx}, + } + } + ) + expected_cov.update(default_part_cov[lang]) + else: + expected_cov.update(default_no_cov[lang]) + return expected_cov + + +def check_one_exec(cov_args, lang): + """ + Find the traces generated by the lang executable, assuming the trace prefix + is lang. Then create a coverage report from each trace, checking the + expected coverage report. + """ + + thistest.log(f"======== Checking {lang} traces =========") + + # We expect the trace to be in the format + # {lang}-{index}.srctrace: + traces = glob.glob(f"{lang}-[0-9].srctrace") + + # There is three dump indications in each main, we should thus have the + # same number of traces. + thistest.fail_if( + len(traces) != 3, comment=f"expected 3 traces, found {len(traces)}" + ) + traces.sort() + + for i in range(len(traces)): + thistest.log(f"-- {i + 1}. --") + output_dir = f"output_{lang}_{i}/" + xcov( + cov_args + [f"--output-dir={output_dir}", traces[i]], + out=f"coverage_{lang}_{i}.log", + ) + check_xcov_reports(output_dir, get_expected_cov(traces[i])) + + +prj_id = "p" + +# Instrument build and run +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid=prj_id, + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + ) + ), + covlevel="stmt+mcdc", + mains=["main_ada", "main_c"], + dump_trigger="manual", + manual_prj_name=prj_id, + extra_coverage_args=["-axcov+"], + extra_instr_args=[ + "--dump-filename-simple", + f"--external-annotations={annotations}", + ], +) + +# Check the individual trace contents for each executable +for lang in ["c", "ada"]: + check_one_exec(cov_args, lang) + +# Do a consolidated check with all the traces. We expect exactly six traces and +# no coverage violations except for the final return statement in the c main. +thistest.log("========== global consolidated check =========") +all_traces = glob.glob("*.srctrace") +thistest.fail_if( + len(all_traces) != 6, comment=f"expected 6 traces, got {len(all_traces)}" +) +output_dir = "consolidated/" +xcov( + cov_args + [f"--output-dir={output_dir}"] + all_traces, + out="consolidated.log", +) +check_xcov_reports( + output_dir, + { + "main_ada.adb.xcov": {"+": {7, 10, 13}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {8, 11, 14}, "-": {16}}, + "pkh.c.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c new file mode 100644 index 000000000..ed78da614 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c @@ -0,0 +1,21 @@ + +int +fact (int n) +{ + if (n == 0) + { + return 1; + } + return n * fact (n - 1); +} + +int +main (void) +{ + return + /* ***************ON "In statement"*/ + fact (0) == 1 + /* ***************OFF)*/ + ? 0 + : 1; +} diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py new file mode 100644 index 000000000..b92f74288 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py @@ -0,0 +1,44 @@ +""" +Check that gnatcov correctly rejects exemption markers intersecting SCOs. +""" + +# TODO: This may need to be moved to a Robustness chapter instead when +# proper qualification tests are written for C. + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, Exempt_Region, generate_annotations +from SUITE.gprutils import GPRswitches + +# Generate external annotations, they will be generated in a dedicated +# temporary directory +annotations = generate_annotations( + [Exempt_Region("main.c", "16:5", "18:31", "In statement")] +) + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.c"], srcdirs=[".."])), + extra_coverage_args=["--annotate=xcov"], + extra_instr_args=[f"--external-annotations={annotations}"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + tolerate_instrument_messages="Exemption .* intersects", +) + +check_xcov_reports( + "obj", + {"main.c.xcov": {"+": {7, 15}, "!": {5, 17}, "-": {9}}}, +) + +thistest.fail_if_no_match( + what="Unexpected instrument output", + regexp=r"(warning: Exemption annotation at main\.c:\d+:\d+ intersects a" + r" coverage obligation \(.*\), ignoring it\n)+", + actual=contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c new file mode 100644 index 000000000..6bdd7e67e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c @@ -0,0 +1,35 @@ +#include "pkg.h" +#include + +#define NOT(A) !A + +// ***************** "whole function single line comment" // # exempt_at +bool // # exempt_at +andThen (bool a, bool b) // # exempt_at +{ // # exempt_at + return a && b; // # exempt_at +} // # exempt_at +// ****************** // # exempt_at + +bool +orElse (bool a, bool b) +{ + // ***************** "if stmt" // # exempt_oe + if (a || b) // # exempt_oe_v1 + { // # exempt_oe + // ****************** // # exempt_oe + return true; + } + else + { + return false; + } +} + +bool +negation (bool a) +{ + /* ***************** "single statement, multiline comment"*/ // # exempt_neg + return NOT (a); // # exempt_neg_v1 + /* ****************** */ // # exempt_neg +} diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h new file mode 100644 index 000000000..419e178b8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h @@ -0,0 +1,12 @@ +#ifndef PKG_H +#define PKG_H + +#include + +extern bool andThen (bool a, bool b); + +extern bool orElse (bool a, bool b); + +extern bool negation (bool a); + +#endif diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c new file mode 100644 index 000000000..10627e6ab --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c @@ -0,0 +1,20 @@ +#include "pkg.h" + +int +main (void) +{ + volatile bool x = orElse (false, true); + x = orElse (false, false); + x = andThen (true, true); + x = andThen (true, false); + x = andThen (false, false); + return 0; +} + +//# pkg.c +// +// /exempt_at/ l# ## x0 +// /exempt_oe/ l* ## x+ +// /exempt_oe_v1/ l= ## Xc! +// /exempt_neg/ l* ## x+ +// /exempt_neg_v1/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py new file mode 100644 index 000000000..00f693d55 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py @@ -0,0 +1,44 @@ +""" +Test simple exemption cases in C sources. This is a copy of +tests/C/mcdc/Exemptions/Nominal, with the comments modified +to not be recognized, and external annotations being generated +instead. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region( + "src/pkg.c", "6:4", "12:22", "whole function single line comment" + ), + Exempt_On("src/pkg.c", "17:4", None, "if stmt"), + Exempt_Off("src/pkg.c", "20:7", None), + Exempt_Region( + "src/pkg.c", "32:3", "34:24", "whole function single line comment" + ), +] + +annot_file = generate_annotations( + annotations, + tolerate_messages=( + r"warning: Could not create an auto-relocating annotation for src." + "pkg.c:6:4 - 12:22, creating an absolute location annotation instead." + ), +) + + +# Check we get the expected results +TestCase(category=CAT.mcdc).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/c_ex/extra.opt b/testsuite/tests/ext_annotations/gen/c_ex/extra.opt new file mode 100644 index 000000000..25d72a22d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD exemptions not supported in bin traces for C diff --git a/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt b/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt new file mode 100644 index 000000000..714f23df4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt @@ -0,0 +1,6 @@ + +main.adb: +- STALE ANNOTATION; id: exempt_ada; kind: Exempt_Region; Justification: Useless code; diagnostic: Contents of changed + +main_c.c: +- STALE ANNOTATION; id: exempt_c; kind: Exempt_Region; Justification: Useless code; diagnostic: Content of declaration ident has changed diff --git a/testsuite/tests/ext_annotations/gen/invalidation/test.py b/testsuite/tests/ext_annotations/gen/invalidation/test.py new file mode 100644 index 000000000..ffa90d1a5 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/test.py @@ -0,0 +1,115 @@ +""" +Basic test concerning invalidation of annotations by gnatcov when the +annotated sources have been modified beyond what stable_sloc can manage. +""" + +import os + +from SCOV.minicheck import ( + build_run_and_coverage, + check_xcov_reports, + contents_of, + xcov, +) +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +annotation_file = "annotations.toml" + +prefix = os.path.join("..", "v1", "") + +# Create annotations for the V1 sources +xcov( + [ + "add-annotation", + "--kind=Exempt_Region", + "--justification", + "Useless code", + "--start-location=4:7", + "--end-location=4:16", + f"--output={annotation_file}", + "--annotation-id=exempt_ada", + f"--source-root={prefix}", + "../v1/main.adb", + ] +) +xcov( + [ + "add-annotation", + "--kind=Exempt_Region", + "--justification", + "Useless code", + "--start-location=5:3", + "--end-location=5:12", + f"--external-annotations={annotation_file}", + f"--output={annotation_file}", + "--annotation-id=exempt_c", + f"--source-root={prefix}", + "../v1/main_c.c", + ] +) + +# Create a project from V2 sources +gprsw = GPRswitches( + root_project=gprfor( + mains=["main.adb"], + srcdirs=["../v2"], + langs=["Ada", "C"], + ) +) + +# Try to show the annotations on the modified sources +show_log = "show.log" +xcov( + [ + "show-annotations", + f"--external-annotations={annotation_file}", + "--quiet", + ] + + gprsw.cov_switches, + out=show_log, +) + +thistest.fail_if_diff( + baseline_file="../show_expected.txt", + actual_file=show_log, + failure_message='Unexpected "gnatcov show-annotations" output', +) + +# Run the coverage workflow, check for expected warnings and that no +# annotations have been taken into acount. Do not consider main_c.c as +# a main to avoid issues with the last_chance_chandler, the coverage results +# are secondary anyways. +coverage_log = "coverage.log" +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=[ + "-axcov", + f"--external-annotations={annotation_file}", + ], + tolerate_coverage_messages="Stale annotation for main.*", + out=coverage_log, +) + +thistest.fail_if_no_match( + "Unexpected 'gnatcov coverage' warnings:", + regexp=r"(\n?warning: Stale annotation for main.*){2}", + actual=contents_of(coverage_log), +) + +# We expect violations and no exempted regions +check_xcov_reports( + reports_dir="obj", + expected_cov={ + "main.adb.xcov": {"+": {6, 9, 12}}, + "main_c.c.xcov": {"-": {6, 12}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb b/testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb new file mode 100644 index 000000000..088538465 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb @@ -0,0 +1,11 @@ +procedure Main is + function Nested (X : Integer) return Integer is + begin + return X; + end Nested; + + Y : Integer; + pragma Volatile (Y); +begin + Y := Nested (2); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c b/testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c new file mode 100644 index 000000000..2932e2a43 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c @@ -0,0 +1,12 @@ + +int +ident (int x) +{ + return x; +} + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb b/testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb new file mode 100644 index 000000000..a6ca7855f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb @@ -0,0 +1,13 @@ +procedure Main is + function Nested (X : Integer) return Integer is + begin + -- Useless + + return X; + end Nested; + + Y : Integer; + pragma Volatile (Y); +begin + Y := Nested (2); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c b/testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c new file mode 100644 index 000000000..856db0d1d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c @@ -0,0 +1,13 @@ + +int +ident (int x) +{ + // Useless + return x; +} + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/readme.md b/testsuite/tests/ext_annotations/gen/readme.md new file mode 100644 index 000000000..85272418d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/readme.md @@ -0,0 +1,22 @@ +This directory contains a copy of a subset of some tests related to exemptions, +and buffer annotations. The modifications compared to the original tests is +that the annotations in sources (pragmas and comments) have been neutralized, +and the test.py scripts have been augmented to include invocations to the +gnatcov add-annotation command to generate equivalent annotations. + +The test results are supposed to be equivalent. + +The purpose of these tests is to ensure that using external annotation file and +the "gnatcov add-annotation" command can be used in place of in-source +annotations. + + +Test directory names may have been shortened to avoid path limit issues in +Windows configs. + +Ada pragmas for exemptions and coverage disabling are replaced by an annotate +pragma for a fictional tool so that the pragmas still generates a SCO + +C/C++ exemption comments are simply emptied. + +Buffer dump comments / pragmas are entirely removed. diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/Ada/annotations.toml b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/annotations.toml new file mode 100644 index 000000000..1bc199463 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/annotations.toml @@ -0,0 +1,69 @@ +[cov_off_1] +file="test_main.adb" +kind="absolute" +[cov_off_1.matcher] +start_line=11 +start_col=5 +end_line=11 +end_col=5 +[[cov_off_1.annotations]] +purpose="xcov.cov.off" + +[cov_on_1] +file="test_main.adb" +kind="absolute" +[cov_on_1.matcher] +start_line=11 +start_col=26 +end_line=11 +end_col=26 +[[cov_on_1.annotations]] +purpose="xcov.cov.on" +insert_after=true + +[cov_off_2] +file="test_main.adb" +kind="absolute" +[cov_off_2.matcher] +start_line=15 +start_col=3 +end_line=15 +end_col=3 +[[cov_off_2.annotations]] +purpose="xcov.cov.off" + +[cov_on_2] +file="test_main.adb" +kind="absolute" +[cov_on_2.matcher] +start_line=15 +start_col=26 +end_line=15 +end_col=26 +[[cov_on_2.annotations]] +purpose="xcov.cov.on" +insert_after=true + +[cov_off_3] +file="test_main.adb" +kind="absolute" +[cov_off_3.matcher] +start_line=17 +start_col=3 +end_line=17 +end_col=3 +[[cov_off_3.annotations]] +justification='"coverage is disabled"' +purpose="xcov.cov.off" + +[cov_on_3] +file="test_main.adb" +kind="absolute" +[cov_on_3.matcher] +start_line=17 +start_col=26 +end_line=17 +end_col=26 +[[cov_on_3.annotations]] +purpose="xcov.cov.on" +insert_after=true diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/Ada/src/test_main.adb b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/src/test_main.adb new file mode 100644 index 000000000..6bb878f98 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/src/test_main.adb @@ -0,0 +1,26 @@ +procedure Test_Main +is + A, B : Boolean := True; + + procedure Foo (B: Boolean) is null; -- # cov_on + + procedure Uncovered; + + procedure Uncovered is + begin + Foo (A and then B); -- # cov_off + end Uncovered; + +begin + Foo (A and then B); -- # cov_off + + Foo (A and then B); -- # cov_off + + Foo (A and then B); -- # partial_cov_on +end Test_Main; + +--# test_main.adb +-- +-- /cov_off/ lD ## 0 +-- /cov_on/ l+ ## 0 +-- /partial_cov_on/ l! ## eF- diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/Ada/test.py b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/test.py new file mode 100644 index 000000000..73315bd8e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/test.py @@ -0,0 +1,20 @@ +""" +Check gnatcov support for selective instrumentation for Ada. + +This variation of the test uses external annotations instead of +in-source pragmas. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* Missing or empty justification for external disabled coverage" + r' region annotation ".*"' + ), +).run(CovControl(instroptions="--external-annotations=../annotations.toml")) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/C/src/cons_a_b.txt b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/cons_a_b.txt new file mode 100644 index 000000000..b78b04823 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/cons_a_b.txt @@ -0,0 +1,12 @@ +drivers=. + +--# pkg.h +-- /cov-off-a/ lD ## dB +-- /cov-off-b/ lD ## dB +-- /cov-on/ l- ## s- +-- +--# test_a.c +-- /covered/ l+ ## 0 +-- +--# test_b.c +-- /covered/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/C/src/pkg.h b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/pkg.h new file mode 100644 index 000000000..5e766d801 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/pkg.h @@ -0,0 +1,17 @@ +int +foo (int a, int b) +{ +#ifdef A + /* PLACEHOLDER */ // # cov-off-a + int c = a && b; // # cov-off-a + /* PLACEHOLDER */ // # cov-off-a +#endif + +#ifdef B + /* PLACEHOLDER */ // # cov-off-b + int d = a && b; // # cov-off-b + /* PLACEHOLDER */ // # cov-off-b +#endif + + return 0; // # cov-on +} diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_a.c b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_a.c new file mode 100644 index 000000000..4a5e24760 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_a.c @@ -0,0 +1,19 @@ +#define A + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-a/ lD ## dB +// /cov-off-b/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_a.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_b.c b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_b.c new file mode 100644 index 000000000..75d7e1f23 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_b.c @@ -0,0 +1,19 @@ +#define B 1 + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-a/ lD ## dB +// /cov-off-b/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_b.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py b/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py new file mode 100644 index 000000000..f22b89bc9 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py @@ -0,0 +1,41 @@ +""" +Check gnatcov support for selective instrumentation for C when a file has +various preprocessing configuration resulting in varying preprocessed versions, +and the user has disabled coverage for every code region differing across +preprocessing invocations. + +Note that in this case, the user must use checkpoint consolidation, as there +can only exists one version of the SIDs at a time. + +This version of the test uses external annotations instead of comments, which +are always loaded irrespectively of preprocessing configuration, we thus have +more regions flagged as "disabled coverage" +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +from SUITE.tutils import Cov_Off, Cov_On, generate_annotations + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = generate_annotations( + [ + Cov_Off("src/pkg.h", "5:3", None), + Cov_On("src/pkg.h", "7:3", None), + Cov_Off("src/pkg.h", "11:3", None), + Cov_On("src/pkg.h", "13:3", None), + ], + tolerate_messages="--justification missing", +) + +thistest.options.consolidate = "checkpoints" +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* Missing or empty justification for external disabled coverage" + r' region annotation ".*"' + ), +).run(CovControl(instroptions=f"--external-annotations={annotations}")) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/extra.opt b/testsuite/tests/ext_annotations/gen/selective_cov/extra.opt new file mode 100644 index 000000000..ea8a3c8ac --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/selective_cov/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific feature diff --git a/testsuite/tests/ext_annotations/simple_name_check/annotations.toml b/testsuite/tests/ext_annotations/simple_name_check/annotations.toml new file mode 100644 index 000000000..b4da3534d --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/annotations.toml @@ -0,0 +1,11 @@ +[region] +file="reset.adb" +kind="absolute" +[region.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=11 +[[region.annotations]] +purpose="xcov.exempt.region" +justification="dummy exemption" diff --git a/testsuite/tests/ext_annotations/simple_name_check/src/reset.adb b/testsuite/tests/ext_annotations/simple_name_check/src/reset.adb new file mode 100644 index 000000000..115293dd7 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/src/reset.adb @@ -0,0 +1,4 @@ +procedure Reset (X : in out Integer) is +begin + X := 0; -- # st +end Reset; diff --git a/testsuite/tests/ext_annotations/simple_name_check/src/reset.ads b/testsuite/tests/ext_annotations/simple_name_check/src/reset.ads new file mode 100644 index 000000000..51b2399e0 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/src/reset.ads @@ -0,0 +1,2 @@ +procedure Reset (X : in out Integer); +-- Reset X to 0 diff --git a/testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb b/testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb new file mode 100644 index 000000000..dbfad0977 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb @@ -0,0 +1,14 @@ +with Reset; + +with Support; + +procedure Test_Reset is + X : Integer := 10; +begin + Reset (X); + Support.Assert (X = 0); +end Test_Reset; + +--# reset.adb +-- +-- /st/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/simple_name_check/test.py b/testsuite/tests/ext_annotations/simple_name_check/test.py new file mode 100644 index 000000000..c7dd490e6 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/test.py @@ -0,0 +1,23 @@ +""" +Test that attempting to retrieve external exemptions for a file with +no obligations does not crash on binary traces. This used to happen +because such files were not registered under their full name in the +file table, thus resulting in a crash when attempting to get their +full name. + +In this instance, gnatcov would crash attempting to retrieve the full filename +for reset.ads. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run( + CovControl( + covoptions="--external-annotations=../annotations.toml", + instroptions="", + ), +) + +thistest.result() diff --git a/testsuite/tests/extract-base64-trace-errors/extra.opt b/testsuite/tests/extract-base64-trace-errors/extra.opt new file mode 100644 index 000000000..5f2157d55 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/extra.opt @@ -0,0 +1 @@ +!src-traces DEAD extract-base64-traces is specific to source traces diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py new file mode 100644 index 000000000..5c21fc74c --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py @@ -0,0 +1,52 @@ +""" +Make sure that an invalid base64 trace that is missing characters does not +generate a corrupted srctrace file. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of, exists +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_channel="base64-stdout", +) + +INVALID_TRACE_FILE = "invalid_trace.b64" +SHOULD_NOT_EXIST_TRACE = "SHOULD_NOT_EXIST.srctrace" +STDERR_EXTRACT = "stderr-extract.txt" + +# Then, modify the trace to make it invalid +with open(INVALID_TRACE_FILE, "w") as f: + original = contents_of("main_output.txt") + f.write(original.replace("AAAA", "AAA")) + +# Try extracting the source trace from base64, but should fail. +xcov( + ["extract-base64-trace", INVALID_TRACE_FILE, SHOULD_NOT_EXIST_TRACE], + register_failure=False, + err=STDERR_EXTRACT, +) + +# Ensure the test failed for the good reason. +thistest.fail_if_no_match( + "Test is expected to fail because we are unable to decode base64 " + "characters 4 by 4", + r".*Invalid Base64 trace: incomplete group of 4 characters", + contents_of(STDERR_EXTRACT), +) + +# Ensure the command did not generate an invalid srctrace file. +thistest.fail_if( + exists(SHOULD_NOT_EXIST_TRACE), "shouldn't have created an srctrace file" +) + +thistest.result() diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py new file mode 100644 index 000000000..46380d19e --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py @@ -0,0 +1,54 @@ +""" +Make sure that an invalid truncated base64 trace (missing '== End ==' suffix) +does not generate a corrupted srctrace file. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of, exists +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_channel="base64-stdout", +) + +INVALID_TRACE_FILE = "invalid_trace.b64" +SHOULD_NOT_EXIST_TRACE = "SHOULD_NOT_EXIST.srctrace" +STDERR_EXTRACT = "stderr-extract.txt" + +# Then, modify the trace to make it invalid +with open(INVALID_TRACE_FILE, "w") as f: + original = contents_of("main_output.txt") + + truncated_output = original.replace("\n== End ==", "") + + f.write(truncated_output) + +# Try extracting the source trace from base64, but should fail. +xcov( + ["extract-base64-trace", INVALID_TRACE_FILE, SHOULD_NOT_EXIST_TRACE], + register_failure=False, + err=STDERR_EXTRACT, +) + +# Ensure the test failed for the good reason. +thistest.fail_if_no_match( + "Test is expected to fail because the base64 is truncated", + r".*Incomplete Base64 trace", + contents_of(STDERR_EXTRACT), +) + +# Ensure the command did not generate an invalid srctrace file. +thistest.fail_if( + exists(SHOULD_NOT_EXIST_TRACE), "shouldn't have created an srctrace file" +) + +thistest.result() diff --git a/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py new file mode 100644 index 000000000..b46321722 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py @@ -0,0 +1,66 @@ +""" +Make sure that a base64 trace that has a line which is too long does not +generate a corrupted srctrace file. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of, exists +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_channel="base64-stdout", +) + +INVALID_TRACE_FILE = "invalid_trace.b64" +SHOULD_NOT_EXIST_TRACE = "SHOULD_NOT_EXIST.srctrace" +STDERR_EXTRACT = "stderr-extract.txt" + +# Then, modify the trace to make it invalid +with open(INVALID_TRACE_FILE, "w") as f: + original = contents_of("main_output.txt") + + b64_digest = original.split("== GNATcoverage source trace file ==\n")[ + 1 + ].split("\n== End ==")[0] + + long_line = "AAAA" * 1000 + digest_with_long_line = f"{b64_digest}\n{long_line}" + + new_b64_trace = ( + "== GNATcoverage source trace file ==\n" + f"\n{digest_with_long_line}\n" + "== End ==" + ) + + f.write(new_b64_trace) + +# Try extracting the source trace from base64, but should fail. +xcov( + ["extract-base64-trace", INVALID_TRACE_FILE, SHOULD_NOT_EXIST_TRACE], + register_failure=False, + err=STDERR_EXTRACT, +) + +# Ensure the test failed for the good reason. +thistest.fail_if_no_match( + "Test is expected to fail because a line is too loong to be " + "valid base64 trace", + r".*Unexpected long line in Base64 trace", + contents_of(STDERR_EXTRACT), +) + +# Ensure the command did not generate an invalid srctrace file. +thistest.fail_if( + exists(SHOULD_NOT_EXIST_TRACE), "shouldn't have created an srctrace file" +) + +thistest.result() diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr new file mode 100644 index 000000000..f13e8c0ab --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr @@ -0,0 +1,15 @@ +abstract project Main_Common is + + Target := project'Target; + + Target_Dir := "error :("; + case Target is + when "x86_64-pc-linux-gnu" => + Target_Dir := "obj-x86"; + when others => + Target_Dir := "unknown-"; + end case; + + Build_Dir := Target_Dir; + +end Main_Common; diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr new file mode 100644 index 000000000..c7e50610d --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr @@ -0,0 +1,16 @@ +with "main_common.gpr"; + +project Main_x86 is + + for Target use "x86_64-pc-linux-gnu"; + + for Languages use ("Ada"); + + for Source_Dirs use ("."); + + for Main use ("main.adb"); + + for Object_Dir use Main_Common.Build_Dir; + for Exec_Dir use "exe"; + +end Main_x86; diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt new file mode 100644 index 000000000..3cde64263 --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt @@ -0,0 +1 @@ +!x86_64-linux DEAD Target specific test diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py new file mode 100644 index 000000000..58a610e96 --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py @@ -0,0 +1,34 @@ +""" +Regression test: check that gnatcov create instrumentation artifacts in the +right object directory. It used to create them in the wrong object directory +when the object directory value depended on the Project'Target attribute and +when the target was passed explicitly on the command line. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +Wdir("tmp_") +for src in ("main_x86.gpr", "main_common.gpr", "main.adb"): + cp(os.path.join("..", src), src) + +build_run_and_coverage( + gprsw=GPRswitches(root_project="main_x86.gpr"), + mains=["main"], + covlevel="stmt", + gpr_exe_dir="exe", + gpr_obj_dir="obj-x86", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + auto_config_args=False, + extra_args=["--target=x86_64-pc-linux-gnu"], +) + +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/gnatcov-run.py b/testsuite/tests/gnatcov-run.py new file mode 100755 index 000000000..c7e8fe98e --- /dev/null +++ b/testsuite/tests/gnatcov-run.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +""" +Example script to be used as a testsuite.py --gnatcov-run argument, which the +suite engine will call instead of "gnatcov run" to execute programs and produce +an execution trace that "gnatcov coverage" can process later on. + +This should return/exit with code 0 in case of success, with another value +otherwise. More generally This needs to be ready to honor the "gnatcov run" +interface, at least the subset of arguments that the testsuite driver might use +for your target configuration. Simplest is to error out on unrecognized +options. + +The code below eventually resorts to a real "gnatcov run" invocation. While +there is no real added value in doing that, this code is useful as an example +of a possible way to achieve the goal of replacing gnatcov run in other +situations. A typical case is one where the program execution is performed on a +real target board, producing a some trace that needs to be converted to a +format gnatcov can process. +""" + +import os +import optparse + +from e3.os.process import Run + + +class Runner: + def __init__(self): + self.parse_command_line() + self.run() + + def parse_command_line(self): + """Parse this script's command line.""" + + op = optparse.OptionParser() + + # --level and --target are expected to always be there: + op.add_option("--level", dest="covlevel", default=None) + op.add_option("--target", dest="target", default=None) + + # For source coverage tests not using project files: + op.add_option("--scos", dest="scos", default=None) + + # For tests using project files + op.add_option("-P", dest="gpr", default=None) + op.add_option( + "--recursive", dest="recurse", default=False, action="store_true" + ) + op.add_option("--projects", dest="projects", default=None) + op.add_option("--units", dest="units", default=None) + + # Then a few optional items + op.add_option("-o", dest="ofile", default=None) + self.options, self.args = op.parse_args() + + def run_command_line(self): + """Compute a list of command line arguments to pass to + gnatcov run from what we have received.""" + + args = [ + "--level=%s" % self.options.covlevel, + "--target=%s" % self.options.target, + ] + + if self.options.scos: + args.append("--scos=%s" % self.options.scos) + + if self.options.gpr: + args.append("-P=%s" % self.options.gpr) + if self.options.gpr: + args.append("--projects=%s" % self.options.projects) + if self.options.gpr: + args.append("--units=%s" % self.options.units) + if self.options.recurse: + args.append("--recursive") + + if self.options.ofile: + args.append("-o %s" % self.options.ofile) + + return args + + def run(self): + print("============== GNATCOV RUN ===================") + + if not self.args: + print("gnatcov: missing EXE for run") + os.exit(1) + + Run(["gnatcov", "run"] + self.run_command_line() + self.args) + + print("==============================================") + + +runner = Runner() diff --git a/testsuite/tests/gpr-scos/src/dec.adb b/testsuite/tests/gpr-scos/src/dec.adb new file mode 100644 index 000000000..3e681318a --- /dev/null +++ b/testsuite/tests/gpr-scos/src/dec.adb @@ -0,0 +1,4 @@ +procedure Dec (X : in out Integer) is +begin + X := X - 1; +end; diff --git a/testsuite/tests/gpr-scos/src/inc.adb b/testsuite/tests/gpr-scos/src/inc.adb new file mode 100644 index 000000000..62ef0bdc5 --- /dev/null +++ b/testsuite/tests/gpr-scos/src/inc.adb @@ -0,0 +1,4 @@ +procedure Inc (X : in out Integer) is +begin + X := X + 1; +end; diff --git a/testsuite/tests/gpr-scos/src/test_ops.adb b/testsuite/tests/gpr-scos/src/test_ops.adb new file mode 100644 index 000000000..0d33f5180 --- /dev/null +++ b/testsuite/tests/gpr-scos/src/test_ops.adb @@ -0,0 +1,18 @@ +with Inc, Dec; + +procedure Test_Ops is + + procedure Assert (P : Boolean) is + begin + if not P then + raise Program_Error; + end if; + end; + + X : Integer := 12; +begin + Inc (X); + Assert (X = 13); + Dec (X); + Assert (X = 12); +end; diff --git a/testsuite/tests/gpr-scos/test.py b/testsuite/tests/gpr-scos/test.py new file mode 100644 index 000000000..c6b525b46 --- /dev/null +++ b/testsuite/tests/gpr-scos/test.py @@ -0,0 +1,74 @@ +""" +Check the interactions between --scos/--sid and -P regarding the set of units +of interest. Essentially, --scos/--sid is expected to override whatever the -P +family would yield. +""" + +from e3.fs import ls, rm + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir("tmp_") + +# Build and run our example test, 1 driver + 2 units +project = gprfor(srcdirs=["../src"], mains=["test_ops.adb"]) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=project), + covlevel="stmt", + mains=["test_ops"], + extra_coverage_args=["--annotate=xcov"], +) + + +# Now exercise various combinations of units of interest +# specifications with --scos and/or -P, and check they produce +# the set of .xcov reports we expect. + +# Arrange to always produce the reports in the current directory, +# regardless of --scos or -P, so they are straightforward to find +# or remove in all circumstances. + + +def trycov(sco_units, with_project, expected_reports): + rm("*.xcov", recursive=False) + + src_trace = thistest.options.trace_mode == "src" + sco_args = [ + "--{}=obj/{}.{}".format( + "sid" if src_trace else "scos", unit, "sid" if src_trace else "ali" + ) + for unit in sco_units + ] + project_args = ["-P", project] if with_project else [] + xcov(xcov_args + sco_args + project_args + ["--output-dir=."]) + + reports = ls("*.xcov") + + thistest.fail_if( + set(reports) != set(expected_reports), + "With %s, %s (found) != %s (expected)" + % (str(sco_args), str(reports), str(expected_reports)), + ) + + +# --scos/--sid alone +trycov( + sco_units=["inc"], with_project=False, expected_reports=["inc.adb.xcov"] +) + +# -P alone +trycov( + sco_units=[], + with_project=True, + expected_reports=["inc.adb.xcov", "dec.adb.xcov", "test_ops.adb.xcov"], +) + +# --scos with -P, check that --scos prevails +trycov(sco_units=["dec"], with_project=True, expected_reports=["dec.adb.xcov"]) + +thistest.result() diff --git a/testsuite/tests/header_not_found/base_foo/base.gpr b/testsuite/tests/header_not_found/base_foo/base.gpr new file mode 100644 index 000000000..44b4bce9c --- /dev/null +++ b/testsuite/tests/header_not_found/base_foo/base.gpr @@ -0,0 +1,3 @@ +project Base is + for Languages use ("C"); +end Base; diff --git a/testsuite/tests/header_not_found/base_foo/support.h b/testsuite/tests/header_not_found/base_foo/support.h new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/header_not_found/base_foo/support.h @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/header_not_found/include_base_foo/prj.gpr b/testsuite/tests/header_not_found/include_base_foo/prj.gpr new file mode 100644 index 000000000..def07ce5d --- /dev/null +++ b/testsuite/tests/header_not_found/include_base_foo/prj.gpr @@ -0,0 +1,5 @@ +project Prj extends "../base_foo/base.gpr" is + for Main use ("test.c"); + for Source_Dirs use ("."); + for Object_Dir use "obj"; +end Prj; diff --git a/testsuite/tests/header_not_found/include_base_foo/test.c b/testsuite/tests/header_not_found/include_base_foo/test.c new file mode 100644 index 000000000..fb779d605 --- /dev/null +++ b/testsuite/tests/header_not_found/include_base_foo/test.c @@ -0,0 +1,7 @@ +#include "support.h" + +int +main () +{ + return foo (); +} diff --git a/testsuite/tests/header_not_found/include_foo/headers/support.h b/testsuite/tests/header_not_found/include_foo/headers/support.h new file mode 100644 index 000000000..1d4a1ab35 --- /dev/null +++ b/testsuite/tests/header_not_found/include_foo/headers/support.h @@ -0,0 +1,7 @@ +int +foo () +{ + // Dummy comment to make this header different from its version in the + // extended project. + return 0; +} diff --git a/testsuite/tests/header_not_found/include_foo/prj.gpr b/testsuite/tests/header_not_found/include_foo/prj.gpr new file mode 100644 index 000000000..6f538b733 --- /dev/null +++ b/testsuite/tests/header_not_found/include_foo/prj.gpr @@ -0,0 +1,5 @@ +project Prj extends "../base_foo/base.gpr" is + for Main use ("test.c"); + for Source_Dirs use (".", "headers"); + for Object_dir use "obj"; +end Prj; diff --git a/testsuite/tests/header_not_found/include_foo/test.c b/testsuite/tests/header_not_found/include_foo/test.c new file mode 100644 index 000000000..fb779d605 --- /dev/null +++ b/testsuite/tests/header_not_found/include_foo/test.c @@ -0,0 +1,7 @@ +#include "support.h" + +int +main () +{ + return foo (); +} diff --git a/testsuite/tests/header_not_found/test.opt b/testsuite/tests/header_not_found/test.opt new file mode 100644 index 000000000..b91fcd5fd --- /dev/null +++ b/testsuite/tests/header_not_found/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Instrumentation specific problem diff --git a/testsuite/tests/header_not_found/test.py b/testsuite/tests/header_not_found/test.py new file mode 100644 index 000000000..ba3332928 --- /dev/null +++ b/testsuite/tests/header_not_found/test.py @@ -0,0 +1,46 @@ +""" +Check that gnatcov correctly instruments an extending project when a source +includes a header belonging to the extended project. Also check that it picks +the version of the header that is in the ultimate extending project. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest + +Wdir("tmp_") + + +def process(gpr_dir, expected_cov): + gpr_obj_dir = os.path.join(gpr_dir, "obj") + build_run_and_coverage( + gprsw=GPRswitches(root_project=os.path.join(gpr_dir, "prj.gpr")), + covlevel="stmt", + mains=["test"], + gpr_obj_dir=gpr_obj_dir, + gpr_exe_dir=gpr_obj_dir, + extra_coverage_args=["--annotate=xcov"], + ) + check_xcov_reports(gpr_obj_dir, expected_cov) + + +# Check that the header in the extended project is picked by gnatcov instrument +# when there is no version in the extending project. +expected_cov = { + "test.c.xcov": {"+": {6}}, + "support.h.xcov": {"+": {4}}, +} +process(os.path.join("..", "include_base_foo"), expected_cov) + +# If there is a version of the header in the extending project, check that this +# is the one picked. +expected_cov = { + "test.c.xcov": {"+": {6}}, + "support.h.xcov": {"+": {6}}, +} +process(os.path.join("..", "include_foo"), expected_cov) + +thistest.result() diff --git a/testsuite/tests/homonym-units-of-interest/prj1/pkg.c b/testsuite/tests/homonym-units-of-interest/prj1/pkg.c new file mode 100644 index 000000000..f939f7693 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/prj1/pkg.c @@ -0,0 +1,5 @@ +int +foo (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/homonym-units-of-interest/prj2/pkg.c b/testsuite/tests/homonym-units-of-interest/prj2/pkg.c new file mode 100644 index 000000000..845f66891 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/prj2/pkg.c @@ -0,0 +1,5 @@ +int +bar (int a, int b) +{ + return a || b; +} diff --git a/testsuite/tests/homonym-units-of-interest/test.c b/testsuite/tests/homonym-units-of-interest/test.c new file mode 100644 index 000000000..6d783a071 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/test.c @@ -0,0 +1,10 @@ +extern int foo (int a, int b); +extern int bar (int a, int b); + +int +main () +{ + foo (0, 1); + bar (0, 1); + return 0; +} diff --git a/testsuite/tests/homonym-units-of-interest/test.py b/testsuite/tests/homonym-units-of-interest/test.py new file mode 100644 index 000000000..405e71a1f --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/test.py @@ -0,0 +1,93 @@ +""" +This test checks that gnatcov can deal with two homonym files belonging to +different projects, with one of the source files being excluded from the +coverage analysis (through project file coverage attributes) while the other +is not. +""" + +import os.path + +from e3.fs import sync_tree + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest, gprfor, xcov + +wd = Wdir("tmp_") + +# Run the build and run in a dedicated directory + +prj1 = gprfor(mains=[], prjid="prj1", srcdirs=["../prj1"], objdir="obj-prj1") +prj2 = gprfor(mains=[], prjid="prj2", srcdirs=["../prj2"], objdir="obj-prj2") +p = gprfor(mains=["test.c"], deps=["prj1", "prj2"], srcdirs=[".."]) + +xcov_args = build_and_run( + # TODO: The test fails if we pass an absolute path to root_project, which + # is unexpected. + gprsw=GPRswitches(root_project=os.path.basename(p)), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], +) + +# Now onto coverage. Try to ignore pkg.c in prj1, and in prj2 in two different +# gnatcov coverage invocations, using the project attributes as this can't be +# specified unambiguously on the command line. +# +# This checks two things: +# +# * a user can ignore a specific source file even if it has an homonym in +# the project tree. Note that the user would probably have the same +# project for instrument / coverage, but for testing purposes, we also +# need to check the second point. +# +# * gnatcov instrument does not generate a single SID file for the two +# homonym source files. + +ignore_pkg = """ +package Coverage is + for Excluded_Units use ("pkg.c"); +end Coverage; +""" + +wd.to_homedir() + + +def check_report(prj_ignore, prj_of_interest): + """ + Check that the report is correct when the homonym source file (pkg.c) is + ignored in prj_ignore and of interest in prj_of_interest. + """ + subdir = f"tmp_cov_ignore_{prj_ignore}" + wd = Wdir(subdir) + sync_tree(os.path.join("..", "tmp_"), ".") + gprfor( + mains=[], + prjid=prj_ignore, + srcdirs=[f"../{prj_ignore}"], + objdir=f"obj-{prj_ignore}", + extra=ignore_pkg, + ) + xcov(xcov_args) + + # The filtering of units of interest is done at a later stage for binary + # traces, and files that may be ignored in the coverage report can have + # been added to gnatcov's file table. This means that the shortest unique + # suffix computed from gnatcov file table to differentiate homonym source + # files will be different from source traces. + xcov_homonoym_filename = ( + f"{prj_of_interest}-pkg.c.xcov" + if thistest.options.trace_mode == "bin" + else "pkg.c.xcov" + ) + check_xcov_reports( + "xcov", + {xcov_homonoym_filename: {"!": {4}}, "test.c.xcov": {"+": {7, 8, 9}}}, + ) + wd.to_homedir() + + +check_report("prj1", "prj2") +check_report("prj2", "prj1") +thistest.result() diff --git a/testsuite/tests/ignored-c-file/foo.c b/testsuite/tests/ignored-c-file/foo.c new file mode 100644 index 000000000..e78bea7cd --- /dev/null +++ b/testsuite/tests/ignored-c-file/foo.c @@ -0,0 +1,5 @@ +int +foo (int n) +{ + return n; +} diff --git a/testsuite/tests/ignored-c-file/test.c b/testsuite/tests/ignored-c-file/test.c new file mode 100644 index 000000000..0a6cb91c2 --- /dev/null +++ b/testsuite/tests/ignored-c-file/test.c @@ -0,0 +1,8 @@ +extern int foo (int n); + +int +main (void) +{ + foo (1); + return 0; +} diff --git a/testsuite/tests/ignored-c-file/test.py b/testsuite/tests/ignored-c-file/test.py new file mode 100644 index 000000000..b0200b7cb --- /dev/null +++ b/testsuite/tests/ignored-c-file/test.py @@ -0,0 +1,22 @@ +""" +Check that ignoring a C file file works as expected. It used to make "gnatcov +coverage" crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.c"], srcdirs=[".."])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov", "--ignore-source-files=foo.c"], +) + +check_xcov_reports("obj", {"test.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/ignored-c-header/identity.c b/testsuite/tests/ignored-c-header/identity.c new file mode 100644 index 000000000..e10714ed4 --- /dev/null +++ b/testsuite/tests/ignored-c-header/identity.c @@ -0,0 +1,7 @@ +#include "identity.h" + +int +id (int n) +{ + return static_identity (n); +} diff --git a/testsuite/tests/ignored-c-header/identity.h b/testsuite/tests/ignored-c-header/identity.h new file mode 100644 index 000000000..fda54f8d6 --- /dev/null +++ b/testsuite/tests/ignored-c-header/identity.h @@ -0,0 +1,5 @@ +static int +static_identity (int n) +{ + return n; +} diff --git a/testsuite/tests/ignored-c-header/test.c b/testsuite/tests/ignored-c-header/test.c new file mode 100644 index 000000000..4878ddf27 --- /dev/null +++ b/testsuite/tests/ignored-c-header/test.c @@ -0,0 +1,10 @@ +#include "twice.h" + +extern int id (int n); + +int +main () +{ + int n = id (twice (2)); + return 0; +} diff --git a/testsuite/tests/ignored-c-header/test.py b/testsuite/tests/ignored-c-header/test.py new file mode 100644 index 000000000..30606b0dc --- /dev/null +++ b/testsuite/tests/ignored-c-header/test.py @@ -0,0 +1,56 @@ +""" +Check that ignoring a C header file works as expected. It used to make "gnatcov +coverage" crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.c"], srcdirs=[".."])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=[ + "--annotate=xcov", + # Ignore directly "twice.h" + "--ignore-source-files=twice.h", + # Ignore indirectly "identity.h", as its CU's origin is "identity.c". + # It is important for test reliability to check this testcase that only + # "identity.c" includes "identity.h". + "--ignore-source-files=identity.c", + ], + tolerate_coverage_messages=".", +) + +expected_coverage = { + "test.c.xcov": {"+": {8, 9}}, + "identity.h.xcov": {"+": {4}}, +} + +# The following is specific to the instrumentation: the CU for "identity.h" +# depends on the "identity.c". As a result, ignoring "identity.c" implicitly +# ignores "identity.h", and gnatcov is supposed to warn for this case. +# +# Since gnatcov emits a report for all source files, we still expect a report +# for "identify.h". +# +# For binary traces, the CU for "identity.h" does not depend on "identity.c" +# (its Origin is "identity.c.gli", instead), so the above is not true. +if thistest.options.trace_mode == "src": + cov_log = contents_of("coverage.log").strip() + thistest.fail_if_no_match( + "'gnatcov coverage' output", + r"warning: gnatcov limitation: ignoring unit identity\.h from" + r".*[\\/]identity\.c\.sid because identity\.c is ignored$", + cov_log, + ) + + expected_coverage["identity.h.xcov"] = {} + +check_xcov_reports("obj", expected_coverage) + +thistest.result() diff --git a/testsuite/tests/ignored-c-header/twice.h b/testsuite/tests/ignored-c-header/twice.h new file mode 100644 index 000000000..df3a7fe00 --- /dev/null +++ b/testsuite/tests/ignored-c-header/twice.h @@ -0,0 +1,5 @@ +static int +twice (int n) +{ + return 2 * n; +} diff --git a/testsuite/tests/ignored-casing/main.adb b/testsuite/tests/ignored-casing/main.adb new file mode 100644 index 000000000..10e85a255 --- /dev/null +++ b/testsuite/tests/ignored-casing/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Do_Things; +end Main; diff --git a/testsuite/tests/ignored-casing/pkg.adb b/testsuite/tests/ignored-casing/pkg.adb new file mode 100644 index 000000000..39d405e46 --- /dev/null +++ b/testsuite/tests/ignored-casing/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Do_Things is + begin + Put_Line ("Hello, world!"); + end Do_Things; + +end Pkg; diff --git a/testsuite/tests/ignored-casing/pkg.ads b/testsuite/tests/ignored-casing/pkg.ads new file mode 100644 index 000000000..d7efa61ac --- /dev/null +++ b/testsuite/tests/ignored-casing/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Do_Things; +end Pkg; diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py new file mode 100644 index 000000000..fc32b3768 --- /dev/null +++ b/testsuite/tests/ignored-casing/test.py @@ -0,0 +1,56 @@ +""" +Check that, except on Windows, the casing of glob patterns for +--ignore-source-files is significant. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +ignore_opt = "--ignore-source-files=Pkg.adb" +expected_reports = { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, +} +if env.build.os.name != "windows": + expected_reports["pkg.adb.xcov"] = {"+": {7}} + +# First check --ignore-source-files on "gnatcov coverage" +thistest.log("== gnatcov coverage --ignore-source-files ==") +tmp = Wdir("tmp_cov") +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=[ + "--annotate=xcov", + "--output-dir=out-cov", + ignore_opt, + ], +) +check_xcov_reports("out-cov", expected_reports) +tmp.to_homedir() + +# Then check it on "gnatcov instrument". This separate test makes sense as +# --ignore-source-files exercises different code paths depending on the gnatcov +# command. +thistest.log("== gnatcov instrument --ignore-source-files ==") +tmp = Wdir("tmp_instr") +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_instr_args=[ignore_opt], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], + trace_mode="src", +) +check_xcov_reports("out-instr", expected_reports, discard_empty=False) +tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb b/testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb b/testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb new file mode 100644 index 000000000..9a0c41ad1 --- /dev/null +++ b/testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb @@ -0,0 +1,6 @@ +with Main; + +procedure Main_Root is +begin + Main; +end Main_Root; diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/test.py b/testsuite/tests/instr-cov/126-main-in-dependency/test.py new file mode 100644 index 000000000..96b3b1402 --- /dev/null +++ b/testsuite/tests/instr-cov/126-main-in-dependency/test.py @@ -0,0 +1,38 @@ +""" +Regression testcase: checks that gnatcov correctly deals with mains in +dependency projects. It used to crash when there was a main in one of the +dependencies. The correct behavior should be not instrumenting them as a main. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +main_prj = gprfor( + srcdirs=[os.path.join("..", "src-main-dep")], + prjid="main_dep", + mains=["main.adb"], + objdir="obj-main", +) +root_prj = gprfor( + srcdirs=[os.path.join("..", "src")], + deps=[main_prj], + mains=["main_root.adb"], + objdir="obj", +) + +# This also checks that we do not produce multiple traces +build_run_and_coverage( + gprsw=GPRswitches(root_project=root_prj), + covlevel="stmt", + mains=["main_root"], + extra_coverage_args=["-axcov"], +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c new file mode 100644 index 000000000..77d01c9d7 --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c @@ -0,0 +1,9 @@ +#include + +int +main (int argc, char **argv) +{ + size_t a = (size_t) 0; + /* GNATCOV_DUMP_BUFFERS */ + return a; +} diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py new file mode 100644 index 000000000..1e66329bf --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py @@ -0,0 +1,36 @@ +""" +Regression testcase: when using the manual dump-trigger, we used to have +mismatching coverage obligations between the step recording preprocessing +information and the step instrumenting. That was because we were missing +standard preprocessor search paths when parsing the source file in the former +step + +As a reminder, to record preprocessing information, we parse the unpreprocessed +file with clang, and we inhibit builtin macros, as well as standard compiler +headers to fully mimick the behavior of the preprocessor _in use_ (e.g. gcc). +This means that if we are missing part of that configuration, which was the +case there, we end up with an ill-formed AST. This results in wrong coverage +obligations for the step recording preprocessing information. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="gen", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6}, "-": {8}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c new file mode 100644 index 000000000..10db6f9ee --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c @@ -0,0 +1,9 @@ +#ifdef MAIN +int +main (int argc, char **argv) +{ + int a = 0; + /* GNATCOV_DUMP_BUFFERS */ + return a; +} +#endif diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py new file mode 100644 index 000000000..5f06b9cab --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py @@ -0,0 +1,30 @@ +""" +Check that we consider unit-specific compiler switches (that have an effect on +the preprocessing) when using the manual dump-trigger. We used to ignore them. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[".."], mains=["main.c"], main_cargs=["-DMAIN=1"] + ) + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="gen", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.c.xcov": {"+": {5}, "-": {7}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/main.c b/testsuite/tests/instr-cov/144-no-unknown-warning/main.c new file mode 100644 index 000000000..f3836d7ba --- /dev/null +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/main.c @@ -0,0 +1,5 @@ +int +main (int argc, char **argv) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/test.opt b/testsuite/tests/instr-cov/144-no-unknown-warning/test.opt new file mode 100644 index 000000000..b4cb46ef9 --- /dev/null +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Compilation option (-Wtrampolines) unsupported by GNAT 5.04 diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/test.py b/testsuite/tests/instr-cov/144-no-unknown-warning/test.py new file mode 100644 index 000000000..819bf69ba --- /dev/null +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/test.py @@ -0,0 +1,28 @@ +""" +Check that gnatcov does not yield "unknown warning warnings" when parsing a +file with warnings not recognized by clang. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[".."], mains=["main.c"], main_cargs=["-Wtrampolines"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/main.adb b/testsuite/tests/instr-cov/198-non-instr-scos/main.adb new file mode 100644 index 000000000..3fff114ee --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + V : Pkg.T := Pkg.Create; +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb new file mode 100644 index 000000000..3f25bad55 --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package body Pkg is + + ------------ + -- Length -- + ------------ + + function Length (Self : T) return Natural is + begin + return 0; + end Length; + +end Pkg; diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads new file mode 100644 index 000000000..5e4ac24fd --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package Pkg is + type T is tagged null record; + + function Length (Self : T) return Natural; + + function Create return T is (null record); +end Pkg; diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/test.opt b/testsuite/tests/instr-cov/198-non-instr-scos/test.opt new file mode 100644 index 000000000..a2a0796ac --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Ada 2012 support required diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/test.py b/testsuite/tests/instr-cov/198-non-instr-scos/test.py new file mode 100644 index 000000000..bdf1a3aab --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/test.py @@ -0,0 +1,35 @@ +""" +Regression testcase specific to the Ada instrumenter: check that a +non-instrumented SCO in one source file (pkg.ads) does not trigger a crash in +the next source file that is instrumented for the same unit (pkg.adb). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + tolerate_instrument_messages=( + ".*cannot instrument an expression function which.*" + ), +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6}}, + "pkg.ads.xcov": {"?": {8}}, + "pkg.adb.xcov": {"-": {11}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/208-no-secsta/gnat.adc b/testsuite/tests/instr-cov/208-no-secsta/gnat.adc new file mode 100644 index 000000000..e479c000b --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/gnat.adc @@ -0,0 +1 @@ +pragma Restrictions (No_Secondary_Stack); diff --git a/testsuite/tests/instr-cov/208-no-secsta/main.adb b/testsuite/tests/instr-cov/208-no-secsta/main.adb new file mode 100644 index 000000000..81dfb35d1 --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Two_Digits : constant Int_Range := (10, 99); +begin + if In_Range (9, Two_Digits) then + Put_Line ("ERROR!"); + elsif not In_Range (10, Two_Digits) then + Put_Line ("ERROR!"); + end if; +end Main; diff --git a/testsuite/tests/instr-cov/208-no-secsta/pkg.adb b/testsuite/tests/instr-cov/208-no-secsta/pkg.adb new file mode 100644 index 000000000..5582cd2cd --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + -------------- + -- In_Range -- + -------------- + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean is + begin + return Value >= Bounds.Low_Bound and then Value <= Bounds.High_Bound; + end In_Range; + +end Pkg; diff --git a/testsuite/tests/instr-cov/208-no-secsta/pkg.ads b/testsuite/tests/instr-cov/208-no-secsta/pkg.ads new file mode 100644 index 000000000..7c4b0232e --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + + type Int_Range is record + Low_Bound, High_Bound : Integer; + end record; + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean; +end Pkg; diff --git a/testsuite/tests/instr-cov/208-no-secsta/test.py b/testsuite/tests/instr-cov/208-no-secsta/test.py new file mode 100644 index 000000000..e9cf5d315 --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/test.py @@ -0,0 +1,39 @@ +""" +Check that projects with the No_Secondary_Stack restriction compile fine after +instrumentation. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +p = gprfor( + srcdirs=[".."], + mains=["main.adb"], + compiler_extra='for Local_Configuration_Pragmas use "../gnat.adc";', +) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": { + "+": {5}, + "!": {7, 9}, + "-": {8, 10}, + }, + "pkg.adb.xcov": {"!": {9}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/216-no-elab-all/main.adb b/testsuite/tests/instr-cov/216-no-elab-all/main.adb new file mode 100644 index 000000000..81dfb35d1 --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Two_Digits : constant Int_Range := (10, 99); +begin + if In_Range (9, Two_Digits) then + Put_Line ("ERROR!"); + elsif not In_Range (10, Two_Digits) then + Put_Line ("ERROR!"); + end if; +end Main; diff --git a/testsuite/tests/instr-cov/216-no-elab-all/pkg.adb b/testsuite/tests/instr-cov/216-no-elab-all/pkg.adb new file mode 100644 index 000000000..5582cd2cd --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + -------------- + -- In_Range -- + -------------- + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean is + begin + return Value >= Bounds.Low_Bound and then Value <= Bounds.High_Bound; + end In_Range; + +end Pkg; diff --git a/testsuite/tests/instr-cov/216-no-elab-all/pkg.ads b/testsuite/tests/instr-cov/216-no-elab-all/pkg.ads new file mode 100644 index 000000000..30ec69f17 --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/pkg.ads @@ -0,0 +1,11 @@ +package Pkg is + + pragma No_Elaboration_Code_All; + + type Int_Range is record + Low_Bound, High_Bound : Integer; + end record; + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/216-no-elab-all/test.py b/testsuite/tests/instr-cov/216-no-elab-all/test.py new file mode 100644 index 000000000..1154302db --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/test.py @@ -0,0 +1,34 @@ +""" +Check that units with the No_Elaboration_Code_All pragma still compile after +instrumentation. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": { + "+": {5}, + "!": {7, 9}, + "-": {8, 10}, + }, + "pkg.adb.xcov": {"!": {9}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_object_path b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_object_path new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path new file mode 100644 index 000000000..430b67d00 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path @@ -0,0 +1,2 @@ +gnat +gnarl diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/adainclude/empty-dir.txt b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/adainclude/empty-dir.txt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb new file mode 100644 index 000000000..fd8b1ce92 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb @@ -0,0 +1,20 @@ +package body System.Task_Primitives.Operations is + + package Specific is + procedure Dummy; + end Specific; + + package body Specific is separate; + + ----------- + -- Dummy -- + ----------- + + procedure Dummy is + begin + Specific.Dummy; + end Dummy; + + function Register_Foreign_Thread return Integer is separate; + +end System.Task_Primitives.Operations; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads new file mode 100644 index 000000000..0dcbf8ace --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads @@ -0,0 +1,5 @@ +package System.Task_Primitives.Operations is + pragma Preelaborate; + procedure Dummy; + function Register_Foreign_Thread return Integer; +end System.Task_Primitives.Operations; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads new file mode 100644 index 000000000..dadd20078 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads @@ -0,0 +1,3 @@ +package System.Task_Primitives is + pragma Preelaborate; +end System.Task_Primitives; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb new file mode 100644 index 000000000..3e4a9163d --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb @@ -0,0 +1,13 @@ +separate (System.Task_Primitives.Operations) +package body Specific is + + ----------- + -- Dummy -- + ----------- + + procedure Dummy is + begin + null; + end Dummy; + +end Specific; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb new file mode 100644 index 000000000..d3d8053a4 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb @@ -0,0 +1,5 @@ +separate (System.Task_Primitives.Operations) +function Register_Foreign_Thread return Integer is +begin + return 0; +end Register_Foreign_Thread; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads new file mode 100644 index 000000000..fed04e343 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads @@ -0,0 +1,4 @@ +package Ada is + pragma No_Elaboration_Code_All; + pragma Pure; +end Ada; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads new file mode 100644 index 000000000..1a286ad12 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads @@ -0,0 +1,114 @@ +package System is + pragma Pure; + pragma No_Elaboration_Code_All; + + subtype Name is String; + System_Name : constant Name := "foo"; + + -- System-Dependent Named Numbers + + Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); + Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; + + Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; + Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; + + Max_Base_Digits : constant := Long_Long_Float'Digits; + Max_Digits : constant := Long_Long_Float'Digits; + + Max_Mantissa : constant := Standard'Max_Integer_Size - 1; + Fine_Delta : constant := 2.0 ** (-Max_Mantissa); + + Tick : constant := 0.000_001; + + -- Storage-related Declarations + + type Address is private; + pragma Preelaborable_Initialization (Address); + Null_Address : constant Address; + + Storage_Unit : constant := 8; + Word_Size : constant := Standard'Word_Size; + Memory_Size : constant := 2 ** Word_Size; + + -- Address comparison + + function "<" (Left, Right : Address) return Boolean; + function "<=" (Left, Right : Address) return Boolean; + function ">" (Left, Right : Address) return Boolean; + function ">=" (Left, Right : Address) return Boolean; + function "=" (Left, Right : Address) return Boolean; + + pragma Import (Intrinsic, "<"); + pragma Import (Intrinsic, "<="); + pragma Import (Intrinsic, ">"); + pragma Import (Intrinsic, ">="); + pragma Import (Intrinsic, "="); + + -- Other System-Dependent Declarations + + type Bit_Order is (High_Order_First, Low_Order_First); + Default_Bit_Order : constant Bit_Order := + Bit_Order'Val (Standard'Default_Bit_Order); + pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning + + -- Priority-related Declarations (RM D.1) + + -- If the scheduling policy is SCHED_FIFO or SCHED_RR the runtime makes use + -- of the entire range provided by the system. + -- + -- If the scheduling policy is SCHED_OTHER the only valid system priority + -- is 1 and other values are simply ignored. + + Max_Priority : constant Positive := 62; + Max_Interrupt_Priority : constant Positive := 63; + + subtype Any_Priority is Integer range 1 .. 63; + subtype Priority is Any_Priority range 1 .. 62; + subtype Interrupt_Priority is Any_Priority range 63 .. 63; + + Default_Priority : constant Priority := 10; + +private + + type Address is mod Memory_Size; + for Address'Size use Standard'Address_Size; + + Null_Address : constant Address := 0; + + -------------------------------------- + -- System Implementation Parameters -- + -------------------------------------- + + -- These parameters provide information about the target that is used + -- by the compiler. They are in the private part of System, where they + -- can be accessed using the special circuitry in the Targparm unit + -- whose source should be consulted for more detailed descriptions + -- of the individual switch values. + + Backend_Divide_Checks : constant Boolean := False; + Backend_Overflow_Checks : constant Boolean := True; + Command_Line_Args : constant Boolean := True; + Configurable_Run_Time : constant Boolean := True; + Denorm : constant Boolean := True; + Duration_32_Bits : constant Boolean := False; + Exit_Status_Supported : constant Boolean := True; + Machine_Overflows : constant Boolean := False; + Machine_Rounds : constant Boolean := True; + Preallocated_Stacks : constant Boolean := False; + Signed_Zeros : constant Boolean := True; + Stack_Check_Default : constant Boolean := False; + Stack_Check_Probes : constant Boolean := True; + Stack_Check_Limits : constant Boolean := False; + Support_Aggregates : constant Boolean := True; + Support_Atomic_Primitives : constant Boolean := True; + Support_Composite_Assign : constant Boolean := True; + Support_Composite_Compare : constant Boolean := True; + Support_Long_Shifts : constant Boolean := True; + Always_Compatible_Rep : constant Boolean := True; + Suppress_Standard_Library : constant Boolean := True; + Use_Ada_Main_Program_Name : constant Boolean := False; + Frontend_Exceptions : constant Boolean := False; + ZCX_By_Default : constant Boolean := True; + +end System; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr new file mode 100644 index 000000000..d4f96c0df --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr @@ -0,0 +1,15 @@ +with "runtime_build.gpr"; + +project Ravenscar_Build is + + for Runtime ("Ada") use Runtime_Build'Runtime ("Ada"); + + for Library_Auto_Init use "False"; + for Library_Name use "gnarl"; + for Library_Dir use "adalib"; + for Object_Dir use "obj"; + for Source_Dirs use ("gnarl"); + + package Compiler renames Runtime_Build.Compiler; + +end Ravenscar_Build; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr new file mode 100644 index 000000000..84e4c4333 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr @@ -0,0 +1,19 @@ +project Runtime_Build is + + for Runtime ("Ada") use Project'Project_Dir; + + for Library_Auto_Init use "False"; + for Library_Name use "gnat"; + for Library_Dir use "adalib"; + for Object_Dir use "obj"; + for Source_Dirs use ("gnat"); + + package Compiler is + for Default_Switches ("Ada") use ("-gnatg"); + end Compiler; + + package Naming is + for Spec_Suffix ("Asm_CPP") use ".inc"; + end Naming; + +end Runtime_Build; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/test.py b/testsuite/tests/instr-cov/217-runtime-subunit/test.py new file mode 100644 index 000000000..f444f8d30 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/test.py @@ -0,0 +1,36 @@ +""" +Check that the instrumentation of the s-tpopsp.adb and s-tporft.adb sources in +the Ada runtime completes (it used to crash). +""" + +import os.path + +from e3.fs import sync_tree + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Create a copy of the runtime to avoid polluting the test directory +sync_tree("../runtime", "runtime") + +runtime_prj = os.path.abspath("runtime/ravenscar_build.gpr") +runtime_dir = os.path.dirname(runtime_prj) + +xcov_instrument( + gprsw=GPRswitches(root_project=runtime_prj), + covlevel="stmt+mcdc", + auto_config_args=False, + auto_target_args=False, + extra_args=["--target", thistest.env.target.triplet, "--RTS", runtime_dir], + # For practical purposes, this test instruments a fake runtime. Since this + # runtime is incomplete, it is not possible to build the coverage runtime + # for it: we cannot run "gnatcov setup" and thus we expect a warning about + # the runtime mismatch. + tolerate_messages="Current runtime is", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb b/testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb new file mode 100644 index 000000000..1a0fbd373 --- /dev/null +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Process; +end Main; diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb b/testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb new file mode 100644 index 000000000..b8a6ee05e --- /dev/null +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + ------------- + -- Process -- + ------------- + + procedure Process is + begin + null; + end Process; + +end Pkg; diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py new file mode 100644 index 000000000..d3848f51a --- /dev/null +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py @@ -0,0 +1,59 @@ +""" +Check that "gnatcov instrument" does not crash when instrumenting an invalid +project setup that lacks the package spec corresponding to a package body. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +filename = "instrument.txt" +p = xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + out=filename, + register_failure=False, +) + +thistest.fail_if(p.status != 0, "'gnatcov instrument' unexpectedly succeeded") + +# There are two warnings that we consider mandatory. Beyound that, we tolerate +# other warnings only (to keep this test robust, we do not want to track the +# exact list of warnings, that may vary as gnatcov evolves). +expected_warnings = { + "warning: While instrumenting main.adb...", + "warning: Cannot find required source file: pkg.ads", +} +actual_warnings = set() +others = [] +for line in lines_of(filename): + if ( + line.startswith("warning: ") + or line.startswith("*** warning:") + or line.startswith( + "*** main.adb:5:4: low_warning: Could not determine if stmt is" + " ghost" + ) + ): + actual_warnings.add(line) + else: + others.append(line) + +missing_warnings = expected_warnings - actual_warnings +thistest.fail_if( + missing_warnings, + 'expected "gnatcov instrument" warnings are missing:\n' + + "\n".join(sorted(missing_warnings)), +) + +thistest.fail_if_not_equal( + '"gnatcov instrument" has non-warnings in its output', + "", + "\n".join(others), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/main.adb b/testsuite/tests/instr-cov/219-non-instr-propagation/main.adb new file mode 100644 index 000000000..15f32db9c --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/main.adb @@ -0,0 +1,16 @@ +with Pkg_1; +with Pkg_2; + +procedure Main is + T1 : Pkg_1.PT; + T2 : Pkg_2.PT; +begin + T1.Say_Hello; + T1.Set_Cond (False); + T1.Set_Cond (True); + T1.Wait_Cond; + + T2.Set_Cond (False); + T2.Set_Cond (True); + T2.Wait_Cond; +end Main; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb new file mode 100644 index 000000000..d8d8f040d --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb @@ -0,0 +1,33 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_1 is + protected body PT is + + procedure Say_Hello is + begin + Put_Line ("Hello"); -- SCO 3 (stmt) + end Say_Hello; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond when Cond is -- SCO 4+5 (decision+condition) + begin + Put_Line ("OK"); -- SCO 6 (stmt) + end Wait_Cond; + + -------------- + -- Set_Cond -- + -------------- + + procedure Set_Cond (Value : Boolean) is + begin + if Value then -- SCO 7-8+9 (stmt+decision+condition) + Put_Line ("OK"); -- SCO 10 (stmt) + end if; + Cond := True; -- SCO 11 (stmt) + end Set_Cond; + + end PT; +end Pkg_1; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads new file mode 100644 index 000000000..1f12e2f18 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads @@ -0,0 +1,11 @@ +pragma Restrictions (Simple_Barriers); + +package Pkg_1 is + protected type PT is -- SCO 1 (stmt) + procedure Say_Hello; + entry Wait_Cond; + procedure Set_Cond (Value : Boolean); + private + Cond : Boolean := False; -- SCO 2 (stmt) + end PT; +end Pkg_1; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb new file mode 100644 index 000000000..737d715a7 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb @@ -0,0 +1,28 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_2 is + protected body PT is + + -------------- + -- Set_Cond -- + -------------- + + procedure Set_Cond (Value : Boolean) is + begin + if Value then -- SCO 3+4+5 (stmt+decision+condition) + Put_Line ("OK"); -- SCO 6 (stmt) + end if; + Cond := True; -- SCO 7 (stmt) + end Set_Cond; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond when Cond is -- SCO 8+9 (decision+condition) + begin + Put_Line ("OK"); -- SCO 10 (stmt) + end Wait_Cond; + + end PT; +end Pkg_2; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads new file mode 100644 index 000000000..44e14452f --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads @@ -0,0 +1,10 @@ +pragma Restrictions (Simple_Barriers); + +package Pkg_2 is + protected type PT is -- SCO 1 (stmt) + procedure Set_Cond (Value : Boolean); + entry Wait_Cond; + private + Cond : Boolean := False; -- SCO 2 (stmt) + end PT; +end Pkg_2; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/test.opt b/testsuite/tests/instr-cov/219-non-instr-propagation/test.opt new file mode 100644 index 000000000..6518f1a79 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/test.opt @@ -0,0 +1,4 @@ +-- This testcase relies on protected bodies, which are not available with +-- light or embedded runtimes. +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/test.py b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py new file mode 100644 index 000000000..e705c6f81 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py @@ -0,0 +1,42 @@ +""" +Check that the "non-instrumented SCO" state does not propagate from one +instrumented unit to the other (this is a regression testcase). + +The sources are carefully arranged so that we have two units (Pkg_1 and Pkg_2) +that yield equivalent sequences of SCOs (stmt, stmt, decision, condition, stmt, +... see the comments in the Ada sources). In Pkg_1, one decision is not +instrumented (because of the entry body guard limitation under the +Simple_Barriers restriction) while the corresponding one in Pkg_2 is +instrumented, and conversely, so that we check the absence of propagation +whether Pkg_1 is instrumented before Pkg_2 or the opposite. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]), + units=["pkg_1", "pkg_2"], + ), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "pkg_1.adb.xcov": {"+": {8, 17, 26, 27, 29}, "?": {15}}, + "pkg_1.ads.xcov": {}, + "pkg_2.adb.xcov": {"+": {12, 13, 15, 24}, "?": {22}}, + "pkg_2.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb new file mode 100644 index 000000000..12aa258d3 --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Mylib is + + --------------- + -- Say_Hello -- + --------------- + + procedure Say_Hello is + begin + Put_Line ("Hello world!"); + end Say_Hello; + +end Mylib; diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads new file mode 100644 index 000000000..008ed737d --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + procedure Say_Hello; +end Mylib; diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb b/testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb new file mode 100644 index 000000000..4b41908b1 --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb @@ -0,0 +1,6 @@ +with Mylib; + +procedure Main is +begin + Mylib.Say_Hello; +end Main; diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/test.opt b/testsuite/tests/instr-cov/221-stale-external-instr/test.opt new file mode 100644 index 000000000..08d567967 --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Checks an instrumentation-specific warning diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/test.py b/testsuite/tests/instr-cov/221-stale-external-instr/test.py new file mode 100644 index 000000000..ec1d0458f --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/test.py @@ -0,0 +1,90 @@ +""" +Check that "gnatcov instrument" warns about instrumented sources found in +externally built projects that are not of interest. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor + + +tmp = Wdir("tmp_") + +# Create the "lib" project, that is externally built by default, and a project +# "p" that depends on "lib". +lib = gprfor( + prjid="lib", + srcdirs=["../src-lib"], + objdir="obj-lib", + mains=[], + extra=""" + type Boolean is ("False", "True"); + Ext_Built : Boolean := external ("LIB_EXT_BUILT", "True"); + for Externally_Built use Ext_Built; + """, +) +p = gprfor( + prjid="p", + deps=["lib"], + srcdirs=["../src-p"], + objdir="obj-p", + mains=["main.adb"], +) + +# Instrument and build the "lib" project +thistest.log("== Instrument Lib ==") +xcov_instrument( + gprsw=GPRswitches(root_project=lib), + covlevel="stmt", + gpr_obj_dir="obj-lib", + extra_args=["-XLIB_EXT_BUILT=False"], + out="instr-lib.txt", +) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + "", + contents_of("instr-lib.txt"), +) +gprbuild(lib, gargs=["-XLIB_EXT_BUILT=False"], out="gprbuild-lib.txt") + +# Instrument the "p" project. We expect gnatcov to notice and warn that there +# are instrumented sources in "lib" even though it is not a project of +# interest. +thistest.log("== Instrument P ==") +xcov_instrument( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + gpr_obj_dir="obj-p", + out="instr-p.txt", + tolerate_messages=".", +) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + 'warning: Project "lib" is externally built and does not contain units of' + " interest, however it contains instrumented sources", + contents_of("instr-p.txt").strip(), +) + +# Sanity check that the warning is useful: +# +# Instrumentation of main.adb considered that sources from "lib.gpr" were not +# of interest, so auto-dumping code does not reference coverage buffer units +# for "lib.gpr". As a result, these coverage buffers are not included in the +# build closure. +# +# However, sources for "lib.gpr" were instrumented and thus try to use coverage +# buffers, so we expect a link failure here. +thistest.log("== Build P ==") +gprbuild_desc = gprbuild(p, out="gprbuild-p.txt", register_failure=False) +thistest.fail_if( + gprbuild_desc.status == 0, + "build of P was expected to fail", +) +thistest.fail_if( + "undefined reference to" not in contents_of("gprbuild-p.txt"), + "Expected link error message not found in gprbuild-p.txt", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb b/testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb new file mode 100644 index 000000000..5b668492e --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb @@ -0,0 +1,34 @@ +procedure Test_Main +is + A, B : Boolean := True; + + procedure Foo (B: Boolean) is null; -- # cov_on + + procedure Uncovered; + + procedure Uncovered is + begin + pragma Annotate (Xcov, Cov_Off); -- # cov_off + Foo (A and then B); -- # cov_off + pragma Annotate (Xcov, Cov_On); -- # cov_off + end Uncovered; + +begin + pragma Annotate (Xcov, Cov_Off); -- # cov_off + Foo (A and then B); -- # cov_off + pragma Annotate (Xcov, Cov_On); -- # cov_off + + -- Check with a justification message + + pragma Annotate (Xcov, Cov_Off, "coverage is disabled"); -- # cov_off + Foo (A and then B); -- # cov_off + pragma Annotate (Xcov, Cov_On); -- # cov_off + + Foo (A and then B); -- # partial_cov_on +end Test_Main; + +--# test_main.adb +-- +-- /cov_off/ lD ## 0 +-- /cov_on/ l+ ## 0 +-- /partial_cov_on/ l! ## eF- diff --git a/testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt new file mode 100644 index 000000000..374349458 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD GNAT 5.04a1 rejects unrecognized annotation pragmas diff --git a/testsuite/tests/instr-cov/223-selective-instr/Ada/test.py b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.py new file mode 100644 index 000000000..a041d027f --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.py @@ -0,0 +1,16 @@ +""" +Check gnatcov support for selective instrumentation for Ada. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* No justification given for disabled coverage region" + ), +).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt b/testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt new file mode 100644 index 000000000..b78b04823 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt @@ -0,0 +1,12 @@ +drivers=. + +--# pkg.h +-- /cov-off-a/ lD ## dB +-- /cov-off-b/ lD ## dB +-- /cov-on/ l- ## s- +-- +--# test_a.c +-- /covered/ l+ ## 0 +-- +--# test_b.c +-- /covered/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h b/testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h new file mode 100644 index 000000000..4ae5d7891 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h @@ -0,0 +1,17 @@ +int +foo (int a, int b) +{ +#ifdef A + /* GNATCOV_COV_OFF */ // # cov-off-a + int c = a && b; // # cov-off-a + /* GNATCOV_COV_ON */ // # cov-off-a +#endif + +#ifdef B + /* GNATCOV_COV_OFF */ // # cov-off-b + int d = a && b; // # cov-off-b + /* GNATCOV_COV_ON */ // # cov-off-b +#endif + + return 0; // # cov-on +} diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c new file mode 100644 index 000000000..667f196fe --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c @@ -0,0 +1,18 @@ +#define A + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-a/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_a.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c new file mode 100644 index 000000000..d81a99966 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c @@ -0,0 +1,18 @@ +#define B 1 + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-b/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_b.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/test.py b/testsuite/tests/instr-cov/223-selective-instr/C/test.py new file mode 100644 index 000000000..fbc1d1794 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/test.py @@ -0,0 +1,23 @@ +""" +Check gnatcov support for selective instrumentation for C when a file has +various preprocessing configuration resulting in varying preprocessed versions, +and the user has disabled coverage for every code region differing across +preprocessing invocations. + +Note that in this case, the user must use checkpoint consolidation, as there +can only exists one version of the SIDs at a time. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +thistest.options.consolidate = "checkpoints" +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* No justification given for disabled coverage region" + ), +).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/223-selective-instr/extra.opt b/testsuite/tests/instr-cov/223-selective-instr/extra.opt new file mode 100644 index 000000000..ea8a3c8ac --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific feature diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c new file mode 100644 index 000000000..bcba1958e --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c @@ -0,0 +1,15 @@ +int +foo () +{ +#ifdef A + /* GNATCOV_COV_OFF */ + return 0; +/* GNATCOV_COV_ON */ +#endif +#ifdef B + /* GNATCOV_COV_OFF */ + return 1; +/* GNATCOV_COV_ON */ +#endif + return 2; +} diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c new file mode 100644 index 000000000..14eebbdb7 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c @@ -0,0 +1,8 @@ +#include "pkg.h" + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py new file mode 100644 index 000000000..53e115dcc --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py @@ -0,0 +1,83 @@ +""" +Check that gnatcov correctly detects annotation inconsistencies, e.g. when the +user tries to produce a report from a source trace resulting from the +instrumentation of a program with annotations that are not the same as the +current source instrumentation data. +""" + +import os +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +Wdir("tmp_") + +# Generate the root project +root_project = gprfor(srcdirs=[os.path.join("..")], mains=["test.c"]) +gprsw = GPRswitches(root_project) + +# Configure the build with -DA which results in the inclusion of an annotated +# region at pkg.c from line 3 to line 6. +tmp_a = Wdir("a") +trace_a = os.path.abspath( + build_and_run( + gprsw=gprsw, + covlevel="stmt", + mains=["test"], + extra_instr_args=["--c-opts=-DA"], + gpr_exe_dir="..", + extra_coverage_args=[], + trace_mode="src", + )[-1] +) +tmp_a.to_homedir() + +# Configure the build with -DB which results in the inclusion of an annotated +# region at pkg.c from line 8 to line 11, thus differing from the above. +tmp_b = Wdir("b") +trace_b = os.path.abspath( + build_and_run( + gprsw=gprsw, + covlevel="stmt", + mains=["test"], + extra_instr_args=["--c-opts=-DB"], + trace_mode="src", + gpr_exe_dir="..", + extra_coverage_args=[], + )[-1] +) +tmp_b.to_homedir() + +# Now, try to generate a coverage report from both traces +os.mkdir("xcov") +xcov( + ["coverage"] + + gprsw.cov_switches + + ["-axcov", "--output-dir=xcov", "--level=stmt", trace_a, trace_b], + tolerate_messages="traces for .* are inconsistent", + out="cov.out", +) + +# Check that gnatcov warns about inconsistency between a.srctrace and the +# source instrumentation data. +thistest.fail_if_no_match( + "'gnatcov coverage' output", + r"warning: traces for .* are inconsistent with the corresponding Source" + " Instrumentation Data", + contents_of("cov.out"), +) + +# Check that the coverage report is as expected (e.g. a.srctrace is skipped). +check_xcov_reports( + "xcov", + { + "test.c.xcov": {"+": {6, 7}}, + "pkg.c.xcov": {"D": {10, 11, 12}, "-": {14}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/225-expr-func-access/main.adb b/testsuite/tests/instr-cov/225-expr-func-access/main.adb new file mode 100644 index 000000000..85c766fbc --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/main.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main is +begin + Get_Ref (True).all := 1; + Get_Ref (False).all := 2; + + Get_Unc_Ref (True).all := @ + 10; + Get_Unc_Ref (False).all := @ + 20; + + Get_Unr_Ref (True).all := @ + 100; + Get_Unr_Ref (False).all := @ + 200; + + Put_Line (A'Image); + Put_Line (B'Image); +end Main; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/pkg.adb b/testsuite/tests/instr-cov/225-expr-func-access/pkg.adb new file mode 100644 index 000000000..49c8f5d94 --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/pkg.adb @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package body Pkg is + + function Get_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Access else B'Access); + + function Get_Unc_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Unchecked_Access else B'Unchecked_Access); + + function Get_Unr_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Unrestricted_Access else B'Unrestricted_Access); + +end Pkg; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/pkg.ads b/testsuite/tests/instr-cov/225-expr-func-access/pkg.ads new file mode 100644 index 000000000..75afac653 --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/pkg.ads @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package Pkg is + + type Integer_Access is access all Integer; + + A : aliased Integer; + B : aliased Integer; + + function Get_Ref (Is_A : Boolean) return Integer_Access; + function Get_Unc_Ref (Is_A : Boolean) return Integer_Access; + function Get_Unr_Ref (Is_A : Boolean) return Integer_Access; + +end Pkg; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.opt b/testsuite/tests/instr-cov/225-expr-func-access/test.opt new file mode 100644 index 000000000..59ae493a2 --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2022, unavailable in 5.04a1 +7.1.2 DEAD Requires Ada 2022, unavailable in 7.1.2 diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.py b/testsuite/tests/instr-cov/225-expr-func-access/test.py new file mode 100644 index 000000000..6ef776dba --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.py @@ -0,0 +1,32 @@ +""" +Check that, in Ada 2022 mode, expression functions that contain +'(Unrestricted_|Unchecked_)Access attribute references are correctly +instrumented. We used to introduce declare expressions in this case, which is +illegal. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {9, 10, 12, 13, 15, 16}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {6, 9, 12}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb new file mode 100644 index 000000000..f2245cc49 --- /dev/null +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + T : Pkg.Test_Type; +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads new file mode 100644 index 000000000..25e847115 --- /dev/null +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + type Test_Type; + type Test_Type_Ptr is access all Test_Type; + type Test_Type is record + Test_Var : Boolean; + end record; +end Pkg; diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py new file mode 100644 index 000000000..787fa11b9 --- /dev/null +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py @@ -0,0 +1,29 @@ +""" +Check that "gnatcov instrument" does not crash when instrumenting an incomplete +type declaration for ATC(C). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+atc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb new file mode 100644 index 000000000..58cffe8aa --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb @@ -0,0 +1,11 @@ +separate (Lib) +function Add (Left, Right : Positive) return Positive is + Result : Positive := Left; + Remainder : Natural := Right; +begin + while Remainder /= 0 loop + Result := Result + 1; + Remainder := Remainder - 1; + end loop; + return Result; +end Add; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb new file mode 100644 index 000000000..64d996f58 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb @@ -0,0 +1,11 @@ +separate (Lib) +function Exp (Left, Right : Positive) return Positive is +begin + if Right = 1 then + return Left; + elsif Right mod 2 = 0 then + return Exp (Mult (Left, Left), Right / 2); + else + return Mult (Left, Exp (Mult (Left, Left), Right / 2)); + end if; +end Exp; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb new file mode 100644 index 000000000..817632681 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb @@ -0,0 +1,11 @@ +separate (Lib) +function Mult (Left, Right : Positive) return Positive is +begin + if Right = 1 then + return Left; + elsif Right mod 2 = 0 then + return 2 * Mult (Left, Right / 2); + else + return Add (2 * Mult (Left, Right / 2), Left); + end if; +end Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb new file mode 100644 index 000000000..77acdf24f --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb @@ -0,0 +1,5 @@ +package body Lib is + function Add (Left, Right : Positive) return Positive is separate; + function Mult (Left, Right : Positive) return Positive is separate; + function Exp (Left, Right : Positive) return Positive is separate; +end Lib; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads new file mode 100644 index 000000000..52ef162c8 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads @@ -0,0 +1,5 @@ +package Lib is + function Add (Left, Right : Positive) return Positive; + function Mult (Left, Right : Positive) return Positive; + function Exp (Left, Right : Positive) return Positive; +end Lib; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr b/testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr new file mode 100644 index 000000000..79c80bcb8 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr @@ -0,0 +1,4 @@ +project Lib is + for Source_Dirs use ("../src/lib-src"); + for Object_Dir use "obj/lib"; +end Lib; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb new file mode 100644 index 000000000..730920dce --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb @@ -0,0 +1,18 @@ +separate (Lib) +function Add (Left, Right : Positive) return Positive is +begin + case Left is + when 1 => + case Right is + when 1 => + return 2; + when others => + null; + end case; + when others => + null; + end case; + + raise Program_Error; + return 1; +end Add; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb new file mode 100644 index 000000000..1bbbe3fd4 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb @@ -0,0 +1,18 @@ +separate (Lib) +function Mult (Left, Right : Positive) return Positive is +begin + case Left is + when 1 => + case Right is + when 1 => + return 1; + when others => + null; + end case; + when others => + null; + end case; + + raise Program_Error; + return 1; +end Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr new file mode 100644 index 000000000..d74326e62 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr @@ -0,0 +1,9 @@ +project Test_Exp extends "lib" is + for Source_Dirs use + ("../src/stub_add", + "../src/stub_mult", + "../src/test_exp"); + for Object_Dir use "obj/test_exp"; + for Exec_Dir use "bin"; + for Main use ("test_exp.adb"); +end Test_Exp; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb new file mode 100644 index 000000000..3698bbd00 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb @@ -0,0 +1,8 @@ +with Lib; + +procedure Test_Exp is +begin + if Lib.Exp (1, 1) /= 1 then + raise Program_Error; + end if; +end Test_Exp; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr new file mode 100644 index 000000000..3167f27fd --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr @@ -0,0 +1,8 @@ +project Test_Mult extends "lib" is + for Source_Dirs use + ("../src/stub_add", + "../src/test_mult"); + for Object_Dir use "obj/test_mult"; + for Exec_Dir use "bin"; + for Main use ("test_mult.adb"); +end Test_Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb new file mode 100644 index 000000000..e11a2b242 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb @@ -0,0 +1,8 @@ +with Lib; + +procedure Test_Mult is +begin + if Lib.Mult (1, 1) /= 1 then + raise Program_Error; + end if; +end Test_Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/test.opt b/testsuite/tests/instr-cov/227-subunit-stub/test.opt new file mode 100644 index 000000000..2d1c5e0d5 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL eng/das/cov/gnatcoverage#227: never worked with bin-traces diff --git a/testsuite/tests/instr-cov/227-subunit-stub/test.py b/testsuite/tests/instr-cov/227-subunit-stub/test.py new file mode 100644 index 000000000..36eccdf2b --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/test.py @@ -0,0 +1,120 @@ +""" +Check that computing coverage on an Ada codebase that contains subunits works +correctly when the subunits are stubbed in tests. +""" + +import dataclasses +import os.path +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, xcov + + +# Note: to avoid "same base name for files" warnings, create local copies of +# project files, but not of sources themselves: project files reference the +# original source directories. + + +@dataclasses.dataclass +class Test: + name: str + """ + Name of this test. + + This is both the name of the project file and the main (executable). + """ + + stubbed_files: list[str] + """ + List of source files from the "lib" project that are stubbed for this + testcase. + """ + + +# Produce one source trace for each testcase. Each testcase use a specific set +# of stubs: exclude them from instrumentation to avoid consolidation warnings +# later on. +cov_argv = [] +all_traces = [] +for test in [ + Test("test_mult", ["lib-add.adb"]), + Test("test_exp", ["lib-add.adb", "lib-mult.adb"]), +]: + thistest.log(f"== {test.name} ==") + tmp = Wdir(f"tmp_{test.name}") + cp("../src/*.gpr", ".") + + cov_argv = build_and_run( + gprsw=GPRswitches(root_project=os.path.abspath(f"{test.name}.gpr")), + covlevel="stmt+decision", + mains=[test.name], + gpr_obj_dir=f"obj/{test.name}", + gpr_exe_dir="bin", + extra_instr_args=[ + f"--ignore-source-files={f}" for f in test.stubbed_files + ], + extra_coverage_args=[], + ) + all_traces.append(os.path.abspath(cov_argv.pop())) + + tmp.to_homedir() + + +# Instrument/compile the "vanilla" (stub-free) library to get the "reference" +# set of SCOs. +thistest.log("== cons ==") +tmp = Wdir("tmp_cons") +cp("../src/*.gpr", ".") +lib_gpr = os.path.abspath("lib.gpr") +mkdir("obj/lib") + +if thistest.options.trace_mode == "src": + xcov_instrument( + gprsw=GPRswitches(root_project=lib_gpr), + covlevel="stmt+decision", + out="instrument.log", + ) + thistest.fail_if_not_equal( + '[consolidation] "gnatcov instrument" output', + "", + contents_of("instrument.log"), + ) +else: + gprbuild(lib_gpr) + +# Produce a coverage report using test traces and these SCOs +mkdir("xcov") +xcov( + [ + "coverage", + "-P", + lib_gpr, + "--level=stmt+decision", + "--annotate=xcov", + "--output-dir=xcov", + *all_traces, + ], + out="coverage.log", +) +thistest.fail_if_not_equal( + '[consolidation] "gnatcov coverage" output', + "", + contents_of("coverage.log"), +) +check_xcov_reports( + "xcov", + { + "lib.ads.xcov": {}, + "lib.adb.xcov": {}, + "lib-add.adb.xcov": {"-": {3, 4, 6, 7, 8, 10}}, + "lib-mult.adb.xcov": {"+": {5}, "!": {4}, "-": {6, 7, 9}}, + "lib-exp.adb.xcov": {"+": {5}, "!": {4}, "-": {6, 7, 9}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb new file mode 100644 index 000000000..43c92f5b1 --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb @@ -0,0 +1,13 @@ +procedure Main_1 +is + T : Boolean := True; +begin + pragma Annotate (Xcov, Exempt_On); + if not T then + null; + end if; + pragma Annotate (Xcov, Exempt_Off, "Superfluous argument"); + pragma Annotate (Xcov, AAA, "Unrecognized annotation"); + pragma Annotate (Xcov); + pragma Annotate (Test); -- No warning from gnatcov +end Main_1; diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb new file mode 100644 index 000000000..f5c651e09 --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb @@ -0,0 +1,7 @@ +procedure Main_2 is +begin + pragma Annotate (1); + pragma Annotate (Xcov, 1); + pragma Annotate (Xcov, Exempt_On, "Valid" & " argument"); + pragma Annotate (Xcov, Exempt_On, 16#DEAD_BEEF#); +end Main_2; diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt new file mode 100644 index 000000000..e32df191c --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires feature support lacking in 5.04a1 diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py new file mode 100644 index 000000000..76c732ada --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py @@ -0,0 +1,60 @@ +""" +Check that any deviation from the expected annotation pragmas is reported to +the user as a warning. Also check that a warning is emitted if an unrecognized +Xcov annotation was found, or if an argument of the wrong type is given. +""" + +from SCOV.minicheck import build_run_and_coverage, xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +# Check gnatcov's behaviour upon encountering annotation pragmas with correctly +# typed arguments. + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="test", srcdirs=[".."], mains=["main_1.adb"], langs=["Ada"] + ) + ), + covlevel="stmt", + trace_mode="src", + mains=["main_1"], + extra_coverage_args=["--annotate=report"], + tolerate_instrument_messages=".", +) + +# Check that gnatcov does not raise an exception when finding incorrect +# annotation pragmas. In these cases, it is the compiler that is expected to +# raise an exception. + +xcov_instrument( + gprsw=GPRswitches( + gprfor( + prjid="test", srcdirs=[".."], mains=["main_2.adb"], langs=["Ada"] + ) + ), + covlevel="stmt", + tolerate_messages=".", +) + +thistest.fail_if_not_equal( + "gnatcov instrument output", + ( + "*** main_1.adb:5:5: warning: No justification given for exempted" + " region\n" + "*** main_1.adb:9:5: warning: At most 2 pragma arguments allowed\n" + "*** main_1.adb:10:5: warning: Invalid Xcov annotation kind: aaa\n" + "*** main_1.adb:11:5: warning: Xcov annotation kind missing\n" + "*** main_2.adb:4:5: warning: Invalid Xcov annotation kind\n" + "*** main_2.adb:6:5: warning: Invalid justification argument:" + " static string expression expected\n" + ), + contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/main.adb b/testsuite/tests/instr-cov/239-qnx-bin-file/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt new file mode 100644 index 000000000..1dedc665b --- /dev/null +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt @@ -0,0 +1,6 @@ +-- The very purpose of this test is to check the correct support of +-- gnatcov_rts' full profile on embedded runtimes: the only currently known +-- configuration where this makes sense is the light-tasking runtime for a QNX +-- target. +src-traces,qnx,RTS_LIGHT_TASKING +ALL DEAD diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/test.py b/testsuite/tests/instr-cov/239-qnx-bin-file/test.py new file mode 100644 index 000000000..2468ed702 --- /dev/null +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/test.py @@ -0,0 +1,44 @@ +""" +Check that the "full" profile for GNATcov_RTS works correctly on QNX. +""" + +import os.path + +from e3.fs import mkdir + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +# Build and install our special gnatcov_rts build +install_dir = os.path.abspath("install") +mkdir(install_dir) +xcov( + ["setup", "--rts-profile=full", "--prefix", install_dir, "-q"], + out="setup.txt", +) +thistest.fail_if_not_equal( + "'gnatcov setup' output not empty", + "", + contents_of("setup.txt"), +) +gnatcov_rts_gpr = os.path.join(install_dir, "share", "gpr", "gnatcov_rts.gpr") + +# Compute code coverage for the test project, to make sure the runtime's +# implementation of the bin-file dump channel works as expected. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + dump_channel="bin-file", + runtime_project=gnatcov_rts_gpr, +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/main.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/main.adb new file mode 100644 index 000000000..8238f29ad --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; + +procedure Main is + use Pkg.Nested; +begin + Set (1); + if Get /= 1 then + Put_Line ("ERROR"); + Pkg.Proc; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb new file mode 100644 index 000000000..25a1f5097 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb @@ -0,0 +1,24 @@ +separate (Pkg) +package body Nested is + + Register : Integer := 0; + + --------- + -- Set -- + --------- + + procedure Set (Value : Integer) is + begin + Register := Value; + end Set; + + --------- + -- Get -- + --------- + + function Get return Integer is + begin + return Register; + end Get; + +end Nested; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb new file mode 100644 index 000000000..6e8e1aebc --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb @@ -0,0 +1,24 @@ +separate (Pkg.Proc) +package body Nested is + + Register : Integer := 0; + + --------- + -- Set -- + --------- + + procedure Set (Value : Integer) is + begin + Register := Value; + end Set; + + --------- + -- Get -- + --------- + + function Get return Integer is + begin + return Register; + end Get; + +end Nested; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb new file mode 100644 index 000000000..8611a17b9 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb @@ -0,0 +1,18 @@ +with Utils; use Utils; + +separate (Pkg) +procedure Proc is + + package Nested is + procedure Set (Value : Integer); + function Get return Integer; + end Nested; + + package body Nested is separate; + +begin + Nested.Set (1); + if Identity (Nested.Get) /= 1 then + raise Program_Error; + end if; +end Proc; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb new file mode 100644 index 000000000..f3b570944 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb @@ -0,0 +1,7 @@ +package body Pkg is + + package body Nested is separate; + + procedure Proc is separate; + +end Pkg; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads new file mode 100644 index 000000000..17230f9b7 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads @@ -0,0 +1,16 @@ +pragma Ada_2012; + +-- CONFIG_PRAGMA + +package Pkg is + + -- PRAGMA + + package Nested is + procedure Set (Value : Integer); + function Get return Integer; + end Nested; + + procedure Proc; + +end Pkg; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/test.py b/testsuite/tests/instr-cov/243-no-elab-subunit/test.py new file mode 100644 index 000000000..6139b84fb --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/test.py @@ -0,0 +1,82 @@ +""" +Check that the Ada instrumenter does not violate elaboration constraints in a +unit spec when instrumenting a subunit corresponding to that spec. +""" + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +pragma_pattern = "-- PRAGMA" +config_pragma_pattern = "-- CONFIG_PRAGMA" + +# Check that gnatcov procedures valid code for a subunit (pkg-nested.adb) when +# that subunit implements a library-level package body. Test both for an +# elaboration pragma and for the No_Elaboration_Code restriction since their +# handling involves different code paths in gnatcov. +# +# Check that we can still compute code coverage for the elaboration of +# declaration in a package body subunit when it is not library level +# (proc-nested.adb). This is possible only if gnatcov knows that this package +# is not library-level: it is possible to insert witness calls even if the unit +# has elaboration restrictions. +for name, pattern, pragma in [ + ( + "no_elab_code", + config_pragma_pattern, + "pragma Restrictions (No_Elaboration_Code);", + ), + ( + "preelab", + pragma_pattern, + "pragma Preelaborate;", + ), + ( + "no_elab_code_all", + pragma_pattern, + "pragma No_Elaboration_Code_All;", + ), +]: + thistest.log(f"== {name}: {pragma} ==") + tmp = Wdir(f"tmp_{name}") + + # Instantiate the project sources in the temporary directory + for ext in ["adb", "ads"]: + cp(f"../*.{ext}", ".") + with open("pkg.ads", "w") as f: + f.write(contents_of("../pkg.ads").replace(pattern, pragma)) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + ) + + expected = { + "main.adb.xcov": {"+": {7, 8}, "-": {9, 10}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {}, + "pkg-nested.adb.xcov": {"+": {12, 21}}, + "pkg-proc.adb.xcov": {"-": {14, 15, 16}}, + "pkg-proc-nested.adb.xcov": {"-": {4, 12, 21}}, + "utils.ads.xcov": {}, + "utils.adb.xcov": {"-": {9}}, + } + # Deal with coverage report discrepancies between source and binary traces + if thistest.options.trace_mode == "bin": + expected.pop("pkg.adb.xcov") + if pattern == config_pragma_pattern: + expected.pop("pkg.ads.xcov") + check_xcov_reports("obj", expected, discard_empty=False) + + tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb new file mode 100644 index 000000000..bd521f374 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb @@ -0,0 +1,12 @@ +package body Utils is + + -------------- + -- Identity -- + -------------- + + function Identity (I : Integer) return Integer is + begin + return I; + end Identity; + +end Utils; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads new file mode 100644 index 000000000..20cc1241f --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads @@ -0,0 +1,10 @@ +package Utils is + + pragma No_Elaboration_Code_All; + pragma Preelaborate; + + function Identity (I : Integer) return Integer; + -- The only purpose of this function is to break the compiler's data flow + -- analysis so that high optimization levels cannot optimize code too much. + +end Utils; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb b/testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb new file mode 100644 index 000000000..5cfc5d418 --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb @@ -0,0 +1,7 @@ +with Mylib; + +procedure Main is +begin + Mylib.Say_Hello; + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb new file mode 100644 index 000000000..9be8d0432 --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Mylib is + + procedure Say_Hello is + begin + pragma Annotate (Xcov, Dump_Buffers); + Put_Line ("Hello, world!"); + end Say_Hello; + +end Mylib; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads new file mode 100644 index 000000000..008ed737d --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + procedure Say_Hello; +end Mylib; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt new file mode 100644 index 000000000..09e22da78 --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Pragma Annotate (Xcov) not supported +bin-traces DEAD Test is specific to instrumentation (manual dumps) diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py new file mode 100644 index 000000000..715e6cf2c --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py @@ -0,0 +1,67 @@ +""" +Check that gnatcov's instrumenter ignores manual dump annotations in externally +built projects even when --externally-built-projects is passed. +""" + +from e3.fs import find + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor + + +tmp = Wdir("tmp_") + +# Build uninstrumented "mylib.gpr" +mylib_gpr = gprfor( + prjid="mylib", + srcdirs="../mylib", + objdir="obj-mylib", + mains=[], + extra=""" + for Library_Name use "mylib"; + for Library_Dir use "lib-mylib"; + + type Boolean is ("False", "True"); + Ext_Built : Boolean := external ("EXT_BUILT", "True"); + for Externally_Built use Ext_Built; + + package Coverage is + for Units use (); + end Coverage; + """, +) +gprbuild(mylib_gpr, gargs=["-XEXT_BUILT=False"]) + +# Build and run "main.adb" from "main.gpr", which depends on "mylib.gpr". If +# manual dump expansion processed mylib's sources, we would get a warning +# saying that the instrumenter has found a manual dump in a subproject. +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + prjid="main", + mains=["main.adb"], + deps=[mylib_gpr], + srcdirs=["../main"], + ), + externally_built_projects=True, + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="main", + extra_coverage_args=["--annotate=xcov"], +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +# As a double check in addition to the warning detection mentionned above, make +# sure that no instrumented sources were created for mylib. +thistest.fail_if_not_equal( + "instrumented sources for mylib", + "", + "\n".join(sorted(find("obj-mylib", "*.ads") + find("obj-mylib", "*.adb"))), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/312-dump-reset/main.c b/testsuite/tests/instr-cov/312-dump-reset/main.c new file mode 100644 index 000000000..d0e13e11e --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/main.c @@ -0,0 +1,15 @@ +extern void stub_puts (const char *); + +int +main (void) +{ + stub_puts ("This should be covered in first dump"); + + /* GNATCOV_DUMP_BUFFERS */ + + /* GNATCOV_RESET_BUFFERS */ + + stub_puts ("This should be covered in second dump"); + + return 0; +} diff --git a/testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c b/testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c new file mode 100644 index 000000000..3c540e6f9 --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c @@ -0,0 +1,5 @@ +void +stub_puts (const char *s) +{ + (void) s; +} diff --git a/testsuite/tests/instr-cov/312-dump-reset/test.opt b/testsuite/tests/instr-cov/312-dump-reset/test.opt new file mode 100644 index 000000000..1c9ab5c59 --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to src trace feature diff --git a/testsuite/tests/instr-cov/312-dump-reset/test.py b/testsuite/tests/instr-cov/312-dump-reset/test.py new file mode 100644 index 000000000..b4c0b6cc9 --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/test.py @@ -0,0 +1,26 @@ +""" +Regression testcase: for a C/C++ source that contains a manual dump directive +followed by a reset directive, "gnatcov instrument" used to get stuck in an +infinite loop. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(srcdirs=[".."], mains=["main.c"]), units=["main.c"] + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="gen", + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6}, "-": {12, 14}}}) +thistest.result() diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/main.adb b/testsuite/tests/instr-cov/323-overriding-null-proc/main.adb new file mode 100644 index 000000000..bdd8e75a0 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/main.adb @@ -0,0 +1,9 @@ +with Pkg; use Pkg; + +procedure Main is + Arg : aliased Arg_Type (1); + Object : T; +begin + Object.P1 (Arg); + Object.P2 (Arg'Access); +end Main; diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb new file mode 100644 index 000000000..84ff70874 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + + overriding procedure P1 (Self : T; Arg : Arg_Type'Class) is null; + overriding procedure P2 (Self : T; Arg : access Arg_Type'Class) is null; + +end Pkg; diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads new file mode 100644 index 000000000..864bb9040 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads @@ -0,0 +1,13 @@ +package Pkg is + + type Arg_Type (I : Integer) is tagged limited null record; + + type I_Type is interface; + procedure P1 (Self : I_Type; Arg : Arg_Type'Class) is abstract; + procedure P2 (Self : I_Type; Arg : access Arg_Type'Class) is abstract; + + type T is new I_Type with null record; + overriding procedure P1 (Self : T; Arg : Arg_Type'Class); + overriding procedure P2 (Self : T; Arg : access Arg_Type'Class); + +end Pkg; diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/test.py b/testsuite/tests/instr-cov/323-overriding-null-proc/test.py new file mode 100644 index 000000000..af7c09c28 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/test.py @@ -0,0 +1,30 @@ +""" +Check that GNAT can compile instrumented code for overriding null procedures +that have a separate declaration. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 5, 7, 8}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {3, 4}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb new file mode 100644 index 000000000..55676c850 --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb @@ -0,0 +1,10 @@ +pragma Annotate (Xcov, Dump_Buffers); +package body Pkg is + + procedure Wrong_Do_Dump is + pragma Annotate (Xcov, Dump_Buffers); + begin + null; -- # st + end Wrong_Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads new file mode 100644 index 000000000..11a9a44b9 --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Wrong_Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb b/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb new file mode 100644 index 000000000..b63f830ec --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb @@ -0,0 +1,13 @@ +with Pkg; + +procedure Test_Pkg is +begin + Pkg.Wrong_Do_Dump; + pragma Annotate (Xcov, Dump_Buffers); +end Test_Pkg; + +-- st can only be covered if both buffer annotations have been ignored + +--# pkg.adb +-- +-- /st/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/test.opt b/testsuite/tests/instr-cov/326-pragma-loc-check/test.opt new file mode 100644 index 000000000..cead7225e --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD test concerns src-trace specific feature +5.04a1 DEAD unknown pragma for the compiler diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/test.py b/testsuite/tests/instr-cov/326-pragma-loc-check/test.py new file mode 100644 index 000000000..4b07e55eb --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/test.py @@ -0,0 +1,30 @@ +""" +Test that buffer dump/reset annotation pragmas located in a location other than +a statement sequence are reported and ignored. +""" + +import os + +from SUITE.context import thistest +from SUITE.tutils import contents_of +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +warning_regexp = ( + r"(\n?\*\*\* pkg\.adb:.*: warning: Incorrect placement" + r" for a buffer dump/reset annotation, the pragma should" + r" be placed in a statement sequence\.)" +) + +TestCase(category=CAT.stmt, tolerate_messages=warning_regexp).run( + CovControl(dump_trigger="manual") +) + +# Actually check that we got the expected messages +thistest.fail_if_no_match( + "missing or unexpected messaged from gnatcov instrument", + regexp=warning_regexp + "+", + actual=contents_of(os.path.join("s_pkg", "xinstr.out")), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb new file mode 100644 index 000000000..7c0e3174a --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb @@ -0,0 +1,8 @@ +pragma Annotate (Xcov, Exempt_On, "Useless unit"); -- # exempt + -- # exempt +package body Exemptions is -- # exempt + -- # exempt + procedure Foo is null; -- # exempt_st + -- # exempt +end Exemptions; -- # exempt +pragma Annotate (Xcov, Exempt_Off); -- # exempt diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads new file mode 100644 index 000000000..4e3a09b32 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads @@ -0,0 +1,5 @@ +package Exemptions is + + procedure Foo; + +end Exemptions; diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads b/testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads new file mode 100644 index 000000000..a09432ba4 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads @@ -0,0 +1,8 @@ +pragma Annotate (Xcov, Cov_Off, "Useless unit"); -- # cov + -- # cov +package Selective is -- # cov + -- # cov + procedure Bar is null; -- # cov + -- # cov +end Selective; -- # cov +pragma Annotate (Xcov, Cov_On); -- # cov diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb b/testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb new file mode 100644 index 000000000..d033978b2 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb @@ -0,0 +1,16 @@ +with Exemptions; +with Selective; + +procedure Test_0 is +begin + null; +end Test_0; + +--# selective.ads +-- +-- /cov/ lD ## dB + +--# exemptions.adb +-- +-- /exempt/ l* ## x+ +-- /exempt_st/ l= ## Xs- diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb b/testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb new file mode 100644 index 000000000..77eb63ed8 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb @@ -0,0 +1,16 @@ +with Exemptions; +with Selective; + +procedure Test_Full is +begin + Exemptions.Foo; + Selective.Bar; +end Test_Full; + +--# selective.ads +-- +-- /cov/ lD ## dB + +--# exemptions.adb +-- +-- /exempt/ l# ## x0 diff --git a/testsuite/tests/instr-cov/326-prelude-prag/test.opt b/testsuite/tests/instr-cov/326-prelude-prag/test.opt new file mode 100644 index 000000000..2a89ffb4a --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD Check instrumentation-specific feature +5.04a1 DEAD pragma Annotate unknown to the compiler diff --git a/testsuite/tests/instr-cov/326-prelude-prag/test.py b/testsuite/tests/instr-cov/326-prelude-prag/test.py new file mode 100644 index 000000000..722840a72 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/test.py @@ -0,0 +1,12 @@ +""" +Test that the instrumentation process correctly takes into account Annotate +pragmas placed in the prelude of a unit. They used to be silently ignored. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase(category=CAT.stmt).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/339-nostdlib/prj.gpr b/testsuite/tests/instr-cov/339-nostdlib/prj.gpr new file mode 100644 index 000000000..8af774f46 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/prj.gpr @@ -0,0 +1,36 @@ +project Prj is + + for Languages use ("Ada", "C"); + for Main use ("main.c"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + + for Runtime ("Ada") use "light"; + + -- We can't build an executable with -nostdlib as a top level + -- builder switch, as this also prevents the c standard library from being + -- linked, and does not use the regular start files. Instead, pass the + -- switch on the binder and liker for Ada sources only, to ensure only the + -- Ada runtime is left out of the link. + + type Yes_No is ("yes", "no"); + Use_Nostdlib : Yes_No := external ("USE_NOSTDLIB", "yes"); + + Stdlib_Switches := (); + + case Use_Nostdlib is + when "yes" => + Stdlib_Switches := ("-nostdlib"); + when "no" => null; + end case; + + package Binder is + for Default_Switches ("Ada") use Stdlib_Switches; + end Binder; + + package Linker is + for Default_Switches ("Ada") use Stdlib_Switches; + end Linker; + +end Prj; diff --git a/testsuite/tests/instr-cov/339-nostdlib/src/main.c b/testsuite/tests/instr-cov/339-nostdlib/src/main.c new file mode 100644 index 000000000..91da81393 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/src/main.c @@ -0,0 +1,26 @@ +#include + +/* Ada code to be called. */ +extern int do_math (int l, int r); + +/* Although there is no Ada runtime, we still need to provide a last chance + handler. */ +void +__gnat_last_chance_handler (char *source_location, int line) +{ + printf ("EXCEPTION at %s\n", source_location); +} + +/* putchar function provided for the coverage runtime. */ +int +gnatcov_rts_putchar (int c) +{ + return putchar (c); +} + +int +main () +{ + int y = do_math (0, 4); + return 0; +} diff --git a/testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb new file mode 100644 index 000000000..3b7238992 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Do_Math (L, R : int) return int is + begin + if L = 0 and then R = 0 then + return 0; + else + return L + R; + end if; + end Do_Math; + +end Pkg; diff --git a/testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads new file mode 100644 index 000000000..0f4eec39b --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads @@ -0,0 +1,8 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + + function Do_Math (L, R : int) return int; + pragma Export (C, Do_Math, External_Name => "do_math"); + +end Pkg; diff --git a/testsuite/tests/instr-cov/339-nostdlib/test.opt b/testsuite/tests/instr-cov/339-nostdlib/test.opt new file mode 100644 index 000000000..59b834cde --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/test.opt @@ -0,0 +1,4 @@ +bin-traces DEAD Test only concerns gnatcov setup & src traces +!native DEAD test bypasses target configuration and assumes native setup +7.1.2 DEAD no light nor zfp runtime support for this compiler version +5.04a1 DEAD no light nor ZFP runtime support for this compiler version diff --git a/testsuite/tests/instr-cov/339-nostdlib/test.py b/testsuite/tests/instr-cov/339-nostdlib/test.py new file mode 100644 index 000000000..7c2b7319e --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/test.py @@ -0,0 +1,151 @@ +""" +Test that "gnatcov setup" produces a coverage library compatible with the +-nostdlib builder switch, and warns on inappropriate configurations. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import xcov + + +tmp = Wdir() + + +def error_case(tc_id, args, expected_out, expect_failure): + """ + Run gnatcov setup with the given args, and check that the output matches + expected_out. Additionally, check the return status of the setup command, + which should match expect_failure. + + The command is run in a temporary subdirectory, with --prefix=. added to + the gnatcov setup args to keep each check separate. id is used as a + temporary directory suffix. + + -q is also added to args to filter out the user directions printed at the + end of the process. + """ + thistest.log(f"====================== {tc_id} =====================") + tmp.to_subdir(f"tmp_{tc_id}") + log = "setup.log" + p = xcov( + ["setup"] + args + ["-q", "--prefix=."], + out=log, + register_failure=not expect_failure, + auto_config_args=False, + tolerate_messages=".", + ) + + thistest.fail_if( + expect_failure and p.status == 0, + "expected 'gnatcov setup' to return a non-zero status code", + ) + + thistest.fail_if_no_match( + "Unexpected 'gnatcov setup' output", + regexp=expected_out, + actual=contents_of(log), + ) + + +# First, test that gnatcov setup correctly warns about suspicious combinations +# of options. + +error_case( + tc_id="profile_incompatibility", + args=["--no-stdlib", "--rts-profile=full"], + expected_out=r'.*: RTS profile "full" not compatible with --no-stdlib', + expect_failure=True, +) + +error_case( + tc_id="suspicious_dump_trigger", + args=["--no-stdlib", "--dump-trigger=atexit", "--RTS=light"], + expected_out="warning: --dump-trigger=atexit may not be compatible with" + " the selected runtime", + expect_failure=False, +) + +error_case( + tc_id="suspicious_dump_channel", + args=["--no-stdlib", "--dump-channel=bin-file", "--RTS=light"], + expected_out="warning: --dump-channel=bin-file may not be compatible with" + " the selected runtime", + expect_failure=False, +) + +# Then check that we can actually build and get a trace from a program +# with Ada code but not linked against the Ada runtime. Do it twice, once with +# and once without and Ada runtime. We expect no coverage difference. +# +# In the code bellow, if use_nostdlib is True then the -nostdlib linker switch +# will be used to build the project, and we do not expect to find the Ada +# runtime library in the linker command. + +for tc_id, use_nostdlib in [ + ("no_stdlib", True), + ("with_stdlib", False), +]: + thistest.log(f"=============== Cov {tc_id} ================") + tmp.to_subdir(f"tmp_{tc_id}") + cp(os.path.join("..", "src"), ".", recursive=True) + cp(os.path.join("..", "prj.gpr"), ".") + + xcov( + [ + "setup", + "-q", + "--prefix=cov_rts", + "--RTS=light", + "--no-stdlib", + ], + auto_config_args=False, + out="setup.log", + ) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project="prj.gpr", + xvars=[("USE_NOSTDLIB", "yes" if use_nostdlib else "no")], + ), + covlevel="stmt+mcdc", + mains=["main"], + dump_trigger=None, + dump_channel="base64-stdout", + extra_coverage_args=["-axcov"], + runtime_project=os.path.join( + "cov_rts", "share", "gpr", "gnatcov_rts.gpr" + ), + auto_config_args=False, + extra_gprbuild_args=["-v"], + ) + + # Check whether we have a libgnat in the gprbuild linker command in the + # log, and compare that against the expected value for this run. + found_libgnat = "libgnat.a" in contents_of("gprbuild.out") + if use_nostdlib: + thistest.fail_if( + found_libgnat, + "Found libgnat.a in gprbuild -v output", + ) + else: + thistest.fail_if( + not found_libgnat, + "Missing libgnat.a in gprbuild -v output", + ) + + check_xcov_reports( + "obj", + { + "main.c.xcov": {"-": {11}, "+": {18, 24, 25}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"-": {6}, "+": {8}, "!": {5}}, + }, + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/342-protected-body/a-b.adb b/testsuite/tests/instr-cov/342-protected-body/a-b.adb new file mode 100644 index 000000000..748b5d783 --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/a-b.adb @@ -0,0 +1,29 @@ +separate (A) + +protected body B +is + + procedure Foo + is + Decl : Integer; + begin + if Decl = 1 then + null; + else + null; + end if; + end Foo; + + procedure Bar + is + begin + null; + end Bar; + + procedure Baz + is + begin + null; + end Baz; + +end B; diff --git a/testsuite/tests/instr-cov/342-protected-body/a.adb b/testsuite/tests/instr-cov/342-protected-body/a.adb new file mode 100644 index 000000000..cdd0b0b4c --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/a.adb @@ -0,0 +1,3 @@ +package body A is + protected body B is separate; +end A; diff --git a/testsuite/tests/instr-cov/342-protected-body/a.ads b/testsuite/tests/instr-cov/342-protected-body/a.ads new file mode 100644 index 000000000..2e328c3ac --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/a.ads @@ -0,0 +1,9 @@ +package A is + + protected type B is + procedure Foo; + procedure Bar; + procedure Baz; + end B; + +end A; diff --git a/testsuite/tests/instr-cov/342-protected-body/main.adb b/testsuite/tests/instr-cov/342-protected-body/main.adb new file mode 100644 index 000000000..e625a6b04 --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/main.adb @@ -0,0 +1,9 @@ +with A; + +procedure Main is + Obj : A.B; +begin + Obj.Foo; + Obj.Bar; + Obj.Baz; +end Main; diff --git a/testsuite/tests/instr-cov/342-protected-body/test.opt b/testsuite/tests/instr-cov/342-protected-body/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/342-protected-body/test.py b/testsuite/tests/instr-cov/342-protected-body/test.py new file mode 100644 index 000000000..76d22337a --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/test.py @@ -0,0 +1,32 @@ +""" +Check that gnatcov correctly processes compilation units when the root node is +a protected body. It used to not consider it as a scope, which resulted in +declarations scope not having a parent scope, making `gnatcov coverage` crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6, 7, 8}}, + "a.ads.xcov": {"+": {3}}, + "a.adb.xcov": {}, + "a-b.adb.xcov": {"+": {8, 10, 13, 20, 26}, "-": {11}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/342-task-body/a-b.adb b/testsuite/tests/instr-cov/342-task-body/a-b.adb new file mode 100644 index 000000000..01aef066b --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/a-b.adb @@ -0,0 +1,33 @@ +separate (A) + +task body B +is + + procedure Foo + is + Decl : Integer; + begin + if Decl = 1 then + return; + else + return; + end if; + end Foo; + + procedure Bar + is + begin + return; + end Bar; + + procedure Baz + is + begin + return; + end Baz; + +begin + Foo; + Bar; + Baz; +end B; diff --git a/testsuite/tests/instr-cov/342-task-body/a.adb b/testsuite/tests/instr-cov/342-task-body/a.adb new file mode 100644 index 000000000..9446f0ef2 --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/a.adb @@ -0,0 +1,3 @@ +package body A is + task body B is separate; +end A; diff --git a/testsuite/tests/instr-cov/342-task-body/a.ads b/testsuite/tests/instr-cov/342-task-body/a.ads new file mode 100644 index 000000000..80570e679 --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/a.ads @@ -0,0 +1,3 @@ +package A is + task B; +end A; diff --git a/testsuite/tests/instr-cov/342-task-body/main.adb b/testsuite/tests/instr-cov/342-task-body/main.adb new file mode 100644 index 000000000..fec42579f --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/main.adb @@ -0,0 +1,6 @@ +with A; + +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/342-task-body/test.opt b/testsuite/tests/instr-cov/342-task-body/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/342-task-body/test.py b/testsuite/tests/instr-cov/342-task-body/test.py new file mode 100644 index 000000000..023478a2b --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/test.py @@ -0,0 +1,31 @@ +""" +Check that gnatcov correctly processes compilation units when the root node is +a task body. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "a.ads.xcov": {"+": {2}}, + "a.adb.xcov": {}, + "a-b.adb.xcov": {"+": {8, 10, 13, 20, 26, 30, 31, 32}, "-": {11}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb b/testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb new file mode 100644 index 000000000..143a59969 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb @@ -0,0 +1,10 @@ +separate(Pkg) +package body Sep is + + Baz : Boolean := False; -- # decl + function Bar return Boolean is + begin + return Foo or else Baz; -- # eval + end Bar; + +end Sep; diff --git a/testsuite/tests/instr-cov/357-separates/src/pkg.adb b/testsuite/tests/instr-cov/357-separates/src/pkg.adb new file mode 100644 index 000000000..f1fbd2e38 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/pkg.adb @@ -0,0 +1,15 @@ +package body Pkg is + + package Sep is + Foo : Boolean := True; -- # decl + function Bar return Boolean; + end Sep; + + package body Sep is separate; + + function Qux return Boolean is + begin + return Sep.Bar; -- # eval + end Qux; + +end Pkg; diff --git a/testsuite/tests/instr-cov/357-separates/src/pkg.ads b/testsuite/tests/instr-cov/357-separates/src/pkg.ads new file mode 100644 index 000000000..83a299851 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Qux return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/357-separates/src/test_sep.adb b/testsuite/tests/instr-cov/357-separates/src/test_sep.adb new file mode 100644 index 000000000..f3c5fd12b --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/test_sep.adb @@ -0,0 +1,16 @@ +with Pkg; + +with Support; + +procedure Test_Sep is +begin + Support.Assert (Pkg.Qux); +end Test_Sep; + +--# pkg.adb pkg-sep.adb +-- +-- /eval/ l+ ## 0 + +--%opts: --trace-mode=src +-- +-- /decl/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/357-separates/test.py b/testsuite/tests/instr-cov/357-separates/test.py new file mode 100644 index 000000000..90363f7a7 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/test.py @@ -0,0 +1,15 @@ +""" +Test that gnatcov does not generate conflicting entities between a package spec +and its separate body. This could happen if the package is a nested package +declared in a body, and the nested package's body is a separate, in which the +suffixes for the entities gnatcov inserts were not different. The instrumented +code used to not compile at all. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT + +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/extra.opt b/testsuite/tests/instr-cov/358-exprf-aspects/extra.opt new file mode 100644 index 000000000..03d283ab0 --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/extra.opt @@ -0,0 +1,3 @@ +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 +7.1.2 DEAD support for expression functions weak in 7.1.2 +bin-traces DEAD Test for expr func aspect instrumentation diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads b/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads new file mode 100644 index 000000000..8b0fbd333 --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Aspect is + + function Foo return Integer is (42) -- # expr + with Convention => Stdcall; + + type Foo_Type is access + function return Integer with Convention => Stdcall; + +end Aspect; diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb new file mode 100644 index 000000000..fb79f88f0 --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb @@ -0,0 +1,8 @@ +with Aspect; use Aspect; + +procedure Foo is + + Dummy : Foo_Type := Foo'Access; -- # d +begin + null; +end; diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb new file mode 100644 index 000000000..a99de6bd5 --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb @@ -0,0 +1,15 @@ +with Foo; + +-- Check that when instrumenting an expression function with aspects, these +-- aspects are also correctly attached to both the new intermediary function +-- and to the augmented expression function. + +procedure Test_Aspect is +begin + Foo; +end Test_Aspect; + +--# aspect.ads +-- /expr/ l- ## s- +--# foo.adb +-- /d/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/test.py b/testsuite/tests/instr-cov/358-exprf-aspects/test.py new file mode 100644 index 000000000..11e55638b --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb new file mode 100644 index 000000000..d23d45788 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + procedure Foo is + begin + null; + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads new file mode 100644 index 000000000..d91f3ae51 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/363-annot-crash/src/test.adb b/testsuite/tests/instr-cov/363-annot-crash/src/test.adb new file mode 100644 index 000000000..e75f2cda7 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/src/test.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Test is +begin + Pkg.Foo; +end Test; diff --git a/testsuite/tests/instr-cov/363-annot-crash/test.py b/testsuite/tests/instr-cov/363-annot-crash/test.py new file mode 100644 index 000000000..9e627d5e9 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/test.py @@ -0,0 +1,38 @@ +""" +Regression test: check that gnatcov does not crash when generating a XML / HTML +report with missing sources. It used to crash when trying to compute scope +metrics. +""" + +from e3.fs import mv, sync_tree + +import os + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +tmp = Wdir("tmp_") + +sync_tree(os.path.join("..", "src"), "src") + +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["src"], mains=["test.adb"]) + ), + covlevel="stmt", + mains=["test"], + extra_coverage_args=[], + trace_mode="src", +) + +# Then hide the sources +os.mkdir("src_hidden") +mv(os.path.join("src", "pkg.adb"), "src_hidden") + +# Try to generate a HTML, and an XML report +xcov(xcov_args + ["-axml"], tolerate_messages="warning: can't open") +xcov(xcov_args + ["-ahtml"], tolerate_messages="warning: can't open") + +thistest.result() diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr b/testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr new file mode 100644 index 000000000..fdd6d1c25 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr @@ -0,0 +1,10 @@ +library project Lib is + + for Library_Dir use "lib"; + for Object_Dir use "obj_lib"; + for Source_Dirs use (".."); + for Excluded_Source_Files use ("main.adb"); + for Library_Kind use "static"; + for Library_Name use "lib"; + +end Lib; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/main.adb b/testsuite/tests/instr-cov/384-SID-cleanup/main.adb new file mode 100644 index 000000000..1f4442127 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/main.adb @@ -0,0 +1,10 @@ +with Pkg; +with Pkh; + +with Support; + +procedure Main is +begin + Support.Assert (Pkg.Foo = 1); + Support.Assert (Pkh.Bar = 2); +end Main; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb new file mode 100644 index 000000000..d507dd4a2 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb @@ -0,0 +1,7 @@ +package body Pkg is + + function Foo return Integer is begin + return 1; + end Foo; + +end Pkg; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads new file mode 100644 index 000000000..8a49d2fad --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Foo return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb new file mode 100644 index 000000000..c27f8a974 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb @@ -0,0 +1,7 @@ +package body Pkh is + + function Bar return Integer is begin + return 2; + end Bar; + +end Pkh; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads new file mode 100644 index 000000000..5c69eae9a --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads @@ -0,0 +1,5 @@ +package Pkh is + + function Bar return Integer; + +end Pkh; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/test.opt b/testsuite/tests/instr-cov/384-SID-cleanup/test.opt new file mode 100644 index 000000000..e6c1eea36 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/test.opt @@ -0,0 +1 @@ +bin-traces DEAD test concerns instrumentation-only feature diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/test.py b/testsuite/tests/instr-cov/384-SID-cleanup/test.py new file mode 100644 index 000000000..ba00b219a --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/test.py @@ -0,0 +1,83 @@ +""" +Verify that gnatcov cleans up existing SID files during instrumentation. +""" + +from e3.fs import cp +import glob + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import contents_of, gprfor + +Wdir("tmp_") +cp("../lib.gpr", ".") + +prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + deps=["lib.gpr"], + extra='for Source_Files use ("main.adb");', +) + +expected_cov = { + "main.adb.xcov": {"+": {9, 8}}, + "pkg.adb.xcov": {"+": {4}}, + "pkg.ads.xcov": {}, + "pkh.adb.xcov": {"+": {4}}, + "pkh.ads.xcov": {}, +} + +# Create a first report using all units +thistest.log("=== All units test ===") +output_full = "all_units" +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir", output_full], +) +check_xcov_reports(output_full, expected_cov) + +thistest.log("=== Without Pkh unit test ===") +# Now same but without pkg in the units of interest, at instrumentation time +# Only change the output dir, and not the object dir so that if the pkh.sid +# file remains after instrumentation, it will be picked up and generate a +# report with violations. +# +# In this case, we expect pkh.sid to be deleted, so no report created for this +# unit (and gnatcov coverage should complain that there is no SID for this +# specific unit). + +output_pkg = "only_pkg" + +# Pass the units argument to gnatcov instrument only to ensure the coverage +# command will attempt to pick up all sid files. +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--units", "main", "--units", "pkg"], + extra_coverage_args=["-axcov", "--output-dir", output_pkg], + tolerate_coverage_messages="no SID file found for unit pkh", +) +expected_cov.pop("pkh.adb.xcov") +expected_cov.pop("pkh.ads.xcov") +check_xcov_reports(output_pkg, expected_cov) + +# Verify that gnatcov complained that there was no SID file found for Pkh +thistest.fail_if_not_equal( + what="Unexpected 'gnatcov coverage' output", + expected="warning: no SID file found for unit pkh", + actual=contents_of("coverage.log").strip(), +) + +# Check that there is indeed no sid file for Pkh +thistest.fail_if_not_equal( + what="Found an SID file for Pkh", + expected=[], + actual=glob.glob("**/pkh.sid"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py new file mode 100644 index 000000000..1425bef11 --- /dev/null +++ b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py @@ -0,0 +1,44 @@ +""" +Check that gnatcov does not crash when passing an invalid target value when +only the C language is enabled. +""" + +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import xcov + +tmp = Wdir("tmp_") + +# Run gnatcov setup with an invalid target, while disabling the Ada language +setup_log = "setup.log" +p = xcov( + [ + "setup", + "--target=INVALID", + "--restricted-to-languages=C", + "--prefix", + "dummy", + ], + out=setup_log, + auto_config_args=False, + auto_target_args=False, + register_failure=False, +) + +thistest.fail_if( + p.status == 0, + "'gnatcov setup' did not reject the invalid target", +) +thistest.fail_if_no_match( + "Unexpectect 'gnatcov setup' output", + regexp=( + "kb: info: can't find a toolchain for the following configuration:" + " language 'Ada', target 'INVALID', default runtime\n" + "kb: info: can't find a toolchain for the following configuration:" + " language 'C', target 'INVALID', default runtime\n" + ".*gnatcov(.exe)?: Cannot get library support for this configuration" + ), + actual=contents_of(setup_log).strip(), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/399-dir-arg/test.opt b/testsuite/tests/instr-cov/399-dir-arg/test.opt new file mode 100644 index 000000000..f4513c683 --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test.opt @@ -0,0 +1 @@ +!native DEAD Use GNATCOV_TRACE_FILE feature only available with the binary file dump-channel diff --git a/testsuite/tests/instr-cov/399-dir-arg/test.py b/testsuite/tests/instr-cov/399-dir-arg/test.py new file mode 100644 index 000000000..6b26aa433 --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test.py @@ -0,0 +1,49 @@ +""" +Check that gnatcov accepts directory arguments for the --trace and +--sid switches. +""" + +import os +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +Wdir("tmp_") + +os.mkdir("traces-dir") +env = dict(os.environ) +env.update({"GNATCOV_TRACE_FILE": "traces-dir/"}) +build_and_run( + gprsw=GPRswitches(gprfor(srcdirs=[".."], mains=["test_1", "test_2"])), + covlevel="stmt", + mains=["test_1", "test_2"], + extra_coverage_args=[], + trace_mode="src", + program_env=env, +) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--sid", + "obj/", + "--trace", + "traces-dir/", + ] +) + +# Check that the coverage report is as expected +check_xcov_reports( + ".", + { + "test_1.adb.xcov": {"+": {3}}, + "test_2.adb.xcov": {"+": {3}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/399-dir-arg/test_1.adb b/testsuite/tests/instr-cov/399-dir-arg/test_1.adb new file mode 100644 index 000000000..130d8e00f --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test_1.adb @@ -0,0 +1,4 @@ +procedure Test_1 is +begin + null; +end Test_1; diff --git a/testsuite/tests/instr-cov/399-dir-arg/test_2.adb b/testsuite/tests/instr-cov/399-dir-arg/test_2.adb new file mode 100644 index 000000000..1023c044d --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test_2.adb @@ -0,0 +1,4 @@ +procedure Test_2 is +begin + null; +end Test_2; diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb new file mode 100644 index 000000000..244590709 --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb @@ -0,0 +1,28 @@ +pragma Ada_2012; + +package body Pkg is + procedure Foo (X : Integer) is null; -- # st + + procedure Bar (X : Integer) is null; -- # st + + procedure Qux (X : Integer) is null; -- # st + pragma Convention (C, Qux); + + procedure Corge (X : Integer) is null with Convention => C; -- # st + + procedure Clip (X : Integer) is null; -- # st + pragma Export + (Convention => C, + Entity => Clip, + External_Name => "clip"); + + procedure Baz (X : Integer) is + begin + Qux (X); -- # st + Corge (X); -- # st + Clip (X); -- # st + end Baz; + + procedure Blop (X : Integer) is null; -- # st + +end Pkg; diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads new file mode 100644 index 000000000..69c296397 --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pkg is + procedure Foo (X : Integer); + pragma Convention (C, Foo); + + procedure Bar (X : Integer) with + Convention => C; + + procedure Baz (X : Integer); + + procedure Blop (X : Integer); + pragma Export (C, Blop, "blop"); + +end Pkg; diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb new file mode 100644 index 000000000..740ac29bc --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb @@ -0,0 +1,11 @@ +with Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + + +--# pkg.adb +-- +-- /st/ l- ## s- diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb new file mode 100644 index 000000000..680f51e5b --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Full is +begin + Pkg.Foo (0); + Pkg.Bar (0); + Pkg.Baz (0); + Pkg.Blop (0); +end Test_Full; + + +--# pkg.adb +-- +-- /st/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/test.opt b/testsuite/tests/instr-cov/408-null-proc-convention/test.opt new file mode 100644 index 000000000..6077b379b --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test requires Ada 2012 features diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/test.py b/testsuite/tests/instr-cov/408-null-proc-convention/test.py new file mode 100644 index 000000000..121c49643 --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/test.py @@ -0,0 +1,11 @@ +""" +Check that gnatcov can instrument null procedures that specify a calling +convention, either through the Convention aspect or through the Export aspect. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb new file mode 100644 index 000000000..c8a0ef4ba --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Pref; use Pref; + +procedure Main_With_Pragma is + procedure Foo (B: Boolean) is + BB : Preference := Preference(B); + begin + if B then + Put_Line ("Coucou"); + elsif Get_Pref (BB) then + Put_Line ("test"); + end if; + end Foo; +begin + Put_Line ("Hello World"); + Foo (True); +end Main_With_Pragma; diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb new file mode 100644 index 000000000..8a0640000 --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb @@ -0,0 +1,17 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pref; use Pref; + +procedure Main_Without_Pragma is + procedure Foo (B: Boolean) is + BB : Preference := Preference(B); + begin + if B then + Put_Line ("Coucou"); + elsif Get_Pref (BB) then + Put_Line ("test"); + end if; + end Foo; +begin + Put_Line ("Hello World"); + Foo (True); +end Main_Without_Pragma; diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads b/testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads new file mode 100644 index 000000000..ca6f0d238 --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pref is + + type Preference is new Boolean; + + function Get_Pref (P : Preference) return Preference is ((case P is + when True => True, + when False => False)); + + function Get_Pref (P : Preference) return String + is ((case P is + when True => "TRUE", + when False => "FALSE")); +end Pref; diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/test.opt b/testsuite/tests/instr-cov/409-ambiguous-operand/test.opt new file mode 100644 index 000000000..2f0d6368e --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/test.opt @@ -0,0 +1,5 @@ +!src-traces DEAD instrumentation-related test +5.04a1 DEAD Test requires Ada 2012 support +7.1.2 DEAD Test requires Ada 2012 support +CARGS_gnat2012 DEAD The test is expected to run on Ada 2005 or lower +CARGS_gnat2022 DEAD The test is expected to run on Ada 2005 or lower diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/test.py b/testsuite/tests/instr-cov/409-ambiguous-operand/test.py new file mode 100644 index 000000000..094e6993f --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/test.py @@ -0,0 +1,60 @@ +""" +Check that when the language version permits it, use an if-expr instead of a +Boolean type conversion to avoid the "ambiguous operand" error. + +Otherwise, the instrumentation may produce code that is not compilable. +Workarounds include manually qualifying the type to disambigue the expression, +or removing the problematic unit from coverage analysis + +NOTE: Assume that the testsuite is run with -gnat05 by default +""" + +import re + +from SCOV.minicheck import build_and_run +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.dutils import contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, gprbuild + +_wd = Wdir("tmp_") + +gpr = gprfor( + mains=["main_with_pragma.adb"], + srcdirs=["../src"], +) + +# Should work +result = build_and_run( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main_with_pragma"], + register_failure=True, + extra_coverage_args=[], +) + +# Do the same but without the version pragma. +gpr_without = gprfor( + mains=["main_without_pragma.adb"], + srcdirs=["../src"], +) +gprsw = GPRswitches(root_project=gpr_without) + +xcov_instrument( + gprsw=gprsw, + covlevel="stmt", +) +build_p = gprbuild( + gprsw.root_project, gargs=gprsw.build_switches, register_failure=False +) + +thistest.fail_if(build_p.status == 0, "Compilation should have failed") +thistest.fail_if_no_match( + "Compilation should fail with 'ambiguous operand'", + re.compile(r".*ambiguous operand.*", flags=re.S), + contents_of("gprbuild.out"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h b/testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h new file mode 100644 index 000000000..c457e8ab2 --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h @@ -0,0 +1,9 @@ +#define CONCAT(X, Y) X##Y + +inline int +ident (int x) +{ + /* GNATCOV_EXEMPT_ON unused*/ + return 0; // # noeval + /*GNATCOV_EXEMPT_OFF */ +} diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c b/testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c new file mode 100644 index 000000000..6457fb92c --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c @@ -0,0 +1,16 @@ +#include "pkg.h" + +int +main () +{ + int CONCAT (/*empty*/, my_var) = 0; // # st + return CONCAT (/*something else*/, my_var); // # st +} + +//# test_pkg.c +// +// /st/ l+ ## 0 + +//# pkg.h +// +// /noeval/ l- ## s- diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/test.opt b/testsuite/tests/instr-cov/419-comment-preprocessing/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/test.py b/testsuite/tests/instr-cov/419-comment-preprocessing/test.py new file mode 100644 index 000000000..a27cb79cf --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/test.py @@ -0,0 +1,34 @@ +""" +Test that gnatcov does not crash when instrumenting a source that cannot be +preprocessed while preserving comments, and instead emits a warning stating +that annotations are ignored. +""" + +import os + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest +from SUITE.cutils import contents_of + +wd = "s_pkg" + +warning_pat = ( + r"warning: Could not preserve comments while pre-processing .*test_pkg\.c" + r", annotations in comments within this file or included headers will not" + r" be taken into account" +) + +TestCase( + category=CAT.stmt, + tolerate_messages=warning_pat, +).run() + +# Actually check that the warning got emitted +thistest.fail_if_no_match( + what="missing warning in the output of 'gnatcov instrument'", + regexp=warning_pat, + actual=contents_of(os.path.join(wd, "xinstr.out")), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb new file mode 100644 index 000000000..62be95641 --- /dev/null +++ b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function F return T is + begin + return null; + end F; + +end Pkg; diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads new file mode 100644 index 000000000..a57c3625c --- /dev/null +++ b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + subtype T is Unknown_Type; + function F return T; +end Pkg; diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/test.py b/testsuite/tests/instr-cov/449-aggregate-crash/test.py new file mode 100644 index 000000000..0997910fc --- /dev/null +++ b/testsuite/tests/instr-cov/449-aggregate-crash/test.py @@ -0,0 +1,20 @@ +""" +Regression test: "gnatcov instrument" used to crash when trying to instrument a +function whose return type is an unresolvable subtype. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(mains=[], srcdirs=[".."])), + covlevel="stmt", + tolerate_messages=r"\*\*\* pkg\.(adb|ads):\d+:\d+: (low_)?warning: .*", +) +thistest.result() diff --git a/testsuite/tests/instr-cov/471-homonym-files/main.c b/testsuite/tests/instr-cov/471-homonym-files/main.c new file mode 100644 index 000000000..4d93cdf34 --- /dev/null +++ b/testsuite/tests/instr-cov/471-homonym-files/main.c @@ -0,0 +1,16 @@ +extern void foo1 (void); +extern void foo2 (void); + +void +print_msg (const char *msg) +{ + (void) msg; +} + +int +main (void) +{ + foo1 (); + foo2 (); + return 0; +} diff --git a/testsuite/tests/instr-cov/471-homonym-files/src1/foo.c b/testsuite/tests/instr-cov/471-homonym-files/src1/foo.c new file mode 100644 index 000000000..41c4cca23 --- /dev/null +++ b/testsuite/tests/instr-cov/471-homonym-files/src1/foo.c @@ -0,0 +1,7 @@ +extern void print_msg (const char *msg); + +void +foo1 (void) +{ + print_msg ("Hello from foo1"); +} diff --git a/testsuite/tests/instr-cov/471-homonym-files/src2/foo.c b/testsuite/tests/instr-cov/471-homonym-files/src2/foo.c new file mode 100644 index 000000000..cf0124a8a --- /dev/null +++ b/testsuite/tests/instr-cov/471-homonym-files/src2/foo.c @@ -0,0 +1,11 @@ +extern void print_msg (const char *msg); + +void +foo2 (void) +{ + int i; + for (i = 0; i < 2; ++i) + { + print_msg ("Hello from foo2"); + } +} diff --git a/testsuite/tests/instr-cov/471-homonym-files/test.py b/testsuite/tests/instr-cov/471-homonym-files/test.py new file mode 100644 index 000000000..03cb718ed --- /dev/null +++ b/testsuite/tests/instr-cov/471-homonym-files/test.py @@ -0,0 +1,38 @@ +""" +Check that gnatcov does not emit spurious warning about source files with same +basenames. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +p1 = gprfor(prjid="p1", srcdirs=["../src1"], mains=[], objdir="obj-p1") +p2 = gprfor(prjid="p2", srcdirs=["../src2"], mains=[], objdir="obj-p2") +main_gpr = gprfor( + prjid="main", mains=["main.c"], srcdirs=[".."], deps=["p1", "p2"] +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) +main_optimized_out = {7} if thistest.options.trace_mode == "bin" else set() +src2_foo_optimized_out = {6} if thistest.options.trace_mode == "bin" else set() +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {7, 13, 14} - main_optimized_out}, + "src1-foo.c.xcov": {"+": {6}}, + "src2-foo.c.xcov": {"+": {6, 7, 9} - src2_foo_optimized_out}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb b/testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_object_path b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_object_path new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path new file mode 100644 index 000000000..a678f5061 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path @@ -0,0 +1,2 @@ +gnat_user +gnat diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/adainclude/empty-dir.txt b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/adainclude/empty-dir.txt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads new file mode 100644 index 000000000..421376db9 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads @@ -0,0 +1 @@ +dummy diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads new file mode 100644 index 000000000..fed04e343 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads @@ -0,0 +1,4 @@ +package Ada is + pragma No_Elaboration_Code_All; + pragma Pure; +end Ada; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads new file mode 100644 index 000000000..1a286ad12 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads @@ -0,0 +1,114 @@ +package System is + pragma Pure; + pragma No_Elaboration_Code_All; + + subtype Name is String; + System_Name : constant Name := "foo"; + + -- System-Dependent Named Numbers + + Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); + Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; + + Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; + Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; + + Max_Base_Digits : constant := Long_Long_Float'Digits; + Max_Digits : constant := Long_Long_Float'Digits; + + Max_Mantissa : constant := Standard'Max_Integer_Size - 1; + Fine_Delta : constant := 2.0 ** (-Max_Mantissa); + + Tick : constant := 0.000_001; + + -- Storage-related Declarations + + type Address is private; + pragma Preelaborable_Initialization (Address); + Null_Address : constant Address; + + Storage_Unit : constant := 8; + Word_Size : constant := Standard'Word_Size; + Memory_Size : constant := 2 ** Word_Size; + + -- Address comparison + + function "<" (Left, Right : Address) return Boolean; + function "<=" (Left, Right : Address) return Boolean; + function ">" (Left, Right : Address) return Boolean; + function ">=" (Left, Right : Address) return Boolean; + function "=" (Left, Right : Address) return Boolean; + + pragma Import (Intrinsic, "<"); + pragma Import (Intrinsic, "<="); + pragma Import (Intrinsic, ">"); + pragma Import (Intrinsic, ">="); + pragma Import (Intrinsic, "="); + + -- Other System-Dependent Declarations + + type Bit_Order is (High_Order_First, Low_Order_First); + Default_Bit_Order : constant Bit_Order := + Bit_Order'Val (Standard'Default_Bit_Order); + pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning + + -- Priority-related Declarations (RM D.1) + + -- If the scheduling policy is SCHED_FIFO or SCHED_RR the runtime makes use + -- of the entire range provided by the system. + -- + -- If the scheduling policy is SCHED_OTHER the only valid system priority + -- is 1 and other values are simply ignored. + + Max_Priority : constant Positive := 62; + Max_Interrupt_Priority : constant Positive := 63; + + subtype Any_Priority is Integer range 1 .. 63; + subtype Priority is Any_Priority range 1 .. 62; + subtype Interrupt_Priority is Any_Priority range 63 .. 63; + + Default_Priority : constant Priority := 10; + +private + + type Address is mod Memory_Size; + for Address'Size use Standard'Address_Size; + + Null_Address : constant Address := 0; + + -------------------------------------- + -- System Implementation Parameters -- + -------------------------------------- + + -- These parameters provide information about the target that is used + -- by the compiler. They are in the private part of System, where they + -- can be accessed using the special circuitry in the Targparm unit + -- whose source should be consulted for more detailed descriptions + -- of the individual switch values. + + Backend_Divide_Checks : constant Boolean := False; + Backend_Overflow_Checks : constant Boolean := True; + Command_Line_Args : constant Boolean := True; + Configurable_Run_Time : constant Boolean := True; + Denorm : constant Boolean := True; + Duration_32_Bits : constant Boolean := False; + Exit_Status_Supported : constant Boolean := True; + Machine_Overflows : constant Boolean := False; + Machine_Rounds : constant Boolean := True; + Preallocated_Stacks : constant Boolean := False; + Signed_Zeros : constant Boolean := True; + Stack_Check_Default : constant Boolean := False; + Stack_Check_Probes : constant Boolean := True; + Stack_Check_Limits : constant Boolean := False; + Support_Aggregates : constant Boolean := True; + Support_Atomic_Primitives : constant Boolean := True; + Support_Composite_Assign : constant Boolean := True; + Support_Composite_Compare : constant Boolean := True; + Support_Long_Shifts : constant Boolean := True; + Always_Compatible_Rep : constant Boolean := True; + Suppress_Standard_Library : constant Boolean := True; + Use_Ada_Main_Program_Name : constant Boolean := False; + Frontend_Exceptions : constant Boolean := False; + ZCX_By_Default : constant Boolean := True; + +end System; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads new file mode 100644 index 000000000..c6278247a --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads @@ -0,0 +1,3 @@ +package Ada.Text_IO is + procedure Put_Line (S : String) is null; +end Ada.Text_IO; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr new file mode 100644 index 000000000..a0dfa9727 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr @@ -0,0 +1,19 @@ +project Runtime_Build is + + for Runtime ("Ada") use Project'Project_Dir; + + for Library_Auto_Init use "False"; + for Library_Name use "gnat"; + for Library_Dir use "adalib"; + for Object_Dir use "obj"; + for Source_Dirs use ("gnat_user", "gnat"); + + package Compiler is + for Default_Switches ("Ada") use ("-gnatg"); + end Compiler; + + package Naming is + for Spec_Suffix ("Asm_CPP") use ".inc"; + end Naming; + +end Runtime_Build; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py b/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py new file mode 100644 index 000000000..097e4979a --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py @@ -0,0 +1,38 @@ +""" +Check that the instrumentation of a project does not crash when the Ada runtime +for this project contains homonym sources in its source directories. +""" + +import os.path + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +# Avoid "creating output path" info messages +os.mkdir("obj") + +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + auto_config_args=False, + auto_target_args=False, + extra_args=[ + "--target", + thistest.env.target.triplet, + "--RTS", + os.path.abspath("../runtime"), + ], + # This test instruments a fake runtime. For practical purposes, that + # runtime is incomplete: it is not possible to build the coverage runtime + # for it, we cannot run "gnatcov setup" and thus we expect a warning about + # the runtime mismatch. + tolerate_messages="Current runtime is", + out="instrument.log", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp b/testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp new file mode 100644 index 000000000..f9a6743f8 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp @@ -0,0 +1,7 @@ +#include + +int +main (int argc, char **argv) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/109-pp-switches/test.py b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py new file mode 100644 index 000000000..f3e9d749d --- /dev/null +++ b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py @@ -0,0 +1,26 @@ +""" +Check that the instrumenter considers the -fno-rtti switch for preprocessing. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.cpp"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c++-opts=-fno-rtti"], + extra_gprbuild_cargs=["-fno-rtti"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.cpp.xcov": {"+": {6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp b/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp new file mode 100644 index 000000000..0539f7b93 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp @@ -0,0 +1,43 @@ +namespace foo +{ +const float PI = 3.14; +const float E = 2.72; +} + +// Purposely not called function. +void +bar () +{ + using namespace foo; // # using + + auto x = PI; // # use_pi +} + +// Purposely not called function. +void +baz () +{ + using foo::PI; // # using + + auto x = PI; // # use_pi +} + +// Purposely not called function. +void +toto () +{ + // importing multiple symbols on the same directive + using foo::PI, foo::E; // # using + + auto x = PI; // # use_pi +} + +int +main (void) +{ + 0; +} + +//# test_call.cpp +// /using/ l. ## 0 +// /use_pi/ l- ## s- diff --git a/testsuite/tests/instr-cov/C++/374-using/test.py b/testsuite/tests/instr-cov/C++/374-using/test.py new file mode 100644 index 000000000..4b051d37e --- /dev/null +++ b/testsuite/tests/instr-cov/C++/374-using/test.py @@ -0,0 +1,11 @@ +""" +Check that the C++ instrumenter does not consider `using` clauses +as statements. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp new file mode 100644 index 000000000..37ae56af3 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp @@ -0,0 +1,11 @@ +#include "pkg.hh" + +int +overly_complex_fact (int n) +{ + return n ? n * // # top_level + [] (int m) { + return m > 1 ? overly_complex_fact (m) : 1; // # lambda + }(n - 1) + : 1; +} diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh new file mode 100644 index 000000000..8b9daab16 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh @@ -0,0 +1 @@ +extern int overly_complex_fact (int n); diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp new file mode 100644 index 000000000..d8bf064a4 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp @@ -0,0 +1,16 @@ +#include "pkg.hh" + +int +main () +{ + if (!overly_complex_fact (2) == 2) + return 1; + if (!overly_complex_fact (0) == 1) + return 1; + return 0; +} + +//# pkg.cpp +// +// /top_level/ l+ ## 0 +// /lambda/ l! ## dT- diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py b/testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py new file mode 100644 index 000000000..d7f890c99 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py @@ -0,0 +1,13 @@ +""" +Check that instrumenting a lambda containing a decision +and that is declared in a statement containing a decision (other than nested in +the lambda) works as intended. gnatcov used to emit duplicate decision SCOs and +thus crash. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp new file mode 100644 index 000000000..54e672d1d --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp @@ -0,0 +1,8 @@ +#include "pkg.h" + +int +main (void) +{ + foo_int (); + foo_float (); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp new file mode 100644 index 000000000..06a90381c --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main (void) +{ + foo_float (); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp new file mode 100644 index 000000000..a49c61e53 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main (void) +{ + foo_int (); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp new file mode 100644 index 000000000..84a3c635c --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main (void) +{ + int foo = 0; +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp new file mode 100644 index 000000000..c3ab7092e --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp @@ -0,0 +1,22 @@ +#include "pkg.h" + +template +void +print_point (Point p) +{ + (void) p; +} + +void +foo_int (void) +{ + Point A = Point (1, 2); + print_point (A); +} + +void +foo_float (void) +{ + Point A = Point (1.5f, 2.5f); + print_point (A); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h new file mode 100644 index 000000000..2c4f6a86e --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h @@ -0,0 +1,17 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo_int (void); +void foo_float (void); + +template struct Point +{ + T x; + T y; + + Point (T x, T y) : x (x), y (y) {} +}; + +template void print_point (Point p); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/C++/c++_generics/test.py b/testsuite/tests/instr-cov/C++/c++_generics/test.py new file mode 100644 index 000000000..31e60085a --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/test.py @@ -0,0 +1,52 @@ +""" +Check that GNATcoverage produces a valid output for generics. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +MAIN_BOTH = "main_both.cpp" +MAIN_INT = "main_int.cpp" +MAIN_FLOAT = "main_float.cpp" +MAIN_NONE = "main_none.cpp" + + +def build_and_run_with_main(main): + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=["../src"], + mains=[main], + ) + ), + covlevel="stmt", + mains=[main.split(".")[0]], + extra_instr_args=["--verbose", "--units=pkg.cpp"], + extra_coverage_args=["-axcov", "--output-dir=xcov", "--units=pkg.cpp"], + extra_gprbuild_args=["-v"], + ) + + +# Testcase both instantiation calls +build_and_run_with_main(MAIN_BOTH) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"+": {7, 13, 14, 20, 21}}}) + +# Testcase only int instantiation call +build_and_run_with_main(MAIN_INT) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"-": {20, 21}}}) + +# Testcase only float instantiation call +build_and_run_with_main(MAIN_FLOAT) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"-": {13, 14}}}) + +# Testcase no instantiation call +build_and_run_with_main(MAIN_NONE) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"-": {7, 13, 14, 20, 21}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp b/testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py new file mode 100644 index 000000000..e7565c956 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py @@ -0,0 +1,25 @@ +""" +Check that the instrumentation produces code that compiles without warnings. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.cpp"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_gprbuild_cargs=["-Werror"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.cpp.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp new file mode 100644 index 000000000..fece5f42a --- /dev/null +++ b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp @@ -0,0 +1,8 @@ +extern "C" +{ + int + main (int argc, char **argv) + { + return 0; + } +} diff --git a/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py new file mode 100644 index 000000000..f8e1e68dd --- /dev/null +++ b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py @@ -0,0 +1,24 @@ +""" +Check that gnatcov correctly instruments a main that is in an extern "C" +linkage specifier. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.cpp"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.cpp.xcov": {"+": {6}}}) +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/main.c b/testsuite/tests/instr-cov/C++/explicit_lang/main.c new file mode 100644 index 000000000..b91c64636 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/explicit_lang/main.c @@ -0,0 +1,16 @@ +class C +{ +public: + int + get_zero () + { + return 0; + } +}; + +int +main () +{ + C c; + return c.get_zero (); +} diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/test.py b/testsuite/tests/instr-cov/C++/explicit_lang/test.py new file mode 100644 index 000000000..aaa7254da --- /dev/null +++ b/testsuite/tests/instr-cov/C++/explicit_lang/test.py @@ -0,0 +1,37 @@ +""" +Check that gnatcov explicitly passes the language to the compiler / parsing +command, otherwise the file might be preprocessed as C code instead of C++ +and reciprocally. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +p = gprfor( + srcdirs=[".."], + mains=["main.c"], + langs=["C++"], + extra=""" + package Naming is + for Body_Suffix ("C++") use ".c"; + end Naming; + """, +) +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.c.xcov": {"+": {7, 14, 15}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/extra.opt b/testsuite/tests/instr-cov/C++/extra.opt new file mode 100644 index 000000000..057749df0 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/extra.opt @@ -0,0 +1,2 @@ +!C++ DEAD Only run C++ tests if we have a supported C++ compiler +bin-traces DEAD C++ not supported with binary traces diff --git a/testsuite/tests/instr-cov/C++/std-c++20/main.cpp b/testsuite/tests/instr-cov/C++/std-c++20/main.cpp new file mode 100644 index 000000000..252ef50c8 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-c++20/main.cpp @@ -0,0 +1,17 @@ +#include + +int +main (int argc, char **argv) +{ + int a[]{ 0, 1, 2 }; + std::span s_all (a); + std::span s_0 = s_all.subspan (0, 1); + std::span s_2 = s_all.subspan (2, 1); + + if (s_0[0] != 0) + return 1; + if (s_2[0] != 2) + return 1; + + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/std-c++20/test.py b/testsuite/tests/instr-cov/C++/std-c++20/test.py new file mode 100644 index 000000000..520f3ada9 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-c++20/test.py @@ -0,0 +1,61 @@ +""" +Check that gnatcov can deal with C/C++ code in another standard than the +default. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor +from SUITE.gprutils import GPRswitches + + +def gen_prj(): + return GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.cpp"])) + + +tmp = Wdir("tmp_valid-instrumentation") + +# Check that passing std=c++20 to both the instrumenter, and the builder, +# compiles and produces the right coverage report. + +build_run_and_coverage( + gprsw=gen_prj(), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c++-opts=-std=c++20"], + extra_gprbuild_cargs=["-std=c++20"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", {"main.cpp.xcov": {"+": {6, 7, 8, 9, 11, 13, 16}, "-": {12, 14}}} +) + +tmp.to_homedir() + +# Now check that when we do not pass std=c++20 to the instrumenter, we +# produce invalid code, that will fail to compile. +# +# TODO: gnatcov instrument should emit warnings. We get diagnostics when +# parsing with clang, but we choose not to emit them, as we are bound to get +# diagnostics even for valid code. One thing we could try would be to filter +# out the diagnostics that we will surely get (references to gcc builtins for +# instance), and print the other ones. + +tmp = Wdir("tmp_invalid-instrumentation") + +gprsw = gen_prj() +xcov_instrument(gprsw=gprsw, covlevel="stmt") +p = gprbuild( + gprsw.root_project, + extracargs=["-std=c++20"], + trace_mode="src", + register_failure=False, +) + +thistest.fail_if(p.status == 0, "Expecting compilation failure") + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp new file mode 100644 index 000000000..42d987a81 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp @@ -0,0 +1,16 @@ +extern "C" void print_msg (const char *msg); + +int +main () +{ +#if defined(__STDC_VERSION__) + // This is true if the code is preprocessed as C code + print_msg ("This is C code"); +#elif __cplusplus == 202002L + // This is true if the code is preprocessed as C++20 code + print_msg ("This is C++20 code"); +#else + print_msg ("This is C++ code"); +#endif + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c b/testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c new file mode 100644 index 000000000..2a2cd1bd8 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c @@ -0,0 +1,5 @@ +void +print_msg (const char *msg) +{ + (void) msg; +} diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/test.py b/testsuite/tests/instr-cov/C++/std-cond-code/test.py new file mode 100644 index 000000000..cc7507009 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-cond-code/test.py @@ -0,0 +1,73 @@ +""" +Check that gnatcov produces valid code when the code needs to be preprocessed +with the right preprocessor configuration. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor + + +def run_variant( + variant_name, + extra_instr_cppargs, + extra_gprbuild_cargs, + tolerate_instrument_messages=None, + pred=lambda: True, + skip_build=False, +): + """ + Build and run the project with the given arguments, and check the predicate + holds. + + :param variant_name: Name of the variant, used as the working dir name. + :param extra_instr_cpp_args: Args passed to gnatcov instrument --c++-opts. + :param extra_gprbuild_cargs: Args passed to gprbuild -cargs. + :param pred: Predicate checked after building and running. + :param skip_build: Whether to skip the build of the instrumented sources. + """ + + tmp = Wdir(f"tmp_{variant_name}") + prj = gprfor(srcdirs=[".."], mains=["main.cpp"], langs=["C", "C++"]) + xcov_instrument( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + extra_args=[f"--c++-opts={','.join(extra_instr_cppargs)}"], + tolerate_messages=tolerate_instrument_messages, + register_failure=False, + ) + + if not skip_build: + gprbuild(prj, extracargs=extra_gprbuild_cargs, trace_mode="src") + + thistest.fail_if( + not pred(), f"Unexpected assertion failure for variant {variant_name}" + ) + + tmp.to_homedir() + + +run_variant( + variant_name="gprbuild-c++20", + extra_instr_cppargs=[], + extra_gprbuild_cargs=["-cargs:C++", "-std=c++20", "-save-temps"], + pred=lambda: "This is C++ code" in contents_of("obj/main.s"), +) +run_variant( + variant_name="instr-c89", + extra_instr_cppargs=["-std=c89"], + extra_gprbuild_cargs=[], + tolerate_instrument_messages="Failed to parse", + pred=lambda: "Failed to parse" in contents_of("instrument.log"), + skip_build=True, +) +run_variant( + variant_name="instr-gprbuild-c++20", + extra_instr_cppargs=["-std=c++20"], + extra_gprbuild_cargs=["-cargs:C++", "-std=c++20", "-save-temps"], + pred=lambda: "This is C++20 code" in contents_of("obj/main.s"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/main.adb b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/main.adb new file mode 100644 index 000000000..07d499161 --- /dev/null +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/main.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +with Pkg_Type_Invariant; use Pkg_Type_Invariant; + +procedure Main is + Dummy_R : Bool_Record := Make_Bool_Record (True); + + function Id (R : Bool_Record) return Bool_Record is (R); + pragma Precondition (Get_Value (R)); + pragma Postcondition (Get_Value (Id'Result)); +begin + Dummy_R := Id (Dummy_R); +end; diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads new file mode 100644 index 000000000..92365d4b7 --- /dev/null +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads @@ -0,0 +1,23 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Pkg_Type_Invariant is + + type Bool_Record is private; + + function Make_Bool_Record (B : Boolean) return Bool_Record; + + function Get_Value (R : Bool_Record) return Boolean; +private + -- Type invariant as pragma + type Bool_Record is + record + B : Boolean := True; + end record; + pragma Type_Invariant (Bool_Record, Check => B); + + function Make_Bool_Record (B : Boolean) return Bool_Record is + ((B => B)); + + function Get_Value (R : Bool_Record) return Boolean is (R.B); +end Pkg_Type_Invariant; diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt new file mode 100644 index 000000000..edd652267 --- /dev/null +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt @@ -0,0 +1,3 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces +5.04a1 DEAD Test contains expression function and Ada_2012 features +7.1.2 DEAD Test contains expression function and Ada_2012 features diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py new file mode 100644 index 000000000..d6f9a9a34 --- /dev/null +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py @@ -0,0 +1,49 @@ +""" +Check that gnatcov behaves properly in the cases where gnatcov cannot +instrument contracts expressed in pragmas: a warning is emitted, the statement +is not instrumented but the rest is. This concerns pre and postconditions and +type invariants. +""" + +from SCOV.minicheck import check_xcov_reports, build_and_run, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + + +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../"], mains=["main.adb"]) + ), + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + covlevel="stmt+decision+atcc", + register_failure=False, +) + +thistest.fail_if_no_match( + "'gnatcov instrument' output", + r".*gnatcov limitation: pragma Precondition ignored.*\n" + + r".*gnatcov limitation: pragma Postcondition ignored.*\n" + + r".*gnatcov limitation: pragma Type_Invariant ignored.*", + contents_of("instrument.log").strip(), +) + +xcov(xcov_args) + +check_xcov_reports( + "xcov", + { + "pkg_type_invariant.ads.xcov": { + "+": {6, 13, 14, 15, 16, 20}, + "-": {22}, + }, + "main.adb.xcov": {"+": {6, 8, 12}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c new file mode 100644 index 000000000..e7ae34c15 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c @@ -0,0 +1,9 @@ +#include "pkg1.h" +#include "pkg2.h" + +int +foo () +{ + int x = bar (); + return x; +} diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h new file mode 100644 index 000000000..7d22617d4 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h @@ -0,0 +1,3 @@ +#include + +extern int foo (); diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c new file mode 100644 index 000000000..9e73ed8dd --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c @@ -0,0 +1,7 @@ +#include + +int +bar () +{ + return 42; +} diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h new file mode 100644 index 000000000..3d2c231a6 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h @@ -0,0 +1 @@ +extern int bar (); diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c new file mode 100644 index 000000000..b895b71b2 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c @@ -0,0 +1,9 @@ +#include "pkg1.h" + +int +main () +{ + int x = foo (); + x += 1; + return 0; +} diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py new file mode 100644 index 000000000..ba68a5552 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py @@ -0,0 +1,67 @@ +""" +Regression testcase: check that the instrumentation of a C source including a +header from a project dependency works. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +def create_lib_gpr(name, deps=None): + """ + Create a gpr file for the library. + + :param name: Name of the library. + """ + + return gprfor( + mains=[], + prjid=name, + srcdirs=f"../src-{name}", + langs=["C"], + deps=deps or [], + extra=f""" + for Library_Name use "{name}"; + for Library_Dir use "{name}"; + """, + ) + + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib1", "lib2"], +) + +# Create the GPR files for the libraries +lib1_gpr = create_lib_gpr("lib1", ["lib2"]) +lib2_gpr = create_lib_gpr("lib2") + +gprsw = GPRswitches(root_project=src_gpr) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {6, 7, 8}}, + "pkg1.c.xcov": {"+": {7, 8}}, + "pkg2.c.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb b/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt new file mode 100644 index 000000000..b2e067acc --- /dev/null +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt @@ -0,0 +1 @@ +aarch64-qnx DEAD Slow IO prevents the test from finishing diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py new file mode 100644 index 000000000..19b0f1af4 --- /dev/null +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py @@ -0,0 +1,52 @@ +""" +Check that "gnatcov extract-base64-trace" handles correctly input files with +very long lines (it used to crash with a stack overflow). +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_trigger="main-end", + dump_channel="base64-stdout", +) + +# Then produce an alternate base64 trace with very long lines +with open("base64_long_lines.txt", "w") as f: + for _ in range(10000): + f.write("A" * 1000) + f.write("\n") + f.write(contents_of("main_output.txt")) + +# Extract the source trace from base64 +xcov( + ["extract-base64-trace", "base64_long_lines.txt", xcov_args[-1]], + out="extract.txt", +) +thistest.fail_if_not_equal( + "'gnatcov extract-base64-trace' output", + "", + contents_of("extract.txt"), +) + +# Produce the coverage report and check its contents +xcov(xcov_args, out="coverage.txt") +thistest.fail_if_not_equal( + "'gnatcov coverage' output", + "", + contents_of("coverage.txt"), +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb new file mode 100644 index 000000000..7f953da17 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; + +package body Bar is + + procedure Msg (M : String) is + begin + Ada.Text_IO.Put_Line (M); -- # msg + end Msg; + + procedure Proc (V : Rec; B : My_Boolean) is + begin + if B -- # cond1 + and not V.Val -- # cond2 + then + Msg("Uh oh"); -- # then + else + Msg("Hooray"); -- # else + end if; + end Proc; + +end Bar; diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads new file mode 100644 index 000000000..04a88f9b6 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Bar is + + type My_Boolean is new Boolean with Convention => C, Object_Size => 8; + + type Rec is record + Val : My_Boolean; + end record; + + procedure Msg (M : String); + procedure Proc (V : Rec; B : My_Boolean); + +end Bar; diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb new file mode 100644 index 000000000..ffd8501ec --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb @@ -0,0 +1,13 @@ +with Bar; use Bar; + +procedure Test_0 is +begin + Msg (""); +end Test_0; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l- ## s- +-- /cond2/ l- ## 0 +-- /then/ l- ## s- +-- /else/ l- ## s- diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb new file mode 100644 index 000000000..4f1def857 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb @@ -0,0 +1,13 @@ +with Bar; use Bar; + +procedure Test_F is +begin + Proc ((Val => True), False); +end Test_F; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l! ## dT- +-- /cond2/ l! ## 0 +-- /then/ l- ## s- +-- /else/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb new file mode 100644 index 000000000..42f785e41 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb @@ -0,0 +1,13 @@ +with Bar; use Bar; + +procedure Test_T is +begin + Proc ((Val => False), True); +end Test_T; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l! ## dF- +-- /cond2/ l! ## 0 +-- /then/ l+ ## 0 +-- /else/ l- ## s- diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb new file mode 100644 index 000000000..9612684e0 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb @@ -0,0 +1,14 @@ +with Bar; use Bar; + +procedure Test_TF is +begin + Proc ((Val => True), True); + Proc ((Val => False), True); +end Test_TF; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l+ ## 0 +-- /cond2/ l+ ## 0 +-- /then/ l+ ## 0 +-- /else/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/ada-derived-bool/test.opt b/testsuite/tests/instr-cov/ada-derived-bool/test.opt new file mode 100644 index 000000000..c41d7f927 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test uses Ada 2012 constructs diff --git a/testsuite/tests/instr-cov/ada-derived-bool/test.py b/testsuite/tests/instr-cov/ada-derived-bool/test.py new file mode 100644 index 000000000..4934f0a5a --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/test.py @@ -0,0 +1,12 @@ +""" +Regression testcase specific to the Ada instrumenter (material and bug report +come from CS0038132): check that gnatcov correctly instruments a decision that +involves a derived boolean type. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/base64_prefix/main1.adb b/testsuite/tests/instr-cov/base64_prefix/main1.adb new file mode 100644 index 000000000..ad381071c --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/main1.adb @@ -0,0 +1,6 @@ +with Pkg; use Pkg; + +procedure Main1 is +begin + Print_Message (Goodbye => False); +end Main1; diff --git a/testsuite/tests/instr-cov/base64_prefix/main2.adb b/testsuite/tests/instr-cov/base64_prefix/main2.adb new file mode 100644 index 000000000..fca526d77 --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/main2.adb @@ -0,0 +1,6 @@ +with Pkg; use Pkg; + +procedure Main2 is +begin + Print_Message (Goodbye => True); +end Main2; diff --git a/testsuite/tests/instr-cov/base64_prefix/pkg.adb b/testsuite/tests/instr-cov/base64_prefix/pkg.adb new file mode 100644 index 000000000..6db039d88 --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/pkg.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + ------------------- + -- Print_Message -- + ------------------- + + procedure Print_Message (Goodbye : Boolean) is + begin + if Goodbye then + Put_Line ("Goodbye!"); + else + Put_Line ("Hello!"); + end if; + end Print_Message; + +end Pkg; diff --git a/testsuite/tests/instr-cov/base64_prefix/pkg.ads b/testsuite/tests/instr-cov/base64_prefix/pkg.ads new file mode 100644 index 000000000..127352e3c --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Print_Message (Goodbye : Boolean); +end Pkg; diff --git a/testsuite/tests/instr-cov/base64_prefix/test.py b/testsuite/tests/instr-cov/base64_prefix/test.py new file mode 100644 index 000000000..69305923e --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/test.py @@ -0,0 +1,99 @@ +""" +Check that "gnatcov extract-base64-trace" can extract trace data from outputs +with arbitrary line prefixes. +""" + +import itertools + +from SCOV.instr import xcov_convert_base64, xcov_instrument +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import exepath_to, gprbuild, gprfor, run_cov_program, xcov + +tmp = Wdir("tmp_") + +# Instrument and build the test project +p = GPRswitches( + root_project=gprfor(srcdirs="..", mains=["main1.adb", "main2.adb"]), + units=["pkg"], +) +xcov_instrument( + gprsw=p, + covlevel="stmt", + dump_trigger="main-end", + dump_channel="base64-stdout", +) +gprbuild(p.root_project, trace_mode="src") + +# Run the two programs, saving their output +mains = ["main1", "main2"] +out_files = [f"{m}_output.txt" for m in mains] + +for main, out_file in zip(mains, out_files): + run_cov_program(exepath_to(main), out=out_file) + +# Expected coverage report for both program executions: +main1_cov = {"pkg.adb.xcov": {"+": {11, 14}, "-": {12}}, "pkg.ads.xcov": {}} +main2_cov = {"pkg.adb.xcov": {"+": {11, 12}, "-": {14}}, "pkg.ads.xcov": {}} + +# Now combine them with different prefixes and check that "gnatcov +# extract-base64-trace" correctly loads the last one. +for label, interleaved_outputs, trailing_output, cov in [ + ("main1_first", out_files, None, main1_cov), + ("main2_first", [out_files[1], out_files[0]], None, main2_cov), + ("main2_trail", [out_files[0]], out_files[1], main2_cov), +]: + thistest.log(f"== {label} ==") + + tracedata_filename = f"{label}_trace_data.txt" + trace_filename = f"{label}.srctrace" + + traces_lines = [] + for i, filename in enumerate(interleaved_outputs): + with open(filename) as f: + traces_lines.append((f"DATA{i}> ", f.readlines())) + + if trailing_output is None: + trailing_lines = [] + else: + with open(trailing_output) as f: + trailing_lines = f.readlines() + + # Interleave all lines to make sure that once gnatcov detects a source + # trace with some prefix, it filters that prefix only until the end of the + # source trace. + with open(tracedata_filename, "w") as f: + for i in itertools.count(0): + had_line = False + for prefix, lines in traces_lines: + if i >= len(lines): + continue + had_line = True + f.write(prefix) + f.write(lines[i]) + if not had_line: + break + + for line in trailing_lines: + f.write("TRAILING> ") + f.write(line) + + # Now run the source trace conversion and create a coverage report from it + xcov_convert_base64(tracedata_filename, trace_filename) + xcov_dir = f"xcov-{label}" + xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--output-dir", + xcov_dir, + trace_filename, + ] + + p.cov_switches + ) + check_xcov_reports(xcov_dir, cov, discard_empty=False) + +thistest.result() diff --git a/testsuite/tests/instr-cov/basic_base64/main.adb b/testsuite/tests/instr-cov/basic_base64/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/basic_base64/pkg.adb b/testsuite/tests/instr-cov/basic_base64/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_base64/pkg.ads b/testsuite/tests/instr-cov/basic_base64/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_base64/test.py b/testsuite/tests/instr-cov/basic_base64/test.py new file mode 100644 index 000000000..99880a5c5 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/test.py @@ -0,0 +1,33 @@ +""" +Test that instrumented source coverage works as expected when using +base64-stdout as the dump channel. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs="..", mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", + dump_channel="base64-stdout", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {5, 6, 8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/basic_decision/main.adb b/testsuite/tests/instr-cov/basic_decision/main.adb new file mode 100644 index 000000000..1f27ba2c3 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + Dummy : constant Integer := Pkg.Fact (0); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/basic_decision/p.gpr b/testsuite/tests/instr-cov/basic_decision/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/basic_decision/pkg.adb b/testsuite/tests/instr-cov/basic_decision/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_decision/pkg.ads b/testsuite/tests/instr-cov/basic_decision/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_decision/test.py b/testsuite/tests/instr-cov/basic_decision/test.py new file mode 100644 index 000000000..b120593f2 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/test.py @@ -0,0 +1,39 @@ +""" +Check that coverage for stmt+decision with source instrumentation works on a +basic project. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6}}, + "pkg.adb.xcov": {"+": {6}, "!": {5}, "-": {8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/basic_stmt/main.adb b/testsuite/tests/instr-cov/basic_stmt/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/basic_stmt/p.gpr b/testsuite/tests/instr-cov/basic_stmt/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/basic_stmt/pkg.adb b/testsuite/tests/instr-cov/basic_stmt/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_stmt/pkg.ads b/testsuite/tests/instr-cov/basic_stmt/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_stmt/test.py b/testsuite/tests/instr-cov/basic_stmt/test.py new file mode 100644 index 000000000..6971047b5 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/test.py @@ -0,0 +1,37 @@ +""" +Test that instrumented source coverage works as expected on a basic scenario. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {5, 6, 8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/bin_file_tunings/main.adb b/testsuite/tests/instr-cov/bin_file_tunings/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/bin_file_tunings/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.opt b/testsuite/tests/instr-cov/bin_file_tunings/test.opt new file mode 100644 index 000000000..57852c494 --- /dev/null +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.opt @@ -0,0 +1,2 @@ +!native DEAD Test specific to source trace binary files directly produced by automatic main instrumentation +RTS_ZFP DEAD Test required bin-file dump channel to be available diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.py b/testsuite/tests/instr-cov/bin_file_tunings/test.py new file mode 100644 index 000000000..e7c22bb40 --- /dev/null +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.py @@ -0,0 +1,128 @@ +""" +Check that the --dump-filename-env-var, --dump-filename-prefix and +--dump-filename-simple options work as expected. +""" + +from dataclasses import dataclass +import glob +import os +from typing import Dict, List + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +@dataclass +class Testcase: + test_name: str + """Name for this testcase.""" + + extra_args: List[str] + """Extra arguments to pass to "gnatcov instrument".""" + + extra_env_vars: Dict[str, str] + """Extra environment variables to pass to the instrumented program.""" + + expected_trace: str + """Glob pattern whose expansion must return exactly one source trace.""" + + +trace_prefix = "main" +if thistest.env.target.os.name == "windows": + trace_prefix += ".exe" + +for tc in [ + # Kind of sanity check: only use defaults, like all other testcases + Testcase("regular", [], {}, f"{trace_prefix}-*.srctrace"), + # Check that with default instrumentation options and + # GNATCOV_TRACE_FILE set to a filename, the trace file is created using + # that filename. + Testcase( + "env_filename", + [], + {"GNATCOV_TRACE_FILE": "foo.srctrace"}, + "foo.srctrace", + ), + # Check that with default instrumentation options and + # GNATCOV_TRACE_FILE set to a directory name, the trace file is created + # with a standard name under that directory. + Testcase( + "env_dir", + [], + {"GNATCOV_TRACE_FILE": "traces-dir/"}, + f"traces-dir/{trace_prefix}-*.srctrace", + ), + # Check that with --dump-filename-env-var, the name of the environment + # variable changes. + Testcase( + "foo_env_1", + ["--dump-filename-env-var=FOO"], + {"GNATCOV_TRACE_FILE": "foo.srctrace"}, + f"{trace_prefix}-*.srctrace", + ), + Testcase( + "foo_env_2", + ["--dump-filename-env-var=FOO"], + {"FOO": "foo.srctrace"}, + "foo.srctrace", + ), + # Check that with --dump-file-name-prefix, the given prefix replaces the + # program basename. + Testcase("prefix", ["--dump-filename-prefix=bar"], {}, "bar-*.srctrace"), + # Check that with --dump-file-name-simple, the produced trace has a + # deterministic name. + Testcase( + "simple", ["--dump-filename-simple"], {}, f"{trace_prefix}.srctrace" + ), +]: + thistest.log(f"==== {tc.test_name} ====") + + wd = Wdir(f"tmp_{tc.test_name}") + os.mkdir("traces-dir") + try: + env = dict(os.environ) + env.update(tc.extra_env_vars) + + xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=tc.extra_args, + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + program_env=env, + # The very goal of this testcase is to produce trace files with + # non-default names. build_and_run cannot deal with them, so skip + # checks here: the computing below are enough to check that the + # expected source trace file was produced. + register_failure=False, + ) + + # Check that we have the expected trace: + traces = glob.glob(tc.expected_trace) + if not traces: + thistest.fail_if( + True, + f"No source trace matched {tc.expected_trace}", + ) + continue + if len(traces) > 1: + thistest.fail_if( + True, + f"Too many source trace matched {tc.expected_trace}:\n" + + "\n".join(f"* {tf}" for tf in traces), + ) + continue + + # Sanity check that expected trace + xcov(xcov_args + traces, out="coverage.log") + check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) + finally: + wd.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/buffer_reset/main_ada.adb b/testsuite/tests/instr-cov/buffer_reset/main_ada.adb new file mode 100644 index 000000000..d51268b1c --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/main_ada.adb @@ -0,0 +1,15 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Main_Ada is +begin + Assert (not Or_Else (False, False)); + pragma Annotate (xcov, Dump_Buffers, "ada-0"); + pragma Annotate (XCov, Reset_Buffers); + Assert (Or_Else (True, False)); + pragma Annotate (xcov, Dump_Buffers, "ada-1"); + pragma Annotate (XCov, Reset_Buffers); + Assert (Or_Else (False, True)); + pragma Annotate (xcov, Dump_Buffers, "ada-2"); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/buffer_reset/main_c.c b/testsuite/tests/instr-cov/buffer_reset/main_c.c new file mode 100644 index 000000000..fe9625da0 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/main_c.c @@ -0,0 +1,17 @@ +#include + +extern bool and_then (bool left, bool right); + +int +main (void) +{ + and_then (true, true); + /* GNATCOV_DUMP_BUFFERS ("c-0") */ + /* GNATCOV_RESET_BUFFERS */ + and_then (true, false); + /* GNATCOV_DUMP_BUFFERS ("c-1") */ + /* GNATCOV_RESET_BUFFERS */ + and_then (false, true); + /* GNATCOV_DUMP_BUFFERS ("c-2") */ + return 0; +} diff --git a/testsuite/tests/instr-cov/buffer_reset/pkg.adb b/testsuite/tests/instr-cov/buffer_reset/pkg.adb new file mode 100644 index 000000000..de46c9e85 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Or_Else (L, R : Boolean) return Boolean is + begin + return L or else R; + end Or_Else; + +end Pkg; diff --git a/testsuite/tests/instr-cov/buffer_reset/pkg.ads b/testsuite/tests/instr-cov/buffer_reset/pkg.ads new file mode 100644 index 000000000..2bedb4461 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Or_Else (L, R : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/buffer_reset/pkh.c b/testsuite/tests/instr-cov/buffer_reset/pkh.c new file mode 100644 index 000000000..016dfffad --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/pkh.c @@ -0,0 +1,7 @@ +#include + +bool +and_then (bool left, bool right) +{ + return left && right; +} diff --git a/testsuite/tests/instr-cov/buffer_reset/test.opt b/testsuite/tests/instr-cov/buffer_reset/test.opt new file mode 100644 index 000000000..83c947030 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD Test specific to src trace feature +!native DEAD Test requires bin-file dump channel diff --git a/testsuite/tests/instr-cov/buffer_reset/test.py b/testsuite/tests/instr-cov/buffer_reset/test.py new file mode 100644 index 000000000..be2244ded --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/test.py @@ -0,0 +1,151 @@ +""" +Test basic functionality of the buffer reset mechanism, in both C and Ada +source files. +""" + +import glob +import re + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +# Map from language to the corresponding main report name, and lines with +# coverage obligations. +main_lines = { + "ada": ("main_ada.adb.xcov", [7, 10, 13]), + "c": ("main_c.c.xcov", [8, 11, 14, 16]), +} + +# Units which will only have a partial coverage result in them, regardless of +# the trace. +default_part_cov = { + "ada": {"pkg.adb.xcov": {"!": {5}}, "pkg.ads.xcov": {}}, + "c": {"pkh.c.xcov": {"!": {6}}}, +} + +# Default "nothing executed" expected result for each unit +default_no_cov = { + "ada": { + "main_ada.adb.xcov": {"-": {7, 10, 13}}, + "pkg.adb.xcov": {"-": {5}}, + "pkg.ads.xcov": {}, + }, + "c": { + "main_c.c.xcov": {"-": {8, 11, 14, 16}}, + "pkh.c.xcov": {"-": {6}}, + }, +} + + +def get_expected_cov(trace_name): + """ + Generate an expected coverage results based on the prefix of the trace + indicating which main was executed, and its index. + """ + match = re.match(pattern=r"(.*)-(\d)\.srctrace", string=trace_name) + thistest.fail_if( + not match, comment="trace name not in expected format: " + trace_name + ) + trace_lang = match.group(1) + idx = int(match.group(2)) + expected_cov = {} + + lines = main_lines[trace_lang][1] + for lang in ("ada", "c"): + if lang == trace_lang: + expected_cov.update( + { + main_lines[lang][0]: { + "+": {lines[idx]}, + "-": {lines[i] for i in range(len(lines)) if i != idx}, + } + } + ) + expected_cov.update(default_part_cov[lang]) + else: + expected_cov.update(default_no_cov[lang]) + return expected_cov + + +def check_one_exec(cov_args, lang): + """ + Find the traces generated by the lang executable, assuming the trace prefix + is lang. Then create a coverage report from each trace, checking the + expected coverage report. + """ + + thistest.log(f"======== Checking {lang} traces =========") + + # We expect the trace to be in the format + # {lang}-{index}.srctrace: + traces = glob.glob(f"{lang}-[0-9].srctrace") + + # There is three dump indications in each main, we should thus have the + # same number of traces. + thistest.fail_if( + len(traces) != 3, comment=f"expected 3 traces, found {len(traces)}" + ) + traces.sort() + + for i in range(len(traces)): + thistest.log(f"-- {i + 1}. --") + output_dir = f"output_{lang}_{i}/" + xcov( + cov_args + [f"--output-dir={output_dir}", traces[i]], + out=f"coverage_{lang}_{i}.log", + ) + check_xcov_reports(output_dir, get_expected_cov(traces[i])) + + +prj_id = "p" + +# Instrument build and run +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid=prj_id, + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + ) + ), + covlevel="stmt+mcdc", + mains=["main_ada", "main_c"], + dump_trigger="manual", + manual_prj_name=prj_id, + extra_coverage_args=["-axcov+"], + extra_instr_args=["--dump-filename-simple"], +) + +# Check the individual trace contents for each executable +for lang in ["c", "ada"]: + check_one_exec(cov_args, lang) + +# Do a consolidated check with all the traces. We expect exactly six traces and +# no coverage violations except for the final return statement in the c main. +thistest.log("========== global consolidated check =========") +all_traces = glob.glob("*.srctrace") +thistest.fail_if( + len(all_traces) != 6, comment=f"expected 6 traces, got {len(all_traces)}" +) +output_dir = "consolidated/" +xcov( + cov_args + [f"--output-dir={output_dir}"] + all_traces, + out="consolidated.log", +) +check_xcov_reports( + output_dir, + { + "main_ada.adb.xcov": {"+": {7, 10, 13}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {8, 11, 14}, "-": {16}}, + "pkh.c.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c-manual-unindented/main.c b/testsuite/tests/instr-cov/c-manual-unindented/main.c new file mode 100644 index 000000000..e184255cb --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/main.c @@ -0,0 +1,11 @@ +extern void stub_puts (const char *); + +/* clang-format off */ +int +main (void) +{ +stub_puts ("Hello world"); +/* GNATCOV_DUMP_BUFFERS */ +return 0; +} +/* clang-format on */ diff --git a/testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c b/testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c new file mode 100644 index 000000000..3c540e6f9 --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c @@ -0,0 +1,5 @@ +void +stub_puts (const char *s) +{ + (void) s; +} diff --git a/testsuite/tests/instr-cov/c-manual-unindented/test.opt b/testsuite/tests/instr-cov/c-manual-unindented/test.opt new file mode 100644 index 000000000..1c9ab5c59 --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to src trace feature diff --git a/testsuite/tests/instr-cov/c-manual-unindented/test.py b/testsuite/tests/instr-cov/c-manual-unindented/test.py new file mode 100644 index 000000000..18f468f94 --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/test.py @@ -0,0 +1,28 @@ +""" +Regression testcase: unindented manual dump/reset directives used to be +incorrectly replaced in instrumented sources due to an off-by-one bug (the +comment opening character used to survive the instrumentation while the rest of +the comment was removed). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(srcdirs=[".."], mains=["main.c"]), units=["main.c"] + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="gen", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_instr_args=["--save-temps"], +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {7}, "-": {9}}}) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c new file mode 100644 index 000000000..9ed5e7f8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c @@ -0,0 +1,11 @@ +#include "message.h" + +void +print_message (const char *str) +{ +} + +void +print_number (const char *str, int n) +{ +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h new file mode 100644 index 000000000..30d6da408 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h @@ -0,0 +1,8 @@ +#ifndef __MESSAGE_H +#define __MESSAGE_H + +void print_message (const char *str); + +void print_number (const char *str, int n); + +#endif // __MESSAGE_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c new file mode 100644 index 000000000..182161aee --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c @@ -0,0 +1,17 @@ +#include "pkg.h" +#include "message.h" + +#define CALL_BAR bar () + +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + print_message ("bar"); // # printf_call +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + CALL_BAR; // # bar_call +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c new file mode 100644 index 000000000..beeb5b999 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.c +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c new file mode 100644 index 000000000..5ca5c8ee8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c @@ -0,0 +1,14 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /.*call/ l- ## s-,c- +// /no-op/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py new file mode 100644 index 000000000..53fe7465b --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works with functions in +macros. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c new file mode 100644 index 000000000..6e984780e --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c @@ -0,0 +1,47 @@ +#include + +// Calls abort after the last chance handler from libsupport. +void __gnat_last_chance_handler (void); + +struct list; + +typedef struct list *(*fct_type) (); + +struct list +{ + struct list *next; + int data; + fct_type get_head; +}; + +static struct list *HEAD = (struct list *) 0; + +struct list * +head_abort () +{ + /* GNATCOV_DUMP_BUFFERS */ + __gnat_last_chance_handler (); // # not-call + return HEAD; // # not-reached +} + +int +main (void) +{ + struct list end = { .next = (struct list *) 0, .data = 1, .get_head = NULL }; + + struct list start = { .next = &end, .data = 1, .get_head = head_abort }; + + HEAD = &start; + + int x = (*HEAD) // # statement + .get_head () // # first_call + ->get_head () // # second_call + ->data; +} + +//# test_abort.c +// /statement/ l+ ## 0 +// /first_call/ l+ ## 0 +// /second_call/ l! ## c- +// /not-reached/ l- ## s- +// /not-call/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt new file mode 100644 index 000000000..ff2263e82 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt @@ -0,0 +1,4 @@ +-- Technically, it could be possible to use exception propagation instead of +-- the exit system call for this test, but this would not help to support this +-- on cross targets. +!native DEAD Tested features requires program abortion diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py new file mode 100644 index 000000000..0952c6194 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py @@ -0,0 +1,13 @@ +""" +Make sure that the instrumentation of calls of a struct member function pointer +is correctly instrumented in C. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True, expect_non_zero_code=True).run( + covcontrol=CovControl(dump_trigger="manual") +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c new file mode 100644 index 000000000..9ed5e7f8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c @@ -0,0 +1,11 @@ +#include "message.h" + +void +print_message (const char *str) +{ +} + +void +print_number (const char *str, int n) +{ +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h new file mode 100644 index 000000000..30d6da408 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h @@ -0,0 +1,8 @@ +#ifndef __MESSAGE_H +#define __MESSAGE_H + +void print_message (const char *str); + +void print_number (const char *str, int n); + +#endif // __MESSAGE_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c new file mode 100644 index 000000000..84034db39 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c @@ -0,0 +1,32 @@ +#include "pkg.h" +#include "message.h" + +int // # add_one_def_1 +add_one (int i) // # add_one_def_2 +{ // # add_one_def_2 + return i + 1; // # return_one +} + +int // # add_two_def_1 +add_two (int i) // # add_two_def_2 +{ // # add_two_def_2 + return i + 2; // # return_two +} + +void // # print_result_def_1 +print_result (int i, fun_type f) // # print_result_def_2 +{ // # print_result_def_2 + print_number ( // # print_call + "Result: %i", // # print_format + f (i) // # fpointer_use + ); // # parenthesis +} + +void // # foo_def_1 +foo (fun_type f) // # foo_def_2 +{ // # foo_def_2 + + print_result (1, // # print_result_call + f // # fpointer_ref + ); // # parenthesis +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h new file mode 100644 index 000000000..7207812b5 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h @@ -0,0 +1,11 @@ +#ifndef _PKG_H +#define _PKG_H + +typedef int (*fun_type) (int); + +int add_one (int i); +int add_two (int i); + +void foo (fun_type); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c new file mode 100644 index 000000000..592ec02d7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c @@ -0,0 +1,13 @@ +#include "pkg.h" + +int +main (void) +{ + foo (add_one); + return 0; +} + +//# pkg.c +// /add_two_def_1/ l- ## f- +// /add_two_def_2/ l- ## 0 +// /return_two/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c new file mode 100644 index 000000000..c9bf9f790 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c @@ -0,0 +1,13 @@ +#include "pkg.h" + +int +main (void) +{ + foo (add_two); + return 0; +} + +//# pkg.c +// /add_one_def_1/ l- ## f- +// /add_one_def_2/ l- ## 0 +// /return_one/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c new file mode 100644 index 000000000..1ae75909d --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c @@ -0,0 +1,18 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /.*call/ l- ## s-,c- +// /no-op/ l- ## s- +// /return_.*/ l- ## s- +// /fpointer_use/ l- ## c- +// /print_format/ l- ## 0 +// /parenthesis/ l- ## 0 +// /fpointer_ref/ l- ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py new file mode 100644 index 000000000..d1c68c5bb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py @@ -0,0 +1,10 @@ +""" +Check that the Fun_Call coverage instrumentation works with functions pointers. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c new file mode 100644 index 000000000..96b364689 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c @@ -0,0 +1,22 @@ +#include "pkg.h" + +int // # add_one_def_1 +add_one (int i) // # add_one_def_2 +{ // # add_one_def_2 + return i + 1; // # return +} + +// Main will be called +int // # foo_def_1 +foo (int i) // # foo_def_2 +{ // # foo_def_2 + int x = // # assignment + add_one ( // # call + add_one ( // # call + add_one ( // # call + add_one ( // # call + add_one (1) // # call + )))); // # parentheses + + return x; // # return +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h new file mode 100644 index 000000000..1d8ddbd96 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +int foo (int i); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c new file mode 100644 index 000000000..65bab67c7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c @@ -0,0 +1,12 @@ +#include "pkg.h" + +int +main (void) +{ + foo (3); + return 0; +} + +//# pkg.c +// /assignment/ l+ ## 0 +// /call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c new file mode 100644 index 000000000..886ba7f5b --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c @@ -0,0 +1,17 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /add_one_def_1/ l- ## f- +// /add_one_def_2/ l- ## 0 +// /foo_def_1/ l- ## f- +// /foo_def_2/ l- ## 0 +// /assignment/ l- ## s- +// /call/ l- ## c- +// /parentheses/ l- ## 0 +// /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py new file mode 100644 index 000000000..f443705a7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for nested functions +calls. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c new file mode 100644 index 000000000..9ed5e7f8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c @@ -0,0 +1,11 @@ +#include "message.h" + +void +print_message (const char *str) +{ +} + +void +print_number (const char *str, int n) +{ +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h new file mode 100644 index 000000000..30d6da408 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h @@ -0,0 +1,8 @@ +#ifndef __MESSAGE_H +#define __MESSAGE_H + +void print_message (const char *str); + +void print_number (const char *str, int n); + +#endif // __MESSAGE_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c new file mode 100644 index 000000000..4a4fbdd60 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c @@ -0,0 +1,36 @@ +#include "pkg.h" +#include "message.h" + +// A forward declaration should not be instrumented for function coverage. +void bar (void); // # bar_decl + +int // # sends_42_def_1 +sends_42 (void) // # sends_42_def_2 +{ // # sends_42_def_2 + + return 42; // # return +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + bar (); // # bar_call + + while (sends_42 ()) // # bar_call + break; // # no-op + + if (sends_42 () == 42) // # bar_call + 0; // # no-op + + for (; sends_42 ();) // # bar_call + break; // # no-op +} + +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + + // call of a function that is not in the same file or compilation unit + print_message ("bar"); // # printf_call +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c new file mode 100644 index 000000000..beeb5b999 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.c +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c new file mode 100644 index 000000000..5ca5c8ee8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c @@ -0,0 +1,14 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /.*call/ l- ## s-,c- +// /no-op/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py new file mode 100644 index 000000000..417b8c9b5 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py @@ -0,0 +1,10 @@ +""" +Check that the Fun_Call coverage instrumentation works for simple C functions. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt new file mode 100644 index 000000000..300e53ef2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt @@ -0,0 +1 @@ +!C++ DEAD test requires a supported C++ compiler diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp new file mode 100644 index 000000000..ec1be9d57 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp @@ -0,0 +1,44 @@ +#include + +struct list; + +typedef struct list *(*fct_type) (); + +struct list +{ + struct list *next; + int data; + fct_type get_head; +}; + +static struct list *HEAD = (struct list *) 0; + +struct list * +head_abort () +{ + /* GNATCOV_DUMP_BUFFERS */ + exit (0); // # not-call + return HEAD; // # not-reached +} + +int +main (void) +{ + struct list end = { .next = (struct list *) 0, .data = 1, .get_head = NULL }; + + struct list start = { .next = &end, .data = 1, .get_head = head_abort }; + + HEAD = &start; + + int x = (*HEAD) // # statement + .get_head () // # first_call + ->get_head () // # second_call + ->data; +} + +//# test_abort.cpp +// /statement/ l+ ## 0 +// /first_call/ l+ ## 0 +// /second_call/ l! ## c- +// /not-reached/ l- ## s- +// /not-call/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt new file mode 100644 index 000000000..ff2263e82 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt @@ -0,0 +1,4 @@ +-- Technically, it could be possible to use exception propagation instead of +-- the exit system call for this test, but this would not help to support this +-- on cross targets. +!native DEAD Tested features requires program abortion diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py new file mode 100644 index 000000000..811552264 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py @@ -0,0 +1,13 @@ +""" +Make sure that the instrumentation of calls of a struct member function pointer +is correctly instrumented in C++. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run( + covcontrol=CovControl(dump_trigger="manual") +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp new file mode 100644 index 000000000..22d95ca93 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp @@ -0,0 +1,19 @@ +#include "pkg.h" + +template void print_point (T p); + +template +void // # print_point_def_1 +print_point (T p) // # print_point_def_2 +{ // # print_point_def_2 + (void) p; // # printing +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + int A = 13; // # var_decl + + print_point (A); // # print_call +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp new file mode 100644 index 000000000..76a9defb6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.cpp +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp new file mode 100644 index 000000000..36c4d7405 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp @@ -0,0 +1,14 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /printing/ l- ## s- +// /var_decl/ l- ## s- +// /print_call/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py new file mode 100644 index 000000000..8cd26a951 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ overloaded +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp new file mode 100644 index 000000000..22b4cea5a --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp @@ -0,0 +1,20 @@ +#include "pkg.h" + +void // # foo_def_1 +foo (int i) // # foo_def_2 +{ // # foo_def_2 + + auto f = // # lambda_assign + [&i] (int x) { // # lambda_def + // # lambda_comment + return x + i; // # lambda_return + }; // # lambda_bracket + + // This should not be instrumented as a call even though under the hood, a + // call to a copy constructor is made for f. + auto f_copy = f; // # assignment + + // A copy of the lambda will cover the lambda for function coverage. + // Also, this call is to be instrumented. + auto y = f_copy (30); // # call_copy +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h new file mode 100644 index 000000000..37f7a1499 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (int i); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp new file mode 100644 index 000000000..3cf8615c6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (4); + return 0; +} + +//# pkg.cpp +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp new file mode 100644 index 000000000..4e2be15e3 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp @@ -0,0 +1,18 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /lambda_assign/ l- ## s- +// /lambda_def/ l- ## f- +// /lambda_comment/ l- ## 0 +// /lambda_return/ l- ## s- +// /lambda_bracket/ l- ## 0 +// /assignment/ l- ## s- +// /call_copy/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py new file mode 100644 index 000000000..8cd26a951 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ overloaded +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp new file mode 100644 index 000000000..362ecb440 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp @@ -0,0 +1,31 @@ +#include "pkg.h" + +class Point2D +{ + int x = 0; + int y = 0; + +public: + Point2D () = default; // # default_ctor_def + Point2D (int x, int y) : x (x), y (y) {}; // # var_ctor_def + + Point2D add (Point2D &other) const; +}; + +Point2D // # point2d_add_def_1 +Point2D::add (Point2D &other) const // # point2d_add_def_2 +{ // # point2d_add_def_2 + + // This calls a constructor + return Point2D (this->x + other.x, this->y + other.y); // # return +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + Point2D A; // # point_a + Point2D B = Point2D (1, 3); // # point_b + + auto sum = A.add (B); // # sum +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp new file mode 100644 index 000000000..172cc279f --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp @@ -0,0 +1,10 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.cpp diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp new file mode 100644 index 000000000..9ae415f1d --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp @@ -0,0 +1,16 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /default_ctor_def/ l. ## 0 +// /var_ctor_def/ l- ## f- +// /return/ l- ## s- +// /point_.*/ l- ## s- +// /sum/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py new file mode 100644 index 000000000..228c2f481 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py @@ -0,0 +1,15 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ classes. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + category=CAT.stmt, + fun_call_lvl=True, + tolerate_messages="cannot instrument constexpr", +).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp new file mode 100644 index 000000000..b2e625f72 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp @@ -0,0 +1,29 @@ +#include "pkg.h" + +namespace sub_module +{ +void hello_world (void); + +void // # hello_def_1 +hello_world (void) // # hello_def_2 +{ // # hello_def_2 + print_msg ("Hello"); // # print +} +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + sub_module:: // # submodule + hello_world (); // # call +} + +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + + using namespace sub_module; // # using_clause + + hello_world (); // # both +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h new file mode 100644 index 000000000..903a1a9b4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h @@ -0,0 +1,12 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); +void bar (void); + +static inline void +print_msg (const char *) +{ +} + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp new file mode 100644 index 000000000..edbb3a442 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +//# pkg.cpp diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp new file mode 100644 index 000000000..ee2ed70c2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp @@ -0,0 +1,15 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /print/ l- ## s-,c- +// /submodule/ l- ## s-,c- +// /call/ l- ## 0 +// /both/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py new file mode 100644 index 000000000..8f48f61cb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py @@ -0,0 +1,10 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ namespaces. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h new file mode 100644 index 000000000..03915b4cb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h @@ -0,0 +1,33 @@ +#pragma once +#include + +class A +{ + int _x; + +public: + A (int x) : _x (x) {}; + + int + get_x () const + { + return this->_x; + } +}; + +class B +{ + A _a; + +public: + B (A a) : _a (a) {}; + + A + get_a () const + { + // Purposely exit early after dumping the buffers. + /* GNATCOV_DUMP_BUFFERS */ + exit (0); + return this->_a; + } +}; diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp new file mode 100644 index 000000000..9508f93c2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp @@ -0,0 +1,19 @@ +#include "pkg.h" + +int +main (void) +{ + A a (5); // # var-decl + B b (a); // # var-decl + + // .get_a() exits the program with 0 status code. + b // # var-ref + .get_a (); // # method-call + + // Program should not reach this point. +} + +//# test_exiting_method.cpp +// /var-decl/ l+ ## 0 +// /var-ref/ l+ ## 0 +// /method-call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp new file mode 100644 index 000000000..8b0308653 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp @@ -0,0 +1,21 @@ +#include "pkg.h" + +int +main (void) +{ + A a (5); // # var-decl + B b (a); // # var-decl + + // .get_a() exits the program with 0 status code. + b // # var-ref + .get_a () // # method-call + .get_x (); // # not-reached + + /* GNATCOV_DUMP_BUFFERS */ +} + +//# test_shortcut_method_chain.cpp +// /var-decl/ l+ ## 0 +// /var-ref/ l+ ## 0 +// /method-call/ l+ ## 0 +// /not-reached/ l! ## c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp new file mode 100644 index 000000000..0dc5ffed4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp @@ -0,0 +1,17 @@ +#include "pkg.h" + +int +main (void) +{ + A a (5); // # var-decl + + a // # var-ref + .get_x (); // # method-call + + /* GNATCOV_DUMP_BUFFERS */ +} + +//# test_simple_call.cpp +// /var-decl/ l+ ## 0 +// /var-ref/ l+ ## 0 +// /method-call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt new file mode 100644 index 000000000..ff2263e82 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt @@ -0,0 +1,4 @@ +-- Technically, it could be possible to use exception propagation instead of +-- the exit system call for this test, but this would not help to support this +-- on cross targets. +!native DEAD Tested features requires program abortion diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py new file mode 100644 index 000000000..d72409884 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py @@ -0,0 +1,13 @@ +""" +This test ensures that method call instrumentation behaves correctly and +produces the expected coverage. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run( + covcontrol=CovControl(dump_trigger="manual") +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp new file mode 100644 index 000000000..1a7cc4801 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp @@ -0,0 +1,29 @@ +class A +{ + int _x; + +public: + A (int x) : _x (x) {}; + + int + get_x () const + { + return this->_x; + } + + int + get_x_plus_one () const + { + return get_x () + 1; // # non-prefix-call + } +}; + +int +main (void) +{ + A (5).get_x_plus_one (); // # method-call +} + +//# test_non_prefix.cpp +// /non-prefix-call/ l+ ## 0 +// /method-call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py new file mode 100644 index 000000000..aa54dd7e8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py @@ -0,0 +1,11 @@ +""" +This test makes sure that the instrumentation of non-prefixed method calls +works correctly. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp new file mode 100644 index 000000000..fdb5a534c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp @@ -0,0 +1,19 @@ +#include "pkg.h" + +bool // # operator_def_1 +operator|| (My_Bool L, My_Bool R) // # operator_def_2 +{ // # operator_def_2 + return L == My_Bool::True || R == My_Bool::True; // # return +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + auto A = My_Bool::True; // # var_decl + auto B = My_Bool::False; // # var_decl + + auto res = // # assignment + A || B // # or_my_bool + || false; // # or_std_bool +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h new file mode 100644 index 000000000..fe596595a --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h @@ -0,0 +1,15 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +enum My_Bool +{ + True, + False, +}; + +// Overload the comma operator +bool operator|| (My_Bool L, My_Bool R); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp new file mode 100644 index 000000000..76a9defb6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.cpp +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp new file mode 100644 index 000000000..123c68147 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp @@ -0,0 +1,16 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /return/ l- ## s- +// /var_decl/ l- ## s- +// /assignment/ l- ## s- +// /or_my_bool/ l- ## c- +// /or_std_bool/ l- ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py new file mode 100644 index 000000000..8cd26a951 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ overloaded +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt new file mode 100644 index 000000000..a9490dec8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Function and call coverage not supported for binary traces diff --git a/testsuite/tests/instr-cov/c_custom_naming/hello.cc b/testsuite/tests/instr-cov/c_custom_naming/hello.cc new file mode 100644 index 000000000..62afcdf8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/hello.cc @@ -0,0 +1,7 @@ +extern void dummy_putf (const char *fmt, ...); + +void +hello (const char *who) +{ + dummy_putf ("Hello %s\n", who); +} diff --git a/testsuite/tests/instr-cov/c_custom_naming/main.cc b/testsuite/tests/instr-cov/c_custom_naming/main.cc new file mode 100644 index 000000000..212dc502d --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/main.cc @@ -0,0 +1,13 @@ +extern void hello (const char *who); + +void +dummy_putf (const char *fmt, ...) +{ +} + +int +main (void) +{ + hello ("world"); + return 0; +} diff --git a/testsuite/tests/instr-cov/c_custom_naming/test.opt b/testsuite/tests/instr-cov/c_custom_naming/test.opt new file mode 100644 index 000000000..300e53ef2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/test.opt @@ -0,0 +1 @@ +!C++ DEAD test requires a supported C++ compiler diff --git a/testsuite/tests/instr-cov/c_custom_naming/test.py b/testsuite/tests/instr-cov/c_custom_naming/test.py new file mode 100644 index 000000000..1bed00933 --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/test.py @@ -0,0 +1,46 @@ +""" +Check that custom naming conventions for file-based languages are properly +handled. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + # gprfor assumes standard naming convention for mains, so we must + # control the mains manually. + root_project=gprfor( + srcdirs=[".."], + mains=[], + langs=["C++"], + extra=""" + for Main use ("main.cc"); + package Naming is + for Body_Suffix ("C++") use ".cc"; + for Spec_Suffix ("C++") use ".hh"; + end Naming; + """, + ), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", + { + "main.cc.xcov": {"+": {11, 12}}, + "hello.cc.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_empty_main/src/test_main.c b/testsuite/tests/instr-cov/c_empty_main/src/test_main.c new file mode 100644 index 000000000..3c521eeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_main/src/test_main.c @@ -0,0 +1,7 @@ +int +main () +{ + // Empty main should not make gnatcov instrument crash +} + +//# test_main.c diff --git a/testsuite/tests/instr-cov/c_empty_main/test.py b/testsuite/tests/instr-cov/c_empty_main/test.py new file mode 100644 index 000000000..1b0063e7f --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_main/test.py @@ -0,0 +1,12 @@ +""" +Regression testcase: checks that gnatcov does not crash when the main that is +to be instrumented for the dump instruction is an empty function (i.e. it +has no statement to insert an instruction before). +""" + +from SCOV.tc import TestCase, CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_empty_source/main.c b/testsuite/tests/instr-cov/c_empty_source/main.c new file mode 100644 index 000000000..1d28fd918 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/main.c @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/c_empty_source/pkg.c b/testsuite/tests/instr-cov/c_empty_source/pkg.c new file mode 100644 index 000000000..59db5edf9 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/pkg.c @@ -0,0 +1,7 @@ +#ifdef UNDEFINED_MACRO +int +foo () +{ + return 0; +} +#endif diff --git a/testsuite/tests/instr-cov/c_empty_source/pkg.h b/testsuite/tests/instr-cov/c_empty_source/pkg.h new file mode 100644 index 000000000..ee9b424fe --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/pkg.h @@ -0,0 +1,3 @@ +#ifdef UNDEFINED_MACRO +int foo (); +#endif diff --git a/testsuite/tests/instr-cov/c_empty_source/test.py b/testsuite/tests/instr-cov/c_empty_source/test.py new file mode 100644 index 000000000..9b2196d8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/test.py @@ -0,0 +1,28 @@ +""" +Regression testcase: checks that gnatcov does not crash when one of the sources +of interest is empty. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", {"main.c.xcov": {"+": {6}}, "pkg.c.xcov": {}}, discard_empty=False +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_header/fact.h b/testsuite/tests/instr-cov/c_header/fact.h new file mode 100644 index 000000000..4cbc8f9a4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_header/fact.h @@ -0,0 +1,8 @@ +static int +fact (int n) +{ + if (n <= 1) + return 1; + else + return n * fact (n - 1); +} diff --git a/testsuite/tests/instr-cov/c_header/main.c b/testsuite/tests/instr-cov/c_header/main.c new file mode 100644 index 000000000..8daba19a4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_header/main.c @@ -0,0 +1,8 @@ +#include "fact.h" + +int +main (void) +{ + int dummy = fact (6); + return 0; +} diff --git a/testsuite/tests/instr-cov/c_header/test.py b/testsuite/tests/instr-cov/c_header/test.py new file mode 100644 index 000000000..0cf4b81cc --- /dev/null +++ b/testsuite/tests/instr-cov/c_header/test.py @@ -0,0 +1,41 @@ +""" +Check that the instrumentation of a C project does not instrument the header +files: we only instrument the code in header files once it has been included in +a ".c" file *when* we instrument that ".c" file. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.c.xcov": {"+": {6, 7}}, + "fact.h.xcov": {"+": {4, 5, 7}}, + }, +) + +# Check that the header file is not instrumented +instr_header = os.path.join("obj", "gen-gnatcov-instr", "fact.h") +thistest.fail_if( + os.path.isfile(instr_header), + f"Found spurious {instr_header} file", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c new file mode 100644 index 000000000..1e5067822 --- /dev/null +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c @@ -0,0 +1,4 @@ +void +print_str (const char *str) +{ +} diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c new file mode 100644 index 000000000..4fcecf768 --- /dev/null +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c @@ -0,0 +1,12 @@ +#include + +extern void print_str (const char *str); + +#define PRINT_HW print_str ("Hello world!\n"); + +int +main (void) +{ + PRINT_HW; + return 0; +} diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py new file mode 100644 index 000000000..caa1d9367 --- /dev/null +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py @@ -0,0 +1,28 @@ +""" +Check that we have no warnings at coverage time for a format report that +needs to preprocess the file, to emit macro reporting. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axml"], + trace_mode="src", +) + +# Check that gnatcov coverage did not raise any warning +thistest.fail_if_not_equal( + "gnatcov coverage output", "", contents_of("coverage.log") +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_metaprog/main.c b/testsuite/tests/instr-cov/c_metaprog/main.c new file mode 100644 index 000000000..3792c88b9 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/main.c @@ -0,0 +1,8 @@ +int +main () +{ + int a = 0; +#define DECISION 1 +#include "meta_inc.h" + return 0; +} diff --git a/testsuite/tests/instr-cov/c_metaprog/meta_inc.h b/testsuite/tests/instr-cov/c_metaprog/meta_inc.h new file mode 100644 index 000000000..06588cca4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/meta_inc.h @@ -0,0 +1,4 @@ +#ifdef DECISION +if (DECISION) + a++; +#endif diff --git a/testsuite/tests/instr-cov/c_metaprog/test.opt b/testsuite/tests/instr-cov/c_metaprog/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/c_metaprog/test.py b/testsuite/tests/instr-cov/c_metaprog/test.py new file mode 100644 index 000000000..ffe8accc4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/test.py @@ -0,0 +1,27 @@ +""" +Checks that gnatcov does not instrument decisions in sources of interest whose +parent statement does not belong to a source of interest. This can happen with +metaprogramming instances in C/C++. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt+decision", + mains=["main"], + extra_instr_args=["--ignore-source-files=meta_inc.h"], + extra_coverage_args=["-axcov"], + trace_mode="src", +) + +check_xcov_reports("obj", {"main.c.xcov": {"+": {4, 7}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/main.c b/testsuite/tests/instr-cov/c_multiline_stmt/main.c new file mode 100644 index 000000000..b44ee29eb --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/main.c @@ -0,0 +1,35 @@ +#include "pkg.h" + +int +id (int x) +{ + return x; +} + +int +main () +{ + int x = 2, i; + + // Check do-while statement. A closing brace should be inserted before the + // while. + do + x++ + // dumb-token + ; + while (x < 2); + + // Check nested if-else statements. For each un-braced control flow stmt, + // a closing brace should be inserted before the next statement, or before + // the else / while if the control flow stmt is featured in a then part / a + // do body respectively. + if (id (x) != x) + for (i = 0; i++; i < 10) + return 0 + // dumb-token + ; + else if (foo ()) + return 0 + // dumb-token + ; +} diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/pkg.c b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.c new file mode 100644 index 000000000..414317712 --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 1; +} diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/pkg.h b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.opt b/testsuite/tests/instr-cov/c_multiline_stmt/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.py b/testsuite/tests/instr-cov/c_multiline_stmt/test.py new file mode 100644 index 000000000..4e077e934 --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.py @@ -0,0 +1,72 @@ +""" +Regression testcase: checks that gnatcov can correctly instrument a statement +body of a control flow statement, when it spans on several lines and has at +least one token separating the statement expression and the terminating +semicolon, e.g. + + if + + // dumb-token + ; + +should be instrumented as + + if () + { + + // dumb-token + ; + } + +gnatcov used to insert the closing brace before the terminating semicolon. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_with_main") + +# Check when the main is a unit of interest +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", + { + "main.c.xcov": {"+": {6, 12, 17, 26, 31, 32}, "-": {27, 28}}, + "pkg.c.xcov": {"+": {4}}, + }, +) + +tmp.to_homedir() +tmp = Wdir("tmp_without_main") + +# Also check when the main needs to be instrumented to dump the buffers with +# main-end but is not a unit of interest. We used to surround the return +# statement with braces, as we needed to declare a variable holding the return +# expression beforehand. This variable is now declared at the beginning of the +# main. +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.c"]), + units=["pkg.c"], + ), + covlevel="stmt", + mains=["main"], + dump_trigger="main-end", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_no_return/empty_main/main.c b/testsuite/tests/instr-cov/c_no_return/empty_main/main.c new file mode 100644 index 000000000..70b41462b --- /dev/null +++ b/testsuite/tests/instr-cov/c_no_return/empty_main/main.c @@ -0,0 +1,4 @@ +int +main () +{ +} diff --git a/testsuite/tests/instr-cov/c_no_return/no_return/main.c b/testsuite/tests/instr-cov/c_no_return/no_return/main.c new file mode 100644 index 000000000..e8241104d --- /dev/null +++ b/testsuite/tests/instr-cov/c_no_return/no_return/main.c @@ -0,0 +1,15 @@ +int +fact (int a) +{ + if (a == 1) + return 1; + return a * fact (a - 1); +} + +int +main (void) +{ + int dummy = fact (6); + if (!dummy) + return 0; +} diff --git a/testsuite/tests/instr-cov/c_no_return/test.py b/testsuite/tests/instr-cov/c_no_return/test.py new file mode 100644 index 000000000..a619e4867 --- /dev/null +++ b/testsuite/tests/instr-cov/c_no_return/test.py @@ -0,0 +1,53 @@ +""" +Check that gnatcov always insert a call to dump buffers, even when the main +does not end with a return statement, when the dump-trigger is main-end. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp_no_return = Wdir("tmp_no_return") + +# Check when the main function does not exit through a return +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[os.path.join("..", "no_return")], mains=["main.c"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", + # With older toolchains, a missing return results in an arbitrary exit + # code, so let's ignore failures. + register_failure=False, +) +check_xcov_reports( + "xcov", {"main.c.xcov": {"+": {4, 5, 6, 12, 13}, "-": {14}}} +) + +tmp_no_return.to_homedir() +tmp = Wdir("tmp_empty_main") + +# Check that we have a source trace even if the main is empty +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[os.path.join("..", "empty_main")], mains=["main.c"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_opts/hello.c b/testsuite/tests/instr-cov/c_opts/hello.c new file mode 100644 index 000000000..677b9f6e6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/hello.c @@ -0,0 +1,4 @@ +void +hello (const char *who) +{ +} diff --git a/testsuite/tests/instr-cov/c_opts/main.c b/testsuite/tests/instr-cov/c_opts/main.c new file mode 100644 index 000000000..6e296318a --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/main.c @@ -0,0 +1,15 @@ +#include "hello.h" + +int +main (void) +{ +#ifdef A + hello ("A"); +#endif + +#ifdef B + hello ("B"); +#endif + + return 0; +} diff --git a/testsuite/tests/instr-cov/c_opts/other/hello.h b/testsuite/tests/instr-cov/c_opts/other/hello.h new file mode 100644 index 000000000..d4370d4a9 --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/other/hello.h @@ -0,0 +1 @@ +extern void hello (const char *who); diff --git a/testsuite/tests/instr-cov/c_opts/test.py b/testsuite/tests/instr-cov/c_opts/test.py new file mode 100644 index 000000000..d503e52b6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/test.py @@ -0,0 +1,52 @@ +""" +Check that --c-opts option for "gnatcov instrument" works as expected. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +other_dir = os.path.abspath("other") +tmp = Wdir("tmp_") + +c_opts = [ + # Without these arguments, "hello.h" cannot be imported, and the A macro is + # not defined. Exercize the various forms for these arguments: -XA, -X A). + # Also add these as two "--c-opts" arguments. + ["-DA", "-D", "B", "-UB"], + ["-I", other_dir], + # Check the processing of backslashes + ["-DBACKSLASH=\\"], + ["-DDOUBLE_BACKSLASH=\\\\"], + ["-DCOMMA=\\,"], +] + +log_file = "instrument.log" +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.c"]), + units=["main.c"], + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=( + ["--c-opts={}".format(",".join(args)) for args in c_opts] + ["-v"] + ), + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +for excerpt in ["-DBACKSLASH=\\", "-DDOUBLE_BACKSLASH=\\", "-DCOMMA=,"]: + thistest.fail_if( + excerpt not in contents_of(log_file), + f"{excerpt} macro definition not found in {log_file}", + ) + +check_xcov_reports("xcov", {"main.c.xcov": {"+": {7, 14}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_prep_error/main.c b/testsuite/tests/instr-cov/c_prep_error/main.c new file mode 100644 index 000000000..3929d095e --- /dev/null +++ b/testsuite/tests/instr-cov/c_prep_error/main.c @@ -0,0 +1,7 @@ +#include "foo.hh" + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/c_prep_error/test.py b/testsuite/tests/instr-cov/c_prep_error/test.py new file mode 100644 index 000000000..2c8a3338b --- /dev/null +++ b/testsuite/tests/instr-cov/c_prep_error/test.py @@ -0,0 +1,34 @@ +""" +Check that C/C++ preprocessing failures are properly reported. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +log_file = "instr.txt" +p = xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + out=log_file, + register_failure=False, +) + +# Make sure that preprocessing fails with exit code 1, that the output mentions +# the missing file (the bit that is useful to users in order to understand what +# went wrong), plus the "abort" message. + +thistest.fail_if_not_equal("'gnatcov instrument' exit code", 1, p.status) + +log = contents_of(log_file) +for excerpt in ["foo.hh", "Preprocessing failed: aborting"]: + thistest.fail_if( + excerpt not in log, f"Missing excerpt in {log_file}: {repr(excerpt)}" + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb b/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb new file mode 100644 index 000000000..468fc16f4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb @@ -0,0 +1,13 @@ +with Interfaces.C; use Interfaces.C; + +procedure Ada_Main is + function Foo (I : int) return int; + pragma Import (C, Foo, "foo"); + + function Bar (A, B, C : int) return int; + pragma Import (C, Bar, "bar"); + + I : constant int := Foo (1) + Bar (1, 0, 2); +begin + null; +end Ada_Main; diff --git a/testsuite/tests/instr-cov/c_special_filenames/bar.c b/testsuite/tests/instr-cov/c_special_filenames/bar.c new file mode 100644 index 000000000..088001447 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/bar.c @@ -0,0 +1,8 @@ +int +bar (int a, int b, int c) +{ + if (a) + return b; + else + return c; +} diff --git a/testsuite/tests/instr-cov/c_special_filenames/foo.c b/testsuite/tests/instr-cov/c_special_filenames/foo.c new file mode 100644 index 000000000..82907e5e7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/foo.c @@ -0,0 +1,5 @@ +int +foo (int i) +{ + return 2 * i; +} diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.py b/testsuite/tests/instr-cov/c_special_filenames/test.py new file mode 100644 index 000000000..846032457 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/test.py @@ -0,0 +1,58 @@ +""" +Test that the instrumentation of C sources with filenames that contain uncommon +characters produces valid instrumented sources. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Copy the sources in the temporary directory. Note that we cannot test the +# case of a filename containing a double quote or a backslash on Windows +# because of filename restrictions on that platform. +copy_map = { + "ada_main.adb": "ada_main.adb", + "bar.c": "src bar.c" if env.build.os.name == "windows" else 'src\\"bar.c', + "foo.c": "src foo$@.c", +} +for src, dest in copy_map.items(): + cp(os.path.join("..", src), dest) + +# Compute the expected coverage report from the actual source filenames. Note +# that in xcov filenames, "gnatcov coverage" first turns '\' to '/' (during +# path separator canonicalization) and then the unique filename machinery turns +# '/' to '-'. +coverage_data = { + "ada_main.adb": {"+": {10, 12}}, + "bar.c": {"+": {4, 5}, "-": {7}}, + "foo.c": {"+": {4}}, +} +expected_report = { + "{}.xcov".format(copy_map[filename].replace("\\", "-")): report + for filename, report in coverage_data.items() +} + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=["."], mains=["ada_main.adb"], langs=["Ada", "C"] + ) + ), + covlevel="stmt", + mains=["ada_main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports("xcov", expected_report) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c b/testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c new file mode 100644 index 000000000..a8dea3024 --- /dev/null +++ b/testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c @@ -0,0 +1,10 @@ +int +main () +{ + int i = 0; + if (i ? 0 : 1) + { + return 0; + } + return 0; +} diff --git a/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py new file mode 100644 index 000000000..0ce0542d4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py @@ -0,0 +1,25 @@ +""" +Check that the instrumentation of a decision whose condition is a ternary +expression works. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4, 5, 7}, "-": {9}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_wrong_main/main.c b/testsuite/tests/instr-cov/c_wrong_main/main.c new file mode 100644 index 000000000..5fe6f506f --- /dev/null +++ b/testsuite/tests/instr-cov/c_wrong_main/main.c @@ -0,0 +1,5 @@ +int +not_a_main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/c_wrong_main/test.py b/testsuite/tests/instr-cov/c_wrong_main/test.py new file mode 100644 index 000000000..045643742 --- /dev/null +++ b/testsuite/tests/instr-cov/c_wrong_main/test.py @@ -0,0 +1,32 @@ +""" +Check that gnatcov emits a fatal error when a main file does not contain the +main program. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Create object directory to avoid GPR warning +mkdir("obj") + +p = xcov_instrument( + GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + register_failure=False, +) +thistest.fail_if_not_equal("gnatcov instrument status code", 1, p.status) +thistest.fail_if_no_match( + "gnatcov instrument output", + ".*gnatcov.*: Could not find main function in main.c", + contents_of("instrument.log").strip(), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/checks_and_warnings/main.adb b/testsuite/tests/instr-cov/checks_and_warnings/main.adb new file mode 100644 index 000000000..cc02a39d8 --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/main.adb @@ -0,0 +1,16 @@ +with Pkg; + +procedure Main is + pragma Warnings (On); + pragma Warnings ("a"); + pragma Style_Checks (On); + pragma Style_Checks ("yg"); + + -- The insertion of the witness call will make the following like exceed + -- the 80 characters limit. Also, S is an unused variable, GNAT will warn + -- about it. + + S : String := "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; +begin + Pkg.P; +end Main; diff --git a/testsuite/tests/instr-cov/checks_and_warnings/p.gpr b/testsuite/tests/instr-cov/checks_and_warnings/p.gpr new file mode 100644 index 000000000..a37807ae5 --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/p.gpr @@ -0,0 +1,8 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Compiler is + for Default_Switches ("Ada") use ("-gnatwae", "-gnatyg"); + end Compiler; +end P; diff --git a/testsuite/tests/instr-cov/checks_and_warnings/pkg.ads b/testsuite/tests/instr-cov/checks_and_warnings/pkg.ads new file mode 100644 index 000000000..39bfceb1a --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/pkg.ads @@ -0,0 +1,23 @@ +package Pkg is + procedure P is null; + -- This test checks that no style warnings are issued when compiling + -- instrumented sources. + -- As a reminder, each instrumented unit has an associated buffer + -- unit (defining the buffers and exporting them as symbols), and a + -- pure buffer unit (defining pointers to coverage buffers and + -- importing the definition symbols). The pure buffer unit is imported + -- into the instrumented unit and the buffers declared in this unit are + -- used for coverage analysis. These generated buffer units do not + -- respect any style conventions, just like instrumented files. + -- + -- Sometimes, gnatcov also needs to generate additional code, to + -- support specific language constructions, such as null procedures. + -- In this case, additional code will be generated in the pure buffer + -- unit body (otherwise, there will be no body for this unit, only a + -- spec, as no actual code is required), as it is the unit imported by + -- the instrumented file. + -- As this testcase should exercise all different kinds of files + -- generated by gnatcov (instrumented files, buffers spec / body), + -- it also exercises this corner case. This explains the null procedure + -- here. +end Pkg; diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.opt b/testsuite/tests/instr-cov/checks_and_warnings/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.py b/testsuite/tests/instr-cov/checks_and_warnings/test.py new file mode 100644 index 000000000..4077a171f --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.py @@ -0,0 +1,40 @@ +""" +Test that style check issues and warnings are properly disabled in instrumented +sources. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + extra_gprbuild_args=["-q"], + extra_gprbuild_cargs=["-gnatwae"], + check_gprbuild_output=True, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {13}}, + "pkg.ads.xcov": {"+": {2}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c b/testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py new file mode 100644 index 000000000..c1b1e1ded --- /dev/null +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py @@ -0,0 +1,28 @@ +""" +Regression test: gnatcov used to produce spurious coverage obligations for code +coming from self-referencing macros defined on the command line, as it was +expanding them another time when parsing the file. This led to warnings at +instrumentation time, and wrong coverage expectations. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c-opts=-Dreturn=int a; return"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/compile_time_pragma/main.adb b/testsuite/tests/instr-cov/compile_time_pragma/main.adb new file mode 100644 index 000000000..1b7eed195 --- /dev/null +++ b/testsuite/tests/instr-cov/compile_time_pragma/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + pragma Compile_Time_Error + (Boolean'Size /= 1 or else Integer'Size < 2, "Dummy error check"); + pragma Compile_Time_Warning (Character'Size /= 8, "Dummy warning check"); + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/compile_time_pragma/test.py b/testsuite/tests/instr-cov/compile_time_pragma/test.py new file mode 100644 index 000000000..c254bc150 --- /dev/null +++ b/testsuite/tests/instr-cov/compile_time_pragma/test.py @@ -0,0 +1,22 @@ +""" +Check that the decision/conditions of Compile_Time_Error pragmas are not +instrumented. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {8}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp new file mode 100644 index 000000000..17dd56060 --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp @@ -0,0 +1,17 @@ +#ifndef A +#error +#endif + +#ifndef B +#error +#endif + +#ifdef C +#error +#endif + +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c new file mode 100644 index 000000000..17dd56060 --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c @@ -0,0 +1,17 @@ +#ifndef A +#error +#endif + +#ifndef B +#error +#endif + +#ifdef C +#error +#endif + +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt new file mode 100644 index 000000000..ee85ccc4c --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt @@ -0,0 +1 @@ +!C++ DEAD Test requires a C++ compiler diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py new file mode 100644 index 000000000..ce87cfaf7 --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py @@ -0,0 +1,66 @@ +""" +Check that compiler switches are properly imported from project files. +GNATcoverage used to ignore Compiler.Switches when it was used to specify +language specific compiler switches. +""" + +from SCOV.minicheck import xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +# Some automatic dump triggers (ravenscar-task-termination) are not available +# for all languages: instrumenting a C/C++ project with the default dump +# trigger in some configurations yields a warning. Explicitly ask for a dump +# trigger that is always supported to avoid this warning. +xcov_args = ["instrument", "--level=stmt", "--dump-trigger=main-end"] + + +def check_lang(lang, file_ext): + def gprfor_wrapper(prjid, compiler_extra): + return gprfor( + prjid=prjid, + srcdirs=[f"../src-{lang}"], + mains=[f"main.{file_ext}"], + compiler_extra=compiler_extra, + ) + + # Check using the Compiler.Default_Switches attribute for language specific + # compiler switches. + prj_lds = gprfor_wrapper( + prjid=f"lang_default_switches_{file_ext}", + compiler_extra=f""" + for Default_Switches ("{lang}") use ("-DA", "-DB"); + """, + ) + xcov(xcov_args + ["-P", prj_lds]) + + # Check using the Compiler.Switches attribute for language specific + # compiler switches. + prj_ls = gprfor_wrapper( + prjid=f"lang_switches_{file_ext}", + compiler_extra=f""" + for Switches ("{lang}") use ("-DA", "-DB"); + """, + ) + xcov(xcov_args + ["-P", prj_ls]) + + # Check using the Compiler.Switches attribute both for file specific + # compiler switches. + prj_fs = gprfor_wrapper( + prjid=f"file_switches_{file_ext}", + compiler_extra=f""" + for Default_Switches ("{lang}") use ("-DC"); + for Switches ("{lang}") use ("-DC"); + for Switches ("main.{file_ext}") use ("-DA", "-DB"); + """, + ) + xcov(xcov_args + ["-P", prj_fs]) + + +check_lang("c", "c") +check_lang("c++", "cpp") + +thistest.result() diff --git a/testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr b/testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr new file mode 100644 index 000000000..bcec9f048 --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr @@ -0,0 +1,7 @@ +library project GNATcov_RTS_Custom extends "gnatcov_rts.gpr" is + for Object_Dir use "obj"; + for Library_Dir use "lib"; + for Library_Name use "gnatcov_rts_custom"; + for Library_Kind use "static"; + for Toolchain_Name ("C") use "MY_GCC"; +end GNATcov_RTS_Custom; diff --git a/testsuite/tests/instr-cov/config_custom_db/main.c b/testsuite/tests/instr-cov/config_custom_db/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml b/testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml new file mode 100644 index 000000000..d94d03d76 --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml @@ -0,0 +1,23 @@ + + + + MY_GCC + gcc + 1.0 + C + + + + + + + + package Compiler is + for Driver ("C") use "gcc"; + for Leading_Required_Switches ("C") use + ("-c", "-x", "c") & Compiler'Leading_Required_Switches ("C"); + for Include_Switches ("C") use ("-I"); + end Compiler; + + + diff --git a/testsuite/tests/instr-cov/config_custom_db/test.opt b/testsuite/tests/instr-cov/config_custom_db/test.opt new file mode 100644 index 000000000..c4b86c03f --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/test.opt @@ -0,0 +1 @@ +!native DEAD Checks support for a custom toolchain only defined natively diff --git a/testsuite/tests/instr-cov/config_custom_db/test.py b/testsuite/tests/instr-cov/config_custom_db/test.py new file mode 100644 index 000000000..1263df9dc --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/test.py @@ -0,0 +1,45 @@ +""" +Check that gnatcov setup / instrument support custom toolchain definitions that +are passed through the --db command line option. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +prj = gprfor( + mains=["main.c"], + srcdirs=[".."], + extra='for Toolchain_Name ("C") use "MY_GCC";', +) +db_args = ["--db", "../my_config"] + +# Setup with our custom toolchain +xcov( + ["setup", "--prefix=install"] + + db_args + + ["../gnatcov-rt-custom/gnatcov_rts_custom.gpr"], + register_failure=True, + auto_config_args=False, + force_project_args=True, +) +env.add_search_path("GPR_PROJECT_PATH", "install/share/gpr") +build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt", + mains=["main"], + extra_args=db_args, + extra_gprbuild_args=db_args, + extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_instr_args=["--runtime-project", "gnatcov_rts_custom"], + auto_config_args=False, +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/config_pragmas/gnat.adc b/testsuite/tests/instr-cov/config_pragmas/gnat.adc new file mode 100644 index 000000000..20d438eb6 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/gnat.adc @@ -0,0 +1 @@ +pragma Restrictions (Simple_Barriers); diff --git a/testsuite/tests/instr-cov/config_pragmas/main.adb b/testsuite/tests/instr-cov/config_pragmas/main.adb new file mode 100644 index 000000000..48561e121 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/main.adb @@ -0,0 +1,12 @@ +with Pkg; + +procedure Main is + T : Pkg.PT; +begin + T.Init (False); + select + T.Wait_Cond; + else + null; + end select; +end Main; diff --git a/testsuite/tests/instr-cov/config_pragmas/pkg.adb b/testsuite/tests/instr-cov/config_pragmas/pkg.adb new file mode 100644 index 000000000..f94440633 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/pkg.adb @@ -0,0 +1,27 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + protected body PT is + + ---------- + -- Init -- + ---------- + + procedure Init (Cond : Boolean) is + begin + PT.Cond := Cond; + end Init; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond + when Cond + is + begin + Put_Line ("OK"); + end Wait_Cond; + + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/config_pragmas/pkg.ads b/testsuite/tests/instr-cov/config_pragmas/pkg.ads new file mode 100644 index 000000000..4cad032f1 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + protected type PT is + procedure Init (Cond : Boolean); + entry Wait_Cond; + private + Cond : Boolean := False; + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/config_pragmas/test.opt b/testsuite/tests/instr-cov/config_pragmas/test.opt new file mode 100644 index 000000000..26465a43d --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/test.opt @@ -0,0 +1,4 @@ +-- These tests use protected bodies, which are not available with light or +-- embedded runtimes. +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/config_pragmas/test.py b/testsuite/tests/instr-cov/config_pragmas/test.py new file mode 100644 index 000000000..c685e7908 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/test.py @@ -0,0 +1,41 @@ +""" +Check that configuration pragmas are correctly interpreted by the instrumenter. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + srcdirs=[".."], + mains=["main.adb"], + compiler_extra=( + 'for Local_Configuration_Pragmas use "../gnat.adc";' + ), + ) + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) + +# If for some reason the instrumenter ignores the Pure_Barrier restriction in +# gnat.adc, it will instrument the entry barrier decision "when Cond" in +# pkg.adb, which will then not compile because the witness call inserted for +# that decision violates the Pure_Barrier restriction. +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6, 8, 10}}, + "pkg.ads.xcov": {"+": {6}}, + "pkg.adb.xcov": {"+": {12}, "-": {23}, "?": {20}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/consistency/main.adb b/testsuite/tests/instr-cov/consistency/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/consistency/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/consistency/p.gpr b/testsuite/tests/instr-cov/consistency/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/consistency/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/consistency/test.py b/testsuite/tests/instr-cov/consistency/test.py new file mode 100644 index 000000000..d476cdd05 --- /dev/null +++ b/testsuite/tests/instr-cov/consistency/test.py @@ -0,0 +1,112 @@ +""" +Test that gnatcov properly report source trace files that are inconsistent with +the provided SID files. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, xcov + + +p_gpr = "p.gpr" +first_sid_file = "first.sid" + +tmp = Wdir("tmp_") + +# As this test modifies source files, create a working copy +for filename in ("p.gpr", "main.adb"): + cp(os.path.join("..", filename), filename) + + +# Instrument the input project and back up the SID file for main.adb +xcov_instrument( + gprsw=GPRswitches(root_project=p_gpr), gpr_obj_dir="obj", covlevel="stmt" +) +cp(os.path.join("obj", "main.sid"), first_sid_file) + +# Modify the source file and re-instrument it +with open("main.adb", "w") as f: + f.write( + """ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 2); + end if; + end Fact; + +begin + Put_Line ("Fact (6) = " & Integer'Image (Fact (6))); +end Main; +""" + ) + +# Now, instrument and build it. Then run the main program, letting it produce a +# trace. +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + gpr_obj_dir="obj", + gpr_exe_dir="obj", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +srctrace = xcov_args[-1] + +# Now try to run a coverage analysis with the trace file produced for the +# second SID file but giving gnatcov the first one. +out_file = "gnatcov.out" +mkdir("xcov") +xcov( + [ + "coverage", + "-axcov", + "-cstmt", + "--output-dir=xcov", + "--sid", + first_sid_file, + srctrace, + ], + out=out_file, + tolerate_messages=( + r"traces for body of main \(from .*\) are" + r" inconsistent with the corresponding Source Instrumentation Data" + ), +) + +# Check that gnatcov warns about inconsistent fingerprints +actual = contents_of(out_file).strip() +expected = ( + "warning: traces for body of main (from {}) are" + " inconsistent with the corresponding Source Instrumentation Data".format( + srctrace + ) +) +thistest.fail_if( + expected != actual, + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(expected), indent(actual)), +) + +# gnatcov only see the first SID file, so it is expected to have the coverage +# obligations coming from the first instrumentation. Besides, since it +# discarded info from the trace file, gnatcov is supposed to report violations +# for all coverage obligations related to the first version of "main.adb". +check_xcov_reports("xcov", {"main.adb.xcov": {"-": {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb b/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb new file mode 100644 index 000000000..1b8869efa --- /dev/null +++ b/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb @@ -0,0 +1,23 @@ +pragma Ada_2012; + +procedure Test_Foo is + Bool1 : Boolean := True; + pragma Volatile (Bool1); + Bool2 : Boolean := True; + pragma Volatile (Bool2); + + -- This test would fail to build if the intrumentation inverted the order + -- of the declaration of Int1 and of the function Foo. + + Int1 : Integer := (if Bool1 and then Bool2 then 0 else 1); -- # Integer + pragma Volatile (Int1); + + function Foo return Integer is (Int1); -- # Expr_Fun +begin + Int1 := Foo; +end Test_Foo; + +--# test_foo.adb +-- +-- /Integer/ l! ## dF- +-- /Expr_Fun/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/decl-inversion/test.opt b/testsuite/tests/instr-cov/decl-inversion/test.opt new file mode 100644 index 000000000..da9fbae6f --- /dev/null +++ b/testsuite/tests/instr-cov/decl-inversion/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD expression functions not available in 5.04 +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/decl-inversion/test.py b/testsuite/tests/instr-cov/decl-inversion/test.py new file mode 100644 index 000000000..91e833410 --- /dev/null +++ b/testsuite/tests/instr-cov/decl-inversion/test.py @@ -0,0 +1,12 @@ +""" +Check that instrumentation of declarations preserves the initial order of the +declarations in the region. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase(category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/default_dump_channel/main.adb b/testsuite/tests/instr-cov/default_dump_channel/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/instr-cov/default_dump_channel/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.opt b/testsuite/tests/instr-cov/default_dump_channel/test.opt new file mode 100644 index 000000000..856e8dc72 --- /dev/null +++ b/testsuite/tests/instr-cov/default_dump_channel/test.opt @@ -0,0 +1,3 @@ +!src-traces DEAD Checks a feature specific to the instrumenter +!native DEAD Checks the default dump channel (bin-file, native only) +RTS_ZFP DEAD requires bin-file available diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.py b/testsuite/tests/instr-cov/default_dump_channel/test.py new file mode 100644 index 000000000..079b47761 --- /dev/null +++ b/testsuite/tests/instr-cov/default_dump_channel/test.py @@ -0,0 +1,77 @@ +""" +Test that programs instrumented with the default dump channel (no +--dump-channel argument) behave as expected given the --dump-filename-* +arguments that are passed (or omitted) to "gnatcov instrument". + +gnatcov used to ignore --dump-trigger and --dump-filename-* options when +--dump-channel was omitted. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field +import glob +import os + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exename_for, + exepath_to, + gprbuild, + gprfor, + run_cov_program, + xcov, +) + + +@dataclass +class Test: + label: str + """Simple string to identify the test.""" + + srctrace_pattern: str + """Glob pattern for the expected source trace file.""" + + options: list[str] = field(default_factory=list) + """List of additional options for "gnatcov instrument".""" + + env: dict[str, str] = field(default_factory=dict) + """Additional environment variables for the executed program.""" + + +# Default prefix for the created source trace ("main.exe" on Windows) +default_prefix = exename_for("main") + +for t in [ + Test("none", f"{default_prefix}-*-*-*-0.srctrace"), + Test("simple", f"{default_prefix}.srctrace", ["--dump-filename-simple"]), + Test("prefix", "bar-*-*-*-0.srctrace", ["--dump-filename-prefix=bar"]), + Test( + "env-var", + "mytrace.srctrace", + ["--dump-filename-env-var=MY_TRACE_FILE"], + {"MY_TRACE_FILE": "mytrace.srctrace"}, + ), +]: + tmp = Wdir(f"tmp_{t.label}") + + prj = gprfor(mains=["main.adb"], srcdirs=[".."]) + xcov( + ["instrument", "-P", prj, "-cstmt", "--dump-trigger=atexit"] + + t.options + ) + gprbuild(prj, trace_mode="src") + + env = dict(os.environ) + env.update(t.env) + run_cov_program(exepath_to("main"), out="run.log", env=env) + + thistest.fail_if( + len(glob.glob(t.srctrace_pattern)) != 1, + f"{t.label}: could not find a file matching {t.srctrace_pattern}", + ) + + tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/end_slocs/main.adb b/testsuite/tests/instr-cov/end_slocs/main.adb new file mode 100644 index 000000000..ffb7d45cf --- /dev/null +++ b/testsuite/tests/instr-cov/end_slocs/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put ("Hello ");Put_Line ("world!"); +end Main; diff --git a/testsuite/tests/instr-cov/end_slocs/p.gpr b/testsuite/tests/instr-cov/end_slocs/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/end_slocs/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/end_slocs/test.py b/testsuite/tests/instr-cov/end_slocs/test.py new file mode 100644 index 000000000..420e059d8 --- /dev/null +++ b/testsuite/tests/instr-cov/end_slocs/test.py @@ -0,0 +1,36 @@ +""" +Regression test: gnatcov used to warn bout duplicate statement SCOs when two +statements were on the same line and not separated by a space. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") + +# If it does not exist, create p.gpr's object directory to avoid noise in +# gnatcov's output. +obj_dir = os.path.abspath("obj") +if not os.path.isdir(obj_dir): + os.mkdir(obj_dir) + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/endianity/main.adb b/testsuite/tests/instr-cov/endianity/main.adb new file mode 100644 index 000000000..7824944ff --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6, True))); +end Main; diff --git a/testsuite/tests/instr-cov/endianity/pkg.adb b/testsuite/tests/instr-cov/endianity/pkg.adb new file mode 100644 index 000000000..7012163f8 --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer; B : Boolean) return Integer is + begin + if I < 2 and then B then + return 1; + else + return I * Fact (I - 1, B); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/endianity/pkg.ads b/testsuite/tests/instr-cov/endianity/pkg.ads new file mode 100644 index 000000000..29d56f436 --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer; B : Boolean) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/endianity/test.py b/testsuite/tests/instr-cov/endianity/test.py new file mode 100644 index 000000000..747f7dc2d --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/test.py @@ -0,0 +1,57 @@ +""" +Test that gnatcov can read source trace files in any endianity. + +This test rewrites an existing trace file itself so that we can test both +endianity even though we are running programs on a host that supports a single +endianity. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.srctracelib import SrcTraceFile +from SUITE.stream_decoder import ByteStreamDecoder +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +# Build a project, run it and create a source trace file +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor("main.adb", srcdirs="..")), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov"], + trace_mode="src", +) +trace_file = xcov_args[-1] + +# Read this trace file and generate two other files, one per endianity +with open(trace_file, "rb") as f: + tf = SrcTraceFile.read(ByteStreamDecoder(f)) +with open("le.srctrace", "wb") as f: + tf.endianity = "little-endian" + tf.write(f) +with open("be.srctrace", "wb") as f: + tf.endianity = "big-endian" + tf.write(f) + +# Check that gnatcov decodes both the same way +for discr in ("be", "le"): + xcov_dir = f"xcov-{discr}" + xcov( + xcov_args + ["--output-dir", xcov_dir, f"{discr}.srctrace"], + out=f"coverage-{discr}.log", + ) + check_xcov_reports( + xcov_dir, + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {6, 8}, "!": {5}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/entry_guards/extra.opt b/testsuite/tests/instr-cov/entry_guards/extra.opt new file mode 100644 index 000000000..26465a43d --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/extra.opt @@ -0,0 +1,4 @@ +-- These tests use protected bodies, which are not available with light or +-- embedded runtimes. +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb new file mode 100644 index 000000000..510602245 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb @@ -0,0 +1,28 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + protected body PT is + + ---------- + -- Init -- + ---------- + + procedure Init (A, B : Boolean) is + begin + PT.A := A; -- # init + PT.B := B; -- # init + end Init; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond + when A and then B -- # guard + is + begin + Put_Line ("OK"); -- # stmt + end Wait_Cond; + + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads new file mode 100644 index 000000000..9c557c2b9 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + protected type PT is + procedure Init (A, B : Boolean); + entry Wait_Cond; + private + A, B : Boolean := False; -- # init + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb new file mode 100644 index 000000000..42b6e3096 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb @@ -0,0 +1,27 @@ +with Pkg; +with Support; use Support; + +procedure Test_0 is +begin + Assert (True); +end Test_0; + +--# pkg.ads +-- /init/ l- ## s- +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l- ## s- +-- =/guard/ l. ## 0 +-- =/stmt/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l- ## s- +-- =/guard/ l- ## d- +-- =/stmt/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l- ## s- +-- =/guard/ l- ## d- +-- =/stmt/ l- ## s- diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb new file mode 100644 index 000000000..f3dac33bd --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb @@ -0,0 +1,32 @@ +with Pkg; + +procedure Test_A is + T : Pkg.PT; +begin + T.Init (A => True, B => False); + select + T.Wait_Cond; + else + null; + end select; +end Test_A; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dT- +-- =/stmt/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dT- +-- =/stmt/ l- ## s- diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb new file mode 100644 index 000000000..b830cf349 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb @@ -0,0 +1,35 @@ +with Pkg; + +procedure Test_A_AB is + T : Pkg.PT; +begin + T.Init (A => True, B => False); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_A_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## c!:"A" +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb new file mode 100644 index 000000000..9f3b3a93a --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb @@ -0,0 +1,42 @@ +with Pkg; + +procedure Test_A_B_AB is + T : Pkg.PT; +begin + T.Init (A => True, B => False); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => False, B => True); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_A_B_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb new file mode 100644 index 000000000..780cae54f --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb @@ -0,0 +1,28 @@ +with Pkg; + +procedure Test_AB is + T : Pkg.PT; +begin + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dF- +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dF- +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb new file mode 100644 index 000000000..dd5e9a222 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb @@ -0,0 +1,35 @@ +with Pkg; + +procedure Test_B_AB is + T : Pkg.PT; +begin + T.Init (A => False, B => True); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_B_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## c!:"B" +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/test.py b/testsuite/tests/instr-cov/entry_guards/full/test.py new file mode 100644 index 000000000..27271256e --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/test.py @@ -0,0 +1,10 @@ +"""Check the coverage for protected bodies entry guards.""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb new file mode 100644 index 000000000..4bf754be0 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb @@ -0,0 +1,28 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + protected body PT is + + ---------- + -- Init -- + ---------- + + procedure Init (A, B : Boolean) is + begin + PT.A := A; + PT.B := B; + end Init; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond + when A and then B + is + begin + Put_Line ("OK"); + end Wait_Cond; + + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads new file mode 100644 index 000000000..75781f03a --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads @@ -0,0 +1,10 @@ +pragma Restrictions (Pure_Barriers); + +package Pkg is + protected type PT is + procedure Init (A, B : Boolean); + entry Wait_Cond; + private + A, B : Boolean := False; + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb b/testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb new file mode 100644 index 000000000..4d0059e11 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Test_True is + T : Pkg.PT; +begin + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_True; diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.opt b/testsuite/tests/instr-cov/entry_guards/restricted/test.opt new file mode 100644 index 000000000..9355892fe --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.opt @@ -0,0 +1,3 @@ +-- Support for the Pure_Barriers pragma is recent in GNAT +5.04a1 DEAD +7.1.2 DEAD diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.py b/testsuite/tests/instr-cov/entry_guards/restricted/test.py new file mode 100644 index 000000000..956a5c6b3 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.py @@ -0,0 +1,36 @@ +""" +Check that protected bodies' entry guard decisions are not instrumented in the +presence of Pure_Barriers restrictions. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +for covlevel, slug, expected_coverage in [ + ("stmt", "st", {"+": {12, 13, 24}}), + ("stmt+decision", "dc", {"+": {12, 13, 24}, "?": {21}}), + ("stmt+mcdc", "mc", {"+": {12, 13, 24}, "?": {21}}), +]: + thistest.log(f"== {covlevel} ==") + tmp = Wdir(f"tmp_{slug}") + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["test_true.adb"]), + units=["pkg"], + ), + covlevel=covlevel, + mains=["test_true"], + extra_coverage_args=["-axcov", "--output-dir=."], + ) + check_xcov_reports( + ".", {"pkg.adb.xcov": expected_coverage, "pkg.ads.xcov": {}} + ) + + tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains/foo.s b/testsuite/tests/instr-cov/explicit_mains/foo.s new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/explicit_mains/main1.adb b/testsuite/tests/instr-cov/explicit_mains/main1.adb new file mode 100644 index 000000000..9f4eac637 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/main1.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main1 is +begin + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (6))); +end Main1; diff --git a/testsuite/tests/instr-cov/explicit_mains/main2.adb b/testsuite/tests/instr-cov/explicit_mains/main2.adb new file mode 100644 index 000000000..fb79c6a0c --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/main2.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main2 is +begin + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (0))); +end Main2; diff --git a/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb new file mode 100644 index 000000000..8bb9c95f0 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb @@ -0,0 +1,16 @@ +package body Pkg is + + ---------- + -- Fact -- + ---------- + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/explicit_mains/test.py b/testsuite/tests/instr-cov/explicit_mains/test.py new file mode 100644 index 000000000..3fc48547e --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/test.py @@ -0,0 +1,186 @@ +""" +Check that passing an explicit list of mains to "gnatcov instrument"'s command +line works as expected. +""" + +import glob +import re + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, srctracename_for +from SUITE.gprutils import GPRswitches + + +def create_gprsw(mains, with_asm=False): + """ + Generate the test project in the current directory (must be the temporary + directory) and return the corresponding GPRswitches instance. + + :param mains: List of source files for the mains. + :param with_asm: Whether to include "Asm" in the list of languages. + """ + # First create a GPR file for the library to test. Make it standalone and + # auto initialized so that buffer units gets linked even if a main contains + # no buffer dumps and thus does not pull it into the link. + gprfor( + mains=[], + prjid="mylib", + srcdirs="../mylib", + objdir="obj-mylib", + langs=["Ada"], + extra=""" + for Library_Name use "mylib"; + for Library_Dir use "lib"; + for Library_Interface use ("pkg"); + for Library_Standalone use "standard"; + """, + ) + + # Then create the GPR file for the mains + langs = ["Ada"] + if with_asm: + langs.append("Asm") + mains_gpr = gprfor( + mains=mains, + prjid="mains", + srcdirs="..", + langs=langs, + deps=["mylib"], + ) + + # Create object/library directories to avoid GPR warnings that they are + # missing. + mkdir("obj-mylib") + mkdir("lib") + mkdir("obj") + + return GPRswitches(root_project=mains_gpr, projects=["mylib"]) + + +# First, test error cases + +wd = Wdir("tmp_errors") + +gprsw = create_gprsw(mains=[], with_asm=True) + + +def check_error(label, mains, expected_error_msg): + """ + Run a test variant to check an error case. + + :param label: Name for this test variant. + :param mains: List of mains to pass on the command line of + "gnatcov instrument". + :param expected_error_msg: Expected error message from + "gnatcov instrument". + """ + thistest.log(f"== {label} ==") + log_file = f"output-{label}.txt" + p = xcov_instrument( + gprsw=gprsw, + covlevel="stmt", + extra_args=mains, + out=log_file, + register_failure=False, + ) + thistest.fail_if_not_equal("gnatcov instrument status code", 1, p.status) + thistest.fail_if_no_match( + "gnatcov instrument output", + f".*gnatcov.*: {re.escape(expected_error_msg)}", + contents_of(log_file).strip(), + ) + + +check_error( + "nosuchfile", ["nosuchfile.adb"], "No such source file: nosuchfile.adb" +) +check_error( + "badlang", + ["foo.s"], + "Cannot instrument main source file (unsupported language): foo.s", +) + +wd.to_homedir() + + +# Now, check that expected mains are instrumented for each cases: no explicit +# main on the command line, one or several explicit mains. Go through the whole +# instrument/build/run cycle and check the absence or presence of a trace file +# in each case. + + +def check_gen_traces( + label, gpr_mains, xcov_mains, program_for_expected_traces +): + """ + Run a test variant to check mains with coverage buffer dumps. + + :param label: Name for this test variant. + :param gpr_mains: List of source files to consider as mains in the project + file. + :param xcov_mains: List of source files to pass as mains to + "gnatcov instrument". + :param program_for_expected_traces: List of program names for which we + expect a source trace to be produced. + """ + thistest.log(f"== {label} ==") + wd = Wdir(f"tmp_{label}") + + build_and_run( + gprsw=create_gprsw(gpr_mains), + covlevel="stmt", + # Build and run all actual mains in all cases (we want to check the + # instrumentation status for all of them). + extra_gprbuild_args=["main1.adb", "main2.adb"], + mains=["main1", "main2"], + extra_instr_args=xcov_mains, + extra_coverage_args=[], + trace_mode="src", + # Since instrumentation may insert coverage buffer dumps only for a + # subset of mains, calls to "gnatcov extract-base64-trace" will fail + # for mains that do not dump. This is as expected, so ignore these + # errors. + register_failure=False, + ) + + # Check that we get exactly the traces that we were expecting + expected_traces = sorted( + srctracename_for(program) for program in program_for_expected_traces + ) + actual_traces = sorted(glob.glob("*.srctrace")) + thistest.fail_if_not_equal( + "Source trace files", expected_traces, actual_traces + ) + + wd.to_homedir() + + +# No mains defined in GPR nor on the gnatcov cmdline: no main creates a trace +# file. +check_gen_traces("gpr0-xcov0", [], [], []) + +# Only the GPR file declares a main: only that main creates a trace file +check_gen_traces("gpr1-xcov0", ["main1.adb"], [], ["main1"]) + +# The GPR file declares one main, but the gnatcov cmdline declares another +# main: the latter takes precedence. +check_gen_traces("gpr1-xcov2", ["main1.adb"], ["main2.adb"], ["main2"]) + +# Likewise, but the gnatcov cmdline declares two mains +check_gen_traces( + "gpr1-xcov12", + ["main1.adb"], + ["main1.adb", "main2.adb"], + ["main1", "main2"], +) + +# The GPR file declares no main, but the gnatcov cmdline declares one: the +# latter creates a trace file. +check_gen_traces("gpr0-xcov1", [], ["main1.adb"], ["main1"]) + +thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb new file mode 100644 index 000000000..df1e48b3f --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb @@ -0,0 +1,11 @@ +with Foo; + +procedure Bar is + X : Natural := 0; + pragma volatile (X); +begin + if X > 0 then + Foo; + end if; + X := 1; +end Bar; diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb new file mode 100644 index 000000000..275310a20 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb @@ -0,0 +1,6 @@ +procedure Foo is + X : Natural := 0; + pragma volatile (X); +begin + X := 1; +end Foo; diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py new file mode 100644 index 000000000..74b0ca0ad --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py @@ -0,0 +1,44 @@ +""" +Check that when mains are provided in the GPR file and in "gnatcov +instrument"'s command line only those in the command line are instrumented as +mains. +""" + +import glob + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, srctracename_for +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr_file = gprfor(mains=["foo.adb", "bar.adb"], srcdirs=[".."]) + +gprsw = GPRswitches(gpr_file) + +build_and_run( + gprsw=gprsw, + covlevel="stmt", + extra_coverage_args=[], + trace_mode="src", + # Only instrument foo.adb as a main + extra_instr_args=["foo.adb"], + # Build and execute foo.adb and bar.adb + extra_gprbuild_args=["foo.adb", "bar.adb"], + mains=["foo", "bar"], + # We expect there not to be a trace file for bar, so don't register not + # finding it as an error. + register_failure=False, +) + +# Check that we only get traces for foo +expected_traces = [srctracename_for("foo")] +actual_traces = sorted(glob.glob("*.srctrace")) + +thistest.fail_if_not_equal( + "Source trace files", expected_traces, actual_traces +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains_uoi/main.adb b/testsuite/tests/instr-cov/explicit_mains_uoi/main.adb new file mode 100644 index 000000000..8e387a0ab --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_uoi/main.adb @@ -0,0 +1,6 @@ +procedure Main is + X : Natural := 0; + pragma volatile (X); +begin + X := 1; +end Main; diff --git a/testsuite/tests/instr-cov/explicit_mains_uoi/test.py b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py new file mode 100644 index 000000000..2201cd2c9 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py @@ -0,0 +1,29 @@ +""" +Check that passing an explicit main that is already a unit of interest to +"gnatcov instrument"'s command line works as expected. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr_file = gprfor(mains=[], srcdirs=[".."]) + +gprsw = GPRswitches(gpr_file) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + extra_instr_args=["main.adb"], + extra_gprbuild_args=["main.adb"], +) + +check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/main.adb b/testsuite/tests/instr-cov/expr_func/410-overriding/main.adb new file mode 100644 index 000000000..317629809 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/main.adb @@ -0,0 +1,10 @@ +pragma Ada_2012; +with Pkg; + +procedure Main +is + Obj : Pkg.T_Child; + B : Boolean := Obj.T_Prim (True, False); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb new file mode 100644 index 000000000..98662c39d --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Pkg is + + overriding function T_Prim (Obj : T_Child; A, B : Boolean) return Boolean + is (A and then B); + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads new file mode 100644 index 000000000..a233bc545 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pkg is + + type T is tagged null record; + function T_Prim (Obj : T; A, B : Boolean) return Boolean is (A or else B); + + type T_Child is new T with record + X : Integer; + end record; + overriding function T_Prim (Obj : T_Child; A, B : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/test.py b/testsuite/tests/instr-cov/expr_func/410-overriding/test.py new file mode 100644 index 000000000..8cb2b2495 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/test.py @@ -0,0 +1,33 @@ +""" +Regression test: GNATcoverage used to create an overriding expression function +when instrumenting an overriding expression function in a package body. This +overriding was declared too late, which resulted in a compilation error. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {6, 7, 9}}, + "pkg.ads.xcov": {"+": {5, 8, 9, 10}, "-": {6}}, + "pkg.adb.xcov": {"!": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads b/testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads new file mode 100644 index 000000000..db5b17d1f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads @@ -0,0 +1,21 @@ +pragma Ada_2022; + +package Gen is + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Weight_Sum (Left, Right : Value_Type) return Natural; + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Both_Weights_Null (Left, Right : Value_Type) return Boolean; + + function Weight_Sum (Left, Right : Value_Type) return Natural is + (Weight (Left) + Weight (Right)); -- # expr_st + + function Both_Weights_Null (Left, Right : Value_Type) return Boolean is + (Weight (Left) = 0 and then Weight (Right) = 0); -- # expr_dc :o/e: + +end Gen; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb new file mode 100644 index 000000000..1a9b12bb1 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Prim is + + function Make_Internal (Cond : Boolean) return T is + (T'(X => (if Cond then 1 else 2))); -- # expr_dc :o/d: + + function Make_Internal (Cond : Boolean) return TT is + (TT'(X => 3, Y => 4)); -- # expr_st + +end Prim; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads new file mode 100644 index 000000000..f05ef1e10 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads @@ -0,0 +1,25 @@ +pragma Ada_2022; + +package Prim is + type T is tagged record + X : Integer; + end record; + function And_Then (X : T; A, B : Boolean) return Boolean is + (A and then B); -- # expr_dc :o/e: + function Or_Else (X : T; A, B : Boolean) return Boolean is + (A or else B); -- # expr_dc :o/e: + + function Make_Internal (Cond : Boolean) return T; + + function Make (Cond : Boolean) return T is (Make_Internal (Cond)); -- # expr_st + + type TT is new T with record + Y : Integer; + end record; + + overriding function Make_Internal (Cond : Boolean) return TT; + + overriding function Make (Cond : Boolean) return TT is + (Make_Internal (Cond)); -- # expr_st + +end Prim; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads b/testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads new file mode 100644 index 000000000..dce3ea8df --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package Rec is + + type T is tagged record + X : Positive; + end record; + + function Fact (Input : T) return Positive is + (if Input.X = 1 then 1 else Input.X * Fact ((X => Input.X - 1))); -- # expr_dc :o/d: + +end Rec; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb new file mode 100644 index 000000000..78c2b7854 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb @@ -0,0 +1,41 @@ +pragma Ada_2012; + +with Gen; use Gen; +with Prim; use Prim; +with Rec; use Rec; + +with Support; use Support; + +procedure Test_All is + function Identity (X : Natural) return Natural is (X); + function Nat_Sum is new Gen.Weight_Sum + (Value_Type => Natural, Weight => Identity); + function Nat_Both_Null is new Gen.Both_Weights_Null + (Value_Type => Natural, Weight => Identity); + Val : Prim.T := (X => 0); + Res_T : Prim.T; + Res_TT : Prim.TT; +begin + -- Ensure we get full coverage + Assert (Nat_Sum (1, 1) = 2); + Assert (Nat_Both_Null (0, 0)); + Assert (not Nat_Both_Null (0, 1)); + Assert (not Nat_Both_Null (1, 0)); + Assert (Fact ((X => 3)) = 6); + Assert (And_Then (Val, True, True)); + Assert (not And_Then (Val, True, False)); + Assert (not And_Then (Val, False, True)); + Assert (not Or_Else (Val, False, False)); + Assert (Or_Else (Val, True, False)); + Assert (Or_Else (Val, False, True)); + Res_T := Make (True); + Assert (Res_T.X = 1); + Res_T := Make (False); + Assert (Res_T.X = 2); + Res_TT := Make (False); + Assert (Res_TT.X = 3 and then Res_TT.Y = 4); +end Test_All; + +--# rec.ads prim.ads prim.adb gen.ads +-- +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb new file mode 100644 index 000000000..b5db57d44 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb @@ -0,0 +1,33 @@ +pragma Ada_2012; + +with Gen; use Gen; +with Prim; use Prim; +with Rec; use Rec; + +with Support; use Support; + +procedure Test_True is + function Identity (X : Natural) return Natural is (X); + function Nat_Sum is new Gen.Weight_Sum + (Value_Type => Natural, Weight => Identity); + function Nat_Both_Null is new Gen.Both_Weights_Null + (Value_Type => Natural, Weight => Identity); + Val : Prim.T := (X => 0); + Res_T : Prim.T; + Res_TT : Prim.TT; +begin + Assert (Nat_Sum (1, 1) = 2); + Assert (Nat_Both_Null (0, 0)); + Assert (Fact ((X => 1)) = 1); + Assert (Or_Else (Val, False, True)); + Assert (And_Then (Val, True, True)); + Res_T := Make (True); + Assert (Res_T.X = 1); + Res_TT := Make (False); + Assert (Res_TT.X = 3 and then Res_TT.Y = 4); +end Test_True; + +--# rec.ads prim.ads prim.adb gen.ads +-- +-- /expr_st/ l+ ## 0 +-- /expr_dc/ l! ## oF- diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/test.opt b/testsuite/tests/instr-cov/expr_func/ada_2022/test.opt new file mode 100644 index 000000000..087421040 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/test.opt @@ -0,0 +1,3 @@ +7.1.2 DEAD Ada 2022 not supported on old toolchains +5.04a1 DEAD Ada 2022 not supported on old toolchains +bin-traces DEAD Ada 2022 not supported on bin traces diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/test.py b/testsuite/tests/instr-cov/expr_func/ada_2022/test.py new file mode 100644 index 000000000..550150f60 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/test.py @@ -0,0 +1,22 @@ +""" +Check that limitations concerning expression function instrumentation are +lifted when Ada 2022, and thus declare expressions are available. + +This test reflects the various limitations that are documented in the user +manual: +- generic expression functions (gen.ads) +- expression functions which are primitives of a tagged type, when that type is + the return type of the expression function. (prim.ads) +- Recursive expression functions which are a primitive of some type (rec.ads) + +The above constructs used to not be instrumented by gnatcov and resulted in +warnings and undetermined coverage items in the reports. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aggr/main.adb b/testsuite/tests/instr-cov/expr_func/aggr/main.adb new file mode 100644 index 000000000..f29953d2d --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aggr/main.adb @@ -0,0 +1,27 @@ +pragma Ada_2012; + +procedure Main is + type Enum_Type is (A, B, C, D); + type Flags_Type is array (Enum_Type) of Boolean; + + type Options_Type is record + A, B, C : Boolean; + end record; + + function Get_Flags (B : Boolean) return Flags_Type is + (others => B); + function Get_Some_Flags (B : Boolean) return Flags_type is + (A => True, Others => B); + + function Get_Options (B : Boolean) return Options_Type is + (others => B); + function Get_Some_Options (B : Boolean) return Options_type is + (A => True, Others => B); + + F1 : Flags_Type := Get_Flags (True); + F2 : Flags_Type := Get_Some_Flags (True); + O1 : Options_Type := Get_Options (True); + O2 : Options_Type := Get_Some_Options (True); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/aggr/p.gpr b/testsuite/tests/instr-cov/expr_func/aggr/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aggr/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/aggr/test.py b/testsuite/tests/instr-cov/expr_func/aggr/test.py new file mode 100644 index 000000000..08ed44e95 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aggr/test.py @@ -0,0 +1,33 @@ +""" +Check that we properly instrument expression functions whose expression is only +an aggregate. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", {"main.adb.xcov": {"+": {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24}}} +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..ef861ec6f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N) -- # expr_func + with Pre => N > 0, + Post => Fact'Result >= N; + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py new file mode 100644 index 000000000..e4cb071b3 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non-recursive expression functions, +with aspects and no previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads new file mode 100644 index 000000000..dab0d9b59 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer + with Pre => N > 0, + Post => Fact'Result >= N; + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N); -- # expr_func + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py new file mode 100644 index 000000000..ff98ed535 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non-recursive expression functions +with aspects and that have a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..f50a262ad --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N); -- # expr_func + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py new file mode 100644 index 000000000..5580d63cc --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non recursive expression functions +without aspects and no previsou declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads new file mode 100644 index 000000000..1518fb104 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer; + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N); -- # expr_func + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py new file mode 100644 index 000000000..cf7f1610c --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non-recursive expression functions +without aspects, but with a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/readme.txt b/testsuite/tests/instr-cov/expr_func/aspects/readme.txt new file mode 100644 index 000000000..d367b8027 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/readme.txt @@ -0,0 +1,10 @@ +Tests in this dir test the instrumentation of various kinds of expression functions +depending on if: +1- they have a previous spec or not +2- they have aspects or not +3- they are self-referencing (or recursive) or not. + +This lead to 8 tests. For each dir, if the expression function under test +is recursive the folder name contains "rec", if it does not it contains "no-rec"; +if it has aspects, it contain "asp", if it does not it contains "no-asp"; +if it has a previous spec it contains "prespec", if it does not, it contains "no-prespec". diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..f0bf6ec38 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N) -- # expr_func + with Pre => N > 0, + Post => Fact'Result >= N; + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py new file mode 100644 index 000000000..70ede0c54 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions +with aspects but with no previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads new file mode 100644 index 000000000..690f200ad --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer + with Pre => N > 0, + Post => Fact'Result >= N; + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N); -- # expr_func + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py new file mode 100644 index 000000000..4ec0303ee --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions with aspects +and a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..40f1d6a84 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N); -- # expr_func + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py new file mode 100644 index 000000000..0bdfb8eed --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions +without aspects and without a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads new file mode 100644 index 000000000..2ebba85a9 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer; + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N); -- # expr_func + +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py new file mode 100644 index 000000000..ba6df99a2 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions +without aspects but with a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb b/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb new file mode 100644 index 000000000..0d8339575 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb @@ -0,0 +1,21 @@ +pragma Ada_2012; + +with Foo; + +procedure Test_Foo is + + procedure Null_Proc (Param : Integer) is null -- # null_proc + with Inline; + +begin + + Null_Proc (Foo.Fact (0)); + +end Test_Foo; + +--# foo.ads +-- +--%opts: --trace-mode=src +-- /expr_func/ l! ## dT- +--%opts: --trace-mode=bin +-- /expr_func/ l! ## d! diff --git a/testsuite/tests/instr-cov/expr_func/basic/main.adb b/testsuite/tests/instr-cov/expr_func/basic/main.adb new file mode 100644 index 000000000..e864bba2e --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/basic/main.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Fact (I : Integer) return Integer is + (if I < 2 + then 1 + else I * Fact (I - 1)); + + X, Y : Boolean; + function X_And_Then_Y return Boolean is (X and then Y); + +begin + Put_Line ("Fact (6) = " & Integer'Image (Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/basic/p.gpr b/testsuite/tests/instr-cov/expr_func/basic/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/basic/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/basic/test.py b/testsuite/tests/instr-cov/expr_func/basic/test.py new file mode 100644 index 000000000..35d113381 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/basic/test.py @@ -0,0 +1,31 @@ +""" +Test that instrumented source coverage works as expected on expression +functions. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {7, 9, 11, 15}, "-": {12}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/completion/main.adb b/testsuite/tests/instr-cov/expr_func/completion/main.adb new file mode 100644 index 000000000..8797d117b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/main.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; +with Pak; use Pak; + +procedure Main is + T_Instance : T := Make (True); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/completion/pak.adb b/testsuite/tests/instr-cov/expr_func/completion/pak.adb new file mode 100644 index 000000000..5327a7bed --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/pak.adb @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package body Pak is + + type BT is tagged record + X : Integer; + end record; + + function Make (Cond : Boolean) return BT + is (BT'(X => (if Cond then 1 else 2))); + + type BTT is new BT with record + Y : Integer; + end record; + + function Make (Cond : Boolean) return BTT + is (BTT'(X => 3, Y => 4)); + + function Exercise_BT (Cond : Boolean) return Integer + is (BT'(Make (Cond)).X); + + function Exercise_BTT (Cond : Boolean) return Integer + is (BTT'(Make (Cond)).Y); + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/completion/pak.ads b/testsuite/tests/instr-cov/expr_func/completion/pak.ads new file mode 100644 index 000000000..e9b0b0864 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/pak.ads @@ -0,0 +1,27 @@ +pragma Ada_2012; + +package Pak is + + type T is private; + + function Make (Cond : Boolean) return T; + + function Exercise_BT (Cond : Boolean) return Integer; + function Exercise_BTT (Cond : Boolean) return Integer; + +private + type T is tagged record + X : Integer; + end record; + + function Make (Cond : Boolean) return T + is (T'(X => (if Cond then 1 else 2))); + + type TT is new T with record + Y : Integer; + end record; + + overriding function Make (Cond : Boolean) return TT + is (TT'(X => 3, Y => 4)); + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/completion/test.py b/testsuite/tests/instr-cov/expr_func/completion/test.py new file mode 100644 index 000000000..adfa1c90c --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/test.py @@ -0,0 +1,43 @@ +""" +Regression test: check that gnatcov does not instrument expression function +that are a primitive of a tagged type T when the controlling parameter is the +return type, and when the expression function is a completion. + +gnatcov used to instrument such expression function, which resulted in +introducing a new primitive (the wrapper generated for MC/DC instrumentation), +which was not defined for derived types. + +This also checks that such expression functions *are* instrumented when they +are not in a package spec: primitives can be declared only in package specs. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + tolerate_instrument_messages=( + "cannot instrument an expression function which" + ), +) + +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7}}, + "pak.ads.xcov": {"+": {5, 13, 14, 15, 20, 21, 22}, "?": {18, 25}}, + "pak.adb.xcov": {"+": {5, 6, 7, 12, 13, 14}, "-": {10, 17, 20, 23}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/extra.opt b/testsuite/tests/instr-cov/expr_func/extra.opt new file mode 100644 index 000000000..6609aef9d --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/extra.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads b/testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads new file mode 100644 index 000000000..27fe4ba68 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads @@ -0,0 +1,21 @@ +pragma Ada_2012; + +package Pkg is + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Weight_Sum (Left, Right : Value_Type) return Natural; + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Both_Weights_Null (Left, Right : Value_Type) return Boolean; + + function Weight_Sum (Left, Right : Value_Type) return Natural is + (Weight (Left) + Weight (Right)); + + function Both_Weights_Null (Left, Right : Value_Type) return Boolean is + (Weight (Left) = 0 and then Weight (Right) = 0); + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb new file mode 100644 index 000000000..62372d526 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb @@ -0,0 +1,26 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_Main is + + type Rec_Type is record + Value : Natural; + end record; + + function Weight (Self : Rec_Type) return Natural is (Self.Value); + + function Weight_Sum is new Pkg.Weight_Sum (Rec_Type, Weight); + function Both_Weights_Null is new Pkg.Both_Weights_Null (Rec_Type, Weight); + + A : constant Rec_Type := (Value => 1); + B : constant Rec_Type := (Value => 2); + +begin + if Weight_Sum (A, B) /= 3 then + raise Program_Error; + end if; + if Both_Weights_Null (A, B) then + raise Program_Error; + end if; +end Test_Main; diff --git a/testsuite/tests/instr-cov/expr_func/generic/test.py b/testsuite/tests/instr-cov/expr_func/generic/test.py new file mode 100644 index 000000000..135495964 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic/test.py @@ -0,0 +1,48 @@ +""" +Check that the instrumentation of generic expression functions produces valid +code. It used to create non-generic expression functions that could reference +generic formals. + +For now we do not know how to instrument generic expression functions, so we +emit a warning for them at instrumentation time and always consider them +non-instrumented. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["test_main.adb"]), + units=["pkg"], + ), + covlevel="stmt+mcdc", + mains=["test_main"], + extra_coverage_args=["-axcov", "--output-dir=."], + trace_mode="src", + tolerate_instrument_messages=( + "cannot instrument generic expression function" + ), +) + +# We only expect non-instrumented lines +check_xcov_reports(".", {"pkg.ads.xcov": {"?": {16, 19}}}) + +# Check that both expression functions are reported as warnings +warning_msg = ( + "gnatcov limitation: cannot instrument generic expression functions." + " Consider turning it into a regular function body." +) +thistest.fail_if_not_equal( + "'gnatcov instrument' log", + f"!!! pkg.ads:15:4: {warning_msg}\n" f"!!! pkg.ads:18:4: {warning_msg}\n", + contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads b/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads new file mode 100644 index 000000000..3b09a3d6c --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads @@ -0,0 +1,3 @@ +with Pkg; + +package Inst is new Pkg (T => Boolean, Init => True); diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads b/testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads new file mode 100644 index 000000000..aeaf8cca4 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads @@ -0,0 +1,16 @@ +pragma Ada_2012; + +generic + type T (<>) is private; + Init : Boolean; +package Pkg is + + type Tagged_Typ is tagged record + Bool : Boolean; + end record; + + function Foo (Self : Tagged_Typ) return Boolean is (Self.Bool); -- # expr + + Obj : constant Tagged_Typ := (Bool => Init); + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb b/testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb new file mode 100644 index 000000000..82eca6a86 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Inst; + +procedure Test_Pkg is + + Res : Boolean with Volatile; + +begin + Res := Inst.Obj.Foo; +end Test_Pkg; + +-- The coverage expectations do not matter much, the point of this test is to +-- check that the instrumented code is accepted by gnat. + +--# pkg.ads +-- +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/test.py b/testsuite/tests/instr-cov/expr_func/generic_prim/test.py new file mode 100644 index 000000000..bb840a4be --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument expression functions that are primitives, +declared in a generic package without triggering any freezing bug. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb new file mode 100644 index 000000000..5f73c963f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; + +package body Pkg is + + -------------- + -- Say_Even -- + -------------- + + procedure Say_Even is + begin + Ada.Text_IO.Put_Line ("Counter is even"); -- # say-even + end Say_Even; + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads new file mode 100644 index 000000000..de1bfe63a --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package Pkg is + + Counter : Natural := 0 with Ghost; + + function Is_Even return Boolean + is (Counter > 0 and then Counter mod 2 = 0) -- # is-even + with Ghost; + + Dummy : Integer; + -- Dummy variable just so that "pkg.ads" appears in the debug info and so + -- that "gnatcov coverage" finds it in binary traces mode. + + procedure Say_Even with Pre => Is_Even; + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb new file mode 100644 index 000000000..fe5074008 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_Main is +begin + Pkg.Say_Even; +end Test_Main; + +--# pkg.adb +-- /say-even/ l+ ## 0 +-- +--# pkg.ads +-- /is-even/ l. ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/ghost/test.py b/testsuite/tests/instr-cov/expr_func/ghost/test.py new file mode 100644 index 000000000..5472c5ec4 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/test.py @@ -0,0 +1,13 @@ +""" +Check that the instrumentation of ghost expression functions produces valid +code. It used to create non-ghost expression functions that could reference +ghost entities. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads b/testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads new file mode 100644 index 000000000..ffbb2c3e7 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pak is + + type T is record + X : Integer; + end record; + function Make (Cond : Boolean) return T is (T'(X => 1)); + + type TT is new T; + overriding function Make (Cond : Boolean) return TT is + (TT'(X => (if Cond then 2 else 3))); -- # dc + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb b/testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb new file mode 100644 index 000000000..3bd172523 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +with Pak; use Pak; + +procedure Test_Foo is + Dummy_1 : constant T := Make (False); + Dummy_2 : constant TT := Make (True); +begin + null; +end Test_Foo; + +--# pak.ads +-- +--%opts: --trace-mode=src +-- /dc/ l! ## dF- +--%opts: --trace-mode=bin +-- /dc/ l! ## d! diff --git a/testsuite/tests/instr-cov/expr_func/overriding/test.py b/testsuite/tests/instr-cov/expr_func/overriding/test.py new file mode 100644 index 000000000..e6092f08a --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/overriding/test.py @@ -0,0 +1,11 @@ +""" +Check that we properly instrument overriding expression functions for MC/DC. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/main.adb b/testsuite/tests/instr-cov/expr_func/parameterless/main.adb new file mode 100644 index 000000000..30c74ef1f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/main.adb @@ -0,0 +1,5 @@ +with Pak; +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/p.gpr b/testsuite/tests/instr-cov/expr_func/parameterless/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/pak.ads b/testsuite/tests/instr-cov/expr_func/parameterless/pak.ads new file mode 100644 index 000000000..6d45ec710 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + A, B : Boolean; + function And_Then return Boolean is (A and then B); +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/test.py b/testsuite/tests/instr-cov/expr_func/parameterless/test.py new file mode 100644 index 000000000..aae78db5e --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/test.py @@ -0,0 +1,34 @@ +""" +Check that we properly instrument expression functions with no parameters +for MC/DC. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", {"main.adb.xcov": {"+": {4}}, "pak.ads.xcov": {"+": {4}, "-": {5}}} +) + + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads b/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads new file mode 100644 index 000000000..b330052b7 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads @@ -0,0 +1,5 @@ +pragma Ada_2012; + +package Bar is + type T_Bar is new Boolean; +end Bar; diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads b/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads new file mode 100644 index 000000000..6a200520c --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Bar; + +package Foo is + + type T is tagged null record; + + function Prim (Self : T) return Bar.T_Bar; -- # decl + +private + use Bar; + + function Prim (Self : T) return T_Bar is + (False); -- # EF +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb b/testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb new file mode 100644 index 000000000..fb7e29d0e --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Foo; +with Bar; +procedure Test_Decl is + Obj : Foo.T; + Res : Bar.T_Bar; + pragma Volatile (Res); +begin + Res := Obj.Prim; +end Test_Decl; + +--# foo.ads +-- +-- /decl/ l. ## 0 +-- /EF/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/test.py b/testsuite/tests/instr-cov/expr_func/prev_decl/test.py new file mode 100644 index 000000000..e91b3c754 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/test.py @@ -0,0 +1,13 @@ +""" +Check that the previous declaration inserted for an augmented expression +function is valid. This test is not so much about what the coverage results +we ge but rather about having the instrumenter emit valid code. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prim/main.adb b/testsuite/tests/instr-cov/expr_func/prim/main.adb new file mode 100644 index 000000000..b67975340 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/main.adb @@ -0,0 +1,7 @@ +pragma Ada_2012; +with Pak; + +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/prim/pak.ads b/testsuite/tests/instr-cov/expr_func/prim/pak.ads new file mode 100644 index 000000000..2418a0f0b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/pak.ads @@ -0,0 +1,18 @@ +pragma Ada_2012; + +package Pak is + type T is tagged record + X : Integer; + end record; + function And_Then (X : T; A, B : Boolean) return Boolean is + (A and then B); + function Or_Else (X : T; A, B : Boolean) return Boolean is + (A or else B); + function Make (Cond : Boolean) return T is (T'(X => (if Cond then 1 else 2))); + + type TT is new T with record + Y : Integer; + end record; + overriding function Make (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.py b/testsuite/tests/instr-cov/expr_func/prim/test.py new file mode 100644 index 000000000..2b3d868c2 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/test.py @@ -0,0 +1,39 @@ +""" +Check that gnatcov correctly processes expression functions that are primitives +of tagged types for MC/DC, e.g. it warns about them, and they are reported as +uninstrumented in the coverage report. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + tolerate_instrument_messages=( + "cannot instrument an expression function which" + ), +) + +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {6}}, + "pak.ads.xcov": { + "+": {4, 5, 6, 13, 14, 15}, + "-": {8, 10}, + "?": {11, 16}, + }, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb new file mode 100644 index 000000000..383233aab --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb @@ -0,0 +1,31 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Containers.Ordered_Sets; + + +procedure Test_Main is + package File_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Unbounded_String); + + type R is record + Source_Files : File_Sets.Set; + end record; + + function It + (Self : R) + return File_Sets.Set_Iterator_Interfaces.Reversible_Iterator'Class + is (Self.Source_Files.Iterate); -- # stmt + + Files : R; +begin + Files.Source_Files.Include (To_Unbounded_String ("A")); -- # stmt + for File in It (Files) loop -- # stmt + Put_Line (To_String (File_Sets.Element (File))); -- # stmt + end loop; +end Test_Main; + +--# test_main.adb +-- +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/program_error/test.opt b/testsuite/tests/instr-cov/expr_func/program_error/test.opt new file mode 100644 index 000000000..832969ef5 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/program_error/test.opt @@ -0,0 +1,2 @@ +!native DEAD Testcase requires standard Ada containers +RTS_ZFP DEAD Testcase requires standard Ada containers diff --git a/testsuite/tests/instr-cov/expr_func/program_error/test.py b/testsuite/tests/instr-cov/expr_func/program_error/test.py new file mode 100644 index 000000000..8d30e03bf --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/program_error/test.py @@ -0,0 +1,13 @@ +""" +Check that the instrumentation of expression functions does not trigger a GNAT +miscompilation bug. The instrumented test program used to crash with a +Program_Error/Storage_Error. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb new file mode 100644 index 000000000..e71551a9b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +procedure Test_Main is + + type Int_Array is array (Positive range <>) of Integer; + + function All_Multiple_Of_2_And_3 (IA : Int_Array) return Boolean is + (for all I in IA'Range => -- # func-stmt + IA (I) mod 2 = 0 and then IA (I) mod 3 = 0); -- # func-dc + +begin + if All_Multiple_Of_2_And_3 ((2, 4, 12)) then -- # call-dc + raise Program_Error; -- # call-error + end if; +end Test_Main; + +--# test_main.adb +-- +-- /func-stmt/ l+ ## 0 +-- /func-dc/ l! ## dT- +-- /call-dc/ l! ## dT- +-- /call-error/ l- ## s- diff --git a/testsuite/tests/instr-cov/expr_func/quantifier/test.py b/testsuite/tests/instr-cov/expr_func/quantifier/test.py new file mode 100644 index 000000000..bbc385463 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/quantifier/test.py @@ -0,0 +1,12 @@ +""" +Check that the instrumentation in MC/DC mode of an expression function that +contains defining identifiers does not crash (it used to). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/p.gpr b/testsuite/tests/instr-cov/ext_gpr/src/p.gpr new file mode 100644 index 000000000..d4e3ff4d4 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/p.gpr @@ -0,0 +1,4 @@ +project P is + for Source_Dirs use ("src-p"); + for Object_Dir use "obj-p"; +end P; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr b/testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr new file mode 100644 index 000000000..e60e3f710 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr @@ -0,0 +1,4 @@ +project P_Ext1 extends "p" is + for Source_Dirs use ("src-p_ext1"); + for Object_Dir use "obj-p_ext1"; +end P_Ext1; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr b/testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr new file mode 100644 index 000000000..19dd8d70a --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr @@ -0,0 +1,4 @@ +project P_Ext2 extends "p_ext1" is + for Source_Dirs use ("src-p_ext2"); + for Object_Dir use "obj-p_ext2"; +end P_Ext2; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads new file mode 100644 index 000000000..f78912afe --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + I : Integer; +end Pkg; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads new file mode 100644 index 000000000..c50ad5356 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads @@ -0,0 +1,3 @@ +package Pkg1 is + I : Integer; +end Pkg1; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads new file mode 100644 index 000000000..5a4613b92 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads @@ -0,0 +1,3 @@ +package Pkg2 is + I : Integer; +end Pkg2; diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py new file mode 100644 index 000000000..42f9ff842 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -0,0 +1,49 @@ +""" +Check that "gnatcov instrument" correctly deals with directories for +instrumented sources in project extension configurations. +""" + +import glob + +from e3.fs import sync_tree + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Create a copy of the testcase material (project sources and dummy object +# directories) and run the instrumenter on the ultimate extending project. +sync_tree("../src", ".") +xcov_instrument(gprsw=GPRswitches(root_project="p_ext2.gpr"), covlevel="stmt") + +# Check that directories for instrumented sources are all empty except for the +# ultimate extending project, which should contain all instrumented sources. +thistest.fail_if_no_match( + "instrumented directories", + "\n".join( + [ + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2-observe\.adb", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2-observe\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg1\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg2\.ads", + ] + ), + "\n".join( + f.replace("\\", "/") + for f in sorted(glob.glob("obj-*/*-gnatcov-instr/*")) + ), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/file-context/main.adb b/testsuite/tests/instr-cov/file-context/main.adb new file mode 100644 index 000000000..1801cb505 --- /dev/null +++ b/testsuite/tests/instr-cov/file-context/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +with Missing_A; +with Missing_B; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/instr-cov/file-context/pkg.ads b/testsuite/tests/instr-cov/file-context/pkg.ads new file mode 100644 index 000000000..2db1f1de6 --- /dev/null +++ b/testsuite/tests/instr-cov/file-context/pkg.ads @@ -0,0 +1,2 @@ +package Pkg is +end Pkg; diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py new file mode 100644 index 000000000..fe6812d99 --- /dev/null +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -0,0 +1,76 @@ +""" +Check that "gnatcov instrument" mentions the source file it is currently +instrumented when it is supposed to: once per source file that triggers an +error/warning, and once for every file in verbose mode. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.cutils import contents_of, lines_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +# Create the object directory to avoid spurious notices +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) +mkdir("obj") + + +def do_instr(label, args): + thistest.log(f"== {label} ==") + output_file = f"{label}.txt" + p = xcov_instrument( + gprsw=gprsw, + covlevel="stmt", + extra_args=args, + out=output_file, + register_failure=False, + ) + thistest.fail_if( + p.status != 0, f'{label}: "gnatcov instrument" unexpected failure' + ) + return output_file + + +# Check that we print the source file that is currently instrumented when +# warnings/errors occur at most once, and never for other files. +log = do_instr("basic", []) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + contents_of(log).strip(), + "\n".join( + [ + "warning: While instrumenting main.adb...", + "warning: Cannot find required source file: missing_a.ads", + "warning: Cannot find required source file: missing_b.ads", + ] + ), +) + +# In verbose mode: always print it once. +log = do_instr("verbose", ["-v"]) +actual_lines = [ + line + for line in lines_of(log) + if ( + line.startswith("[GNATCOV.INSTRUMENT_SOURCES] Instrumenting ") + or line.startswith("warning: ") + ) +] +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + "\n".join( + [ + "[GNATCOV.INSTRUMENT_SOURCES] Instrumenting main.adb", + "warning: Cannot find required source file: missing_a.ads", + "warning: Cannot find required source file: missing_b.ads", + "[GNATCOV.INSTRUMENT_SOURCES] Instrumenting pkg.ads", + ] + ), + "\n".join(actual_lines), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/ghost_generic/gen.adb b/testsuite/tests/instr-cov/ghost_generic/gen.adb new file mode 100644 index 000000000..046d47ac4 --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/gen.adb @@ -0,0 +1,11 @@ +package body Gen is + function Eq (X : T) return Boolean is + begin + return X = Val; + end Eq; + + function Non_Eq (X : T) return Boolean is + begin + return X /= Val; + end Non_Eq; +end Gen; diff --git a/testsuite/tests/instr-cov/ghost_generic/gen.ads b/testsuite/tests/instr-cov/ghost_generic/gen.ads new file mode 100644 index 000000000..90ccf8cb8 --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/gen.ads @@ -0,0 +1,8 @@ +generic + type T is (<>); + Init : T; +package Gen is + Val : T := Init; + function Eq (X : T) return Boolean; + function Non_Eq (X : T) return Boolean; +end Gen; diff --git a/testsuite/tests/instr-cov/ghost_generic/main.adb b/testsuite/tests/instr-cov/ghost_generic/main.adb new file mode 100644 index 000000000..d3250370f --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/main.adb @@ -0,0 +1,16 @@ +with Gen; +with Non_Ghost_Inst; + +procedure Main is + + package Ghost_Pak is + pragma Ghost; + package Ghost_Gen is new Gen (T => Boolean, Init => True); + end Ghost_Pak; + + Res : Boolean; + pragma Volatile (Res); +begin + pragma Assert (Ghost_Pak.Ghost_Gen.Eq (True)); + Res := Non_Ghost_Inst.Non_Eq (False); +end Main; diff --git a/testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads b/testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads new file mode 100644 index 000000000..97d0305ce --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads @@ -0,0 +1,3 @@ +with Gen; + +package Non_Ghost_Inst is new Gen (T => Boolean, Init => True); diff --git a/testsuite/tests/instr-cov/ghost_generic/test.py b/testsuite/tests/instr-cov/ghost_generic/test.py new file mode 100644 index 000000000..9a9c3f9bf --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/test.py @@ -0,0 +1,33 @@ +""" +Check that generics that are instantiated as ghost entites can be correctly +compiled when instrumented with --spark-compat. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--spark-compat"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {11, 15}}, + "gen.adb.xcov": {"+": {9}, "-": {4}}, + "gen.ads.xcov": {}, + "non_ghost_inst.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/gpr-complex/main_body.gpr b/testsuite/tests/instr-cov/gpr-complex/main_body.gpr new file mode 100644 index 000000000..109449cf5 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_body.gpr @@ -0,0 +1,5 @@ +project Main_Body extends "lib" is + for Source_Dirs use ("src-main_body"); + for Object_Dir use "obj-main_body"; + for Main use ("main.adb"); +end Main_Body; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr b/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr new file mode 100644 index 000000000..d4ba368f8 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr @@ -0,0 +1,5 @@ +project Main_Sep extends "lib" is + for Source_Dirs use ("src-main_sep"); + for Object_Dir use "obj-main_sep"; + for Main use ("main.adb"); +end Main_Sep; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr new file mode 100644 index 000000000..425fcab8f --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr @@ -0,0 +1,5 @@ +project Main_Simple extends "lib" is + for Source_Dirs use ("src-main_simple"); + for Object_Dir use "obj-main_simple"; + for Main use ("main.adb"); +end Main_Simple; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr b/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr new file mode 100644 index 000000000..ffa5ac70a --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr @@ -0,0 +1,5 @@ +project Main_Spec extends "lib" is + for Source_Dirs use ("src-main_spec"); + for Object_Dir use "obj-main_spec"; + for Main use ("main.adb"); +end Main_Spec; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr b/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr new file mode 100644 index 000000000..f88001ac7 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr @@ -0,0 +1,4 @@ +project Lib is + for Source_Dirs use ("."); + for Object_Dir use "obj"; +end Lib; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb new file mode 100644 index 000000000..f5189aa0d --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb @@ -0,0 +1,4 @@ +separate (Pkg) procedure Bar is +begin + null; +end Bar; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb new file mode 100644 index 000000000..fa79eb10a --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb @@ -0,0 +1,9 @@ +package body Pkg is + + procedure Foo is + begin + null; + end Foo; + + procedure Bar is separate; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads new file mode 100644 index 000000000..52d41a411 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Foo; + procedure Bar; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb new file mode 100644 index 000000000..b8658aeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb new file mode 100644 index 000000000..3c7879b61 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Foo is + begin + Put_Line ("Hello from main-body"); + end Foo; + + procedure Bar is separate; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb new file mode 100644 index 000000000..b8658aeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb new file mode 100644 index 000000000..2d280f90a --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) procedure Bar is +begin + Put_Line ("Hello from main-sep"); +end Bar; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb new file mode 100644 index 000000000..b8658aeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb new file mode 100644 index 000000000..2d8a449a0 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; + Pkg.Baz; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads new file mode 100644 index 000000000..953e0ab4b --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + procedure Foo; + procedure Bar; + procedure Baz is null; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/test.opt b/testsuite/tests/instr-cov/gpr-complex/test.opt new file mode 100644 index 000000000..a1bd93a6f --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/test.opt @@ -0,0 +1,2 @@ +!native DEAD hardcoded project files without board information +all-warnings XFAIL Warnings pending resolution of eng/das/cov/gnatcoverage#66 diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py new file mode 100644 index 000000000..32d35310c --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -0,0 +1,128 @@ +""" +This test checks that gnatcov correctly instruments projects with a complex +structure, and with unit parts implemented in different projects of the project +tree, some of them being instrumented while some of them not (through project +extension). +""" + +import os + +from e3.fs import cp + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprinstall + + +Wdir("tmp_") + +# Start by installing the library. Every main subproject depends on it. +install_dir = os.path.abspath("install") +cp(os.path.join("..", "src-lib"), ".", recursive=True) +lib_prj = os.path.join("src-lib", "lib.gpr") +xcov_instrument( + gprsw=GPRswitches(root_project=lib_prj), + covlevel="stmt", +) +gprbuild(lib_prj) +gprinstall( + lib_prj, + [ + f"--prefix={install_dir}", + "--src-subdirs=gnatcov-instr", + "--implicit-with=gnatcov_rts", + ], +) + +# Add the newly installed library to gprbuild's project lookup path. Use the +# ADA_PROJECT_PATH environment variable to be compatible with the 5.04 +# toolchain. +env.add_search_path( + "ADA_PROJECT_PATH", os.path.join(install_dir, "share", "gpr") +) + + +def check(label, name, expected_xcov): + """ + Copy the "name" project from the test directory to the current directory + and run it through the instrument/build/run/coverage steps. Check that the + coverage report produced matches "expected_cov". + """ + thistest.log(f"== {label} ({name}) ==") + + main_prj = f"{name}.gpr" + obj_dir = f"obj-{name}" + + cp(os.path.join("..", main_prj), ".", recursive=True) + cp(os.path.join("..", f"src-{name}"), ".", recursive=True) + + build_run_and_coverage( + gprsw=GPRswitches(root_project=os.path.join(main_prj)), + covlevel="stmt", + mains=["main"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + extra_coverage_args=[ + "--annotate=xcov", + "--externally-built-projects", + "--units=pkg", + ], + ) + check_xcov_reports(obj_dir, expected_xcov) + + +# Try the simple case: the main project extends the library, but does not +# redefine anything. +check( + "Simple case", + "main_simple", + expected_xcov={ + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {3}}, + }, +) + +# Now the main project defines an alternate body. TODO! as we reinstrument the +# whole unit if a part of it was redefined (including the parts that were not +# redefined), we end up instrumenting the instrumented version for sources +# belonging to the library. We should fix this (and adjust coverage +# expectations) if possible. +check( + "Redefining Pkg body", + "main_body", + expected_xcov={ + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {7}}, + "pkg-bar.adb.xcov": {"+": {3}}, + }, +) + + +# Now the main project defines an alternate separate. +check( + "Redefining Pkg.Bar separate", + "main_sep", + expected_xcov={ + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {5}}, + }, +) + +# Now the main project defines an alternate spec. +check( + "Redefining Pkg spec", + "main_spec", + expected_xcov={ + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {3}}, + "pkg.ads.xcov": {"+": {4}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb new file mode 100644 index 000000000..a23fbbfc7 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb @@ -0,0 +1,15 @@ +pragma Ada_2022; + +package body Pkg is + function Foo(A : Animal) return String is + begin + if -- # if + (case A is -- # case + when Dog | Cat => True, -- # when_dog_cat + when Cow => False) then -- # when_cow + return "pet"; -- # return_pet + else + return "cattle"; -- # return_cattle + end if; + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads new file mode 100644 index 000000000..c8fd54e02 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + type Animal is (Dog, Cat, Cow); + + function Foo(A : Animal) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb new file mode 100644 index 000000000..60fad0146 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_False is +begin + Put_Line (Foo (Cow)); +end Test_False; + +--# pkg.adb +-- /if/ l+ ## 0 +-- /case/ l! ## dT- +-- /when_dog_cat/ l! ## g- +-- /when_cow/ l! ## 0 +-- /return_pet/ l- ## s- +-- /return_cattle/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb new file mode 100644 index 000000000..bb260f8ba --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (Foo (Dog)); + Put_Line (Foo (Cow)); +end Test_Full; + +--# pkg.adb +-- /if/ l+ ## 0 +-- /case/ l+ ## 0 +-- /when/ l+ ## 0 +-- /return/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb new file mode 100644 index 000000000..d38e3d3c0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True is +begin + Put_Line (Foo (Cat)); +end Test_True; + +--# pkg.adb +-- /if/ l+ ## 0 +-- /case/ l! ## dF- +-- /when_dog_cat/ l! ## 0 +-- /when_cow/ l! ## g- +-- /return_pet/ l+ ## 0 +-- /return_cattle/ l- ## s- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py new file mode 100644 index 000000000..61ce1aba0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure decision coverage is not affected by case-expression +in if conditions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb new file mode 100644 index 000000000..12896ad8e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package body Life is + function Scream(A : Animal; Silent : Boolean) return String is + begin + return -- # return + (if not Silent then -- # if_cond + (case A is -- # case + when Dog => "Woof", -- # dog + when Cat => "Meow", -- # cat + when Cow => "Mooo") -- # cow + else "...."); -- # else + end Scream; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads new file mode 100644 index 000000000..123280c17 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads @@ -0,0 +1,5 @@ +package Life is + type Animal is (Dog, Cat, Cow); + + function Scream(A : Animal; Silent : Boolean) return String; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb new file mode 100644 index 000000000..fa2ad84a2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_All_Enum_True_False is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_All_Enum_True_False; + +--# life.adb +-- /dog/ l! ## g- +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb new file mode 100644 index 000000000..90476354a --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb @@ -0,0 +1,17 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, True)); + Put_Line (Scream (Cow, True)); + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_Full; + +--# life.adb +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb new file mode 100644 index 000000000..2146e7550 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Full is +begin + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Full; + +--# life.adb +-- /if_cond/ l! ## dF- +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb new file mode 100644 index 000000000..372dcbb20 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Part is +begin + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Part ; + +--# life.adb +-- /if_cond/ l! ## dF- +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb new file mode 100644 index 000000000..3ee3fdd73 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_True is +begin + Put_Line (Scream (Cow, True)); +end Test_If_True; + +--# life.adb +-- /if_cond/ l! ## dT- +-- /case/ l! ## g- +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb new file mode 100644 index 000000000..1dfd02e51 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String is + begin + return (case A is -- # ret + when True => -- # case_true + (if B then "TT" else "TF"), -- # if_true + when False => "F."); -- # case_false + end If_Expr_In_Case_Expr; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads new file mode 100644 index 000000000..444a4f375 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb new file mode 100644 index 000000000..158d89f1e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_False_Full is +begin + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_False_Full; + +--# pkg.adb +-- /case_true/ l! ## g- +-- /if_true/ l! ## g-,g-,d- +-- 2 gexpr violations (both branches of the unexecuted if) diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb new file mode 100644 index 000000000..eb6b1998e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_Full; + +--# pkg.adb +-- /ret/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l+ ## 0 +-- /case_false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb new file mode 100644 index 000000000..8b96031b0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); +end Test_True_Full; + +--# pkg.adb +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb new file mode 100644 index 000000000..4fe928be6 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Part is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); +end Test_True_Part; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l! ## dF-,g- +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/extra.opt b/testsuite/tests/instr-cov/guarded-exprs/extra.opt new file mode 100644 index 000000000..38e2aab7b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/extra.opt @@ -0,0 +1,3 @@ +5.04a1 DEAD Requires Ada 2022, unavailable 5.04a1 +7.1.2 DEAD Requires Ada 2022, unavailable in 7.1.2 +bin-traces DEAD coverage level not supported in binary traces diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb new file mode 100644 index 000000000..a619613c2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Pkg is + function Foo (A : Animal; B, C : Boolean) return String is + begin + return -- # return + (case A is -- # case + when Dog => "", -- # dog + when Cat => "Meow", -- # cat + when Cow => -- # cow + (if -- # if + B and then C -- # cond + then + "Moooh" -- # true + else + "No Moo :(")); -- # false + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads new file mode 100644 index 000000000..f5e9b9eab --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + type Animal is (Dog, Cat, Cow); + + function Foo (A : Animal; B, C : Boolean) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb new file mode 100644 index 000000000..4f734bd5e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (Foo (Dog, True, True)); + Put_Line (Foo (Cat, True, True)); + Put_Line (Foo (Cow, True, True)); + Put_Line (Foo (Cow, True, False)); + Put_Line (Foo (Cow, False, False)); +end Test_Full; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /cond/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb new file mode 100644 index 000000000..667ded0bf --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_MCDC_Not_Covered is +begin + Put_Line (Foo (Dog, True, True)); + Put_Line (Foo (Cat, True, True)); + Put_Line (Foo (Cow, True, True)); + Put_Line (Foo (Cow, False, False)); +end Test_MCDC_Not_Covered; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /cond/ l! ## c! +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb new file mode 100644 index 000000000..0f5315804 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb @@ -0,0 +1,16 @@ +pragma Ada_2022; + +package body Life is + function Animal_Is_Meowing (A : Animal) return Boolean is + begin + return -- # return + (declare -- # decl + Sound: constant String := -- # sound + (case A is -- # case + when Dog => "Woof", -- # dog + when Cat => "Meow", -- # cat + when Cow => "Mooo"); -- # cow + begin -- # begin + Sound = "Meow"); -- # cmp + end Animal_Is_Meowing; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads new file mode 100644 index 000000000..aed61f294 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads @@ -0,0 +1,5 @@ +package Life is + type Animal is (Dog, Cat, Cow); + + function Animal_Is_Meowing (A : Animal) return Boolean; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb new file mode 100644 index 000000000..217375830 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is +begin + Put_Line(Animal_Is_Meowing (Dog)'Image); + Put_Line(Animal_Is_Meowing (Cat)'Image); + Put_Line(Animal_Is_Meowing (Cow)'Image); +end Test_Full; + +--# life.adb +-- /return/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /sound/ l+ ## 0 +-- /case/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /begin/ l+ ## 0 +-- /cmp/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb new file mode 100644 index 000000000..6c8d256fe --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_None is +begin + null; +end Test_None; + +--# life.adb +-- /return/ l- ## s- +-- /decl/ l- ## 0 +-- /sound/ l- ## s- +-- /case/ l- ## 0 +-- /dog/ l- ## g- +-- /cat/ l- ## g- +-- /cow/ l- ## g- +-- /begin/ l- ## 0 +-- /cmp/ l- ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb new file mode 100644 index 000000000..4ea6c3b2b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Part is +begin + Put_Line(Animal_Is_Meowing (Cat)'Image); +end Test_Part; + +--# life.adb +-- /dog/ l! ## g- +-- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb new file mode 100644 index 000000000..12896ad8e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package body Life is + function Scream(A : Animal; Silent : Boolean) return String is + begin + return -- # return + (if not Silent then -- # if_cond + (case A is -- # case + when Dog => "Woof", -- # dog + when Cat => "Meow", -- # cat + when Cow => "Mooo") -- # cow + else "...."); -- # else + end Scream; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads new file mode 100644 index 000000000..123280c17 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads @@ -0,0 +1,5 @@ +package Life is + type Animal is (Dog, Cat, Cow); + + function Scream(A : Animal; Silent : Boolean) return String; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb new file mode 100644 index 000000000..fa2ad84a2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_All_Enum_True_False is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_All_Enum_True_False; + +--# life.adb +-- /dog/ l! ## g- +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb new file mode 100644 index 000000000..90476354a --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb @@ -0,0 +1,17 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, True)); + Put_Line (Scream (Cow, True)); + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_Full; + +--# life.adb +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb new file mode 100644 index 000000000..e5aed4903 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Full is +begin + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Full; + +--# life.adb +-- /if_cond/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb new file mode 100644 index 000000000..b44453214 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Part is +begin + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Part ; + +--# life.adb +-- /if_cond/ l+ ## 0 +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb new file mode 100644 index 000000000..2a977b171 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_True is +begin + Put_Line (Scream (Cow, True)); +end Test_If_True; + +--# life.adb +-- /if_cond/ l+ ## 0 +-- /case/ l! ## g- +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb new file mode 100644 index 000000000..1dfd02e51 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String is + begin + return (case A is -- # ret + when True => -- # case_true + (if B then "TT" else "TF"), -- # if_true + when False => "F."); -- # case_false + end If_Expr_In_Case_Expr; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads new file mode 100644 index 000000000..444a4f375 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb new file mode 100644 index 000000000..c2f8b42de --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_False_Full is +begin + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_False_Full; + +--# pkg.adb +-- /case_true/ l! ## g- +-- /if_true/ l! ## g-,g- +-- 2 gexpr violations (both branches of the unexecuted if) diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb new file mode 100644 index 000000000..eb6b1998e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_Full; + +--# pkg.adb +-- /ret/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l+ ## 0 +-- /case_false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb new file mode 100644 index 000000000..8b96031b0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); +end Test_True_Full; + +--# pkg.adb +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb new file mode 100644 index 000000000..508c0dfba --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Part is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); +end Test_True_Part; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l! ## g- +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb new file mode 100644 index 000000000..4b492793c --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb @@ -0,0 +1,13 @@ +pragma Ada_2022; + +package body Animal is + function Scream (A : Animal) return String is + Sound : constant String := -- # decl + (case A is -- # case_root + when Dog => "Woof", -- # alt_dog + when Cat => "Meow", -- # alt_cat + when Cow => "Mooo"); -- # alt_cow + begin + return Sound; -- # return + end Scream; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads new file mode 100644 index 000000000..4a288112d --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads @@ -0,0 +1,5 @@ +package Animal is + type Animal is (Dog, Cat, Cow); + + function Scream (A : Animal) return String; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb new file mode 100644 index 000000000..ef149ca67 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Full is +begin + Put_Line (Scream (Dog)); + Put_Line (Scream (Cat)); + Put_Line (Scream (Cow)); +end Test_Full; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l+ ## 0 +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb new file mode 100644 index 000000000..724a98b97 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_None is +begin + null; +end Test_None; + +--# animal.adb +-- /decl/ l- ## s- +-- /return/ l- ## s- +-- /case_root/ l- ## 0 +-- /alt_dog/ l- ## g- +-- /alt_cat/ l- ## g- +-- /alt_cow/ l- ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb new file mode 100644 index 000000000..fdcdda275 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Part is +begin + Put_Line (Scream (Cat)); +end Test_Part; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l! ## g- +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py new file mode 100644 index 000000000..871091395 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expressions in declaration sections are +correctly instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb new file mode 100644 index 000000000..0235f973b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package body Animal is + function Scream (A : Animal) return String is + begin + return -- # return + (case A is -- # case_root + when Dog => "Woof", -- # alt_dog + when Cat => "Meow", -- # alt_cat + when Cow => "Mooo"); -- # alt_cow + end Scream; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads new file mode 100644 index 000000000..4a288112d --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads @@ -0,0 +1,5 @@ +package Animal is + type Animal is (Dog, Cat, Cow); + + function Scream (A : Animal) return String; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb new file mode 100644 index 000000000..ef149ca67 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Full is +begin + Put_Line (Scream (Dog)); + Put_Line (Scream (Cat)); + Put_Line (Scream (Cow)); +end Test_Full; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l+ ## 0 +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb new file mode 100644 index 000000000..cf5e01f44 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_None is +begin + null; +end Test_None; + +--# animal.adb +-- /return/ l- ## s- +-- /case_root/ l- ## 0 +-- /alt_dog/ l- ## g- +-- /alt_cat/ l- ## g- +-- /alt_cow/ l- ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb new file mode 100644 index 000000000..fdcdda275 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Part is +begin + Put_Line (Scream (Cat)); +end Test_Part; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l! ## g- +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py new file mode 100644 index 000000000..5cef9ffd0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expressions in assignation statements are +correctly instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb new file mode 100644 index 000000000..1f2d35dbe --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Life is + function Scream (A : Animal) return String is + begin + return -- # return + (case A.T is -- # case_animal + when Mammal => -- # when_mammal + (case A.M_Kind is -- # case_mammal + when Dog => "Woof", -- # when_dog + when Cat => "Meow", -- # when_cat + when Cow => "Mooo"), -- # when_cow + when Reptile => -- # when_reptile + (case A.R_Kind is -- # case_reptile + when Snake => "Ssss", -- # when_snake + when Turtle => "....")); -- # when_turtle + end Scream; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads new file mode 100644 index 000000000..3105bec63 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads @@ -0,0 +1,16 @@ +package Life is + type Mammal_Kind is (Dog, Cat, Cow); + type Reptile_Kind is (Snake, Turtle); + type Animal_Kind is (Mammal, Reptile); + + type Animal (T : Animal_Kind) is record + case T is + when Mammal => + M_Kind : Mammal_Kind; + when Reptile => + R_Kind : Reptile_Kind; + end case; + end record; + + function Scream (A : Animal) return String; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb new file mode 100644 index 000000000..72634b9df --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb @@ -0,0 +1,26 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is + A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); + A_Cat : constant Animal := (T => Mammal, M_Kind => Cat); + A_Cow : constant Animal := (T => Mammal, M_Kind => Cow); + A_Snake : constant Animal := (T => Reptile, R_Kind => Snake); + A_Turtle : constant Animal := (T => Reptile, R_Kind => Turtle); +begin + Put_Line (Scream (A_Dog)); + Put_Line (Scream (A_Cat)); + Put_Line (Scream (A_Cow)); + Put_Line (Scream (A_Snake)); + Put_Line (Scream (A_Turtle)); +end Test_Full; + +--# life.adb +-- /return/ l+ ## 0 +-- /when_mammal/ l+ ## 0 +-- /when_dog/ l+ ## 0 +-- /when_cat/ l+ ## 0 +-- /when_cow/ l+ ## 0 +-- /when_reptile/ l+ ## 0 +-- /when_snake/ l+ ## 0 +-- /when_turtle/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb new file mode 100644 index 000000000..9faf73b26 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_None is +begin + null; +end Test_None; + +--# life.adb +-- /return/ l- ## s- +-- /case_animal/ l- ## 0 +-- /when_mammal/ l- ## g- +-- /case_mammal/ l- ## 0 +-- /when_dog/ l- ## g- +-- /when_cat/ l- ## g- +-- /when_cow/ l- ## g- +-- /when_reptile/ l- ## g- +-- /case_reptile/ l- ## 0 +-- /when_snake/ l- ## g- +-- /when_turtle/ l- ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb new file mode 100644 index 000000000..f45ecd3fe --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb @@ -0,0 +1,23 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Partial_Leaf is + A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); + A_Cat : constant Animal := (T => Mammal, M_Kind => Cat); + A_Cow : constant Animal := (T => Mammal, M_Kind => Cow); +begin + Put_Line (Scream (A_Dog)); + Put_Line (Scream (A_Cat)); + Put_Line (Scream (A_Cow)); +end Test_Partial_Leaf; + +--# life.adb +-- /return/ l+ ## 0 +-- /when_mammal/ l+ ## 0 +-- /when_dog/ l+ ## 0 +-- /when_cat/ l+ ## 0 +-- /when_cow/ l+ ## 0 +-- /when_reptile/ l! ## g- +-- /case_reptile/ l! ## 0 +-- /when_snake/ l! ## g- +-- /when_turtle/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb new file mode 100644 index 000000000..1642bdf5a --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Partial_Root is + A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); + A_Snake : constant Animal := (T => Reptile, R_Kind => Snake); +begin + Put_Line (Scream (A_Dog)); + Put_Line (Scream (A_Snake)); +end Test_Partial_Root; + +--# life.adb +-- /return/ l+ ## 0 +-- /when_mammal/ l+ ## 0 +-- /when_dog/ l+ ## 0 +-- /when_cat/ l! ## g- +-- /when_cow/ l! ## g- +-- /when_reptile/ l+ ## 0 +-- /when_snake/ l+ ## 0 +-- /when_turtle/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py new file mode 100644 index 000000000..74ff286ee --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that nested case-expressions are correctly +instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb new file mode 100644 index 000000000..a07bcf9aa --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb @@ -0,0 +1,8 @@ +pragma Ada_2022; + +package body Pkg is + function Foo (A, B : Natural) return Boolean is + begin + return (for some I in A .. B => I = 10); -- # expr + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads new file mode 100644 index 000000000..8545d840f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function Foo (A, B : Natural) return Boolean; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb new file mode 100644 index 000000000..5d70df138 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Empty is + result : Boolean := Foo (1, 0); +begin + null; +end Test_Empty; + +--# pkg.adb +-- /expr/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb new file mode 100644 index 000000000..524e17085 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Non_Empty is + result : Boolean := Foo (1, 5); +begin + null; +end Test_Non_Empty; + +--# pkg.adb +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py new file mode 100644 index 000000000..84cfc812b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py @@ -0,0 +1,9 @@ +""" +Regression test: Ensure that quantified-expressions are correctly instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb new file mode 100644 index 000000000..0fbcfbb80 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Animal is + function Scream (A : Animal) return String is + begin + return -- # return + (case A is -- # case_root + when Dog => "Woof", -- # alt_dog + when Cat => "Meow", -- # alt_cat + when Cow => "Mooo"); -- # alt_cow + end Scream; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads new file mode 100644 index 000000000..4a288112d --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads @@ -0,0 +1,5 @@ +package Animal is + type Animal is (Dog, Cat, Cow); + + function Scream (A : Animal) return String; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb new file mode 100644 index 000000000..3ad6e4689 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Full is +begin + Put_Line (Scream (Dog)); + Put_Line (Scream (Cat)); + Put_Line (Scream (Cow)); +end Test_Full; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l? ## g? +-- /alt_cat/ l? ## g? +-- /alt_cow/ l? ## g? diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py new file mode 100644 index 000000000..775ee0d1b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py @@ -0,0 +1,13 @@ +""" +Regression test: Check the "undetermined coverage" for guarded expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase( + gexpr_lvl=True, + tolerate_messages="warning: Guarded Expression coverage is not" + " available before Ada2022", +).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/hidden_standard/src/std.adb b/testsuite/tests/instr-cov/hidden_standard/src/std.adb new file mode 100644 index 000000000..0e1074238 --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/src/std.adb @@ -0,0 +1,12 @@ +package body Std is + Top_Category : Boolean := (Cat = Premium); + + type My_Bool is new Boolean; + + procedure Process (X : in out Integer) is + begin + if My_Bool (Top_Category) then -- # eval + X := X + 15; + end if; + end Process; +end Std; diff --git a/testsuite/tests/instr-cov/hidden_standard/src/std.ads b/testsuite/tests/instr-cov/hidden_standard/src/std.ads new file mode 100644 index 000000000..7e55af6a7 --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/src/std.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Std is + type Category is (Standard, System, Premium); + + Cat : Category := Premium; + pragma Volatile (Cat); + + procedure Process (X : in out Integer); +end; diff --git a/testsuite/tests/instr-cov/hidden_standard/src/test_std.adb b/testsuite/tests/instr-cov/hidden_standard/src/test_std.adb new file mode 100644 index 000000000..5e9991bae --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/src/test_std.adb @@ -0,0 +1,14 @@ +-- test_std.adb + +with Std; +with Support; use Support; + +procedure Test_Std is + X : Integer := 12; +begin + Std.Process (X); + Assert (X = 12 + 15); +end; + +--# std.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/instr-cov/hidden_standard/test.py b/testsuite/tests/instr-cov/hidden_standard/test.py new file mode 100644 index 000000000..36055a8ed --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/test.py @@ -0,0 +1,11 @@ +""" +This is a regression test that checks that gnatcov produces valid code even +if the standard package is hidden by a user-defined enumeration member. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/include_switch/main.c b/testsuite/tests/instr-cov/include_switch/main.c new file mode 100644 index 000000000..36cedc329 --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/main.c @@ -0,0 +1,15 @@ +int +main (void) +{ + hello_from_pkg1 (); + hello_from_pkg2 (); + hello_from_pkg3 (); + hello_from_pkg4 (); + return 0; +} + +void +print_msg (const char *msg) +{ + (void *) msg; +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg1.h b/testsuite/tests/instr-cov/include_switch/pkg1.h new file mode 100644 index 000000000..2ef0ae73c --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg1.h @@ -0,0 +1,7 @@ +extern void print_msg (const char *msg); + +void +hello_from_pkg1 (void) +{ + print_msg ("Hello from pkg1\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg2.h b/testsuite/tests/instr-cov/include_switch/pkg2.h new file mode 100644 index 000000000..be0316e2c --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg2.h @@ -0,0 +1,7 @@ +extern void print_msg (const char *msg); + +void +hello_from_pkg2 (void) +{ + print_msg ("Hello from pkg2\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg3.h b/testsuite/tests/instr-cov/include_switch/pkg3.h new file mode 100644 index 000000000..1e228d9a1 --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg3.h @@ -0,0 +1,7 @@ +extern void print_msg (const char *msg); + +void +hello_from_pkg3 (void) +{ + print_msg ("Hello from pkg3\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg4.h b/testsuite/tests/instr-cov/include_switch/pkg4.h new file mode 100644 index 000000000..8571386eb --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg4.h @@ -0,0 +1,7 @@ +extern void print_msg (const char *msg); + +void +hello_from_pkg4 (void) +{ + print_msg ("Hello from pkg4\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/test.opt b/testsuite/tests/instr-cov/include_switch/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/include_switch/test.py b/testsuite/tests/instr-cov/include_switch/test.py new file mode 100644 index 000000000..56e9e3f63 --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/test.py @@ -0,0 +1,47 @@ +""" +Check that gnatcov instrument correctly processes `-include` switches which can +alter the preprocessing of the file. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Test every possible way for extra safety +c_opts = [ + ["--include=../pkg1.h"], + ["--include", "../pkg2.h"], + ["-include", "../pkg3.h"], + ["-include../pkg4.h"], +] + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=( + ["--c-opts={}".format(",".join(args)) for args in c_opts] + ), + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", + { + "main.c.xcov": {"+": {4, 5, 6, 7, 8, 14}}, + "pkg1.h.xcov": {"+": {6}}, + "pkg2.h.xcov": {"+": {6}}, + "pkg3.h.xcov": {"+": {6}}, + "pkg4.h.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/library_projects/.gitignore b/testsuite/tests/instr-cov/library_projects/.gitignore new file mode 100644 index 000000000..429797921 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/.gitignore @@ -0,0 +1,3 @@ +obj-main +obj-math +obj-vectors diff --git a/testsuite/tests/instr-cov/library_projects/main.gpr b/testsuite/tests/instr-cov/library_projects/main.gpr new file mode 100644 index 000000000..df0b267e7 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/main.gpr @@ -0,0 +1,8 @@ +with "math"; +with "vectors"; + +project Main is + for Source_Dirs use ("src-main"); + for Object_Dir use "obj-main"; + for Main use ("main.adb"); +end Main; diff --git a/testsuite/tests/instr-cov/library_projects/math.gpr b/testsuite/tests/instr-cov/library_projects/math.gpr new file mode 100644 index 000000000..c7c1baaa5 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/math.gpr @@ -0,0 +1,4 @@ +project Math is + for Source_Dirs use ("src-math"); + for Object_Dir use "obj-math"; +end Math; diff --git a/testsuite/tests/instr-cov/library_projects/src-main/main.adb b/testsuite/tests/instr-cov/library_projects/src-main/main.adb new file mode 100644 index 000000000..22e390882 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-main/main.adb @@ -0,0 +1,14 @@ +with Math; +with Vectors; + +procedure Main is + package Number_Vectors is new Vectors (Math.Number, 10); + + use Math, Number_Vectors; + + V : Vector; +begin + Push (V, From_Integer (1)); + Push (V, From_Integer (2)); + Push (V, Element (V, 1) + Element (V, Last_Index (V))); +end Main; diff --git a/testsuite/tests/instr-cov/library_projects/src-math/math.adb b/testsuite/tests/instr-cov/library_projects/src-math/math.adb new file mode 100644 index 000000000..08fd53202 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-math/math.adb @@ -0,0 +1,18 @@ +package body Math is + + function From_Integer (Value : Integer) return Number is + begin + return (Value => Value); + end From_Integer; + + function "+" (Left, Right : Number) return Number is + begin + return (Value => Left.Value + Right.Value); + end "+"; + + function "-" (Left, Right : Number) return Number is + begin + return (Value => Left.Value - Right.Value); + end "-"; + +end Math; diff --git a/testsuite/tests/instr-cov/library_projects/src-math/math.ads b/testsuite/tests/instr-cov/library_projects/src-math/math.ads new file mode 100644 index 000000000..493a7c2dc --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-math/math.ads @@ -0,0 +1,15 @@ +package Math is + + type Number is private; + + function From_Integer (Value : Integer) return Number; + function "+" (Left, Right : Number) return Number; + function "-" (Left, Right : Number) return Number; + +private + + type Number is record + Value : Integer; + end record; + +end Math; diff --git a/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb new file mode 100644 index 000000000..a54bd10ab --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb @@ -0,0 +1,32 @@ +package body Vectors is + + function Last_Index (Self : Vector) return Natural is + begin + return Self.Last_Index; + end Last_Index; + + function Element (Self : Vector; Index : Positive) return Element_Type is + begin + return Self.Elements (Index); + end Element; + + procedure Push (Self : in out Vector; Element : Element_Type) is + begin + if Self.Last_Index = Capacity then + raise Constraint_Error; + else + Self.Last_Index := Self.Last_Index + 1; + Self.Elements (Self.Last_Index) := ElemenT; + end if; + end Push; + + procedure Pop (Self : in out Vector) is + begin + if Self.Last_Index = 0 then + raise Constraint_Error; + else + Self.Last_Index := Self.Last_Index - 1; + end if; + end Pop; + +end Vectors; diff --git a/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads new file mode 100644 index 000000000..c600f2a90 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads @@ -0,0 +1,22 @@ +generic + type Element_Type is private; + Capacity : Natural; +package Vectors is + + type Vector is private; + + function Last_Index (Self : Vector) return Natural; + function Element (Self : Vector; Index : Positive) return Element_Type; + procedure Push (Self : in out Vector; Element : Element_Type); + procedure Pop (Self : in out Vector); + +private + + type Element_Array is array (1 .. Capacity) of Element_Type; + + type Vector is record + Elements : Element_Array; + Last_Index : Natural := 0; + end record; + +end Vectors; diff --git a/testsuite/tests/instr-cov/library_projects/test.py b/testsuite/tests/instr-cov/library_projects/test.py new file mode 100644 index 000000000..01384418a --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/test.py @@ -0,0 +1,42 @@ +""" +Test that instrumented source coverage works as expected on a setup of library +projects and one program project. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +main_gpr = os.path.abspath("main.gpr") +main_obj_dir = os.path.abspath("obj-main") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=main_gpr, projects=["main", "math", "vectors"] + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=main_obj_dir, + gpr_exe_dir=main_obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 9, 11, 12, 13}}, + "vectors.ads.xcov": {"+": {6, 15, 17, 18, 19, 20}}, + "vectors.adb.xcov": {"+": {5, 10, 15, 18, 19}, "-": {16, 25, 26, 28}}, + "math.ads.xcov": {"+": {3, 11, 12, 13}}, + "math.adb.xcov": {"+": {5, 10}, "-": {15}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/library_projects/vectors.gpr b/testsuite/tests/instr-cov/library_projects/vectors.gpr new file mode 100644 index 000000000..3509e8264 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/vectors.gpr @@ -0,0 +1,4 @@ +project Vectors is + for Source_Dirs use ("src-vectors"); + for Object_Dir use "obj-vectors"; +end Vectors; diff --git a/testsuite/tests/instr-cov/logging/baseline-my_tool.txt b/testsuite/tests/instr-cov/logging/baseline-my_tool.txt new file mode 100644 index 000000000..9a276ad33 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/baseline-my_tool.txt @@ -0,0 +1,19 @@ +info: creating output path [TMP]/obj/my_tool +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing My_Tool + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/my_tool.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/my_tool/my_tool-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +Coverage instrumentation + [C++] my_tool.cpp +[GNATCOV.INSTRUMENT_SOURCES] Writing C++ buffer unit [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrt_b_[HASH#1].cpp + [GNATCOV.INSTRUMENT_SOURCES] Project: My_Tool + [GNATCOV.INSTRUMENT_SOURCES] For files: + [GNATCOV.INSTRUMENT_SOURCES] * [TMP]/src-my_tool/my_tool.cpp +Main instrumentation + [C++] my_tool.cpp +[GNATCOV.INSTRUMENT_SOURCES] Writing C++ dump helper unit [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrt_d_[HASH#2].cpp + [GNATCOV.INSTRUMENT_SOURCES] Project: My_Tool + [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrt_d_[HASH#2].cpp + [GNATCOV.INSTRUMENT_SOURCES] For main: [TMP]/obj/my_tool/my_tool-gnatcov-instr/my_tool.cpp +[GNATCOV.INSTRUMENT_SOURCES] Writing C++ buffer list unit [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrtc-my_tool.cpp + [GNATCOV.INSTRUMENT_SOURCES] Project: My_Tool diff --git a/testsuite/tests/instr-cov/logging/baseline-tests.txt b/testsuite/tests/instr-cov/logging/baseline-tests.txt new file mode 100644 index 000000000..6debef3d4 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/baseline-tests.txt @@ -0,0 +1,58 @@ +info: creating output path [TMP]/obj/tests +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib/mylib-gnatcov-instr +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib_Extended + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib_extended.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Harness + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/harness.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/harness/harness-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it is an externally built project +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Tests + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/tests.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/tests/tests-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +Coverage instrumentation + [Ada] mylib +[GNATCOV.INSTRUMENT_SOURCES] Instrumenting mylib.ads +[GNATCOV.INSTRUMENT_SOURCES] Instrumenting mylib.adb +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada buffer unit GCVRT.B[HASH#1] + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib_Extended + [GNATCOV.INSTRUMENT_SOURCES] Filename: gcvrt-b[HASH#1].ads + [GNATCOV.INSTRUMENT_SOURCES] For units: + [GNATCOV.INSTRUMENT_SOURCES] * mylib spec + [GNATCOV.INSTRUMENT_SOURCES] * mylib body +[GNATCOV.INSTRUMENT_SOURCES] Writing pure Ada buffer unit GCVRT.P[HASH#1] + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib_Extended + [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr/gcvrt-p[HASH#1].ads + [GNATCOV.INSTRUMENT_SOURCES] For units: + [GNATCOV.INSTRUMENT_SOURCES] * mylib spec + [GNATCOV.INSTRUMENT_SOURCES] * mylib body + [C] mylib_ext.c +[GNATCOV.INSTRUMENT_SOURCES] Writing C buffer unit [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr/gcvrt_b_[HASH#2].c + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib_Extended + [GNATCOV.INSTRUMENT_SOURCES] For files: + [GNATCOV.INSTRUMENT_SOURCES] * [TMP]/src-mylib/mylib_ext.c +Main instrumentation + [Ada] test1 +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada dump helper unit GCVRT.DB_[HASH#3] + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Spec filename: gcvrt-db_[HASH#3].ads + [GNATCOV.INSTRUMENT_SOURCES] Body filename: gcvrt-db_[HASH#3].adb + [GNATCOV.INSTRUMENT_SOURCES] For main: test1 body + [Ada] test2 +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada dump helper unit GCVRT.DB_[HASH#4] + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Spec filename: gcvrt-db_[HASH#4].ads + [GNATCOV.INSTRUMENT_SOURCES] Body filename: gcvrt-db_[HASH#4].adb + [GNATCOV.INSTRUMENT_SOURCES] For main: test2 body + [C] test3.c +[GNATCOV.INSTRUMENT_SOURCES] Writing C dump helper unit [TMP]/obj/tests/tests-gnatcov-instr/gcvrt_d_[HASH#5].c + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/tests/tests-gnatcov-instr/gcvrt_d_[HASH#5].c + [GNATCOV.INSTRUMENT_SOURCES] For main: [TMP]/src-tests/test3.c +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada buffer list unit GCVRT.Tests + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Filename: gcvrt-tests.ads diff --git a/testsuite/tests/instr-cov/logging/harness.gpr b/testsuite/tests/instr-cov/logging/harness.gpr new file mode 100644 index 000000000..1bc47f73d --- /dev/null +++ b/testsuite/tests/instr-cov/logging/harness.gpr @@ -0,0 +1,6 @@ +project Harness is + + for Source_Dirs use ("src-harness"); + for Object_Dir use "obj/harness"; + for Externally_Built use external ("HARNESS_BUILT", "true"); +end Harness; diff --git a/testsuite/tests/instr-cov/logging/my_tool.gpr b/testsuite/tests/instr-cov/logging/my_tool.gpr new file mode 100644 index 000000000..6794d38f4 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/my_tool.gpr @@ -0,0 +1,6 @@ +project My_Tool is + for Languages use ("C++"); + for Source_Dirs use ("src-my_tool"); + for Object_Dir use "obj/my_tool"; + for Main use ("my_tool.cpp"); +end My_Tool; diff --git a/testsuite/tests/instr-cov/logging/mylib.gpr b/testsuite/tests/instr-cov/logging/mylib.gpr new file mode 100644 index 000000000..b4f45385e --- /dev/null +++ b/testsuite/tests/instr-cov/logging/mylib.gpr @@ -0,0 +1,5 @@ +project Mylib is + for Languages use ("Ada", "C"); + for Source_Dirs use ("src-mylib"); + for Object_Dir use "obj/mylib"; +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/mylib_extended.gpr b/testsuite/tests/instr-cov/logging/mylib_extended.gpr new file mode 100644 index 000000000..3d287687d --- /dev/null +++ b/testsuite/tests/instr-cov/logging/mylib_extended.gpr @@ -0,0 +1,4 @@ +project Mylib_Extended extends "mylib.gpr" is + for Source_Dirs use ("src-mylib_extended"); + for Object_Dir use "obj/mylib_extended"; +end Mylib_Extended; diff --git a/testsuite/tests/instr-cov/logging/src-harness/harness.adb b/testsuite/tests/instr-cov/logging/src-harness/harness.adb new file mode 100644 index 000000000..6a7980d9b --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-harness/harness.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Harness is + + ------------------ + -- Assert_Equal -- + ------------------ + + procedure Assert_Equal (Label : String; Expected, Actual : Integer) is + begin + if Expected = Actual then + Put_Line ("OK " & Label); + else + Put_Line ("FAIL " & Label); + end if; + end Assert_Equal; + +end Harness; diff --git a/testsuite/tests/instr-cov/logging/src-harness/harness.ads b/testsuite/tests/instr-cov/logging/src-harness/harness.ads new file mode 100644 index 000000000..233aa8312 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-harness/harness.ads @@ -0,0 +1,3 @@ +package Harness is + procedure Assert_Equal (Label : String; Expected, Actual : Integer); +end Harness; diff --git a/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp b/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp new file mode 100644 index 000000000..f951746e3 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp @@ -0,0 +1,11 @@ +void +print_msg (const char *) +{ +} + +int +main () +{ + std::cout << "Hello world" << std::endl; + return 0; +} diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib.adb b/testsuite/tests/instr-cov/logging/src-mylib/mylib.adb new file mode 100644 index 000000000..60555e524 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads b/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads new file mode 100644 index 000000000..0d34eadd9 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads @@ -0,0 +1,8 @@ +package Mylib is + + function Next (I : Integer) return Integer; + + function Identity (I : Integer) return Integer + with Import, Convention => C, External_Name => "mylib__identity"; + +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c b/testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c new file mode 100644 index 000000000..042960c32 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c @@ -0,0 +1,5 @@ +int +mylib__identity (int i) +{ + return i; +} diff --git a/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads b/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads new file mode 100644 index 000000000..0350894d6 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads @@ -0,0 +1,9 @@ +package Mylib is + + function Next (I : Integer) return Integer; + function Prev (I : Integer) return Integer is (I - 1); + + function Identity (I : Integer) return Integer + with Import, Convention => C, External_Name => "mylib__identity"; + +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-tests/test1.adb b/testsuite/tests/instr-cov/logging/src-tests/test1.adb new file mode 100644 index 000000000..98c282ae3 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-tests/test1.adb @@ -0,0 +1,8 @@ +with Harness; +with Mylib; + +procedure Test1 is +begin + Harness.Assert_Equal ("Next (0)", 1, Mylib.Next (0)); + Harness.Assert_Equal ("Next (1)", 2, Mylib.Next (1)); +end Test1; diff --git a/testsuite/tests/instr-cov/logging/src-tests/test2.adb b/testsuite/tests/instr-cov/logging/src-tests/test2.adb new file mode 100644 index 000000000..fbd995e98 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-tests/test2.adb @@ -0,0 +1,8 @@ +with Harness; +with Mylib; + +procedure Test2 is +begin + Harness.Assert_Equal ("Prev (1)", 0, Mylib.Prev (1)); + Harness.Assert_Equal ("Prev (2)", 1, Mylib.Prev (2)); +end Test2; diff --git a/testsuite/tests/instr-cov/logging/src-tests/test3.c b/testsuite/tests/instr-cov/logging/src-tests/test3.c new file mode 100644 index 000000000..c7932deb4 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-tests/test3.c @@ -0,0 +1,18 @@ +#include + +extern int mylib__identity (int); + +static void +assert_equal (const char *label, int expected, int actual) +{ + const char *status = (expected == actual) ? "OK " : "FAIL"; + printf ("%s %s\n", status, label); +} + +int +main (void) +{ + assert_equal ("Identity (0)", 0, mylib__identity (0)); + assert_equal ("Identity (1)", 1, mylib__identity (1)); + return 0; +} diff --git a/testsuite/tests/instr-cov/logging/test.opt b/testsuite/tests/instr-cov/logging/test.opt new file mode 100644 index 000000000..4cd5a9881 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/test.opt @@ -0,0 +1 @@ +!C++ DEAD C++ toolchain required to instrument C++ sources diff --git a/testsuite/tests/instr-cov/logging/test.py b/testsuite/tests/instr-cov/logging/test.py new file mode 100644 index 000000000..49fccb8d1 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/test.py @@ -0,0 +1,154 @@ +""" +Check that "gnatcov instrument" produces the expected debug logging. +""" + +from __future__ import annotations + +import glob +import os.path +import re + +from e3.fs import mkdir, sync_tree +from e3.testsuite.driver.diff import OutputRefiner, Substitute + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +# Copy projects and their sources in a temporary directory +tmp = Wdir("tmp_") +for pattern in ["*.gpr", "src-*"]: + for item in glob.glob(os.path.join("..", pattern)): + sync_tree(item, os.path.basename(item)) + +# Create an instrumentation output directories to exercise +# INSTRUMENT_CLEAN_OBJDIRS variations. +for project in ["mylib", "harness"]: + mkdir(os.path.join("obj", project, f"{project}-gnatcov-instr")) + + +class HashRefiner(OutputRefiner): + """Output refiner to hide hashes from the instrumented files. + + Actual hashes are not portable as they vary depending on the absolute path + for original source files. + """ + + hash_re = re.compile("z([0-9a-f]{8})") + + def __init__(self): + self.map = {} + + def repl(self, match): + hash_value = match.group(0) + try: + return self.map[hash_value] + except KeyError: + result = f"[HASH#{len(self.map) + 1}]" + self.map[hash_value] = result + return result + + def refine(self, output): + return self.hash_re.sub(self.repl, output) + + +class SortByFiles(OutputRefiner): + """Output refiner to sort lines by instrumented source file. + + The order in which "gnatcov instrument" processes units is not specified, + and varies in practice. This refiner reorders logs to have stable + baselines. + """ + + def refine(self, output): + result = [] + + # When processing a section that contains logs for a list of source + # files ("Coverage instrumentation" or "Main instrumentation"), + # "by_file" maps seen filenames to the corresponding list of log lines + # while "current_file" designates the last file seen for that section. + by_file = None + current_file = None + + def flush_files(): + """Append all log lines for files seen so far to result.""" + if by_file is None: + return + for _, lines in sorted(by_file.items()): + result.extend(lines) + + for line in output.splitlines(): + if line in ("Coverage instrumentation", "Main instrumentation"): + # This line starts a new section: flush log lines for the + # previous section (if any) and reset "by_file" and + # "current_file" to be ready for the new section. + flush_files() + by_file = {} + current_file = None + result.append(line) + elif line.startswith( + "[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing " + ): + _, project_name = line.rsplit(None, 1) + if by_file is None: + flush_files() + by_file = {} + by_file[project_name] = [line] + current_file = project_name + elif by_file is None: + # No section being processed: just forward this log line + result.append(line) + else: + # If this line marks the start of processing for a new source + # file, set "current_file" accordingly and start a new log line + # for it. + chunks = line.split() + if len(chunks) == 2 and chunks[0] in ("[Ada]", "[C]", "[C++]"): + current_file = chunks[1] + assert current_file not in by_file + by_file[current_file] = [line] + else: + by_file[current_file].append(line) + flush_files() + + return "".join(f"{line}\n" for line in result) + + +# Run "gnatcov instrument" and check its output against our logging baselines +# for all example projects. +for project, subproject in [("tests", "mylib"), ("my_tool", "my_tool")]: + log = f"instr-{project}.txt" + xcov( + [ + "instrument", + f"-P{project}.gpr", + "-cstmt", + f"--projects={subproject}", + "--log=instrument_clean_objdirs", + "--log=instrument_sources", + # Some automatic dump triggers (ravenscar-task-termination) are not + # available for all languages: instrumenting a C/C++ project with + # the default dump trigger in some configurations yields a warning. + # Explicitly ask for a dump trigger that is always supported to + # avoid this warning. + "--dump-trigger=main-end", + ], + out=log, + ) + thistest.fail_if_diff( + baseline_file=f"../baseline-{project}.txt", + actual_file=log, + failure_message=f'[{project}] "gnatcov instrument" output', + # To have portable baseline comparison, hide the actual CWD and + # canonicalize directory separators. + output_refiners=[ + Substitute(os.getcwd(), "[TMP]"), + SortByFiles(), + HashRefiner(), + Substitute("\\", "/"), + ], + ignore_white_chars=False, + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/logging/tests.gpr b/testsuite/tests/instr-cov/logging/tests.gpr new file mode 100644 index 000000000..697814df3 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/tests.gpr @@ -0,0 +1,9 @@ +with "harness"; +with "mylib_extended"; + +project Tests is + for Languages use ("Ada", "C"); + for Source_Dirs use ("src-tests"); + for Object_Dir use "obj/tests"; + for Main use ("test1.adb", "test2.adb", "test3.c"); +end Tests; diff --git a/testsuite/tests/instr-cov/main-spec/generic_main.adb b/testsuite/tests/instr-cov/main-spec/generic_main.adb new file mode 100644 index 000000000..b10af690c --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/generic_main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Generic_Main is +begin + Put_Line ("Hello world"); +end Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/generic_main.ads b/testsuite/tests/instr-cov/main-spec/generic_main.ads new file mode 100644 index 000000000..9a4ff9488 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/generic_main.ads @@ -0,0 +1,2 @@ +generic +procedure Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/inst_main.ads b/testsuite/tests/instr-cov/main-spec/inst_main.ads new file mode 100644 index 000000000..8969c0e8a --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/inst_main.ads @@ -0,0 +1,3 @@ +with Generic_Main; + +procedure Inst_Main is new Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/pkg-child_main.ads b/testsuite/tests/instr-cov/main-spec/pkg-child_main.ads new file mode 100644 index 000000000..b911b12a5 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/pkg-child_main.ads @@ -0,0 +1,3 @@ +with Generic_Main; + +procedure Pkg.Child_Main is new Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/pkg.ads b/testsuite/tests/instr-cov/main-spec/pkg.ads new file mode 100644 index 000000000..2db1f1de6 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/pkg.ads @@ -0,0 +1,2 @@ +package Pkg is +end Pkg; diff --git a/testsuite/tests/instr-cov/main-spec/test.py b/testsuite/tests/instr-cov/main-spec/test.py new file mode 100644 index 000000000..a6b18e367 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/test.py @@ -0,0 +1,45 @@ +""" +Check that instrumentation with automatic dump works correctly when the main is +an Ada spec. +""" + +import os.path + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir() + +main_sources = ["inst_main.ads", "pkg-child_main.ads"] +mains = [os.path.splitext(f)[0] for f in main_sources] + +expected_cov = { + "generic_main.adb.xcov": {"+": {5}}, + "inst_main.ads.xcov": {}, + "pkg-child_main.ads.xcov": {}, +} +if thistest.options.trace_mode == "src": + expected_cov["generic_main.ads.xcov"] = {} + expected_cov["pkg.ads.xcov"] = {} + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + thistest.log(f"== {dump_trigger} ==") + tmp.to_subdir(f"tmp_{dump_trigger}") + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=main_sources, srcdirs=[".."]), + ), + covlevel="stmt", + mains=mains, + extra_coverage_args=["--annotate=xcov"], + ) + check_xcov_reports("obj", expected_cov, discard_empty=False) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb new file mode 100644 index 000000000..026a2fb5d --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb @@ -0,0 +1,10 @@ +with Interfaces.C; use Interfaces.C; + +procedure Main is + function fact (N : int) return int; + pragma Import (C, fact); +begin + if fact (1) /= 1 then + raise Program_Error; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c new file mode 100644 index 000000000..6b157b0fe --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c @@ -0,0 +1,8 @@ +int +fact (int n) +{ + if (n <= 1) + return n; + else + return n * fact (n - 1); +} diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c new file mode 100644 index 000000000..b22f14e53 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c @@ -0,0 +1,10 @@ +extern int fact (int n); +extern void check (int c); + +int +main (void) +{ + int n = fact (1); + check (n == 1); + return 0; +} diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb new file mode 100644 index 000000000..9debcbf5f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb @@ -0,0 +1,27 @@ +package body Pkg is + + ---------- + -- Fact -- + ---------- + + function Fact (N : int) return int is + begin + if N <= 1 then + return N; + else + return N * Fact (N - 1); + end if; + end Fact; + + ----------- + -- Check -- + ----------- + + procedure Check (Cond : int) is + begin + if Cond = 0 then + raise Program_Error; + end if; + end Check; + +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads new file mode 100644 index 000000000..eecc1958c --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads @@ -0,0 +1,13 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + + function Fact (N : int) return int; + pragma Export (C, Fact, "fact"); + + procedure Check (Cond : int); + pragma Export (C, Check, "check"); + -- This is akin to "assert", with an int arg and not + -- conflicting with the libsupport exposed one. + +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py new file mode 100644 index 000000000..d8abb1fa2 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py @@ -0,0 +1,63 @@ +""" +Check that gnatcov correctly instruments mains for the automatic dump of +coverage buffers even if these mains are in languages for which coverage is +disabled. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +# First check with a project that contains a C unit (to analyze) driven by an +# Ada main (not to analyze). +tmp = Wdir("tmp_ada-main") +thistest.log("== ada-main ==") +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../ada-main"], mains=["main.adb"]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--restricted-to-languages=C"], + extra_coverage_args=[ + "-axcov", + "--output-dir=xcov", + "--restricted-to-languages=C", + ], + trace_mode="src", +) +check_xcov_reports("xcov", {"tested.c.xcov": {"+": {5}, "-": {7}}}) +tmp.to_homedir() + +# Now check with a project that contains an Ada unit (to analyze) driven by a +# C main (not to analyze). +tmp = Wdir("tmp_c-main") +thistest.log("== c-main ==") +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../c-main"], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--restricted-to-languages=Ada"], + extra_coverage_args=[ + "-axcov", + "--output-dir=xcov", + "--restricted-to-languages=Ada", + ], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "pkg.adb.xcov": {"+": {10, 22}, "-": {12, 23}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) +tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb new file mode 100644 index 000000000..1f59650f6 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb @@ -0,0 +1,19 @@ +procedure Dotted.Decl is + procedure Foo; + procedure Bar; + + procedure Foo is + begin + null; + end Foo; + + procedure Bar is + begin + Dotted.Decl.Foo; + Decl.Foo; + end Bar; + +begin + Dotted.Decl.Bar; + Decl.Foo; +end Dotted.Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb new file mode 100644 index 000000000..345dbb981 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb @@ -0,0 +1,17 @@ +procedure Dotted.Exn is + procedure Foo is + begin + raise Program_Error; + end Foo; + + procedure Bar is + begin + null; + end Bar; +begin + Dotted.Exn.Bar; + Exn.Foo; +exception + when Program_Error => + Exn.Bar; +end Dotted.Exn; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb new file mode 100644 index 000000000..129303111 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb @@ -0,0 +1,12 @@ +procedure Dotted.No_Decl is +begin + Block : declare + procedure Foo is + begin + null; + end Foo; + begin + Dotted.No_Decl.Block.Foo; + No_Decl.Block.Foo; + end Block; +end Dotted.No_Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb new file mode 100644 index 000000000..7bf467818 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb @@ -0,0 +1,15 @@ +package body Dotted is + + package body Simple_Decl is + procedure Foo is + begin + null; + end Foo; + end Simple_Decl; + + procedure Bar is + begin + raise Program_Error; + end Bar; + +end Dotted; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads new file mode 100644 index 000000000..5eb2a513f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads @@ -0,0 +1,8 @@ +package Dotted is + package Simple_Decl is + procedure Foo; + end Simple_Decl; + + procedure Bar; + +end Dotted; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb new file mode 100644 index 000000000..bb658b783 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb @@ -0,0 +1,21 @@ +with Dotted; + +procedure Simple_Decl is + + procedure Foo; + procedure Bar; + + procedure Foo is + begin + null; + end Foo; + + procedure Bar is + begin + Simple_Decl.Foo; + Dotted.Simple_Decl.Foo; + end Bar; +begin + Simple_Decl.Bar; + Dotted.Simple_Decl.Foo; +end Simple_Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb new file mode 100644 index 000000000..b5ed47a9e --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb @@ -0,0 +1,17 @@ +procedure Simple_Exn is + procedure Foo is + begin + raise Program_Error; + end Foo; + + procedure Bar is + begin + null; + end Bar; +begin + Bar; + Simple_Exn.Foo; +exception + when Program_Error => + Simple_Exn.Bar; +end Simple_Exn; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb new file mode 100644 index 000000000..e7fc26e2a --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb @@ -0,0 +1,11 @@ +procedure Simple_No_Decl is +begin + Block : declare + procedure Foo is + begin + null; + end Foo; + begin + Simple_No_Decl.Block.Foo; + end Block; +end Simple_No_Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb new file mode 100644 index 000000000..13be0bda0 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Dotted; + +procedure Simple_Only_Exn is +begin + Block : declare + procedure Foo is + begin + Put_Line ("Foo was called"); + end Foo; + begin + Simple_Only_Exn.Block.Foo; + Dotted.Bar; + end Block; +exception + when Program_Error => + Put_Line ("Program_Error"); + when Constraint_Error => + Put_Line ("Constraint_Error"); +end Simple_Only_Exn; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt b/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt new file mode 100644 index 000000000..ddd35d955 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test only makes sense with exception propagation +RTS_LIGHT_TASKING DEAD Test only makes sens with exception propagation diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py new file mode 100644 index 000000000..fe3f4ca1b --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py @@ -0,0 +1,74 @@ +""" +Check that the instrumenter correctly renames qualified names in the mains. +This test mainly checks that the various mains used are correctly built after +instrumentation, and that their coverage results are correct. +This also checks the instrumentation of the main source correctly inserts +buffers dump code when the main procedure has top-level exception handlers. +(Former test S607-033-instr-exc-handler) +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir() + +# Names of the various mains tested. +# +# Mains of the form "test_simple*"" are mains with a simple name +# (i.e. not dotted) whereas those of the form "test_dotted*" are mains with +# a dotted name. +# +# Mains of the form "*decl" are mains with top level declarations, +# those of the form "*exn" are mains with top level exception handlers, +# and should have their qualified names be modified. +# +# The mains of the form "*no_decl" have no top level decalrations nor exception +# handlers, and should not have their qualified names renamed. +main_names = [ + "simple_no_decl", + "simple_decl", + "simple_exn", + "simple_only_exn", + "dotted-decl", + "dotted-no_decl", + "dotted-exn", +] + +# The expected results are not really of imporance here, what matters is that +# the mains got instrumented and build correctly. +expected_results = { + "dotted-decl": {"dotted-decl.adb.xcov": {"+": {7, 12, 13, 17, 18}}}, + "dotted-no_decl": {"dotted-no_decl.adb.xcov": {"+": {6, 9, 10}}}, + "dotted-exn": {"dotted-exn.adb.xcov": {"+": {4, 9, 12, 13, 16}}}, + "simple_decl": {"simple_decl.adb.xcov": {"+": {10, 15, 16, 19, 20}}}, + "simple_no_decl": {"simple_no_decl.adb.xcov": {"+": {6, 9}}}, + "simple_exn": {"simple_exn.adb.xcov": {"+": {4, 9, 12, 13, 16}}}, + "simple_only_exn": { + "simple_only_exn.adb.xcov": {"+": {10, 13, 14, 18}, "-": {20}} + }, +} + + +def do_one_main(main_name): + """ + create a project, instrument build and compute coverage reports for the + given main, from the expected results dictionnary defined above. + """ + tmp.to_subdir(f"tmp_{main_name}") + p = gprfor(mains=[f"{main_name}.adb"], srcdirs=[".."]) + build_run_and_coverage( + gprsw=GPRswitches(root_project=p, units=[main_name.replace("-", ".")]), + covlevel="stmt", + mains=[main_name], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + ) + check_xcov_reports("xcov", expected_results[main_name]) + + +for main_name in main_names: + do_one_main(main_name) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb b/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb new file mode 100644 index 000000000..51a659f98 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb @@ -0,0 +1,17 @@ +with System; use System; + +procedure Main is + pragma Priority (Priority'First); + + function Ident (X : Boolean) return Boolean; + + function Ident (X : Boolean) return Boolean is + begin + return X; + end; + + X : Boolean := True; + pragma Volatile (X); +begin + X := Ident (X); +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt new file mode 100644 index 000000000..2675fc275 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD requires tasking pragma availability diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py new file mode 100644 index 000000000..3f0024f06 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py @@ -0,0 +1,33 @@ +""" +Check that the instrumentation of Ada mains is compatible with the presence of +a pragma Priority in the main. It should be left in the top level declarations +of the main, otherwise the main will fail to compile. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports("obj", {"main.adb.xcov": {"+": {10, 13, 16}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb b/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb new file mode 100644 index 000000000..9bde02b5f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb @@ -0,0 +1,6 @@ +separate (Main) + +function Inner (X : Boolean) return Boolean is +begin + return X; +end Inner; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/main.adb b/testsuite/tests/instr-cov/main_autodump/stubs/main.adb new file mode 100644 index 000000000..e7e33130f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/main.adb @@ -0,0 +1,8 @@ +procedure Main is + function Inner (X : Boolean) return Boolean is separate; + + X : Boolean := True; + pragma Volatile (X); +begin + X := Inner (X); +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/test.py b/testsuite/tests/instr-cov/main_autodump/stubs/test.py new file mode 100644 index 000000000..0adef7d3d --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/test.py @@ -0,0 +1,39 @@ +""" +Check that the instrumentation of Ada mains is compatible with the presence of +stub declarations in the declarative part of the main. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports( + "obj", + { + "main.adb.xcov": {"+": {4, 7}}, + "main-inner.adb.xcov": {"+": {5}}, + }, + ) + + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb new file mode 100644 index 000000000..9bde02b5f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb @@ -0,0 +1,6 @@ +separate (Main) + +function Inner (X : Boolean) return Boolean is +begin + return X; +end Inner; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb new file mode 100644 index 000000000..0c334161e --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb @@ -0,0 +1,16 @@ +with System; use System; + +with Pkg; use Pkg; + +procedure Main is + pragma Priority (Priority'First); + + function Inner (X : Boolean) return Boolean is separate; + + X : Boolean := True; + pragma Volatile (X); + + Ctrl_Object : Ctrl_Type; +begin + X := Inner (X); +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb new file mode 100644 index 000000000..60fbc3077 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Finalize (Self : in out Ctrl_type) is + begin + Put_Line ("Got finalized"); + end Finalize; +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads new file mode 100644 index 000000000..e4e9b2a67 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads @@ -0,0 +1,8 @@ +with Ada.Finalization; + +package Pkg is + + type Ctrl_Type is new Ada.Finalization.Controlled with null record; + + procedure Finalize (Self : in out Ctrl_Type); +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt new file mode 100644 index 000000000..f53f5512d --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD uses controlled types not available in light runtimes +RTS_LIGHT_TASKING DEAD uses controlled types not available in light-tasking runtimes diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py new file mode 100644 index 000000000..3afb42e59 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py @@ -0,0 +1,41 @@ +""" +Check that the instrumentation of Ada mains is compatible with both the +presence of stub declarations in the declarative part of the main, and the +presence of controlled types in the main. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports( + "obj", + { + "main.adb.xcov": {"+": {10, 13, 15}}, + "main-inner.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {"+": {6}}, + "pkg.ads.xcov": {"+": {5}}, + }, + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb b/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb new file mode 100644 index 000000000..09cd7e2d1 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Real_Time; use Ada.Real_Time; + +procedure Main is + + Val : Boolean := False; + pragma Volatile (Val); + + task T; + + task body T is + begin + delay until Clock + Seconds (5); + Put_Line ("In Task"); + Val := True; + end T; + +begin + Put_Line ("In main"); +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt new file mode 100644 index 000000000..8c98d2f26 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD embedded runtimes do not support task hierarchy diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py new file mode 100644 index 000000000..ba8a58e6f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py @@ -0,0 +1,32 @@ +""" +Check that coverage of code inside tasks depending on the main, but +which terminates after the main's handled statements, is correctly assessed. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports("obj", {"main.adb.xcov": {"+": {6, 9, 13, 14, 15, 19}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_no_ext/main.adb b/testsuite/tests/instr-cov/main_no_ext/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/main_no_ext/p.gpr b/testsuite/tests/instr-cov/main_no_ext/p.gpr new file mode 100644 index 000000000..358e08bd4 --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/p.gpr @@ -0,0 +1,5 @@ +project P is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Main use ("main"); +end P; diff --git a/testsuite/tests/instr-cov/main_no_ext/test.opt b/testsuite/tests/instr-cov/main_no_ext/test.opt new file mode 100644 index 000000000..b91fcd5fd --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Instrumentation specific problem diff --git a/testsuite/tests/instr-cov/main_no_ext/test.py b/testsuite/tests/instr-cov/main_no_ext/test.py new file mode 100644 index 000000000..aed543d3b --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/test.py @@ -0,0 +1,30 @@ +""" +Check that gnatcov correctly instruments as a main a file specified as a Main +through the Main attribute of the GPR file, but without an extension. Since +gnatcov instrument did not consider that main.adb as a main, it did not +instrument it as a main, and as a result coverage buffers were not included in +the link closure. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest + +Wdir("tmp_") + +gpr_obj_dir = os.path.join("..", "obj") +build_run_and_coverage( + gprsw=GPRswitches(root_project=os.path.join("..", "p.gpr")), + covlevel="stmt", + mains=["main"], + gpr_obj_dir=gpr_obj_dir, + gpr_exe_dir=gpr_obj_dir, + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports(gpr_obj_dir, {"main.adb.xcov": {"+": {3}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.adb new file mode 100644 index 000000000..3db35b9fd --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.adb @@ -0,0 +1,9 @@ +package body Lib1 is + function Foo return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.ads b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.adb new file mode 100644 index 000000000..326f4aa54 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.adb @@ -0,0 +1,9 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.ads b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src/main.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src/main.adb new file mode 100644 index 000000000..6242717d5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src/main.adb @@ -0,0 +1,30 @@ +pragma Ada_2012; + +with Lib1; +with Lib2; +with Manual_Dump; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + -- The only call that should not count as a violation when never executed + -- is that of the dump buffers procedure. + if 1 = I + 1 then + pragma Annotate (Xcov, Dump_Buffers); + I := I+ 1; + end if; + + Increment (I); + pragma Annotate (Xcov, Dump_Buffers); + I := I + Lib1.Foo; + I := I + Lib2.Bar; + Manual_Dump.Dump; + Increment (I); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.adb new file mode 100644 index 000000000..16b06f89c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.adb @@ -0,0 +1,6 @@ +package body Manual_Dump is + procedure Dump is + begin + pragma Annotate (Xcov, Dump_Buffers); + end Dump; +end Manual_Dump; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.ads b/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.ads new file mode 100644 index 000000000..898439fa6 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.ads @@ -0,0 +1,3 @@ +package Manual_Dump is + procedure Dump; +end Manual_Dump; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.opt b/testsuite/tests/instr-cov/manual-dump/ada_only/test.opt new file mode 100644 index 000000000..df44ecc9c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.opt @@ -0,0 +1 @@ +block DEAD Manual dump wrapped in procedure call (unsupported when using block coverage) diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py new file mode 100644 index 000000000..f0cb98e73 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -0,0 +1,86 @@ +""" +Test that when using manual dump trigger in Ada with a specific pragma +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, srctrace_pattern_for + +tmp = Wdir("tmp_") + +lib1_p = gprfor( + mains=[], + prjid="lib1", + srcdirs="../src-lib1", + objdir="obj-lib1", + langs=["Ada"], +) + +lib2_p = gprfor( + mains=[], + prjid="lib2", + srcdirs="../src-lib2", + objdir="obj-lib2", + langs=["Ada"], +) + +p = gprfor( + prjid="gen", + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], +) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="gen", + tolerate_instrument_messages=instr_warning, +) + +# Check that gnatcov inserted the call to the dump buffers procedure in the +# lib2.adb which is not a unit of interest + + +def check_call(file): + thistest.fail_if_no_match( + "missing dump buffers procedure call", + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers(.*);" "(\n|.)*", + contents_of(file), + ) + + +check_call("obj-lib2/lib2-gnatcov-instr/lib2.adb") + +# Generate and check coverage reports, using the last trace generated for the +# root project. +trace_file = sorted( + glob.glob(srctrace_pattern_for("main", manual=True, manual_prj_name="gen")) +)[-1] + +xcov(cov_args + [trace_file], out="coverage.log") +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {12, 15, 19, 24, 26, 27, 28}, "-": {21, 29}}, + "lib1.adb.xcov": {"+": {4, 7}}, + "lib1.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.adb b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.adb new file mode 100644 index 000000000..83adfaee4 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.adb @@ -0,0 +1,12 @@ +with Lib2; + +package body Lib1 is + function Foo return Integer + is + Res : Integer := 1; + begin + Res := Res + Lib2.Bar; + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.ads b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.adb b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.adb new file mode 100644 index 000000000..dac52ea6c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.adb @@ -0,0 +1,8 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.ads b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/src/main.adb b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src/main.adb new file mode 100644 index 000000000..d52e99f7a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src/main.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Lib1; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + Increment (I); + I := I + Lib1.Foo; + Increment (I); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py new file mode 100644 index 000000000..12f407e44 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -0,0 +1,90 @@ +""" +Test that when using manual dump trigger in Ada with the appropriate buffers +dump pragma only in a subproject itself dependent on another subproject +gnatcov is able to provide the correct coverage analysis. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +def make_lib_gpr(name, srcdirs, deps): + return gprfor( + mains=[], + prjid=name, + srcdirs=srcdirs, + objdir="obj-" + name, + langs=["Ada"], + deps=deps, + ) + + +def check_one(with_units): + """ + Do a build, run, coverage, and report-check workflow, ensuring we get the + expected warnings and coverage results. + + with_units controls wether the --units option is passed + to gnatcov instrument to restrict analysis to the units in the projects + where the manual dump indication has visibility. + """ + + suffix = "units" if with_units else "no_units" + tmp = Wdir("tmp_" + suffix) + + make_lib_gpr("lib1", "../src-lib1", ["lib2"]) + make_lib_gpr("lib2", "../src-lib1/src-lib2", None) + + p = gprfor( + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], + ) + + # Check that we get the expected coverage reports + + # Running gnatcov natively allows to have one source trace file per + # project. + instr_warning = ( + r"warning: Manual buffer dump/reset indications were" r" found in.*" + ) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=p, units=["lib1", "lib2"] if with_units else None + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov_" + suffix], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="lib1", + tolerate_instrument_messages=instr_warning, + ) + + # If with_units is False, we expect coverage violations for main.adb + check_xcov_reports( + "xcov_" + suffix, + { + "lib1.adb.xcov": {"+": {6, 8}, "-": {10}}, + "lib1.ads.xcov": {}, + "lib2.adb.xcov": {"+": {4, 6}}, + "lib2.ads.xcov": {}, + } + | ( + {} + if with_units + else {"main.adb.xcov": {"-": {10, 13, 15, 16, 17}}} + ), + ) + tmp.to_homedir() + + +check_one(with_units=False) +check_one(with_units=True) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb new file mode 100644 index 000000000..0e71f53e7 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb @@ -0,0 +1,16 @@ +with Ada.Command_Line; + +with Interfaces.C.Strings; use Interfaces.C.Strings; + +with GCVRT.Main; +with GNATcov_RTS.Traces.Output.Files; + +procedure Covdump is + Filename : chars_ptr := + New_String (Ada.Command_Line.Command_Name & ".srctrace"); +begin + GNATcov_RTS.Traces.Output.Files.Write_Trace_File + (Buffers_Groups => GCVRT.Main .List, + Filename => Filename); + Free (Filename); +end Covdump; diff --git a/testsuite/tests/instr-cov/manual-dump/basic/covdump__nocov.adb b/testsuite/tests/instr-cov/manual-dump/basic/covdump__nocov.adb new file mode 100644 index 000000000..f696c5b21 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/basic/covdump__nocov.adb @@ -0,0 +1,4 @@ +procedure Covdump is +begin + null; +end Covdump; diff --git a/testsuite/tests/instr-cov/manual-dump/basic/main.adb b/testsuite/tests/instr-cov/manual-dump/basic/main.adb new file mode 100644 index 000000000..485e3b597 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/basic/main.adb @@ -0,0 +1,6 @@ +with Covdump; + +procedure Main is +begin + Covdump; +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/basic/test.opt b/testsuite/tests/instr-cov/manual-dump/basic/test.opt new file mode 100644 index 000000000..b8eef9d73 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/basic/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD Uses the full instrumentation runtime. diff --git a/testsuite/tests/instr-cov/manual-dump/basic/test.py b/testsuite/tests/instr-cov/manual-dump/basic/test.py new file mode 100644 index 000000000..44352cfd8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/basic/test.py @@ -0,0 +1,55 @@ +""" +This test checks that we don't break the GNATcov_RTS API for manual trace +dumps. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="main", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada"], + # Depending on the build mode, use a different implementation of + # the Covdump procedure. This allows the regular build to work (no + # dependency on GNATcov_RTS nor coverage buffers) and at the same + # time, allows the coverage build to do the coverage dump. + scenario_extra=""" + type Boolean is ("False", "True"); + Cov_Build : Boolean := external ("COV_BUILD", "False"); + """, + extra=""" + package Naming is + case Cov_Build is + when "False" => + for Body ("covdump") use "covdump__nocov.adb"; + when "True" => + for Body ("covdump") use "covdump__cov.adb"; + end case; + end Naming; + """, + ), + units=["main"], + ), + covlevel="stmt", + mains=["main"], + extra_gprbuild_args=["-XCOV_BUILD=True"], + extra_coverage_args=["--annotate=xcov", "-XCOV_BUILD=True"], + tolerate_instrument_messages="warning: no indication for dump location was" + " found, this might be caused by a" + " misspelling in the expected pragma" + " statement.", + dump_trigger="manual", + manual_prj_name="main", +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.c b/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.c new file mode 100644 index 000000000..690bc85c0 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.c @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* GNATCOV_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.h b/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/src/main.c b/testsuite/tests/instr-cov/manual-dump/c_only/src/main.c new file mode 100644 index 000000000..151547cf5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/c_only/src/main.c @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* GNATCOV_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* GNATCOV_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py new file mode 100644 index 000000000..2579c7014 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -0,0 +1,80 @@ +""" +Test that when using manual dump trigger in C with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.c" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.c.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp new file mode 100644 index 000000000..690bc85c0 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* GNATCOV_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp b/testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp new file mode 100644 index 000000000..151547cf5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* GNATCOV_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* GNATCOV_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt new file mode 100644 index 000000000..5a8819395 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt @@ -0,0 +1 @@ +!C++ DEAD test specific to C++ handling diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py new file mode 100644 index 000000000..2ff10fdc2 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py @@ -0,0 +1,82 @@ +""" +Test that when using manual dump trigger in C++ with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.cpp"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C++"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C++"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +# Ensure we get no compilation warnings, this used to be the case without the +# proper dump function declaration. +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.cpp" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.cpp.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.cpp.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb new file mode 100644 index 000000000..b2860eb02 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c new file mode 100644 index 000000000..0323c2bc8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp new file mode 100644 index 000000000..333e8cdda --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + std::cout << "hello C++ world!" << std::endl; + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt new file mode 100644 index 000000000..ab2120f34 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test uses stdio +!C++ DEAD test requires C++ compiler +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/test.py b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.py new file mode 100644 index 000000000..ba0fb7d71 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.py @@ -0,0 +1,68 @@ +""" +Check that using --dump-trigger=manual works correctly when gnatcov is not run +in the same directory as where the project's output directory is created. + +In these situations, gnatcov used to not emit the dump helper unit, as gnatcov +used to check the existence of the basename of the object directory, which was +thus not found. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, run_cov_program, exepath_to + +Wdir("tmp_") + +# Name for the main_c and main_cpp executable traces +c_trace_name = "main_c.srctrace" +cpp_trace_name = "main_cpp.srctrace" + + +# Create an object directory deeply nested, so that gnatcov is not run in the +# same directory as where it will be created. +obj_dir = "deep/obj/dir" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so all mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the other mains manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + objdir=obj_dir, + mains=["main_ada.adb", "main_c.c", "main_cpp.cpp"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + gpr_obj_dir=obj_dir, + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov", c_trace_name, cpp_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) + +env["GNATCOV_TRACE_FILE"] = cpp_trace_name +run_cov_program(exepath_to("main_cpp"), env=env) + +xcov(cov_args) +check_xcov_reports( + obj_dir, + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + "main_cpp.cpp.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb new file mode 100644 index 000000000..9923e2521 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Do_Dump; +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c new file mode 100644 index 000000000..12ea53f32 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c @@ -0,0 +1,8 @@ +#include "pkg_c.h" + +int +main () +{ + do_dump (); + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb new file mode 100644 index 000000000..e681359db --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + procedure Do_Dump is + begin + pragma Annotate (Xcov, Dump_Buffers); + end Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads new file mode 100644 index 000000000..410a9040d --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c new file mode 100644 index 000000000..01a1528f5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c @@ -0,0 +1,7 @@ +#include "pkg_c.h" + +void +do_dump () +{ + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h new file mode 100644 index 000000000..7b02b950e --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h @@ -0,0 +1 @@ +void do_dump (); diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt new file mode 100644 index 000000000..df25bcf77 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt @@ -0,0 +1,2 @@ +!native XFAIL Build failure with mixed language mains. See #212 +block DEAD Manual dump wrapped in procedure call (unsupported when using block coverage) diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py new file mode 100644 index 000000000..26f590832 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py @@ -0,0 +1,47 @@ +""" +Test that the sources generated when using --dump-trigger=manual on a project +which has a dotted name compile correctly. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Empty dummy project, just to make the Base.Prj a legal project +empty = gprfor(srcdirs=[], prjid="empty", mains=[]) + +# The prjid is at the heart of this test, keep it a dotted name +gpr = gprfor( + mains=["main.adb", "main_c.c"], + prjid="empty.prj", + srcdirs="../src", + deps=[empty], + langs=["Ada", "C"], +) + +build_run_and_coverage( + gprsw=GPRswitches(gpr), + covlevel="stmt", + mains=["main", "main_c"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="empty.prj", +) + +# Check that we got the expected coverage report +check_xcov_reports( + "obj", + { + "main_c.c.xcov": {"+": {6}, "-": {7}}, + "pkg_c.c.xcov": {}, + "main.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {}, + "pkg.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr b/testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr new file mode 100644 index 000000000..716dbeab1 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr @@ -0,0 +1,7 @@ +project P_Ext extends "./p_base.gpr" is + + for Source_Dirs use ("../src_ext"); + for Object_Dir use "obj_ext"; + for Exec_Dir use "."; + +end P_Ext; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb new file mode 100644 index 000000000..54a20625b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Common is + + procedure Say_Hello is + begin + Put_Line ("Hello from Base!"); + + -- This is to check that this overridden source does not generate a + -- trace, as it should not be compiled even after instrumentation. + + pragma Annotate (Xcov, Dump_Buffers); + end Say_Hello; + +end Common; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads new file mode 100644 index 000000000..b65b7a750 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads @@ -0,0 +1,5 @@ +package Common is + + procedure Say_Hello; + +end Common; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb new file mode 100644 index 000000000..301de539c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Contractor is + + procedure Say_Hello is null; + +end Contractor; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads new file mode 100644 index 000000000..28eae2237 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads @@ -0,0 +1,5 @@ +package Contractor is + + procedure Say_Hello; + +end Contractor; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb new file mode 100644 index 000000000..b3cf894f7 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb @@ -0,0 +1,7 @@ +with Common; + +procedure Main is +begin + Common.Say_Hello; + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb new file mode 100644 index 000000000..45145b1df --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb @@ -0,0 +1,5 @@ +with Contractor; + +package body Common is + procedure Say_Hello renames Contractor.Say_Hello; +end Common; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb new file mode 100644 index 000000000..7df3e7c8a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Contractor is + + procedure Say_Hello is + begin + Put_Line ("Hello from Ext!"); + end Say_Hello; + +end Contractor; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py b/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py new file mode 100644 index 000000000..316097f46 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py @@ -0,0 +1,64 @@ +""" +Test that instrumentation of a project tree including an extended project +produces valid sources, and that coverage for all units is properly dumped. +""" + +import glob +import os + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +base_gpr = gprfor( + mains=["main.adb"], + srcdirs=["../src_base"], + objdir="obj_base", + prjid="p_base", +) +ext_gpr = "p_ext.gpr" + +# gprfor does not allow the creation of an extend project, so use our own. +cp(os.path.join("..", ext_gpr), ".") + +# Run the coverage cycle +build_run_and_coverage( + gprsw=GPRswitches(ext_gpr), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj_ext", + dump_trigger="manual", + manual_prj_name="P_Ext", + extra_coverage_args=["-axcov"], +) + + +# Check that there only is a single trace produced, to ensure that the manual +# dump indication in the overridden common.adb file has not been compiled. +traces = glob.glob("*.srctrace") +thistest.fail_if_not_equal( + "Unexpected number of traces", + expected=1, + actual=len(traces), +) + +# Check the coverage contents +check_xcov_reports( + "obj_ext", + { + "main.adb.xcov": {"+": {5}}, + "common.ads.xcov": {}, + "common.adb.xcov": {}, + "contractor.ads.xcov": {}, + "contractor.adb.xcov": {"+": {7}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/extra.opt b/testsuite/tests/instr-cov/manual-dump/extra.opt new file mode 100644 index 000000000..ab2569354 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to src traces feature diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h b/testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h new file mode 100644 index 000000000..586ab1103 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h @@ -0,0 +1,4 @@ +static inline void +print_msg (const char *msg) +{ +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb new file mode 100644 index 000000000..f64863d5c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Unit_Ada_Process; + +procedure Main_Ada_Process is +begin + Put_Line ("Start main"); + Unit_Ada_Process; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada_Process; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb new file mode 100644 index 000000000..a5fe5f131 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Unit_Ada_Skipped; + +procedure Main_Ada_Skipped is +begin + Put_Line ("Start main"); + Unit_Ada_Skipped; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb new file mode 100644 index 000000000..5022d04a9 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_C_Process is + procedure Unit_C_Process; + pragma Import (C, Unit_C_Process, "unit_c_process"); +begin + Put_Line ("Start main"); + Unit_C_Process; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_C_Process; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb new file mode 100644 index 000000000..09e0ba55b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_C_Skipped is + procedure Unit_C_Skipped; + pragma Import (C, Unit_C_Skipped, "unit_c_skipped"); +begin + Put_Line ("Start main"); + Unit_C_Skipped; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_C_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt b/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt new file mode 100644 index 000000000..faf04374b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD GNAT 5.04a1 crashes on unrecognized pragmas diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py new file mode 100644 index 000000000..77a19a6e4 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py @@ -0,0 +1,181 @@ +""" +This test checks that when instrumenting a file with +`--dump-trigger=manual,@file`, where file contains the list of files with +manual indications, gnatcov only processes the specific files. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +# Expected xcov report. We have 4 main closures with always the same structure: + +# [main] print 1 +# [main] call unit procedure +# [main] print 2 +# [main] dump buffers +# +# [unit] print 3 +# [unit] reset buffers +# [unit] print 4 +# +# We will always process manual annotations in mains (to dump buffers), but the +# annotations in units (to reset buffers) will be ignored in "unit_*_skipped*" +# sources. As a result, the coverage of: +# +# [main] print 1 +# [main] call unit procedure +# [unit] print 3 +# +# will be 1) covered when unit annotations are ignored and 2) uncovered +# otherwise. +expected_xcov = { + "main_ada_process.adb.xcov": {"+": {9}, "-": {7, 8}}, + "main_ada_skipped.adb.xcov": {"+": {7, 8, 9}}, + "unit_ada_process.adb.xcov": {"+": {7}, "-": {5}}, + "unit_ada_skipped.adb.xcov": {"+": {5, 7}}, + "main_c_process.adb.xcov": {"+": {9}, "-": {7, 8}}, + "main_c_skipped.adb.xcov": {"+": {7, 8, 9}}, + "unit_c_process.c.xcov": {"+": {8}, "-": {6}}, + "unit_c_skipped.c.xcov": {"+": {6, 8}}, +} + +# Mains always have their first statement covered, so in block coverage, we +# expect the whole statement sequence to be covered. +if thistest.options.block: + for filename, report in expected_xcov.items(): + if filename.startswith("main_") and "-" in report: + report["+"].update(report.pop("-")) + +# List of source files, as well as the mains in the generated project +source_files = [os.path.splitext(filename)[0] for filename in expected_xcov] +mains_files = [ + filename for filename in source_files if filename.startswith("main_") +] +mains_exe = [os.path.splitext(filename)[0] for filename in mains_files] + +# Source files in which to process manual directives +manual_files = [ + os.path.abspath(filename) + for filename in source_files + if filename.startswith("main_") or "_skipped" not in filename +] + + +def get_gprsw(): + """ + Generate a project file in the current directory and return the GPRswitches + instance. + """ + return GPRswitches(gprfor(prjid="main", srcdirs=[".."], mains=mains_files)) + + +# +# Regular cases +# + +thistest.log("====== Pass filenames on the command line ======") +tmp = Wdir("tmp_simple") +build_run_and_coverage( + gprsw=get_gprsw(), + covlevel="stmt", + mains=mains_exe, + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], + dump_trigger="manual", + extra_instr_args=["--manual-dump-files=" + ",".join(manual_files)], + manual_prj_name="main", +) +check_xcov_reports("xcov", expected_xcov) +tmp.to_homedir() + +# Same test as above, but passes +# `--manual-dump-files foo.c --manual-dump-files bar.c` +# instead of `--manual-dump-files=foo.c,bar.c` +thistest.log( + "====== Pass filenames on the command line through several" + " arguments ======" +) +tmp = Wdir("tmp_multiple") +build_run_and_coverage( + gprsw=get_gprsw(), + covlevel="stmt", + mains=mains_exe, + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], + dump_trigger="manual", + extra_instr_args=[ + arg for file in manual_files for arg in ["--manual-dump-files", file] + ], + manual_prj_name="main", +) +check_xcov_reports("xcov", expected_xcov) +tmp.to_homedir() + +thistest.log("====== Pass filenames through a response file ======") +tmp = Wdir("tmp_resp") +with open("resp", "w") as f: + for filename in manual_files: + print(os.path.abspath(filename), file=f) +build_run_and_coverage( + gprsw=get_gprsw(), + covlevel="stmt", + mains=mains_exe, + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], + dump_trigger="manual", + extra_instr_args=["--manual-dump-files=@resp"], + manual_prj_name="main", +) +check_xcov_reports("xcov", expected_xcov) +tmp.to_homedir() + +# +# Error cases +# + +thistest.log("====== Check error cases ======") +tmp = Wdir("tmp_err") +get_gprsw() + +for label, dump_trigger, files, error in [ + ( + # Check that gnatcov exits with an error when passing a file that does + # not exist. + "instr_wrong_file", + "manual", + "unknown", + r".*gnatcov(\.exe)?: File unknown does not exist", + ), + ( + # Check that gnatcov exits with an error when passing + # --dump-trigger=atexit,file. + "instr_wrong_trigger", + "atexit", + "../main.adb", + r".*gnatcov(\.exe)?: --manual-dump-files requires" + " --dump-trigger=manual", + ), +]: + instr_out = f"{label}.out" + xcov( + [ + "instrument", + "-Pmain", + "--level=stmt", + f"--dump-trigger={dump_trigger}", + f"--manual-dump-files={files}", + "--quiet", + ], + out=instr_out, + register_failure=False, + ) + thistest.fail_if_no_match( + "missing error in gnatcov instrument output", + error, + contents_of(instr_out), + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb new file mode 100644 index 000000000..05826d0b6 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Unit_Ada_Process is +begin + Put_Line ("Start unit"); + pragma Annotate (Xcov, Reset_Buffers); + Put_Line ("End unit"); +end Unit_Ada_Process; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb new file mode 100644 index 000000000..ff30f2b0d --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Unit_Ada_Skipped is +begin + Put_Line ("Start unit"); + pragma Annotate (Xcov, Reset_Buffers); + Put_Line ("End unit"); +end Unit_Ada_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c new file mode 100644 index 000000000..ccc1e6d48 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c @@ -0,0 +1,9 @@ +#include "c_print.h" + +void +unit_c_process (void) +{ + print_msg ("Start unit"); + /* GNATCOV_RESET_BUFFERS */ + print_msg ("End unit"); +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c new file mode 100644 index 000000000..0b9d8fb0a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c @@ -0,0 +1,9 @@ +#include "c_print.h" + +void +unit_c_skipped (void) +{ + print_msg ("Start unit"); + /* GNATCOV_RESET_BUFFERS */ + print_msg ("End unit"); +} diff --git a/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py new file mode 100644 index 000000000..1062c195e --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py @@ -0,0 +1,94 @@ +""" +Test that there are no issues when the LAL context is recreated when querying a +unit during the search of manual dump/reset indications. +Two bugs used to make this crash: + - The JSON configuration pragma file used to be deleted after finishing the + coverage instrumentation, thus crashing gnatcov when a LAL context was + recreated. + - The manual dump search first performs a search of the relevant pragmas on + all sources, and only starts a rewriting session once one such pragma is + found. This results in two calls to get_from_file for the same unit, which + leads to stale references once the rewriting sessions was initialized. +This regression test reproduces both bugs. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches, gprcov_for +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Number of LAL unit queries after which gnatcov reset the LAL context +GNATCOV_CTX_RESET_LIMIT = 50 + + +def gen_project(): + """ + Generate a project capable of reproducing the bug. + We need to create exactly 50 sources to instrument for coverage (the limit + at which gnatcov resets its LAL context) then inspect at least one source + in search of a manual buffer dump indication. + Returns a tuple consisting in the generated project name (by gprfor) and + the expected coverage result. + """ + + # First, generate the sources to be instrumented. They'll only consist in + # the bare minimum to generate an obligation: a simple variable + # declaration. + for i in range(GNATCOV_CTX_RESET_LIMIT): + with open(f"pkg_{i}.ads", "w") as pkg_file: + pkg_file.write(f"package Pkg_{i} is\n") + pkg_file.write(" Dummy_Bool : Boolean := False;\n") + pkg_file.write(f"end Pkg_{i};\n") + + # Then, generate a main that pulls all these units in the compilation + # closure, and includes a manual dump indication. + + with open("main.adb", "w") as main_file: + for i in range(GNATCOV_CTX_RESET_LIMIT): + main_file.write(f"with Pkg_{i};\n") + main_file.write("procedure Main is\n") + main_file.write("begin\n") + main_file.write(" null;\n") + main_file.write(" pragma Annotate (Xcov, Dump_Buffers);\n") + main_file.write("end Main;\n") + + # Create a project. The Pkg_{i} sources are of interest for coverage + # purposes, but the main not. + prj = gprfor( + mains=["main.adb"], + prjid="prj", + srcdirs=".", + objdir="obj", + extra=gprcov_for( + units_in=[f"Pkg_{i}" for i in range(GNATCOV_CTX_RESET_LIMIT)] + ), + ) + expected_cov = { + f"pkg_{i}.ads.xcov": {"+": {2}} for i in range(GNATCOV_CTX_RESET_LIMIT) + } + return prj, expected_cov + + +# First, generate a project + +prj, expected_cov = gen_project() + +# Then instrument, build, run, coverage and check +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + mains=["main"], + covlevel="stmt", + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name=os.path.splitext(prj)[0], +) + +check_xcov_reports("obj", expected_cov) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_ada.adb new file mode 100644 index 000000000..b2860eb02 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_c.c b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_c.c new file mode 100644 index 000000000..0323c2bc8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.opt b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.opt new file mode 100644 index 000000000..c4fdf2d52 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD test uses stdio +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.py b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.py new file mode 100644 index 000000000..5c9da1d96 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.py @@ -0,0 +1,54 @@ +""" +Check that using --dump-trigger=manual works correctly in projects where a +manual dump indication is present both in an Ada source and in a C-like source. + +This is a regression test, gnatcov used to not emit the helper unit for one of +the language kinds, resulting in the instrumented sources failing to build. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, run_cov_program, exepath_to + +Wdir("tmp_") + +# Name for the main_c executable trace +c_trace_name = "main_c.srctrace" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so both mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the second main manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + langs=["Ada", "C"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov", c_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) +xcov(cov_args) +check_xcov_reports( + "obj", + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb new file mode 100644 index 000000000..b2860eb02 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c new file mode 100644 index 000000000..0323c2bc8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp new file mode 100644 index 000000000..333e8cdda --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + std::cout << "hello C++ world!" << std::endl; + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt new file mode 100644 index 000000000..ab2120f34 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test uses stdio +!C++ DEAD test requires C++ compiler +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/test.py b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.py new file mode 100644 index 000000000..0967aa292 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.py @@ -0,0 +1,61 @@ +""" +Check that using --dump-trigger=manual works correctly in projects where a +manual dump indication is present in an Ada source and in all supported C-like +sources. + +This is a regression test, gnatcov used to emit helper units with colliding +object filenames, resulting in the instrumented sources failing to build. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, run_cov_program, exepath_to + +Wdir("tmp_") + +# Name for the main_c and main_cpp executable traces +c_trace_name = "main_c.srctrace" +cpp_trace_name = "main_cpp.srctrace" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so all mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the other mains manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c", "main_cpp.cpp"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov", c_trace_name, cpp_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) + +env["GNATCOV_TRACE_FILE"] = cpp_trace_name +run_cov_program(exepath_to("main_cpp"), env=env) + +xcov(cov_args) +check_xcov_reports( + "obj", + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + "main_cpp.cpp.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp new file mode 100644 index 000000000..850a19c37 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp @@ -0,0 +1,22 @@ +#include "stuff.hpp" + +void +print_int (int) +{ +} + +int +main (int argc, char **argv) +{ + + (void) argc; + (void) argv; + + Stuff a = { 5 }; + + print_int (a.data); + + /* GNATCOV_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp new file mode 100644 index 000000000..f599519ae --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp @@ -0,0 +1,6 @@ +#pragma once + +struct Stuff +{ + int data; +}; diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt new file mode 100644 index 000000000..195e6c2d4 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt @@ -0,0 +1 @@ +!C++ DEAD test requires C++ compiler diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py new file mode 100644 index 000000000..10ef871cc --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py @@ -0,0 +1,50 @@ +""" +Regression test: check that gnatcov does not process headers in the context of +the manual dump trigger preprocessing. To do that, put a #pragma once in a +header, and instrument with -Werror. + +Also checks that it puts the right external linkage prefix for a C++ file (e.g. +extern "C"), as otherwise the dependency is not resolved at link time as +gnatcov declares the dump/reset procedures as C symbols. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr = gprfor( + mains=["main.cpp"], + prjid="main", + srcdirs="../src", + compiler_extra='for Default_Switches("C++") use ("-Werror");', + extra=""" + package Naming is + for Spec_Suffix ("C++") use ".hpp"; + for Body_Suffix ("C++") use ".cpp"; + end Naming; + """, +) +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) +build_run_and_coverage( + gprsw=GPRswitches(gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", {"main.cpp.xcov": {"+": {12, 13, 15, 17}, "-": {21}}} +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb new file mode 100644 index 000000000..78b1c7fef --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is + Trace_Prefix : constant String := "ada_trace"; +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (XCov, Dump_Buffers, Main_Ada.Trace_Prefix); + pragma Annotate (XCov, Dump_Buffers, "valid" & "prefix"); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c new file mode 100644 index 000000000..0c0eba97f --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c @@ -0,0 +1,10 @@ +#include + +int +main (void) +{ + char *trace_prefix = "c_trace"; + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS (trace_prefix) */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt new file mode 100644 index 000000000..b4e2b265a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt @@ -0,0 +1 @@ +!native DEAD test only makes sense for bin-file dump channel diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py new file mode 100644 index 000000000..d5535affd --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py @@ -0,0 +1,80 @@ +""" +Test that the prefix for the trace can be configured from sources, using +either + + pragma Annotate (Xcov, Dump_Buffers, Prefix); + +or + + /* GNATCOV_DUMP_BUFFERS (prefix) */ + +where prefix designates any expression evaluating to an Ada String or a C +null-terminated char *. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +expected_cov = { + "ada": { + "main_ada.adb.xcov": {"+": {4, 6}}, + "main_c.c.xcov": {"-": {6, 7, 9}}, + }, + "c": { + "main_c.c.xcov": {"+": {6, 7}, "-": {9}}, + "main_ada.adb.xcov": {"-": {4, 6}}, + }, +} + + +def check_one_trace(cov_args, lang): + """ + Find the trace generated by the lang executable, assuming the trace prefix + is {lang}_trace. Then create a coverage report from that trace and check we + got the expected results. + """ + + thistest.log(f"======== Checking {lang} trace =========") + + # We expect the trace to be in the format + # {lang}_trace-{unique-part}.srctrace: + trace = glob.glob(f"{lang}_trace-*.srctrace") + + output_dir = f"output_{lang}/" + xcov( + cov_args + [f"--output-dir={output_dir}"] + trace, + out=f"coverage_{lang}.log", + ) + check_xcov_reports(output_dir, expected_cov[lang]) + + +prj_id = "p" + +# Instrument build and run +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid=prj_id, + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + ) + ), + covlevel="stmt", + mains=["main_ada", "main_c"], + dump_trigger="manual", + manual_prj_name=prj_id, + extra_coverage_args=["-axcov"], +) + +# Check the trace name and report for each executable +for lang in ["c", "ada"]: + check_one_trace(cov_args, lang) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/main.adb b/testsuite/tests/instr-cov/manual-dump/trace_index/main.adb new file mode 100644 index 000000000..f94b2081b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put ("Hello"); + pragma Annotate (Xcov, Dump_Buffers); + Put (" Ada"); + pragma Annotate (Xcov, Dump_Buffers); + Put_Line (" world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.opt b/testsuite/tests/instr-cov/manual-dump/trace_index/test.opt new file mode 100644 index 000000000..2fc2f0620 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.opt @@ -0,0 +1 @@ +!native DEAD Test specific to bin-file dump channel, not available on cross diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py new file mode 100644 index 000000000..998bd8ae2 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py @@ -0,0 +1,76 @@ +""" +Test that when multiple traces are dumped by the same executable, no trace file +gets overwritten and we get as many traces as there are dump indications in +the sources. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, srctrace_pattern_for + +tmp = Wdir("tmp_") + +expected_cov = [ + {"+": {5}, "-": {7, 9}}, + {"+": {5, 7}, "-": {9}}, + {"+": {5, 7, 9}}, +] + + +def check_trace(cov_args, traces, index): + """ + Create a coverage report from cov_args and traces[index], in the + report_{index} directory, and check the report against expected_cov, + for the corresponding index. + """ + thistest.log(f"======= Checking trace {index + 1} =========") + output_dir = f"report_{index + 1}" + xcov( + cov_args + [traces[index], f"--output-dir={output_dir}"], + out=f"xcov_{index}", + ) + check_xcov_reports(output_dir, {"main.adb.xcov": expected_cov[index]}) + + +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main.adb"], + ) + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov"], +) + +# Remove the traces from the coverage arguments +cov_args = cov_args[:-3] + +traces = glob.glob( + srctrace_pattern_for("main", manual=True, manual_prj_name="p") +) +traces.sort() + +thistest.fail_if( + len(traces) != 3, comment=f"Expected three traces, got {len(traces)}" +) + +# Check that the traces do indeed contain an index in their filename +thistest.fail_if( + any(not traces[i].endswith(f"-{i}.srctrace") for i in range(3)), + comment=f"missing trace index in trace filenames: {traces}", +) + +# Check for each trace the coverage results +for i in range(3): + check_trace(cov_args, traces, i) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s b/testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s new file mode 100644 index 000000000..cee911602 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s @@ -0,0 +1,23 @@ + .file "ident.c" + .text + .globl ident + .type ident, @function +ident: +.LFB0: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl %edi, -4(%rbp) + movl -4(%rbp), %eax + nop + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size ident, .-ident + .ident "GCC: (GNU) 13.2.1 20240204 (for GNAT Pro 25.0w 20240204)" + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb new file mode 100644 index 000000000..253f5de2f --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb @@ -0,0 +1,11 @@ +with Interfaces.C; use Interfaces.C; + +with Support; + +procedure Main_Ada is + function ASM_Ident (X : int) return int; + pragma Import (C, ASM_Ident, "ident"); +begin + Support.Assert (ASM_Ident (3) = 3); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt new file mode 100644 index 000000000..beda2dc39 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt @@ -0,0 +1,2 @@ +x86_64-linux +ALL DEAD test contains assembly sources, only compiles on x86_64-linux diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py new file mode 100644 index 000000000..db3e95dd9 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py @@ -0,0 +1,34 @@ +""" +Check that using --dump-trigger=manual properly ignores files for languages +unknown to gnatcov. This used to crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +prj_name = "prj" + +prj = gprfor( + mains=["main_ada.adb"], + prjid=prj_name, + langs=["Ada", "Asm"], + srcdirs=[".."], +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + mains=["main_ada"], + covlevel="stmt", + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name=prj_name, +) + +check_xcov_reports("obj", {"main_ada.adb.xcov": {"+": {9}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/missing-runtime-dir/main.adb b/testsuite/tests/instr-cov/missing-runtime-dir/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/instr-cov/missing-runtime-dir/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/instr-cov/missing-runtime-dir/test.py b/testsuite/tests/instr-cov/missing-runtime-dir/test.py new file mode 100644 index 000000000..7f36ff129 --- /dev/null +++ b/testsuite/tests/instr-cov/missing-runtime-dir/test.py @@ -0,0 +1,27 @@ +""" +Check that instrumentation an Ada project does not fail when the +ADA_INCLUDE_PATH environment variable (classified as a "runtime directory" by +the GPR system) does not exist. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +os.environ["ADA_INCLUDE_PATH"] = os.path.abspath("nosuchdir") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/mixed_and/main.adb b/testsuite/tests/instr-cov/mixed_and/main.adb new file mode 100644 index 000000000..7e338c326 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_and/main.adb @@ -0,0 +1,19 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + Who : constant String := "world"; +begin + if Who'Length = 0 then + raise Constraint_Error; + elsif Who'Length = 1 and Who (Who'First) = 'h' then + raise Constraint_Error; + elsif Who'Length = 0 or Who (Who'First) = 'h' then + raise Constraint_Error; + elsif Who'Length = 0 xor Who (Who'First) = 'h' then + raise Constraint_Error; + elsif Who'Length = 0 or else Who (Who'First) = 'h' then + raise Constraint_Error; + else + Put_Line ("Hello " & Who); + end if; +end Main; diff --git a/testsuite/tests/instr-cov/mixed_and/p.gpr b/testsuite/tests/instr-cov/mixed_and/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_and/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/mixed_and/test.py b/testsuite/tests/instr-cov/mixed_and/test.py new file mode 100644 index 000000000..d66b949ea --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_and/test.py @@ -0,0 +1,39 @@ +""" +Test that AND/OR/XOR boolean expressions are correctly wrapped in parens when +inserting a witness call before them. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": { + "+": {4, 6, 8, 10, 12, 14, 17}, + "-": {7, 9, 11, 13, 15}, + } + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/code.ada b/testsuite/tests/instr-cov/multi_unit_source/src/code.ada new file mode 100644 index 000000000..e419b4817 --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/code.ada @@ -0,0 +1,28 @@ +package U1 is + A : Integer := 1; +end U1; + +package U2 is + B : Integer := 2; + procedure Increment; + procedure Decrement; +end U2; + +package body U2 is + procedure Increment is + begin + B := B + 1; + end Increment; + procedure Decrement is + begin + B := B - 1; + end Decrement; +end U2; + +with U1, U2; +procedure U3 is +begin + U2.Increment; + U1.A := U1.A + U2.B; + U2.Decrement; +end U3; diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/main.adb b/testsuite/tests/instr-cov/multi_unit_source/src/main.adb new file mode 100644 index 000000000..a3dacf4ab --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/main.adb @@ -0,0 +1,6 @@ +with Pck; + +procedure Main is +begin + Pck.Call; +end Main; diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/pck.adb b/testsuite/tests/instr-cov/multi_unit_source/src/pck.adb new file mode 100644 index 000000000..c0e8e6ac1 --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/pck.adb @@ -0,0 +1,14 @@ +with U1; +with U2; +with U3; + +package body Pck is + + procedure Call is + begin + U2.Increment; + U1.A := U1.A + U2.B; + U3; + end Call; + +end Pck; diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/pck.ads b/testsuite/tests/instr-cov/multi_unit_source/src/pck.ads new file mode 100644 index 000000000..9616e13ad --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/pck.ads @@ -0,0 +1,3 @@ +package Pck is + procedure Call; +end Pck; diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.opt b/testsuite/tests/instr-cov/multi_unit_source/test.opt new file mode 100644 index 000000000..e9bca8553 --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD multi-unit sources not supported with GNAT 5.04 diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.py b/testsuite/tests/instr-cov/multi_unit_source/test.py new file mode 100644 index 000000000..b1fe6d57f --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/test.py @@ -0,0 +1,67 @@ +""" +Check that the instrumentation of a project containing a multi-unit source does +not crash. +""" + +import os +import os.path + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +extra = """ + package Naming is + for Spec ("U1") use "code.ada" at 1; + for Spec ("U2") use "code.ada" at 2; + for Body ("U2") use "code.ada" at 3; + for Body ("U3") use "code.ada" at 4; + end Naming; +""" + +mkdir("obj") +prj = gprfor( + srcdirs=[os.path.join("..", "src")], mains=["main.adb"], extra=extra +) + +# Check that the instrumentation crashes and does not leave stale +# instrumentation artefacts when trying to instrument the multi-unit source. +xcov_instrument( + gprsw=GPRswitches(prj), covlevel="stmt", register_failure=False +) +thistest.fail_if_no_match( + "gnatcov instrument output", + ( + ".*gnatcov.*: instrumentation failed for .*code.ada\n" + ".*gnatcov.*: source files containing multiple compilation units are" + " not supported" + ), + contents_of("instrument.log"), +) +thistest.fail_if( + os.path.exists(os.path.join("obj", "gen-gnatcov-instr", "main.adb")), + "unexpected instrumented files", +) + +# Now check that everything runs fine when we exclude the culprit multi-unit +# source from the coverage analysis. +build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--units=pck"], + extra_coverage_args=["--units=pck", "-axcov"], +) + +check_xcov_reports( + "obj", {"pck.adb.xcov": {"+": {9, 10, 11}}, "pck.ads.xcov": {}} +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/multiline_marker/main.c b/testsuite/tests/instr-cov/multiline_marker/main.c new file mode 100644 index 000000000..57138847f --- /dev/null +++ b/testsuite/tests/instr-cov/multiline_marker/main.c @@ -0,0 +1,17 @@ +#include + +int +main (int argc, char *argv[]) +{ + volatile int a = 0, b = 0; + + // Implicit example: the expansion of the assert macro will generate + // redundant line markers. + assert (a == 0 && b == 0); + + // Explicit example with redundant line markers +#line 14 + int c; +#line 14 + return 0; +} diff --git a/testsuite/tests/instr-cov/multiline_marker/test.opt b/testsuite/tests/instr-cov/multiline_marker/test.opt new file mode 100644 index 000000000..8dd5f5b75 --- /dev/null +++ b/testsuite/tests/instr-cov/multiline_marker/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD No libc in light runtimes diff --git a/testsuite/tests/instr-cov/multiline_marker/test.py b/testsuite/tests/instr-cov/multiline_marker/test.py new file mode 100644 index 000000000..d25d2a855 --- /dev/null +++ b/testsuite/tests/instr-cov/multiline_marker/test.py @@ -0,0 +1,29 @@ +""" +Check that gnatcov produces correct SCOs (i.e. with no source location nesting) +when there are redundant line markers resulting in nested SCOs. + +This can happen with macro expansions mixing user-code and systems-header code +(such as the assert macro). The resulting expansion will have multiple line +markers, with a special flag for the code that comes from system headers. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +wd = Wdir("tmp_") + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6, 10, 14}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/multiple_mains/src/test_a.adb b/testsuite/tests/instr-cov/multiple_mains/src/test_a.adb new file mode 100644 index 000000000..bcb125fc0 --- /dev/null +++ b/testsuite/tests/instr-cov/multiple_mains/src/test_a.adb @@ -0,0 +1,4 @@ +procedure Test_A is +begin + null; +end Test_A; diff --git a/testsuite/tests/instr-cov/multiple_mains/src/test_b.adb b/testsuite/tests/instr-cov/multiple_mains/src/test_b.adb new file mode 100644 index 000000000..58bc27953 --- /dev/null +++ b/testsuite/tests/instr-cov/multiple_mains/src/test_b.adb @@ -0,0 +1,6 @@ +with Test_A; + +procedure Test_B is +begin + null; +end Test_B; diff --git a/testsuite/tests/instr-cov/multiple_mains/test.py b/testsuite/tests/instr-cov/multiple_mains/test.py new file mode 100644 index 000000000..07e205110 --- /dev/null +++ b/testsuite/tests/instr-cov/multiple_mains/test.py @@ -0,0 +1,29 @@ +""" +Check that the instrumentation of multiple mains, with one of the main being +in the closure of the other, works. + +With gnatcov instrument, we used to generate a unique C symbol for the +Dump_Buffer procedure, that resulted in symbol name clashing when linking. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_and_run( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=["../src"], mains=["test_a.adb", "test_b.adb"] + ) + ), + covlevel="stmt", + mains=[], + extra_coverage_args=[], + trace_mode="src", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/nested_ternary/main.c b/testsuite/tests/instr-cov/nested_ternary/main.c new file mode 100644 index 000000000..a50a7a7a0 --- /dev/null +++ b/testsuite/tests/instr-cov/nested_ternary/main.c @@ -0,0 +1,6 @@ +int +main () +{ + int a = 1 ? 0 : 1 ? 0 : 1; + return a; +} diff --git a/testsuite/tests/instr-cov/nested_ternary/test.py b/testsuite/tests/instr-cov/nested_ternary/test.py new file mode 100644 index 000000000..797c3d6c6 --- /dev/null +++ b/testsuite/tests/instr-cov/nested_ternary/test.py @@ -0,0 +1,26 @@ +""" +Check that the instrumentation of a nested ternary expression works. It used +to produce duplicate SCOs and make gnatcov crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov", {"main.c.xcov": {"!": {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/no-compiler/main.c b/testsuite/tests/instr-cov/no-compiler/main.c new file mode 100644 index 000000000..881f7b1aa --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/main.c @@ -0,0 +1,12 @@ +extern void adainit (void); +extern void adafinal (void); +extern void pkg_foo (void); + +int +main (void) +{ + adainit (); + pkg_foo (); + adafinal (); + return 0; +} diff --git a/testsuite/tests/instr-cov/no-compiler/pkg.adb b/testsuite/tests/instr-cov/no-compiler/pkg.adb new file mode 100644 index 000000000..37b06eefa --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Foo is + begin + Put_Line ("Ada"); + end Foo; + +end Pkg; diff --git a/testsuite/tests/instr-cov/no-compiler/pkg.ads b/testsuite/tests/instr-cov/no-compiler/pkg.ads new file mode 100644 index 000000000..35a997406 --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Foo; + pragma Export (C, Foo, "pkg_foo"); +end Pkg; diff --git a/testsuite/tests/instr-cov/no-compiler/test.py b/testsuite/tests/instr-cov/no-compiler/test.py new file mode 100644 index 000000000..0cc4d8d1d --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/test.py @@ -0,0 +1,78 @@ +""" +Check that gnatcov properly reports a missing C/C++ compiler in the +environment. It used to emit a cryptic error message: invalid path "". +""" + +from e3.os.process import DEVNULL, Run, STDOUT + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Create a configuration file so that only the Ada compiler is available to +# gnatcov. +config_file = "for_ada.cgpr" +Run( + [ + "gprconfig", + "--batch", + f"--target={env.target.triplet}", + "-o", + config_file, + f"--config=Ada,,{thistest.options.RTS or ''}", + ], + input=DEVNULL, + output="gprconfig.out", + error=STDOUT, +) + +gpr = GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])) + +# Now run the instrumenter on a C project with this configuration file and +# check the error message. +thistest.log("== Instrument all ==") +output = "instr_0.log" +p = xcov_instrument( + gprsw=gpr, + covlevel="stmt", + extra_args=[f"--config={config_file}"], + out=output, + auto_config_args=False, + auto_target_args=False, + register_failure=False, +) +thistest.fail_if_not_equal("'gnatcov instrument' exit code", 1, p.status) +thistest.fail_if_no_match( + "'gnatcov instrument' output", + ".*gnatcov.*: could not find a compiler for C", + contents_of(output).strip(), +) + + +# Likewise, but this time with only Ada units that can be of interest: the C +# source will be instrumented as a main only. +thistest.log("== Instrument Ada only ==") +output = "instr_1.log" +p = xcov_instrument( + gprsw=gpr, + covlevel="stmt", + extra_args=[f"--config={config_file}", "--restricted-to-languages=Ada"], + out=output, + auto_config_args=False, + auto_target_args=False, + register_failure=False, +) +thistest.fail_if_not_equal("'gnatcov instrument' exit code", 1, p.status) +thistest.fail_if_no_match( + "'gnatcov instrument' output", + ".*gnatcov.*: could not find a compiler for C", + contents_of(output).strip(), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/no_main/main.adb b/testsuite/tests/instr-cov/no_main/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/no_main/p.gpr b/testsuite/tests/instr-cov/no_main/p.gpr new file mode 100644 index 000000000..0208ec6ab --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/p.gpr @@ -0,0 +1,8 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Coverage is + for Units use ("pkg"); + end Coverage; +end P; diff --git a/testsuite/tests/instr-cov/no_main/pkg.adb b/testsuite/tests/instr-cov/no_main/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/no_main/pkg.ads b/testsuite/tests/instr-cov/no_main/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/no_main/test.py b/testsuite/tests/instr-cov/no_main/test.py new file mode 100644 index 000000000..b2842abae --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/test.py @@ -0,0 +1,35 @@ +""" +Test the instrumentation (--auto-dump-buffers) of a main that is not a unit of +interest. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + {"pkg.adb.xcov": {"+": {5, 6, 8}}, "pkg.ads.xcov": {}}, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/not_array/main.adb b/testsuite/tests/instr-cov/not_array/main.adb new file mode 100644 index 000000000..1b0fb51b4 --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/main.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +procedure Main is + type Enum_Type is (A, B, C, D); + type Flags_Type is array (Enum_Type) of Boolean; + + function Identity (B : Boolean) return Boolean is (B); + function Get_Flags (B : Boolean) return Flags_Type + is (Flags_Type'(others => B)); + + X : Boolean := Identity (True); + Y : Boolean := Identity (False); + Flags : Flags_Type := not Get_Flags (X and then Y); +begin + Flags := not Flags; +end Main; diff --git a/testsuite/tests/instr-cov/not_array/p.gpr b/testsuite/tests/instr-cov/not_array/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/not_array/test.opt b/testsuite/tests/instr-cov/not_array/test.opt new file mode 100644 index 000000000..89202c61f --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD Test requires System.Boolean_Array_Operations.Vector_Not +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/not_array/test.py b/testsuite/tests/instr-cov/not_array/test.py new file mode 100644 index 000000000..e92947c6c --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/test.py @@ -0,0 +1,44 @@ +""" +Check that we don't consider "not" as a decision operation when standalone. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +# Use --all-decisions so that, even though we are using stmt+decision, we can +# check if the "X and then Y" decision is properly instrumented (thanks to its +# "outcome True not exercized" violation). +# +# TODO: use MC/DC instead not to use --all-decisions. This currently creates +# sources that make GNAT crash. +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov", "--all-decisions"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": { + "+": {4, 5, 7, 9, 11, 12, 15}, + "!": {13}, + } + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/null_proc_generic/src/main.adb b/testsuite/tests/instr-cov/null_proc_generic/src/main.adb new file mode 100644 index 000000000..51ce6a341 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/src/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + procedure P is new Pkg.P (Integer); +begin + P (0); +end Main; diff --git a/testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads b/testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads new file mode 100644 index 000000000..5873d9a1b --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + generic + type T is private; + procedure P (Item : T); + + procedure P (Item : T) is null; +end Pkg; diff --git a/testsuite/tests/instr-cov/null_proc_generic/test.opt b/testsuite/tests/instr-cov/null_proc_generic/test.opt new file mode 100644 index 000000000..f31a3b293 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 +7.1.2 DEAD overloading of generic null procedures not supported in 7.1.2 diff --git a/testsuite/tests/instr-cov/null_proc_generic/test.py b/testsuite/tests/instr-cov/null_proc_generic/test.py new file mode 100644 index 000000000..cece8fe2d --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/test.py @@ -0,0 +1,46 @@ +""" +Check that the instrumentation of generic null procedures produces valid +code. It used to instantiate generic packages with a generic formal not +available at that point, which is not valid Ada code. + +For now we do not know how to instrument generic null procedures, so we +emit a warning for them at instrumentation time and always consider them +non-instrumented. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["main.adb"]), + units=["pkg"], + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=."], + trace_mode="src", + tolerate_instrument_messages="cannot instrument generic null procedures", +) + +# We only expect non-instrumented lines +check_xcov_reports(".", {"pkg.ads.xcov": {"?": {6}}}) + +# Check that the null procedure is reported as a warning +warning_msg = ( + "gnatcov limitation: cannot instrument generic null procedures." + " Consider turning it into a regular procedure body." +) +thistest.fail_if_not_equal( + "'gnatcov instrument' log", + f"!!! pkg.ads:6:4: {warning_msg}\n", + contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads b/testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads new file mode 100644 index 000000000..588b28283 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Pkg is + + type String_Access is access all String; + My_String : aliased String := "hello world"; + + procedure Ignore_1 (S : not null String_Access) is null; -- # p-1 + procedure Ignore_2 (S : not null access constant String) is null; -- # p-2 + +end Pkg; diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb new file mode 100644 index 000000000..70d61acf3 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_1 is +begin + Pkg.Ignore_1 (Pkg.My_String'Access); +end Test_1; + +--# pkg.ads +-- /p-1/ l+ ## 0 +-- /p-2/ l- ## s- diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb new file mode 100644 index 000000000..4dd290aca --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_12 is +begin + Pkg.Ignore_1 (Pkg.My_String'Access); + Pkg.Ignore_2 (Pkg.My_String'Access); +end Test_12; + +--# pkg.ads +-- /p-1/ l+ ## 0 +-- /p-2/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb new file mode 100644 index 000000000..8dcb6c390 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_2 is +begin + Pkg.Ignore_2 (Pkg.My_String'Access); +end Test_2; + +--# pkg.ads +-- /p-1/ l- ## s- +-- /p-2/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb new file mode 100644 index 000000000..f58d70201 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_No is +begin + Pkg.My_String (Pkg.My_String'First) := 'H'; +end Test_No; + +--# pkg.ads +-- /p-1/ l- ## s- +-- /p-2/ l- ## s- diff --git a/testsuite/tests/instr-cov/null_proc_not_null/test.py b/testsuite/tests/instr-cov/null_proc_not_null/test.py new file mode 100644 index 000000000..f24ecfe05 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/test.py @@ -0,0 +1,12 @@ +""" +Check that the instrumentation of null procedures with a "not null" argument +produces valid code. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/orphan-unit/main.adb b/testsuite/tests/instr-cov/orphan-unit/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/instr-cov/orphan-unit/pkg-child.adb b/testsuite/tests/instr-cov/orphan-unit/pkg-child.adb new file mode 100644 index 000000000..8f6b24be8 --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/pkg-child.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg.Child is + procedure Do_Things is + begin + Put_Line ("Doing things"); + end Do_Things; +end Pkg.Child; diff --git a/testsuite/tests/instr-cov/orphan-unit/pkg-child.ads b/testsuite/tests/instr-cov/orphan-unit/pkg-child.ads new file mode 100644 index 000000000..d3df3d14a --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/pkg-child.ads @@ -0,0 +1,3 @@ +package Pkg.Child is + procedure Do_Things; +end Pkg.Child; diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py new file mode 100644 index 000000000..85d9f390e --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -0,0 +1,40 @@ +""" +Check that instrumenting a project that contains an "orphan" unit (i.e. a +source file present in the project but not used in the build and not +compilable) works as expected. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +expected_cov = {"main.adb.xcov": {"+": {5}}} +if thistest.options.trace_mode == "src": + expected_cov["pkg-child.ads.xcov"] = {} + expected_cov["pkg-child.adb.xcov"] = {"-": {6}} + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + tolerate_instrument_messages=".", + extra_coverage_args=["--annotate=xcov"], + tolerate_coverage_messages="no ALI file found for unit pkg.child", +) + +if thistest.options.trace_mode == "src": + thistest.fail_if_not_equal( + '"gnatcov instrument" output', + ( + "warning: While instrumenting pkg-child.ads...\n" + "warning: Cannot find required source file: pkg.ads" + ), + contents_of("instrument.log").strip(), + ) + +check_xcov_reports("obj", expected_cov) + +thistest.result() diff --git a/testsuite/tests/instr-cov/parallel-sanity-check/main.adb b/testsuite/tests/instr-cov/parallel-sanity-check/main.adb new file mode 100644 index 000000000..b8aeb491d --- /dev/null +++ b/testsuite/tests/instr-cov/parallel-sanity-check/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Identity (I : Integer) return Integer; + pragma Import (C, Identity, "identity"); +begin + Put_Line (Integer'Image (Identity (1))); +end Main; diff --git a/testsuite/tests/instr-cov/parallel-sanity-check/test.py b/testsuite/tests/instr-cov/parallel-sanity-check/test.py new file mode 100644 index 000000000..f51c4816b --- /dev/null +++ b/testsuite/tests/instr-cov/parallel-sanity-check/test.py @@ -0,0 +1,28 @@ +""" +Check that "gnatcov instrument" works correctly when run with more than one +job. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["-j2"], + extra_coverage_args=["--annotate=xcov"], +) +check_xcov_reports( + "obj", {"main.adb.xcov": {"+": {7}}, "utils.c.xcov": {"+": {4}}} +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/parallel-sanity-check/utils.c b/testsuite/tests/instr-cov/parallel-sanity-check/utils.c new file mode 100644 index 000000000..c5582d06a --- /dev/null +++ b/testsuite/tests/instr-cov/parallel-sanity-check/utils.c @@ -0,0 +1,5 @@ +int +identity (int i) +{ + return i; +} diff --git a/testsuite/tests/instr-cov/pragma_after_cu/main.adb b/testsuite/tests/instr-cov/pragma_after_cu/main.adb new file mode 100644 index 000000000..5a68074d4 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/main.adb @@ -0,0 +1,10 @@ +with Raise_Error; +with Silent_Last_Chance; + +procedure Main is +begin + Raise_Error; +exception + when Program_Error => + null; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb new file mode 100644 index 000000000..a14c78034 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb @@ -0,0 +1,4 @@ +procedure Raise_Error is +begin + raise Program_Error; +end Raise_Error; diff --git a/testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads new file mode 100644 index 000000000..3d1de63cd --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads @@ -0,0 +1,2 @@ +procedure Raise_Error; +pragma No_Return (Raise_Error); diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.opt b/testsuite/tests/instr-cov/pragma_after_cu/test.opt new file mode 100644 index 000000000..2b7d39df5 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.opt @@ -0,0 +1,2 @@ +src-traces,RTS_ZFP DEAD Cannot dump coverage buffers in this test without non-local exception propagation +src-traces,RTS_LIGHT_TASKING DEAD requires exception propagation diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.py b/testsuite/tests/instr-cov/pragma_after_cu/test.py new file mode 100644 index 000000000..7d9b2d7ec --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.py @@ -0,0 +1,31 @@ +""" +Check that units whose compilation unit contains pragmas after the body are +properly handled. They used to make the instrumenter crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {6}}, + "raise_error.adb.xcov": {"+": {3}}, + "raise_error.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_assert/src/pkg.ads b/testsuite/tests/instr-cov/pragma_assert/src/pkg.ads new file mode 100644 index 000000000..dff448938 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + Foo, Bar : Boolean := True; +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_assert/src/test_main.adb b/testsuite/tests/instr-cov/pragma_assert/src/test_main.adb new file mode 100644 index 000000000..84d0c535c --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/src/test_main.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; +with Pkg; + +procedure Test_Main is + + -- We expect gnatcov to detect two decisions below: one for the whole + -- IF expression, and one for its condition (Pkg.Foo). + + pragma Assert -- # assert_stmt + ((if -- # inner_decision + Pkg.Foo -- # inner_cond_1 + then Pkg.Bar) and then Pkg.Foo); -- # inner_cond_2 + +begin + for J in 1 .. 3 loop + + -- Regression test: gnatcov used to instrument Loop_Invariant as + -- statements, by inserting a witness statement right before. This + -- does not work, as Loop_Invariant pragmas must be groupped + -- together. + + pragma Loop_Invariant (Pkg.Foo); --# loop_invariant_1 + pragma Loop_Invariant (Pkg.Bar); --# loop_invariant_2 + end loop; +end Test_Main; + +--# test_main.adb +-- +-- /assert_stmt/ l. ## 0 +-- /inner_decision/ l. ## 0 +-- /inner_cond_1/ l. ## 0 +-- /inner_cond_2/ l. ## 0 +-- /loop_invariant_1/ l. ## 0 +-- /loop_invariant_2/ l. ## 0 diff --git a/testsuite/tests/instr-cov/pragma_assert/test.opt b/testsuite/tests/instr-cov/pragma_assert/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/instr-cov/pragma_assert/test.py b/testsuite/tests/instr-cov/pragma_assert/test.py new file mode 100644 index 000000000..f702a743e --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/test.py @@ -0,0 +1,13 @@ +""" +Check that the coverage of nested decisions in pragma Assert works as expected. +TODO: revisit this test once we decide on how to enable instrumentation of +assertions (U528-022) +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase(category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb b/testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads b/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads new file mode 100644 index 000000000..b85c4653a --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads @@ -0,0 +1,16 @@ +pragma Ada_2012; +pragma Assertion_Policy (Disable); + +package Pkg is + + type R1 is record + X, Y : Integer; + end record + with Ghost_Predicate => R1.X /= 0 and then R1.Y /= 0; + + subtype R2 is R1 + with Ghost_Predicate => R2.X mod 2 = 0 and then R2.Y mod 2 = 0; + + procedure Foo is null; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.opt b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.opt new file mode 100644 index 000000000..61483536e --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Test support for an Ada 2012 feature +7.1.2 DEAD Test support for an Ada 2012 feature diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py new file mode 100644 index 000000000..e2f3bc2ba --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py @@ -0,0 +1,31 @@ +""" +Check that decisions in Ghost_Predicate aspects are not instrumented. + +They used to be instrumented as decisions, and thus be reported as uncovered in +this example program. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {"+": {14}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_no_body/main.adb b/testsuite/tests/instr-cov/pragma_no_body/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb new file mode 100644 index 000000000..679ab442a --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb @@ -0,0 +1,6 @@ +package body Orig_Pkg is + procedure Foo is + begin + null; + end Foo; +end Orig_Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads new file mode 100644 index 000000000..678e99088 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads @@ -0,0 +1,3 @@ +package Orig_Pkg is + procedure Foo; +end Orig_Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_body/pkg.adb b/testsuite/tests/instr-cov/pragma_no_body/pkg.adb new file mode 100644 index 000000000..4eede424d --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/pkg.adb @@ -0,0 +1 @@ +pragma No_Body; diff --git a/testsuite/tests/instr-cov/pragma_no_body/pkg.ads b/testsuite/tests/instr-cov/pragma_no_body/pkg.ads new file mode 100644 index 000000000..81b994920 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/pkg.ads @@ -0,0 +1,3 @@ +with Orig_Pkg; + +package Pkg renames Orig_Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.opt b/testsuite/tests/instr-cov/pragma_no_body/test.opt new file mode 100644 index 000000000..258f07a37 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD 5.04a1 does not support pragma No_Body diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.py b/testsuite/tests/instr-cov/pragma_no_body/test.py new file mode 100644 index 000000000..863ff033f --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/test.py @@ -0,0 +1,31 @@ +""" +Check that units only containing "pragma No_Body;" are properly handled. They +used to make the instrumenter crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "orig_pkg.ads.xcov": {}, + "orig_pkg.adb.xcov": {"+": {4}}, + "pkg.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb b/testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb new file mode 100644 index 000000000..07a2d970a --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +procedure Main is +begin + if Is_Space ('C') then + null; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb new file mode 100644 index 000000000..bf91d8818 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb @@ -0,0 +1,21 @@ +package body Pkg is + + function Is_Space (C : Character) return Boolean is + begin + if C = ' ' then + return True; + + -- If gnatcov instrument wrongly propagates `pragma Ada_2012` from + -- the spec to this body, it will create an if-expression here. + -- This would make the instrumented sources fail to compile when gnat + -- is invoked with -gnat05 or lower. + + elsif C = ASCII.HT then + + return True; + end if; + + return False; + end Is_Space; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads new file mode 100644 index 000000000..e5efe936b --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pkg is + + function Is_Space (C : Character) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/test.opt b/testsuite/tests/instr-cov/pragma_no_propagate/test.opt new file mode 100644 index 000000000..bd27d7482 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/test.opt @@ -0,0 +1,2 @@ +CARGS_gnat2012 DEAD The test is expected to run on Ada 2005 or lower +CARGS_gnat2022 DEAD The test is expected to run on Ada 2005 or lower diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/test.py b/testsuite/tests/instr-cov/pragma_no_propagate/test.py new file mode 100644 index 000000000..23660ef52 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/test.py @@ -0,0 +1,31 @@ +""" +Ensure that a `Pragma Ada_` in a unit's spec does not propagate to its +body at instrumentation. +To do so, use the alternative instrumentation of elsifs, which uses if exprs +with Ada>=2012, and casts otherwise. + +Note: The test is supposed to run on a Ada 2005 or below +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +_wd = Wdir("tmp_") + +gpr = gprfor( + mains=["main.adb"], + srcdirs=["../src"], +) + +result = build_and_run( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt+gexpr", + mains=["main"], + register_failure=True, + extra_coverage_args=[], +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/preelaborated_units/main.adb b/testsuite/tests/instr-cov/preelaborated_units/main.adb new file mode 100644 index 000000000..a93934020 --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main is +begin + Put_Line ("Fact (1) = " & Integer'Image (Pkg.Fact (1))); + Pkg.Reset_Coverage; + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (0))); + Pkg.Dump_Coverage; +end Main; diff --git a/testsuite/tests/instr-cov/preelaborated_units/pkg.adb b/testsuite/tests/instr-cov/preelaborated_units/pkg.adb new file mode 100644 index 000000000..95292e23d --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/pkg.adb @@ -0,0 +1,34 @@ +package body Pkg is + + -------------------- + -- Reset_Coverage -- + -------------------- + + procedure Reset_Coverage is + begin + pragma Annotate (Xcov, Reset_Buffers); + end Reset_Coverage; + + ------------------- + -- Dump_Coverage -- + ------------------- + + procedure Dump_Coverage is + begin + pragma Annotate (Xcov, Dump_Buffers); + end Dump_Coverage; + + ---------- + -- Fact -- + ---------- + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/preelaborated_units/pkg.ads b/testsuite/tests/instr-cov/preelaborated_units/pkg.ads new file mode 100644 index 000000000..c4dfb4fdf --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/pkg.ads @@ -0,0 +1,9 @@ +package Pkg is + + pragma Preelaborate; + + procedure Reset_Coverage; + procedure Dump_Coverage; + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/preelaborated_units/test.py b/testsuite/tests/instr-cov/preelaborated_units/test.py new file mode 100644 index 000000000..dc364242b --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/test.py @@ -0,0 +1,35 @@ +""" +Check that we can compute code coverage for preelaborated units and reset/dump +coverage state from them. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + dump_trigger="manual", + manual_prj_name="gen", + trace_mode="src", +) +expected_report = { + "main.adb.xcov": ( + {"+": {7, 8, 9, 10}} + if thistest.options.block + else {"+": {9, 10}, "-": {7, 8}} + ), + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {27, 28}, "-": {30}}, +} +check_xcov_reports("xcov", expected_report, discard_empty=False) + +thistest.result() diff --git a/testsuite/tests/instr-cov/pretty_print/main.adb b/testsuite/tests/instr-cov/pretty_print/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/pretty_print/pkg.adb b/testsuite/tests/instr-cov/pretty_print/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pretty_print/pkg.ads b/testsuite/tests/instr-cov/pretty_print/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pretty_print/test.opt b/testsuite/tests/instr-cov/pretty_print/test.opt new file mode 100644 index 000000000..87a62fc19 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD GNAT-based gnatpp does not work on a source with missing dependencies +7.1.2 DEAD GNAT-based gnatpp does not work on a source with missing dependencies diff --git a/testsuite/tests/instr-cov/pretty_print/test.py b/testsuite/tests/instr-cov/pretty_print/test.py new file mode 100644 index 000000000..c347da5a5 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/test.py @@ -0,0 +1,32 @@ +""" +Test that running gnatcov instrument with the --pretty-print switch does not +yield any warning. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs="..", mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--pretty-print"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {5, 6, 8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/protected_body/src/foo.adb b/testsuite/tests/instr-cov/protected_body/src/foo.adb new file mode 100644 index 000000000..a03047ad0 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/src/foo.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +package body Foo is + + protected body Obj_Type is + + procedure Set (X : Integer) is + begin + Val := X; + end Set; + + procedure Do_Nothing (X : Integer) is null; -- # null_proc + + function Get return Integer is (Val); -- # int_expr + + function Cond return Boolean is (Val > 0 or else Val = -5); -- # bool_expr + + end Obj_Type; + +end Foo; diff --git a/testsuite/tests/instr-cov/protected_body/src/foo.ads b/testsuite/tests/instr-cov/protected_body/src/foo.ads new file mode 100644 index 000000000..2625b9de4 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/src/foo.ads @@ -0,0 +1,20 @@ +pragma Ada_2012; + +package Foo is + + protected type Obj_Type is + procedure Set (X : Integer); + + procedure Do_Nothing (X : Integer); + + function Get return Integer; + + function Cond return Boolean; + + private + Val : Integer := 0; -- # decl + end Obj_Type; + + Obj : Obj_Type; + +end Foo; diff --git a/testsuite/tests/instr-cov/protected_body/src/test_foo.adb b/testsuite/tests/instr-cov/protected_body/src/test_foo.adb new file mode 100644 index 000000000..af784b10a --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/src/test_foo.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; + +with Support; use Support; + +with Foo; use Foo; + +procedure Test_Foo is +begin + Obj.Set (3); + Assert (Obj.Get = 3); + Assert (Obj.Cond); + Obj.Do_Nothing (0); + Obj.Set (-3); + Assert (not Obj.Cond); +end Test_Foo; + +--# foo.adb + +-- /null_proc/ l+ ## 0 +-- /int_expr/ l+ ## 0 +-- /bool_expr/ l! ## c!:"Val = -5" + +-- Declarations in protected type private parts only started getting +-- SCOS from the compiler after the 22 release branch, and the gnatcov +-- instrumenter was adjusted accordingly just before the branch. +-- +-- So, for binary traces only, we can't count on a SCO until GNAT Pro 23. +-- +-- We don't have a way to check for versions in a flexible manner and +-- this is very minor so just stick a weak expectation at this stage. + +--# foo.ads + +-- /decl/ ~l+ ## 0 diff --git a/testsuite/tests/instr-cov/protected_body/test.opt b/testsuite/tests/instr-cov/protected_body/test.opt new file mode 100644 index 000000000..67126a044 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Protected objects not available in zfp runtimes diff --git a/testsuite/tests/instr-cov/protected_body/test.py b/testsuite/tests/instr-cov/protected_body/test.py new file mode 100644 index 000000000..ed32e5903 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/test.py @@ -0,0 +1,11 @@ +""" +Check that degenerate subprograms are correctly instrumented in protected +bodies +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/pure_units/main.adb b/testsuite/tests/instr-cov/pure_units/main.adb new file mode 100644 index 000000000..ff20c1dc0 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; +with Pkg.Child; use Pkg.Child; + +procedure Main is + Dummy : Boolean := Pkg.Opposite (True); +begin + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (0))); + Pkg.Do_Nothing_2; + Pkg.Child.Do_Nothing_3; +end Main; diff --git a/testsuite/tests/instr-cov/pure_units/p.gpr b/testsuite/tests/instr-cov/pure_units/p.gpr new file mode 100644 index 000000000..000deffc5 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/p.gpr @@ -0,0 +1,8 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Coverage is + for Units use ("pkg", "pkg.child"); + end Coverage; +end P; diff --git a/testsuite/tests/instr-cov/pure_units/pkg-child.ads b/testsuite/tests/instr-cov/pure_units/pkg-child.ads new file mode 100644 index 000000000..d6d05df4e --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/pkg-child.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pkg.Child is + + pragma Pure (Child); + + type Stuff_Child is null record; + + procedure Do_Nothing_3 is null; + procedure Do_Nothing_4 is null; + + function Identity_Child (B : Boolean) return Boolean is (B); + function Opposite_Child (B : Boolean) return Boolean is (not B); + +end Pkg.Child; diff --git a/testsuite/tests/instr-cov/pure_units/pkg.adb b/testsuite/tests/instr-cov/pure_units/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pure_units/pkg.ads b/testsuite/tests/instr-cov/pure_units/pkg.ads new file mode 100644 index 000000000..97b754550 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/pkg.ads @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package Pkg is + + pragma Pure; + + function Fact (I : Integer) return Integer; + + type Stuff is null record; + + procedure Do_Nothing_1 is null; + procedure Do_Nothing_2 is null; + + function Identity (B : Boolean) return Boolean is (B); + function Opposite (B : Boolean) return Boolean is (not B); + +end Pkg; diff --git a/testsuite/tests/instr-cov/pure_units/test.opt b/testsuite/tests/instr-cov/pure_units/test.opt new file mode 100644 index 000000000..2b67c9ffb --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/pure_units/test.py b/testsuite/tests/instr-cov/pure_units/test.py new file mode 100644 index 000000000..118fecec0 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/test.py @@ -0,0 +1,37 @@ +""" +Check that we can compute code coverage for Pure units. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "pkg.ads.xcov": {"+": {12, 15}, "-": {11, 14}}, + "pkg.adb.xcov": {"+": {5, 6}, "-": {8}}, + "pkg-child.ads.xcov": {"+": {9}, "-": {10, 12, 13}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-dummy/.gitignore b/testsuite/tests/instr-cov/remove_extra_src/src-dummy/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb new file mode 100644 index 000000000..0e1a12f3b --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb @@ -0,0 +1,10 @@ +package body Mylib is + function Foo (B : Boolean) return Integer is + begin + if B then + return 1; + else + return 2; + end if; + end Foo; +end Mylib; diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads new file mode 100644 index 000000000..e655a845e --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + function Foo (B : Boolean) return Integer; +end Mylib; diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb b/testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb new file mode 100644 index 000000000..fdcbe8493 --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb @@ -0,0 +1,8 @@ +with Mylib; + +procedure Prog is +begin + if Mylib.Foo (True) = 3 then + raise Program_Error; + end if; +end Prog; diff --git a/testsuite/tests/instr-cov/remove_extra_src/test.py b/testsuite/tests/instr-cov/remove_extra_src/test.py new file mode 100644 index 000000000..2d18f6af0 --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/test.py @@ -0,0 +1,82 @@ +""" +Test that "gnatcov instrument" removes "$project_name-gnatcov-instr" +directories for projects that are not of interest. + +Create a hierarchy of three projects: a library (mylib), a dummy project +(dummy) and a program using them (myprog). First instrument only the library +(to produce the "$project_name-gnatcov-instr" directory in the library's object +directory). Then, instrument only the program. + +The latter is supposed to remove the library's "$project_name-gnatcov-instr" +directory. If it does not, building the program will trigger link errors: +gprbuild will blindly use the library's instrumented units but the instrumented +main will not pull the buffer units. + +The dummy project has the same object directory as myprog. This used to make +gnatcov remove myprog's all instrumented source files, so the presence of dummy +in the tree of projects is here to check this does not happen anymore. +""" + +import os.path + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +Wdir("tmp_") + +# Create projects +mylib_gpr = gprfor( + prjid="mylib", + mains=[], + langs=["Ada"], + srcdirs=["../src-mylib"], + objdir="obj-mylib", +) +dummy_gpr = gprfor( + prjid="dummy", + mains=[], + langs=[], + srcdirs=["../src-dummy"], + objdir="obj-myprog", +) +myprog_gpr = gprfor( + prjid="myprog", + mains=["prog.adb"], + srcdirs=["../src-myprog"], + objdir="obj-myprog", + deps=["mylib", "dummy"], +) + +# Instrument mylib.gpr +xcov_instrument( + gprsw=GPRswitches(root_project=mylib_gpr), + covlevel="stmt", + gpr_obj_dir="obj-mylib", + out="instr-mylib.log", +) + +# Create a non-empty directory in the mylib-gnatcov-instr folder, to check that +# the removal machinery handles it well (ignores it). +subdir = os.path.join("obj-mylib", "mylib-gnatcov-instr", "foo") +os.mkdir(subdir) +with open(os.path.join(subdir, "foo.txt"), "w") as f: + pass + +# Instrument, build, run and generate a coverage report for myprog.gpr (and not +# mylib.gpr). +build_run_and_coverage( + gprsw=GPRswitches(root_project=myprog_gpr, no_subprojects=True), + covlevel="stmt", + mains=["prog"], + gpr_obj_dir="obj-myprog", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports("xcov", {"prog.adb.xcov": {"+": {5}, "-": {6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/scalar_and/main.adb b/testsuite/tests/instr-cov/scalar_and/main.adb new file mode 100644 index 000000000..4ee776bfc --- /dev/null +++ b/testsuite/tests/instr-cov/scalar_and/main.adb @@ -0,0 +1,7 @@ +with Interfaces; use Interfaces; + +procedure Main is + U : Unsigned_32 := 1337; +begin + U := U and 255; +end Main; diff --git a/testsuite/tests/instr-cov/scalar_and/p.gpr b/testsuite/tests/instr-cov/scalar_and/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/scalar_and/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/scalar_and/test.py b/testsuite/tests/instr-cov/scalar_and/test.py new file mode 100644 index 000000000..9a5f058d4 --- /dev/null +++ b/testsuite/tests/instr-cov/scalar_and/test.py @@ -0,0 +1,28 @@ +"""Check that we don't instrument "A and B" as a decision.""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {4, 6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/select_when/src/pkg.adb b/testsuite/tests/instr-cov/select_when/src/pkg.adb new file mode 100644 index 000000000..1d9deb7f9 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/pkg.adb @@ -0,0 +1,27 @@ +package body Pkg is + task body T is + A, B : Boolean; -- # init + begin + accept Init (A, B : Boolean) do -- # init + T.A := A; -- # init + T.B := B; -- # init + end; + + loop + select -- # init + accept Set_A (Value : Boolean) do -- # set-a-stmts + A := Value; -- # set-a-stmts + end; + or + accept Set_B (Value : Boolean) do -- # set-b-stmts + B := Value; -- # set-b-stmts + end; + or + when A and then B => -- # wait-guard + accept Wait_Cond; -- # wait-stmts + or + terminate; + end select; + end loop; + end T; +end Pkg; diff --git a/testsuite/tests/instr-cov/select_when/src/pkg.ads b/testsuite/tests/instr-cov/select_when/src/pkg.ads new file mode 100644 index 000000000..df4066f9f --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + task type T is + entry Init (A, B : Boolean); + entry Set_A (Value : Boolean); + entry Set_B (Value : Boolean); + entry Wait_Cond; + end T; +end Pkg; diff --git a/testsuite/tests/instr-cov/select_when/src/test_0.adb b/testsuite/tests/instr-cov/select_when/src/test_0.adb new file mode 100644 index 000000000..20099974f --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_0.adb @@ -0,0 +1,30 @@ +with Pkg; +with Support; use Support; + +procedure Test_0 is +begin + Assert (True); +end Test_0; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l- ## s- +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l- ## s- +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l- ## d- +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l- ## s- +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l- ## d- +-- =/wait-stmts/ l- ## s- diff --git a/testsuite/tests/instr-cov/select_when/src/test_a_ab.adb b/testsuite/tests/instr-cov/select_when/src/test_a_ab.adb new file mode 100644 index 000000000..51501be39 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_a_ab.adb @@ -0,0 +1,39 @@ +with Pkg; + +procedure Test_A_AB is + T : Pkg.T; +begin + T.Init (A => True, B => False); + + select + T.Wait_Cond; -- Guard: True and False => False + else + null; + end select; + + T.Set_B (True); + T.Wait_Cond; -- Guard: True and True => True +end Test_A_AB; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l! ## c!:"A" +-- =/wait-stmts/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb b/testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb new file mode 100644 index 000000000..246c24e47 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb @@ -0,0 +1,48 @@ +with Pkg; + +procedure Test_A_B_AB is + T : Pkg.T; +begin + T.Init (A => False, B => False); + + T.Set_A (True); + select + T.Wait_Cond; -- Guard: True and False => False + else + null; + end select; + + T.Set_A (False); + T.Set_B (True); + select + T.Wait_Cond; -- Guard: False and True => False + else + null; + end select; + + T.Set_A (True); + T.Wait_Cond; -- Guard: True and True => True +end Test_A_B_AB; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/select_when/src/test_b_ab.adb b/testsuite/tests/instr-cov/select_when/src/test_b_ab.adb new file mode 100644 index 000000000..1c6b249ff --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_b_ab.adb @@ -0,0 +1,39 @@ +with Pkg; + +procedure Test_B_AB is + T : Pkg.T; +begin + T.Init (A => False, B => True); + + select + T.Wait_Cond; -- Guard: False and True => False + else + null; + end select; + + T.Set_A (True); + T.Wait_Cond; -- Guard: True and True => True +end Test_B_AB; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l! ## c!:"B" +-- =/wait-stmts/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/select_when/src/test_false.adb b/testsuite/tests/instr-cov/select_when/src/test_false.adb new file mode 100644 index 000000000..2994fe364 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_false.adb @@ -0,0 +1,36 @@ +with Pkg; + +procedure Test_False is + T : Pkg.T; +begin + T.Init (A => False, B => False); + + select + T.Wait_Cond; -- Guard: False and False => False + else + null; + end select; +end Test_False; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l! ## dT- +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l! ## dT- +-- =/wait-stmts/ l- ## s- diff --git a/testsuite/tests/instr-cov/select_when/test.opt b/testsuite/tests/instr-cov/select_when/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/select_when/test.py b/testsuite/tests/instr-cov/select_when/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc b/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc new file mode 100644 index 000000000..4c135ee37 --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc @@ -0,0 +1 @@ +pragma Short_Circuit_And_Or; diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/main.adb b/testsuite/tests/instr-cov/short_circuit_and_or/main.adb new file mode 100644 index 000000000..2aa195da3 --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/main.adb @@ -0,0 +1,136 @@ +-- TODO: Type_Pkg needed to avoid problems with type conversion in the main +-- when instrumenting for MC/DC (U706-036) + +with Type_Pkg; use Type_Pkg; + +procedure Main is + + procedure Regular_And_Or (L, R : Typ; Res_And, Res_Or : out Typ); + + procedure Regular_And_Or_Use_Pkg (L, R : Typ; Res_And, Res_Or: out Typ); + + procedure Overloaded_And_Or (L, R : Typ; Res_And, Res_Or : out Typ); + + procedure Derived_And_Or (L, R : Derived; Res_And, Res_Or : out Derived); + + package Pkg is + function "and" (Left, Right : Typ) return Typ; + function "or" (Left, Right : Typ) return Typ; + end Pkg; + + package body Pkg is + function "and" (Left, Right : Typ) return Typ is + begin + if Left then + return Right; + end if; + return False; + end "and"; + + function "or" (Left, Right : Typ) return Typ is + begin + if Left then + return True; + else + return Right; + end if; + end "or"; + end Pkg; + + procedure Regular_And_Or (L, R : Typ; Res_And, Res_Or : out Typ) is + begin + Res_And := L and R; -- Should be instrumented for MCDC + Res_Or := L or R; -- Same + end Regular_And_Or; + + procedure Regular_And_Or_Use_Pkg (L, R : Typ; Res_And, Res_Or: out Typ) is + use Pkg; + begin + -- Use clause visibility cannot hide declarations happening within the + -- Standard Ada package, so the following should resolve to the + -- Standard.Boolean operators, which need to be instrumented for MC/DC. + + Res_And := L and R; + Res_Or := L or R; + end Regular_And_Or_Use_Pkg; + + procedure Overloaded_And_Or (L, R : Typ; Res_And, Res_Or : out Typ) is + function "and" (Left, Right : Typ) return Typ is + begin + if Left then + return Right; + else + return False; + end if; + end "and"; + + function "or" (Left, Right : Typ) return Typ is + begin + if Left then + return True; + else + return Right; + end if; + end "or"; + + begin + -- Here there is no use clause visibility involved, so the operators + -- used are the ones defined above, and should not be instrumented for + -- MCDC. + + Res_And := L and R; + Res_Or := L or R; + end Overloaded_And_Or; + + procedure Derived_And_Or (L, R : Derived; Res_And, Res_Or : out Derived) is + begin + Res_And := L and R; + Res_Or := L or R; + end Derived_And_Or; + + True_Var : Boolean := True; + pragma Volatile (True_Var); + + False_Var : Boolean := False; + pragma Volatile (False_Var); + + True_Var_Der : Derived := True; + pragma Volatile (True_Var_Der); + + False_Var_Der : Derived := False; + pragma Volatile (False_Var_Der); + + Res_And, Res_Or : Typ; + pragma Volatile (Res_And); + pragma Volatile (Res_Or); + + Res_And_Der, Res_Or_Der : Derived; + pragma Volatile (Res_And_Der); + pragma Volatile (Res_Or_Der); + +begin + + Regular_And_Or (True_Var, True_Var, Res_And, Res_Or); + Regular_And_Or (False_Var, False_Var, Res_And, Res_Or); + + Regular_And_Or_Use_Pkg (True_Var, True_Var, Res_And, Res_Or); + Regular_And_Or_Use_Pkg (False_Var, False_Var, Res_And, Res_Or); + + Overloaded_And_Or (True_Var, True_Var, Res_And, Res_Or); + Overloaded_And_Or (False_Var, False_Var, Res_And, Res_Or); + + Derived_And_Or (True_Var_Der, True_Var_Der, Res_And_Der, Res_Or_Der); + Derived_And_Or (False_Var_Der, False_Var_Der, Res_And_Der, Res_Or_Der); + + -- These do not actively test anything, but are used to make sure the + -- procedures "and" and "or" in package Pkg are marked as covered, + -- so coverage violation only happen in lines where the operators are + -- called. + + Res_And := Pkg."and" (True_Var, True_Var); + Res_And := Pkg."and" (False_Var, False_Var); + + Res_Or := Pkg."or" (True_Var, True_Var); + Res_Or := Pkg."or" (False_Var, False_Var); + +end Main; diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.opt b/testsuite/tests/instr-cov/short_circuit_and_or/test.opt new file mode 100644 index 000000000..321252117 --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.opt @@ -0,0 +1 @@ +src-traces XFAIL eng/libadalang/libadalang#1224: overloading resolution bug diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.py b/testsuite/tests/instr-cov/short_circuit_and_or/test.py new file mode 100644 index 000000000..5744f52af --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.py @@ -0,0 +1,74 @@ +""" +Test that when --short-circuit-and-or is passed, or in the presence +of a Short_Circuit_And_Or configuration pragma, gnatcov considers the 'and' +and 'or' boolean operators as having short-circuit semantics, and instruments +their operands as conditions for MC/DC coverage. + +This test checks that the Standard.Boolean and/or operators are +considered to have short-circuit semantics (including for subtypes of +Standard.Boolean) but that the and/or operators for a type derived from +Standard.Boolean are not. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +def check_results(): + check_xcov_reports( + "obj", + { + "main.adb.xcov": {"!": {42, 43, 53, 54}, "+": {81, 82, 87, 88}}, + "type_pkg.ads.xcov": {}, + }, + discard_empty=False, + ) + + +tmp = Wdir() + +# First, verify that passing --short-circuit-and-or activates the +# instrumentation of non-short circuit boolean operators for MC/DC. +# This part of the test is deactivated for bin traces as the option +# only controls the instrumenter. +if thistest.options.trace_mode == "src": + tmp.to_subdir("tmp_switch") + prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + ) + + build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt+mcdc", + mains=["main"], + extra_instr_args=["--short-circuit-and-or"], + extra_coverage_args=["-axcov"], + ) + + check_results() + + +# Then, check that the presence of a "pragma Short_Circuit_And_Or" is +# correctly taken into account during instrumentation. +tmp.to_subdir("tmp_config") + +prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + compiler_extra='for Local_Configuration_Pragmas use "../gnat.adc";', +) + +build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +check_results() + +thistest.result() diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads b/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads new file mode 100644 index 000000000..ff12ef1a8 --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads @@ -0,0 +1,7 @@ +package Type_Pkg is + + subtype Typ is Boolean; + + type Derived is new Boolean; + +end Type_Pkg; diff --git a/testsuite/tests/instr-cov/stmt_after_accept/main.adb b/testsuite/tests/instr-cov/stmt_after_accept/main.adb new file mode 100644 index 000000000..f92ba8aa0 --- /dev/null +++ b/testsuite/tests/instr-cov/stmt_after_accept/main.adb @@ -0,0 +1,33 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + task type My_Task is + entry Pass_Boolean (B : Boolean); + entry Pass_Integer (I : Integer); + end My_Task; + + task body My_Task is + Stored_B : Boolean; + begin + select + accept Pass_Boolean (B : Boolean) do + Stored_B := B; + end Pass_Boolean; + + Put_Line ("Hello, world!"); + if Stored_B then + Put_Line ("B was True"); + end if; + or + accept Pass_Integer (I : Integer) do + pragma Unreferenced (I); + null; + end Pass_Integer; + end select; + end My_Task; + + T : My_Task; +begin + T.Pass_Boolean (False); +end Main; diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.opt b/testsuite/tests/instr-cov/stmt_after_accept/test.opt new file mode 100644 index 000000000..caccd7ad3 --- /dev/null +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.opt @@ -0,0 +1,2 @@ +!native DEAD Uses full runtime only constructs +RTS_ZFP DEAD Uses full runtime constructs diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.py b/testsuite/tests/instr-cov/stmt_after_accept/test.py new file mode 100644 index 000000000..a44b88bcc --- /dev/null +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.py @@ -0,0 +1,29 @@ +""" +Regression test for the instrumenter. It used to crash when instrumenting +statements that appear after "accept" blocks. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {14, 15, 18, 19, 30, 32}, "-": {20, 23, 25}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/unexpected-ada-main/main.ads b/testsuite/tests/instr-cov/unexpected-ada-main/main.ads new file mode 100644 index 000000000..2ed96e9de --- /dev/null +++ b/testsuite/tests/instr-cov/unexpected-ada-main/main.ads @@ -0,0 +1,2 @@ +package Main is +end Main; diff --git a/testsuite/tests/instr-cov/unexpected-ada-main/test.py b/testsuite/tests/instr-cov/unexpected-ada-main/test.py new file mode 100644 index 000000000..d57ff9e40 --- /dev/null +++ b/testsuite/tests/instr-cov/unexpected-ada-main/test.py @@ -0,0 +1,29 @@ +""" +Check that "gnatcov instrument" emits a warning when it fails to insert the +dump of coverage buffers in mains. +""" + +from SCOV.instr import xcov_instrument +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(mains=["main.ads"], srcdirs=[".."])), + covlevel="stmt", + out="instrument.log", + tolerate_messages=".", +) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + ( + "warning: cannot dump coverage buffers in main.ads:" + " subprogram body expected" + ), + contents_of("instrument.log").strip(), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/unknown_unit/main.adb b/testsuite/tests/instr-cov/unknown_unit/main.adb new file mode 100644 index 000000000..a2ed76204 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/main.adb @@ -0,0 +1,7 @@ +with Pkg; use Pkg; + +procedure Main is + Dummy : Integer := Pkg.Fact (6); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/unknown_unit/p.gpr b/testsuite/tests/instr-cov/unknown_unit/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/unknown_unit/pkg.adb b/testsuite/tests/instr-cov/unknown_unit/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/unknown_unit/pkg.ads b/testsuite/tests/instr-cov/unknown_unit/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/unknown_unit/test.py b/testsuite/tests/instr-cov/unknown_unit/test.py new file mode 100644 index 000000000..e30ba57c5 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/test.py @@ -0,0 +1,67 @@ +""" +Check that "gnatcov coverage" properly report a source trace entry referencing +an unknown instrumented unit. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import xcov + + +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") +unrelated_sid = "unrelated_instr.sid" + +tmp = Wdir("tmp_") + +# Instrument the main, only to get an SID file that is unrelated to the units +# we want to cover (pkg). +xcov_instrument( + gprsw=GPRswitches(root_project=p_gpr, units=["main"]), + gpr_obj_dir="obj", + covlevel="stmt", +) +cp(os.path.join("..", "obj", "main.sid"), unrelated_sid) + +# Instrument/build/run the project only for the "pkg" unit +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p_gpr, units=["pkg"]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode="src", +) +trace_file = xcov_args[-1] + +# Try to produce a coverage report for it, but providing the wrong SID +mkdir("xcov") +p = xcov( + [ + "coverage", + "-v", + "-axcov", + "--output-dir=xcov", + "--level", + "stmt", + "--sid", + unrelated_sid, + trace_file, + ], + out="coverage.log", +) +thistest.fail_if( + "[GNATCOV.MISC] discarding source trace entry for unknown instrumented" + " unit: body of pkg" not in lines_of("coverage.log") +) + +thistest.result() diff --git a/testsuite/tests/integrated_instr_cross/basic_C/main.c b/testsuite/tests/integrated_instr_cross/basic_C/main.c new file mode 100644 index 000000000..10cdcd956 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/basic_C/main.c @@ -0,0 +1,15 @@ +#include +#include + +int +main () +{ + bool all_good = true; + bool all_good_really = true; + printf ("Hello "); + if (all_good && all_good_really) + printf ("world!\n"); + else + printf ("... actually no"); + return 0; +} diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.opt b/testsuite/tests/integrated_instr_cross/basic_C/test.opt new file mode 100644 index 000000000..1ddcc4440 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.opt @@ -0,0 +1,3 @@ +!bareboard DEAD This test relies on examples specific to bareboard targets +morello-elf DEAD No BSP provided with this toolchain +leon3-elf XFAIL Linker cannot find fwrite (to be investigated) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.py b/testsuite/tests/integrated_instr_cross/basic_C/test.py new file mode 100644 index 000000000..6b6562eb7 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.py @@ -0,0 +1,106 @@ +""" +Simple sanity check test for integrated instrumentation for bareboard targets. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SUITE.control import env, GPRBUILD +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import ( + get_c_bsp, + cmdrun, + driver_for_lang, + run_cov_program, + thistest, + xcov, +) + +Wdir("tmp_") + +# We need to setup the coverage runtime with no Ada support as otherwise we'll +# get undefined references to GNAT.IO + +gcvrt_prefix = "gcvrt" +xcov(["setup", f"--prefix={gcvrt_prefix}", "--restricted-to-languages=C"]) +env.add_search_path( + "GPR_PROJECT_PATH", + os.path.join(gcvrt_prefix, "share", "gpr"), +) + +cp("../main.c", ".") + +# Build the C BSP +bsp_root = "bsp_root" +mkdir(bsp_root) +bsp_prj_name = get_c_bsp(thistest.options.RTS, bsp_root) + +bsp_prj = os.path.join(bsp_root, f"{bsp_prj_name}.gpr") + +# Generate a simple project +main_prj = "prj.gpr" +with open(main_prj, "w") as prj_file: + print(f'with "{bsp_prj}";', file=prj_file) + print("project Prj is", file=prj_file) + print( + f' for Target use "{thistest.env.target.platform}";', + file=prj_file, + ) + print(' for Languages use ("C");', file=prj_file) + print(' for Source_Dirs use (".");', file=prj_file) + print(' for Main use ("main.c");', file=prj_file) + print(' for Object_Dir use "obj";', file=prj_file) + print( + f" package Compiler renames {bsp_prj_name}.Compiler;", + file=prj_file, + ) + print(" package Linker is", file=prj_file) + print( + f' for Switches ("C") use {bsp_prj_name}.Linker_Switches;', + file=prj_file, + ) + print(" end Linker;", file=prj_file) + print("end Prj;", file=prj_file) + +# Setup the integrated instrumentation +compiler = driver_for_lang("C") +gnatcov_artifact_dir = "gcv_artifacts" +xcov( + [ + "setup-integration", + "--level=stmt+mcdc", + f"--files={os.path.abspath('main.c')}", + f"--compilers={os.path.basename(compiler)}", + f"--output-dir={gnatcov_artifact_dir}", + ] +) +env.add_path(gnatcov_artifact_dir) + +# Build our simple C main and execute it +cmdrun([GPRBUILD, "-P", main_prj], for_pgm=False) +run_log = "run.log" +run_cov_program("./obj/main", out=run_log) + +trace_name = "main.srctrace" +xcov(["extract-base64-trace", run_log, trace_name]) +xcov( + [ + "coverage", + "--sid", + os.path.join(gnatcov_artifact_dir, "main.c.sid"), + "-axcov", + "-cstmt+mcdc", + trace_name, + ] +) +check_xcov_reports( + reports_dir=".", + expected_cov={ + "main.c.xcov": {"+": {7, 8, 9, 11, 14}, "!": {10}, "-": {13}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/integrated_instr_cross/extra.opt b/testsuite/tests/integrated_instr_cross/extra.opt new file mode 100644 index 000000000..a69bb239b --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/extra.opt @@ -0,0 +1 @@ +native DEAD test meant specifically for cross targets diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp b/testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp new file mode 100644 index 000000000..2650762fa --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp @@ -0,0 +1,12 @@ +#include + +int +main (void) +{ + int sum = 0; + for (auto i : { 1, 2, 3 }) + { + sum += i; + } + return 0; +} diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt new file mode 100644 index 000000000..0d9edcec5 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt @@ -0,0 +1,4 @@ +!bareboard DEAD This test relies on examples specific to bareboard targets +morello-elf DEAD No BSP provided with this toolchain +leon3-elf XFAIL Linker cannot find fwrite (to be investigated) +ppc-elf DEAD Structure of the bsp project is not as expected diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py new file mode 100644 index 000000000..19017e74f --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py @@ -0,0 +1,108 @@ +""" +Test initializer range for integrated instrumentation for bareboard targets. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SUITE.control import env, GPRBUILD +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import ( + get_c_bsp, + cmdrun, + driver_for_lang, + run_cov_program, + thistest, + xcov, +) + +Wdir("tmp_") + +# We need to setup the coverage runtime with no Ada support as otherwise we'll +# get undefined references to GNAT.IO + +gcvrt_prefix = "gcvrt" +xcov(["setup", f"--prefix={gcvrt_prefix}", "--restricted-to-languages=C,C++"]) +env.add_search_path( + "GPR_PROJECT_PATH", + os.path.join(gcvrt_prefix, "share", "gpr"), +) + +cp("../main.cpp", ".") + +# Build the C BSP +bsp_root = "bsp_root" +mkdir(bsp_root) +bsp_prj_name = get_c_bsp(thistest.options.RTS, bsp_root) + +bsp_prj = os.path.join(bsp_root, f"{bsp_prj_name}.gpr") + +# Generate a simple project +main_prj = "prj.gpr" +with open(main_prj, "w") as prj_file: + print(f'with "{bsp_prj}";', file=prj_file) + print("project Prj is", file=prj_file) + print( + f' for Target use "{thistest.env.target.platform}";', + file=prj_file, + ) + print(' for Languages use ("C++");', file=prj_file) + print(' for Source_Dirs use (".");', file=prj_file) + print(' for Main use ("main.cpp");', file=prj_file) + print(' for Object_Dir use "obj";', file=prj_file) + print(" package Compiler is", file=prj_file) + print( + f""" + for Switches ("C++") use {bsp_prj_name}.Common_Switches; + """, + file=prj_file, + ) + print(" end Compiler;", file=prj_file) + print(" package Linker is", file=prj_file) + print( + f' for Switches ("C++") use {bsp_prj_name}.Linker_Switches;', + file=prj_file, + ) + print(" end Linker;", file=prj_file) + print("end Prj;", file=prj_file) + +# Setup the integrated instrumentation +compiler = driver_for_lang("C++") +gnatcov_artifact_dir = "gcv_artifacts" +xcov( + [ + "setup-integration", + "--level=stmt+mcdc", + f"--files={os.path.abspath('main.cpp')}", + f"--compilers={os.path.basename(compiler)}", + f"--output-dir={gnatcov_artifact_dir}", + ] +) +env.add_path(gnatcov_artifact_dir) + +# Build our simple C main and execute it +cmdrun([GPRBUILD, "-P", main_prj], for_pgm=False) +run_log = "run.log" +run_cov_program("./obj/main", out=run_log) + +trace_name = "main.srctrace" +xcov(["extract-base64-trace", run_log, trace_name]) +xcov( + [ + "coverage", + "--sid", + os.path.join(gnatcov_artifact_dir, "main.cpp.sid"), + "-axcov", + "-cstmt+mcdc", + trace_name, + ] +) +check_xcov_reports( + reports_dir=".", + expected_cov={"main.cpp.xcov": {"+": {6, 7, 9, 11}}}, +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr new file mode 100644 index 000000000..481b201fb --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr @@ -0,0 +1 @@ +INVALID PROJECT FILE FOR TEST PURPOSES diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py new file mode 100644 index 000000000..46073e130 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py @@ -0,0 +1,39 @@ +""" +Test that the error message emitted by the "gnatcov setup-integration" command +is helpful when failing to load the coverage runtime project. +""" + +from SUITE.cutils import Wdir +from SUITE.tutils import contents_of, thistest, xcov + +tmp = Wdir("tmp_") + +# Try to setup for a simple main file +integration_log = "setup-integration.log" +p = xcov( + [ + "setup-integration", + "-cstmt+mcdc", + "--output-dir=.", + "--files=../main.c", + "--runtime-project=no_such_gnatcov_rts", + ], + out=integration_log, + register_failure=False, +) + +thistest.fail_if(p.status == 0, "gnatcov exit status shouldn't be success") + +# Check that the error message correctly reports an issue with the coverage +# runtime. +thistest.fail_if_no_match( + what="gnatcov error message", + regexp=( + 'no_such_gnatcov_rts\\.gpr: error: project file ".*" not found' + "\n.*gnatcov.*: Could not load the coverage runtime project" + " no_such_gnatcov_rts" + ), + actual=contents_of(integration_log).strip(), +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h b/testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h new file mode 100644 index 000000000..d0e7c1eea --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h @@ -0,0 +1 @@ +const int special_0 = 0; diff --git a/testsuite/tests/integrated_instrumentation/401-M-flags/test.c b/testsuite/tests/integrated_instrumentation/401-M-flags/test.c new file mode 100644 index 000000000..dddbe4dda --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/401-M-flags/test.c @@ -0,0 +1,7 @@ +#include "special_0.h" + +int +main () +{ + return special_0; +} diff --git a/testsuite/tests/integrated_instrumentation/401-M-flags/test.py b/testsuite/tests/integrated_instrumentation/401-M-flags/test.py new file mode 100644 index 000000000..b6dec82f5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/401-M-flags/test.py @@ -0,0 +1,60 @@ +""" +Test that the output of the -M family of flags of the GCC preprocessor is not +clobbered with references to instrumentation artifacts. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import cmdrun, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources in the temporary directory +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "special_0.h"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) +baseline_dep_file = "test.dep.expected" +compile_cmd = [ + "gcc", + "test.c", + "-MM", + "-MF", + baseline_dep_file, +] + +# Generate the baseline dep file with the regular compiler +cmdrun(compile_cmd, for_pgm=False) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Ask gcc to produce a dep file, using the gnatcov wrapper this time +dep_file = "test.dep.actual" +compile_cmd.pop() +compile_cmd.append(dep_file) +cmdrun(compile_cmd, for_pgm=False) + +thistest.fail_if_not_equal( + what="Difference in generated dep file", + expected=contents_of(baseline_dep_file), + actual=contents_of(dep_file), +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/427-initializer-list/test.py b/testsuite/tests/integrated_instrumentation/427-initializer-list/test.py new file mode 100644 index 000000000..18c7001f1 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/427-initializer-list/test.py @@ -0,0 +1,56 @@ +""" +Test the integrated instrumentation on an initializer list, to verify that, on +native x86 compiler this doesn't cause parsing errors in libclang and we get +the expected coverage results. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "test_for_range.cpp"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test_for_range.cpp')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Compile our simple program +cmdrun(["gcc", "test_for_range.cpp", "-o", "test_for_range"], for_pgm=False) + +# Run the executable +cmdrun(["test_for_range"], for_pgm=True) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test_for_range.cpp.sid", + "-axcov", + srctracename_for("test_for_range"), + ] +) +check_xcov_reports(".", {"test_for_range.cpp.xcov": {"+": {6, 7, 9, 11}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp b/testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp new file mode 100644 index 000000000..2650762fa --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp @@ -0,0 +1,12 @@ +#include + +int +main (void) +{ + int sum = 0; + for (auto i : { 1, 2, 3 }) + { + sum += i; + } + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py b/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py new file mode 100644 index 000000000..4d83c82fd --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py @@ -0,0 +1,50 @@ +""" +Test that compiler output is correctly forwarded to the user on error. +""" + +import os +import re + +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import cmdrun, xcov + + +Wdir("tmp_") + +# Setup the instrumentation process +with open("main.c", "w"): + pass +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=main.c", + "--compilers=gcc", + "--output-dir=.", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Run the GCC wrapper with an invalid flag and check its output +output_file = "gcc-output.txt" +cmdrun( + ["gcc", "-c", "main.c", "-invalid-switch"], + out=output_file, + for_pgm=False, + expect_non_zero_code=True, +) + +output = contents_of(output_file) +error_msg = "gcc: error: unrecognized command-line option '-invalid-switch'" +thistest.fail_if_no_match( + "gcc wrapper output", f"(.|\n)*{re.escape(error_msg)}(.|\n)*", output +) +thistest.fail_if_match( + "gcc wrapper output", re.escape("== gnatcov bug detected =="), output +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/C++/Makefile b/testsuite/tests/integrated_instrumentation/C++/Makefile new file mode 100644 index 000000000..08f3a54de --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/C++/Makefile @@ -0,0 +1,11 @@ +CC=g++ +OBJ = test.o + +%.o: %.cpp + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/C++/test.cpp b/testsuite/tests/integrated_instrumentation/C++/test.cpp new file mode 100644 index 000000000..0097946c9 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/C++/test.cpp @@ -0,0 +1,8 @@ +#include + +int +main () +{ + std::cout << "Hello, World!" << std::endl; + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/C++/test.py b/testsuite/tests/integrated_instrumentation/C++/test.py new file mode 100644 index 000000000..2e2d756bc --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/C++/test.py @@ -0,0 +1,55 @@ +""" +Check the integrated instrumentation on a C++ source. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.cpp"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test.cpp')}", + "--compilers=g++", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test.cpp.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"test.cpp.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c b/testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/test.opt b/testsuite/tests/integrated_instrumentation/architecture_switches/test.opt new file mode 100644 index 000000000..e2424aac9 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/test.opt @@ -0,0 +1,12 @@ +-- This tests the fixes that makes gnatcov pass the architecture-specific +-- compiler switches (-m*) to: +-- +-- 1. the compilation of buffer units, +-- 2. the compilation of buffer list units, +-- 3. the partial linking command that merges object files for the buffer +-- unit and the corresponding "user" unit. +-- +-- Since 1 and 2 are just data units (they contain no subprogram), the only +-- switch that is relevant in this context is "-m32" from x86_64 toolchains, +-- so running this test makes no sense in other contexts. +!x86_64 DEAD diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/test.py b/testsuite/tests/integrated_instrumentation/architecture_switches/test.py new file mode 100644 index 000000000..6ab95b4cd --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/test.py @@ -0,0 +1,37 @@ +""" +Regression test: test that gnatcov correctly compile instrumentation artifacts +with the architecture-specific switches (such as -m32) passed to the original +compiler driver invocation. It used not to, which resulted in an error when +linking the instrumentation artifacts with the instrumented source, which was +compiled with them. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import cmdrun, thistest, xcov + +Wdir("tmp_") + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=../pkg.c", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Try to compile the source: the test used to fail there, because gnatcov used +# to run partial linking ("gcc -r"), to combine the actual code unit +# (expectedly built with -m32) with the coverage buffer unit (unexpectedly +# built with default settings: -m64), which the linker rejected. +cmdrun(["gcc", "-m32", "../pkg.c", "-c"], for_pgm=False) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt b/testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt new file mode 100644 index 000000000..b5e617d04 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt @@ -0,0 +1,4 @@ +project(HelloWorld) +cmake_minimum_required(VERSION 3.0) + +add_executable(hello_world main.c) diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/main.c b/testsuite/tests/integrated_instrumentation/basic_cmake/main.c new file mode 100644 index 000000000..8bfd10171 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/main.c @@ -0,0 +1,8 @@ +#include + +int +main () +{ + printf ("Hello world!\n"); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.opt b/testsuite/tests/integrated_instrumentation/basic_cmake/test.opt new file mode 100644 index 000000000..41b867856 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.opt @@ -0,0 +1 @@ +windows DEAD CMake builds with gcc not working on windows diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py new file mode 100644 index 000000000..00ab4be79 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py @@ -0,0 +1,54 @@ +""" +Regression test: gnatcov used to leave paths passed to the --files switch +un-normalized, which resulted in some units of interest being ignored at +instrumentation time. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + f"--files={os.path.join(cwd, '..', 'main.c')}", + "--compilers=gcc", + "--level=stmt", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +compiler_wrapper = os.path.join(cwd, "gcc") +cmdrun( + ["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False +) +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["hello_world"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=main.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports(".", {"main.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/Makefile b/testsuite/tests/integrated_instrumentation/basic_lib/Makefile new file mode 100644 index 000000000..eacae9bab --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/Makefile @@ -0,0 +1,12 @@ +main: main.o lib/libfoobar.a + gcc -o main main.o -Llib/ -lfoobar + +lib/libfoobar.a: + $(MAKE) -C lib + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -rf main.o + $(MAKE) -C lib clean diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile b/testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile new file mode 100644 index 000000000..258da872a --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile @@ -0,0 +1,8 @@ +libfoobar.a: foo.o bar.o + ar -rc $@ $^ + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -f foo.o bar.o libfoobar.a diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c b/testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c b/testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/main.c b/testsuite/tests/integrated_instrumentation/basic_lib/main.c new file mode 100644 index 000000000..2286f6957 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/main.c @@ -0,0 +1,10 @@ +extern int foo (); +extern int bar (); + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/test.py b/testsuite/tests/integrated_instrumentation/basic_lib/test.py new file mode 100644 index 000000000..507088d13 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/test.py @@ -0,0 +1,63 @@ +""" +Basic test for the integrated instrumentation approach. This test checks that +we integrate smoothly in a Makefile build process with: + * A library compiled with its own Makefile in the lib directory, producing + libfoobar.a and with foo.c and bar.c sources of interest. + * A main linked with the library (holding instrumented version of the + sources). The main is not a source of interest itself. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "main.c"), ".") +cp(os.path.join("..", "lib"), ".", recursive=True) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'lib', 'foo.c')}", + f"--files={os.path.join(cwd, 'lib', 'bar.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["main"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=foo.c.sid", + "--sid=bar.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports(".", {"bar.c.xcov": {"+": {4}}, "foo.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/Makefile b/testsuite/tests/integrated_instrumentation/basic_stmt/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c b/testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/test.c b/testsuite/tests/integrated_instrumentation/basic_stmt/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/test.py b/testsuite/tests/integrated_instrumentation/basic_stmt/test.py new file mode 100644 index 000000000..027a67b9d --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/test.py @@ -0,0 +1,73 @@ +""" +Basic test for the integrated instrumentation approach. This test checks that +we integrate smoothly in a standard (and very easy) Makefile build process, +that compiles the sources of the project, and then links. + +The integrated instrumentation process is as followed: + * The user sets up the instrumentation runtime + * The user sets up the instrumentation using the instrument-setup command. He + must indicate the list of sources of interest (through the --files switch), + the install location of the instrumentation runtime (through the + --runtime-install-dir) switch, and the list of compiler wrappers that he + wants gnatcov to generate (through the --compilers switch). + * This setup command produces compiler wrappers _and_ an instrumentation + configuration file. The user must then set his PATH to have the compiler + wrapper appear _before_ the actual compiler. + * Then, he can launch the build process unchanged. It will call the compiler + wrapper instead of the actual compiler, which will instrument on the fly. + * Running the executable should then produce a trace prefixed with the main + simple name. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py new file mode 100644 index 000000000..0a79488d1 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py @@ -0,0 +1,49 @@ +""" +Regression test-case: checks that the use of the compiler wrapper is +transparent to the user, meaning that all adequate use of the compiler are +supported by the compiler wrapper, and not only compiling / linking commands. +gnatcov used to crash on e.g. `gcc --version`. Also check other special cases +for robustness. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import cmdrun, thistest, xcov + +Wdir("tmp_") + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join('..', 'pkg.c')}", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Check that gcc --version do not crash +cmdrun(["gcc", "--version"], for_pgm=False) + +# Check that gcc -### -c pkg.c -o pkg.o does not crash and does not produce an +# object file. +cmdrun(["gcc", "-###", "-c", "../pkg.c", "-o", "pkg.o"], for_pgm=False) +thistest.fail_if( + os.path.exists("pkg.o"), + "unexpected pkg.o file", +) + +# Check that gcc -E pkg.c produces uninstrumented preprocessed code +cmdrun(["gcc", "-E", "../pkg.c", "-o", "pkg.pp"], for_pgm=False) +thistest.fail_if( + "witness" in contents_of("pkg.pp"), + "unexpected instrumented preprocessed file", +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt b/testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt new file mode 100644 index 000000000..b5e617d04 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt @@ -0,0 +1,4 @@ +project(HelloWorld) +cmake_minimum_required(VERSION 3.0) + +add_executable(hello_world main.c) diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c b/testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c new file mode 100644 index 000000000..257cb6860 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c @@ -0,0 +1,7 @@ +int +main () +{ + // Implicitly imported by --include=pkg.h on the command line + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h b/testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt new file mode 100644 index 000000000..439c70b1c --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt @@ -0,0 +1 @@ +windows DEAD CMake builds with gcc not supported on windows diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py new file mode 100644 index 000000000..9f44f8387 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py @@ -0,0 +1,68 @@ +""" +Regression test: check that the gcc compiler wrapper correctly discards the +different variations of the include switch when invoking the original compiler +driver command. +""" + +import os +import os.path + +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + + +def process(c_flags, subdir): + # Run the integrated instrumentation process with the given c_flags, and in + # the given subdir + tmp = Wdir(subdir) + cwd = os.getcwd() + # Setup the instrumentation process + xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, '..', 'main.c')}", + f"--files={os.path.join(cwd, '..', 'pkg.h')}", + "--compilers=gcc", + ] + ) + # Run the build + coverage process with the given c_flags + compiler_wrapper = os.path.join(cwd, "gcc") + cmdrun( + [ + "cmake", + "..", + f"-DCMAKE_C_COMPILER={compiler_wrapper}", + f'-DCMAKE_C_FLAGS={" ".join(c_flags)}', + ], + for_pgm=False, + ) + cmdrun(["make"], for_pgm=False) + + # Run the executable + cmdrun(["./hello_world"], for_pgm=False) + + # Check coverage expectations + xcov( + [ + "coverage", + "--level=stmt", + "--sid=main.c.sid", + "-axcov", + srctracename_for("main"), + ] + ) + check_xcov_reports( + ".", {"main.c.xcov": {"+": {5, 6}}, "pkg.h.xcov": {"+": {4}}} + ) + tmp.to_homedir() + + +header = os.path.join(os.getcwd(), "pkg.h") +process(["-include", header], "tmp_short_space_arg") +process([f"-include{header}"], "tmp_short_no_space_arg") +process(["--include", header], "tmp_long_space_arg") +process([f"--include={header}"], "tmp_long_eq_arg") + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt b/testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt new file mode 100644 index 000000000..f7753fa2e --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt @@ -0,0 +1,9 @@ +project(HelloWorld) +cmake_minimum_required(VERSION 3.0) + +# Create a static library from the sources in src +add_library(my_lib STATIC src/lib.c) + +# Create an executable using the library previously declared +add_executable(hello_world src/main.c) +target_link_libraries(hello_world my_lib) diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c new file mode 100644 index 000000000..184eb25dc --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c @@ -0,0 +1,7 @@ +#include "lib.h" + +int +identity (int x) +{ + return x; +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h new file mode 100644 index 000000000..5bc6dd5af --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h @@ -0,0 +1,6 @@ +#ifndef LIB_H_ +#define LIB_H_ + +int identity (int x); + +#endif // LIB_H_ diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c b/testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c new file mode 100644 index 000000000..d9036b833 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c @@ -0,0 +1,10 @@ +#include + +#include "lib.h" + +int +main () +{ + printf ("Hello world!\n"); + return identity (0); +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.opt b/testsuite/tests/integrated_instrumentation/cmake_lib/test.opt new file mode 100644 index 000000000..439c70b1c --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.opt @@ -0,0 +1 @@ +windows DEAD CMake builds with gcc not supported on windows diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py new file mode 100644 index 000000000..ac33a6a75 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py @@ -0,0 +1,63 @@ +""" +Test that gnatcov correctly takes into account instrumented units present +in a static library passed as a positional argument on the link command line. +This is what is done by CMake when defining a library, then using it in an +executable in the same CMakeLists.txt. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + f"--files={os.path.join(cwd, '..', 'src', 'main.c')}", + f"--files={os.path.join(cwd, '..', 'src', 'lib.c')}", + "--compilers=gcc", + "--level=stmt", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +compiler_wrapper = os.path.join(cwd, "gcc") +cmdrun( + ["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False +) +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["hello_world"], for_pgm=True) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=main.c.sid", + "--sid=lib.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports( + ".", + { + "main.c.xcov": {"+": {8, 9}}, + "lib.c.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c b/testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/test.c b/testsuite/tests/integrated_instrumentation/compile_and_link/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/test.py b/testsuite/tests/integrated_instrumentation/compile_and_link/test.py new file mode 100644 index 000000000..794a0e972 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/test.py @@ -0,0 +1,56 @@ +""" +Test for the integrated instrumentation approach, where we do not split the +compilation process from the link process: both are done through one command. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources in the temporary directory +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the compile + link command +cmdrun(["gcc", "-o", "test", "test.c", "pkg.c"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile new file mode 100644 index 000000000..bdb2aacbf --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile @@ -0,0 +1,16 @@ +main: main.o libbar/libbar.a libfoo/libfoo.a + gcc -o main main.o -Llibbar/ -Llibfoo -lbar -lfoo + +libbar/libbar.a: + $(MAKE) -C libbar + +libfoo/libfoo.a: + $(MAKE) -C libfoo + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -rf main.o + $(MAKE) -C libbar clean + $(MAKE) -C libfoo clean diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile new file mode 100644 index 000000000..1521b5f39 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile @@ -0,0 +1,8 @@ +libbar.a: foo.o bar.o + ar -rc $@ $^ + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -f foo.o bar.o libbar.a diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile new file mode 100644 index 000000000..ec29beda6 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile @@ -0,0 +1,8 @@ +libfoo.a: foo.o bar.o + ar -rc $@ $^ + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -f foo.o bar.o libfoo.a diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c new file mode 100644 index 000000000..2286f6957 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c @@ -0,0 +1,10 @@ +extern int foo (); +extern int bar (); + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py new file mode 100644 index 000000000..45afcaffe --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -0,0 +1,82 @@ +""" +Check that gnatcov integrated instrumentation only includes coverage buffer +symbols that are in the main link closure. It used to include in the coverage +buffers list every coverage buffer symbol that was in a library / object file +on the link command line. This could result in pulling into the link closure +object files that would have not been included otherwise, and thus result in +clashing symbols. + +Also check that gnatcov generates unique SID names when there are homonym +files +""" + +import os +import os.path + +from e3.fs import cp + +from SCOV.minicheck import check_xcov_reports +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +for item in ["Makefile", "libbar", "libfoo", "main.c"]: + cp(os.path.join("..", item), ".", recursive=True) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'libbar', 'bar.c')}", + f"--files={os.path.join(cwd, 'libbar', 'foo.c')}", + f"--files={os.path.join(cwd, 'libfoo', 'bar.c')}", + f"--files={os.path.join(cwd, 'libfoo', 'foo.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + "-v", + "--save-temps", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["main"], for_pgm=True) + +# Check coverage expectations +log_file = "coverage.log" +xcov( + [ + "coverage", + "--level=stmt", + "--sid=libbar-foo.c.sid", + "--sid=libbar-bar.c.sid", + "--sid=libfoo-foo.c.sid", + "--sid=libfoo-bar.c.sid", + "-axcov", + srctracename_for("main"), + ], + out=log_file, +) + +check_xcov_reports( + ".", + { + "libbar-bar.c.xcov": {"+": {4}}, + "libbar-foo.c.xcov": {"+": {4}}, + "libfoo-bar.c.xcov": {"-": {4}}, + "libfoo-foo.c.xcov": {"-": {4}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/Makefile b/testsuite/tests/integrated_instrumentation/every_uoi/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/pkg.c b/testsuite/tests/integrated_instrumentation/every_uoi/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/test.c b/testsuite/tests/integrated_instrumentation/every_uoi/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/test.py b/testsuite/tests/integrated_instrumentation/every_uoi/test.py new file mode 100644 index 000000000..d0dea20b5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/test.py @@ -0,0 +1,60 @@ +""" +Check that every file is of interest by default when using integrated +instrumentation without the `--files` switch of the gnatcov setup-integration +command. +""" + +import glob +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations. +xcov( + [ + "coverage", + "--level=stmt", + "-axcov", + srctracename_for("test"), + ] + + [f"--sid={sid}" for sid in glob.glob("*.sid")] +) +check_xcov_reports( + ".", {"pkg.c.xcov": {"+": {4}}, "test.c.xcov": {"+": {6, 7}}} +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/extra.opt b/testsuite/tests/integrated_instrumentation/extra.opt new file mode 100644 index 000000000..f38570883 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/extra.opt @@ -0,0 +1,2 @@ +native,linux,src-traces,!5.04a1,!7.1.2,!RTS_ZFP +ALL DEAD Prototype for integrated instrumentation functional for native linux diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/Makefile b/testsuite/tests/integrated_instrumentation/fake_ldd/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/ldd b/testsuite/tests/integrated_instrumentation/fake_ldd/ldd new file mode 100755 index 000000000..e0f18120f --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/ldd @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import subprocess +import sys + +with open("ldd.out", "w") as out: + process = subprocess.run(["/usr/bin/ldd", sys.argv[1]], stdout=out) + out.write("\tdummy.so => ()") + +with open("ldd.out", "r") as out: + print(out.read()) diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c b/testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/test.c b/testsuite/tests/integrated_instrumentation/fake_ldd/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/test.py b/testsuite/tests/integrated_instrumentation/fake_ldd/test.py new file mode 100644 index 000000000..d8200888a --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/test.py @@ -0,0 +1,74 @@ +""" +Regression test for integrated instrumentation, with a fake ldd that yields the +following output: + linux-vdso.so.1 => (0x00007ffda3d11000) + libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007d8894a00000) + /lib64/ld-linux-x86-64.so.2 (0x00007d8894dcc000) + +The difference with ldd is the first line, which is normally displayed as: + linux-vdso.so.1 (0x00007ffda3d11000) + +As gnatcov relies on the contents after the arrow, and before the loading +address to get the library path, it grabbed an invalid name in the former case. +There was no consistency check, which resulted in the compiler wrapper +crashing. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Copy the fake ldd in the temporary directory +cp(os.path.join("..", "ldd"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Put the compiler wrapper and the fake ldd on the PATH +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Remove our fake ldd to avoid shadowing the system one at execution time +cmdrun(["rm", "ldd"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/include_switch/glob.h b/testsuite/tests/integrated_instrumentation/include_switch/glob.h new file mode 100644 index 000000000..c15b449d6 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/include_switch/glob.h @@ -0,0 +1,3 @@ +// Define a global variable. If this file ends up included multiple time, this +// will yield an error. +int glob = 2; diff --git a/testsuite/tests/integrated_instrumentation/include_switch/test.c b/testsuite/tests/integrated_instrumentation/include_switch/test.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/include_switch/test.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/include_switch/test.py b/testsuite/tests/integrated_instrumentation/include_switch/test.py new file mode 100644 index 000000000..722a50312 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/include_switch/test.py @@ -0,0 +1,63 @@ +""" +Regression test: when the user passed the -include switch to gcc, it was +processed both by gnatcov when instrumenting the file and by gcc when compiling +the instrumented file. This resulted in reincluding the file, which could yield +a compilation error. GNATcov now passes the -fpreprocessed switch to the gcc +invocation, which means it now longer tries to preprocess the instrumented file +(that is already preprocessed). +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources in the temporary directory +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "glob.h"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, compile and link. Test all the various way of passing a -include file +cmdrun(["gcc", "-include", "glob.h", "test.c", "-o", "test"], for_pgm=False) +cmdrun(["gcc", "--include", "glob.h", "test.c", "-o", "test"], for_pgm=False) +cmdrun(["gcc", "--include=glob.h", "test.c", "-o", "test"], for_pgm=False) +cmdrun(["gcc", "-include./glob.h", "test.c", "-o", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"test.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/isystem/include/pkg.h b/testsuite/tests/integrated_instrumentation/isystem/include/pkg.h new file mode 100644 index 000000000..96dfea3e5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/isystem/include/pkg.h @@ -0,0 +1,5 @@ +static int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/isystem/test.c b/testsuite/tests/integrated_instrumentation/isystem/test.c new file mode 100644 index 000000000..14eebbdb7 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/isystem/test.c @@ -0,0 +1,8 @@ +#include "pkg.h" + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/isystem/test.py b/testsuite/tests/integrated_instrumentation/isystem/test.py new file mode 100644 index 000000000..1853bf065 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/isystem/test.py @@ -0,0 +1,65 @@ +""" +Regression test: checks that gnatcov accounts for the isystem switch. It used +to plainly ignore it, which resulted in preprocessing failures. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=../test.c", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Then, run the compile + link command +gcc_output = "gcc.out" +cmdrun( + [ + "gcc", + "-o", + "test", + os.path.join("..", "test.c"), + "-isystem", + os.path.join("..", "include"), + ], + out=gcc_output, + for_pgm=False, +) + +thistest.fail_if_not_equal( + "compiler output", + "", + contents_of(gcc_output), +) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"test.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp b/testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp new file mode 100644 index 000000000..b8f3853fe --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp @@ -0,0 +1,22 @@ +#include "foo.hh" + +#include +#include + +void +foo_dump (void) +{ + /* GNATCOV_DUMP_BUFFERS */ +} + +void +foo_warn (const char *s) +{ + std::cout << "WARN :" << s << std::endl; +} + +void +foo_error (const char *s) +{ + std::cout << "ERROR:" << s << std::endl; +} diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/foo.hh b/testsuite/tests/integrated_instrumentation/manual_dump/foo.hh new file mode 100644 index 000000000..1387c9932 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/foo.hh @@ -0,0 +1,7 @@ +#pragma once + +void foo_dump (void); + +void foo_warn (const char *s); + +void foo_error (const char *s); diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/main.cpp b/testsuite/tests/integrated_instrumentation/manual_dump/main.cpp new file mode 100644 index 000000000..9cee91bd4 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/main.cpp @@ -0,0 +1,11 @@ +#include + +#include "foo.hh" + +int +main () +{ + foo_warn ("Hello there"); + foo_dump (); + foo_error ("General Kenobi"); +} diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/test.py b/testsuite/tests/integrated_instrumentation/manual_dump/test.py new file mode 100644 index 000000000..503c67c25 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/test.py @@ -0,0 +1,69 @@ +""" +Ensure the manual dump trigger flag works as expected in integrated +instrumentation mode. +""" + +import os + +from SCOV.minicheck import check_xcov_reports +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +CXX = "g++" +CXX_OUTPUT = "cc.out" +BIN = "main" + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=../foo.cpp", + f"--compilers={CXX}", + "--dump-trigger=manual", + "--manual-dump-files=../foo.cpp", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +cmdrun( + [ + CXX, + "-o", + BIN, + os.path.join("..", "main.cpp"), + os.path.join("..", "foo.cpp"), + "-I../", + ], + out=CXX_OUTPUT, + for_pgm=False, +) + + +thistest.fail_if_not_equal( + "compiler output", + "", + contents_of(CXX_OUTPUT), +) + +# Run the executable +cmdrun([BIN], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=foo.cpp.sid", + "-axcov", + srctracename_for(BIN), + ] +) +check_xcov_reports(".", {"foo.cpp.xcov": {"-": {21}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/Makefile b/testsuite/tests/integrated_instrumentation/no_uoi/Makefile new file mode 100644 index 000000000..922360d92 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/Makefile @@ -0,0 +1,11 @@ +CC=g++ +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -pedantic -Wall -o $@ $< + +test: $(OBJ) + $(CC) -pedantic -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/pkg.c b/testsuite/tests/integrated_instrumentation/no_uoi/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/test.c b/testsuite/tests/integrated_instrumentation/no_uoi/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/test.py b/testsuite/tests/integrated_instrumentation/no_uoi/test.py new file mode 100644 index 000000000..09e33ad13 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/test.py @@ -0,0 +1,52 @@ +""" +Check that gnatcov does not break compilation with the -pedantic switch. The +code generated for an empty buffers list used to be uncompilable with +-pedantic. Note that -pedantic should only diagnose warnings and not errors, +so this is not expected, but we can work around the issue easily so fix the +wrong code. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import cmdrun, thistest, xcov + + +# To avoid source repository pollution and interference between successive test +# runs, copy source material to a temporary directory and run the test there, +# which is common practice in the gnatcov testsuite. Doing so is however +# absolutely not a requirement to use the integrated instrumentation scheme. +Wdir("tmp_") + +src_dir = os.path.abspath("src") +run_dir = os.path.abspath("run") +os.mkdir(src_dir) +os.mkdir(run_dir) + +for filename in ["Makefile", "pkg.c", "test.c"]: + cp(os.path.join("..", filename), os.path.join(src_dir, filename)) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--compilers=g++", + f"--output-dir={run_dir}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=run_dir) + +# Then, run the build process unchanged +cmdrun(["make", "-C", src_dir, "test"], for_pgm=False) + +# Run the executable +cmdrun([os.path.join(src_dir, "test")], for_pgm=False) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/setup/Makefile b/testsuite/tests/integrated_instrumentation/setup/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/setup/pkg.c b/testsuite/tests/integrated_instrumentation/setup/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/setup/test.c b/testsuite/tests/integrated_instrumentation/setup/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/setup/test.py b/testsuite/tests/integrated_instrumentation/setup/test.py new file mode 100644 index 000000000..8725f1b4f --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/test.py @@ -0,0 +1,77 @@ +""" +Regression test for integrated instrumentation approach, using an +instrumentation runtime built and installed with `gnatcov setup +--restricted-to-languages=c` prior. The setup-integration command used to crash +with a `Could not load the coverage runtime project gnatcov_rts` message. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Install the instrumentation runtime with `--restricted-to-languages=C` +xcov( + [ + "setup", + "--prefix=install", + "--restricted-to-languages=c", + "--install-name=gnatcov_rts_c", + ] +) +env.add_search_path("GPR_PROJECT_PATH", "install/share/gpr") + +# Then, setup the instrumentation process. Do not pass --config, as that this +# was necessary to reproduce the original bug. Do not pass --target neither, as +# "gnatcov setup-integration" does not support it: let GPR code pick up the +# right native compiler from the environment and thus correctly guess the +# target. +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + "--runtime-project=gnatcov_rts_c", + ], + auto_config_args=False, + auto_target_args=False, +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/Makefile b/testsuite/tests/integrated_instrumentation/shared_lib/Makefile new file mode 100644 index 000000000..527ff9c30 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/Makefile @@ -0,0 +1,14 @@ +include lib/common.mk + +main: main.o lib/$(LIB) + gcc -o main main.o -Llib/ -lfoobar + +lib/$(LIB): + $(MAKE) -C lib + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -rf main.o + $(MAKE) -C lib clean diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile b/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile new file mode 100644 index 000000000..1e94beb96 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile @@ -0,0 +1,10 @@ +include common.mk + +$(LIB): foo.o bar.o + gcc -shared -o $@ $^ + +%.o: %.c + gcc -c -fpic $< -o $@ + +clean: + rm -f foo.o bar.o $(LIB) diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c b/testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk b/testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk new file mode 100644 index 000000000..378147cca --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk @@ -0,0 +1,5 @@ +ifeq ($(OS),Windows_NT) + LIB := libfoobar.dll +else + LIB := libfoobar.so +endif diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c b/testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/main.c b/testsuite/tests/integrated_instrumentation/shared_lib/main.c new file mode 100644 index 000000000..2286f6957 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/main.c @@ -0,0 +1,10 @@ +extern int foo (); +extern int bar (); + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/test.py b/testsuite/tests/integrated_instrumentation/shared_lib/test.py new file mode 100644 index 000000000..e112885be --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/test.py @@ -0,0 +1,88 @@ +""" +Regression test: when using integrated instrumentation and linking against +and instrumented shared library, gnatcov used not to include coverage buffers +from the shared library, which resulted in the shared library units not being +covered. +""" + +import os +import os.path + +from e3.fs import cp + +from SCOV.minicheck import check_xcov_reports +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "main.c"), ".") +cp(os.path.join("..", "lib"), ".", recursive=True) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'lib', 'foo.c')}", + f"--files={os.path.join(cwd, 'lib', 'bar.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# For windows, the OS looks for the DLL in the PATH, and for Linux, it looks +# in the LD_LIBRARY_PATH. +if thistest.env.target.os.name == "windows": + so_path = "PATH" + so_name = "libfoobar.dll" +else: + so_path = "LD_LIBRARY_PATH" + so_name = "libfoobar.so" + +# Check that when running the build process without LD_LIBRARY_PATH set, +# gnatcov warns that it cannot find the shared library dependency (because it +# relies on ldd, which looks at the LD_LIBRARY_PATH to know the shared library +# location). +cmdrun(["make"], out="make.out", for_pgm=False) +thistest.fail_if( + f"warning: Could not find library {so_name}. Add its directory to" + f" the {so_path} if this is an instrumented library." + not in contents_of("make.out"), + "Missing warning in make output", +) + +# Then, run the build process +env.add_search_path( + so_path, + os.path.join(cwd, "lib"), +) +cmdrun(["make", "clean"], for_pgm=False) +cmdrun(["make"], for_pgm=False) + + +# Run the executable +cmdrun(["main"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=foo.c.sid", + "--sid=bar.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports(".", {"bar.c.xcov": {"+": {4}}, "foo.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/bar.c b/testsuite/tests/integrated_instrumentation/special_filenames/bar.c new file mode 100644 index 000000000..1b5f37c42 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/bar.c @@ -0,0 +1,5 @@ +int +bar (int c) +{ + return c + 1; +} diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/foo.c b/testsuite/tests/integrated_instrumentation/special_filenames/foo.c new file mode 100644 index 000000000..069e4ecdb --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/foo.c @@ -0,0 +1,8 @@ +int +foo (int a, int b) +{ + if (a) + return a; + else + return b; +} diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.c b/testsuite/tests/integrated_instrumentation/special_filenames/test.c new file mode 100644 index 000000000..5c8b273b5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.c @@ -0,0 +1,10 @@ +extern int foo (int a, int b); +extern int bar (int c); + +int +main (void) +{ + foo (0, 1); + bar (0); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.py b/testsuite/tests/integrated_instrumentation/special_filenames/test.py new file mode 100644 index 000000000..2b81fd9c3 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.py @@ -0,0 +1,71 @@ +""" +Check that the integration instrumentation handles correctly filenames that +contain spaces. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +# Copy the sources in the temporary directory. Note that we cannot test the +# case of a filename containing a double quote or a backslash on Windows +# because of filename restrictions on that platform. +copy_map = { + "bar.c": "src bar.c" if env.build.os.name == "windows" else 'src\\"bar.c', + "foo.c": "src foo$@.c", + "test.c": "test.c", +} +for src, dest in copy_map.items(): + cp(os.path.join("..", src), dest) + +# Compute canonicalized filenames, which will be the base names for gnatcov +# artifacts (SID and xcov files). Note that "gnatcov" first turns '\' to '/' +# (during path separator canonicalization) and then the unique filename +# machinery turns '/' to '-'. +canonicalized_filenames = { + filename: mapped.replace("\\", "-") + for filename, mapped in copy_map.items() +} + +# Compute the expected coverage report from the actual source filenames +coverage_data = { + "test.c": {"+": {7, 8, 9}}, + "foo.c": {"+": {4, 7}, "-": {5}}, + "bar.c": {"+": {4}}, +} +expected_report = { + "{}.xcov".format(canonicalized_filenames[filename]): report + for filename, report in coverage_data.items() +} + +# Setup the instrumentation process +sources = [os.path.abspath(filename) for filename in copy_map.values()] +files = [f"--files={filename}" for filename in sources] +xcov( + ["setup-integration", "--level=stmt", "--compilers=gcc", "--output-dir=."] + + files +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Build the test program and run it +cmdrun(["gcc", "-o", "test program"] + sources, for_pgm=False) +cmdrun(["test program"], for_pgm=False) + +# Check coverage expectations +sid_args = [ + f"--sid={filename}.sid" for filename in canonicalized_filenames.values() +] +xcov(["coverage", "-cstmt", "-axcov", srctracename_for("test")] + sid_args) +check_xcov_reports(".", expected_report) + +thistest.result() diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.adb new file mode 100644 index 000000000..8f753bfd8 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.adb @@ -0,0 +1,23 @@ +package body Andthen is + + AA, BB : Boolean; + + function Expr + (Value : Boolean := AA and then BB) -- # andthen + return Boolean; + + function Expr + (Value : Boolean := AA and then BB) -- # andthen + return Boolean + is + begin + return Value; -- # retVal + end; + + function And_Then (A, B : Boolean) return Boolean is + begin + AA := A; -- # retVal + BB := B; -- # retVal + return Expr; -- # retVal + end; +end; diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads new file mode 100644 index 000000000..087fa3b2c --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads @@ -0,0 +1,3 @@ +package Andthen is + function And_Then (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb new file mode 100644 index 000000000..2d9b08a86 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb @@ -0,0 +1,17 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Single is +begin + Assert (not And_Then (False, False)); +end; + +--# andthen.adb +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## d? diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py new file mode 100644 index 000000000..b6309b0a7 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py @@ -0,0 +1,13 @@ +import re + +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase( + tolerate_messages=re.escape( + "!!! andthen.adb:6:26: gnatcov limitation: cannot find local" + " declarative part for MC/DC" + ) +).run() +thistest.result() diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb new file mode 100644 index 000000000..3a6008e03 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb @@ -0,0 +1,12 @@ +package body Andthen is + + type Expr (AA, BB : Boolean) is record + Value : Boolean := AA and then BB; -- # andthen + end record; + + function And_Then (A, B : Boolean) return Boolean is + E : Expr (A, B); -- # retVal + begin + return E.Value; -- # retVal + end; +end; diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.ads b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.ads new file mode 100644 index 000000000..087fa3b2c --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.ads @@ -0,0 +1,3 @@ +package Andthen is + function And_Then (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_0.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_0.adb new file mode 100644 index 000000000..087fb52f8 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_0.adb @@ -0,0 +1,17 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_0 is +begin + Assert (True); +end; + +--# andthen.adb +-- /retTrue/ l- ## s- +-- /retFalse/ l- ## s- +-- /retVal/ l- ## s- +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l! ## e- diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_a.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_a.adb new file mode 100644 index 000000000..f80767cca --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_a.adb @@ -0,0 +1,18 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_A is +begin + Assert (And_Then (True, True) = True); + Assert (And_Then (False, True) = False); +end; + +--# andthen.adb +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## e? diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_ab.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_ab.adb new file mode 100644 index 000000000..b5d1b8cb8 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_ab.adb @@ -0,0 +1,19 @@ +with Support, Andthen ; use Support, Andthen; + +procedure Test_Andthen_AB is +begin + Assert (And_Then (True, True) = True); + Assert (And_Then (True, False) = False); + Assert (And_Then (False, True) = False); +end; + +--# andthen.adb +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## e? diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_b.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_b.adb new file mode 100644 index 000000000..20fabb13d --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_b.adb @@ -0,0 +1,18 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_B is +begin + Assert (And_Then (True, True) = True); + Assert (And_Then (True, False) = False); +end; + +--# andthen.adb +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## e? diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_f.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_f.adb new file mode 100644 index 000000000..9824883e7 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_f.adb @@ -0,0 +1,18 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_F is +begin + Assert (And_Then (False, True) = False); + Assert (And_Then (True, False) = False); +end; + +--# andthen.adb +-- /retTrue/ l- ## s- +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l! ## eT- diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_t.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_t.adb new file mode 100644 index 000000000..e2b3d9865 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_t.adb @@ -0,0 +1,17 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_T is +begin + Assert (And_Then (True, True) = True); +end; + +--# andthen.adb +-- /retTrue/ l+ ## 0 +-- /retFalse/ l- ## s- +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l! ## eF- diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py new file mode 100644 index 000000000..13284503b --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py @@ -0,0 +1,13 @@ +import re + +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase( + tolerate_messages=re.escape( + "!!! andthen.adb:4:26: gnatcov limitation: cannot find local" + " declarative part for MC/DC" + ) +).run() +thistest.result() diff --git a/testsuite/tests/llvm/rust-llvm-reports/basic/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/basic/coverage.json new file mode 100644 index 000000000..9e2032f4b --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/basic/coverage.json @@ -0,0 +1,733 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/basic/src/mcdc_basic.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 8, + 48, + 9 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 13, + 48, + 14 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 18, + 48, + 19 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 23, + 48, + 24 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 28, + 48, + 29 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 33, + 48, + 34 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 38, + 48, + 39 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 44, + 1, + 48, + 9 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 48, + 13, + 48, + 14 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 18, + 48, + 19 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 23, + 48, + 24 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 28, + 48, + 29 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 33, + 48, + 34 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 38, + 48, + 39 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 48, + 40, + 50, + 6 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 50, + 5, + 50, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 51, + 1, + 51, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::condition_too_long", + "mcdc_records": [ + { + "num_conditions": 7, + "span": [ + 48, + 8, + 48, + 39 + ], + "test_vectors": [ + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1, + -1, + -1, + -1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic18condition_too_long" + }, + { + "branch_regions": [ + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 36, + 9, + 36, + 10 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 36, + 14, + 36, + 15 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 36, + 19, + 36, + 20 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 34, + 1, + 36, + 10 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 36, + 14, + 36, + 15 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 36, + 19, + 36, + 20 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 37, + 5, + 39, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 39, + 12, + 41, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 42, + 1, + 42, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::simple_not_covered", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 36, + 9, + 36, + 20 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic18simple_not_covered" + }, + { + "branch_regions": [ + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 16, + 9, + 16, + 10 + ], + "true_count": 5 + }, + { + "false_count": 3, + "kind": "MCDCBranchRegion", + "span": [ + 16, + 15, + 16, + 16 + ], + "true_count": 2 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 16, + 20, + 16, + 21 + ], + "true_count": 1 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 10, + 24, + 11 + ], + "true_count": 5 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 15, + 24, + 16 + ], + "true_count": 1 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 22, + 24, + 23 + ], + "true_count": 4 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 27, + 24, + 28 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 11, + 1, + 16, + 10 + ] + }, + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 16, + 15, + 16, + 16 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 16, + 20, + 16, + 21 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 17, + 5, + 19, + 6 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 19, + 12, + 21, + 6 + ] + }, + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 24, + 10, + 24, + 11 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 24, + 15, + 24, + 16 + ] + }, + { + "count": 6, + "kind": "CodeRegion", + "span": [ + 24, + 22, + 24, + 23 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 24, + 27, + 24, + 28 + ] + }, + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 25, + 5, + 27, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 27, + 12, + 29, + 6 + ] + }, + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 31, + 5, + 32, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::several_decisions_in_one_fct", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 16, + 9, + 16, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1 + ] + } + ] + }, + { + "num_conditions": 4, + "span": [ + 24, + 9, + 24, + 29 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0, + -1, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + -1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1, + 1, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1, + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1, + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic28several_decisions_in_one_fct" + }, + { + "branch_regions": [ + { + "false_count": 3, + "kind": "BranchRegion", + "span": [ + 4, + 8, + 4, + 13 + ], + "true_count": 4 + } + ], + "code_regions": [ + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 4, + 13 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 4, + 14, + 6, + 6 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 6, + 12, + 8, + 6 + ] + }, + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 9, + 1, + 9, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::bar", + "mcdc_records": [], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic3bar" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 53, + 1, + 66, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::main", + "mcdc_records": [], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic4main" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/basic/src/mcdc_basic.rs b/testsuite/tests/llvm/rust-llvm-reports/basic/src/mcdc_basic.rs new file mode 100644 index 000000000..3f99df4d5 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/basic/src/mcdc_basic.rs @@ -0,0 +1,66 @@ +use std::hint::black_box; + +fn bar(b: u32) { + if b > 6 { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn several_decisions_in_one_fct(a: bool, b: bool, c: bool, + d: bool, e: bool) { + let mut x = 0; + + if + a && (b || c) + { + x = 3; + } else { + x = 8; + } + + if + (a || d) && (e || b) + { + x += 3; + } else { + x += 8; + } + + bar(x); +} + +fn simple_not_covered(a: bool, b: bool, c: bool) { + if + a && b || c + { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn condition_too_long(a: bool, b: bool, c: bool, d: bool, + e: bool, f: bool, g: bool) { + // This condition should not be instrumented by the + // current implementation, because it is too long + if a && b || c || d && e || f && g { + black_box(33); + } +} + +fn main() { + several_decisions_in_one_fct(true, false, false, true, true); + several_decisions_in_one_fct(true, true, false, true, true); + several_decisions_in_one_fct(true, false, true, true, true); + several_decisions_in_one_fct(false, false, true, true, true); + several_decisions_in_one_fct(false, false, false, false, false); + several_decisions_in_one_fct(true, false, false, false, false); + several_decisions_in_one_fct(true, true, false, false, false); + + simple_not_covered(true, true, false); + simple_not_covered(true, false, false); + + condition_too_long(true, true, true, true, true, true, false); +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/basic/test.py b/testsuite/tests/llvm/rust-llvm-reports/basic/test.py new file mode 100644 index 000000000..2406bf45d --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/basic/test.py @@ -0,0 +1,40 @@ +""" +Check the correct loading of JSON files generated with the LLVM trace adapter. +This test checks simple constructions : several decisions in one function, +a non covered case, and a decision not instrumented because of its too +many conditions. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {36, 48, 50} + +uncovered = set() # foo + +covered = ( + multi_range( + (3, 9), # bar + (11, 32), # several_decisions_in_one_fct + (34, 42), # simple_not_covered + (53, 66), # condition_too_long + minus=[14, 22, 23, 30], + ) + - uncovered + - incomplete +) + +expected_report = { + "mcdc_basic.rs.xcov": { + "+": covered, + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report, cov_level="stmt+mcdc") + +thistest.result() diff --git a/testsuite/tests/llvm/rust-llvm-reports/closures/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/closures/coverage.json new file mode 100644 index 000000000..bee3adaf1 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/closures/coverage.json @@ -0,0 +1,165 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/closures/src/closures.rs", + "functions": [ + { + "branch_regions": [], + "code_regions": [ + { + "count": 35, + "kind": "CodeRegion", + "span": [ + 14, + 27, + 14, + 39 + ] + } + ], + "demangled_name": "closures::closure_imm::{closure#0}", + "mcdc_records": [], + "name": "_RNCNvCseR1raopjrvP_8closures11closure_imm0B3_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 35, + "kind": "CodeRegion", + "span": [ + 4, + 29, + 4, + 41 + ] + } + ], + "demangled_name": "closures::closure_in_var::{closure#0}", + "mcdc_records": [], + "name": "_RNCNvCseR1raopjrvP_8closures14closure_in_var0B3_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 21, + 27, + 21, + 39 + ] + } + ], + "demangled_name": "closures::closure_uncovered::{closure#0}", + "mcdc_records": [], + "name": "_RNCNvCseR1raopjrvP_8closures17closure_uncovered0B3_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 1, + 14, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 39, + 17, + 2 + ] + } + ], + "demangled_name": "closures::closure_imm", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures11closure_imm" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 4, + 16 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 6, + 9, + 10, + 2 + ] + } + ], + "demangled_name": "closures::closure_in_var", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures14closure_in_var" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 1, + 21, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 21, + 39, + 24, + 2 + ] + } + ], + "demangled_name": "closures::closure_uncovered", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures17closure_uncovered" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 26, + 1, + 30, + 2 + ] + } + ], + "demangled_name": "closures::main", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures4main" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/closures/src/closures.rs b/testsuite/tests/llvm/rust-llvm-reports/closures/src/closures.rs new file mode 100644 index 000000000..a7c944971 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/closures/src/closures.rs @@ -0,0 +1,30 @@ +use std::hint::black_box; + +fn closure_in_var(x: u32) { + let is_even = |n: &u32| (n & 1) == 0; + + let res: Vec<_> = (0..x) + .filter(is_even) + .collect(); + black_box(res); +} + +fn closure_imm(x: u32) { + let res: Vec<_> = (0..x) + .filter(|n: &u32| (n & 1) == 0) + .collect(); + black_box(res); +} + +fn closure_uncovered(_: u32) { + let res: Vec<_> = (0..0) + .filter(|n: &u32| (n & 1) == 0) + .collect(); + black_box(res); +} + +fn main() { + closure_in_var(35); + closure_imm(35); + closure_uncovered(35); +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/closures/test.py b/testsuite/tests/llvm/rust-llvm-reports/closures/test.py new file mode 100644 index 000000000..7ca6848e5 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/closures/test.py @@ -0,0 +1,28 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of closures' coverage. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {21} + +uncovered = set() + +expected_report = { + "closures.rs.xcov": { + "+": multi_range((3, 10), (12, 17), (19, 24), (26, 30), minus=[5]) + - incomplete + - uncovered, + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report) + +thistest.result() diff --git a/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/coverage.json new file mode 100644 index 000000000..7588328de --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/coverage.json @@ -0,0 +1,187 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/diff_formatting/src/diff_formatting.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 1, + "kind": "BranchRegion", + "span": [ + 19, + 16, + 19, + 26 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 18, + 1, + 18, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 9, + 19, + 10 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 16, + 19, + 26 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 19, + 29, + 19, + 46 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 56, + 19, + 72 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 21, + 5, + 22, + 2 + ] + } + ], + "demangled_name": "diff_formatting::bar", + "mcdc_records": [], + "name": "_RNvCs4ofb7EzyXpa_15diff_formatting3bar" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "BranchRegion", + "span": [ + 5, + 12, + 7, + 14 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 3, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 4, + 9, + 4, + 10 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 5, + 12, + 7, + 14 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 9, + 13, + 9, + 30 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 11, + 13, + 11, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 5, + 15, + 2 + ] + } + ], + "demangled_name": "diff_formatting::foo", + "mcdc_records": [], + "name": "_RNvCs4ofb7EzyXpa_15diff_formatting3foo" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 1, + 27, + 2 + ] + } + ], + "demangled_name": "diff_formatting::main", + "mcdc_records": [], + "name": "_RNvCs4ofb7EzyXpa_15diff_formatting4main" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/src/diff_formatting.rs b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/src/diff_formatting.rs new file mode 100644 index 000000000..1d98f3ca5 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/src/diff_formatting.rs @@ -0,0 +1,27 @@ +use std::hint::black_box; + +fn foo(x : u32) { + let y = + if x % 2 + == + 0 + { + black_box("even") + } else { + black_box("odd") + }; + + black_box(y); +} + +// bar is the same as foo, but formatted differently +fn bar(x : u32) { + let y = if x % 2 == 0 { black_box("even") } else { black_box("odd") }; + + black_box(y); +} + +fn main() { + foo(3); + bar(3); +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/test.py b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/test.py new file mode 100644 index 000000000..24565bf0e --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/test.py @@ -0,0 +1,53 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of identical code that is formatted differently. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {19} # bar + +uncovered = {9} # foo + +covered = multi_range(3, 4, 11, 14, 15, 18, 21, 22, (24, 27)) + + +expected_report = { + "diff_formatting.rs.xcov": { + "+": covered, + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report) + +# With MCDC + +mcdc_incomplete = { + 5, # foo + 19, # bar +} + +mcdc_uncovered = {6, 7, 9} # foo + +mcdc_covered = multi_range(3, 4, 11, 14, 15, 18, 21, 22, (24, 27)) + +mcdc_expected_report = { + "diff_formatting.rs.xcov": { + "+": mcdc_covered, + "!": mcdc_incomplete, + "-": mcdc_uncovered, + } +} + + +check_llvm_reports( + "coverage.json", mcdc_expected_report, cov_level="stmt+mcdc" +) + +thistest.result() diff --git a/testsuite/tests/llvm/rust-llvm-reports/impl/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/impl/coverage.json new file mode 100644 index 000000000..30cd35456 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/impl/coverage.json @@ -0,0 +1,171 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/impl/src/impl.rs", + "functions": [ + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 49, + 1, + 58, + 2 + ] + } + ], + "demangled_name": "impl::main", + "mcdc_records": [], + "name": "_RNvCslINASTaKc5F_4impl4main" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 8, + 5, + 12, + 6 + ] + } + ], + "demangled_name": "::new", + "mcdc_records": [], + "name": "_RNvMCslINASTaKc5F_4implNtB2_3Foo3new" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 5, + 16, + 6 + ] + } + ], + "demangled_name": "::print", + "mcdc_records": [], + "name": "_RNvMCslINASTaKc5F_4implNtB2_3Foo5print" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 44, + 5, + 46, + 6 + ] + } + ], + "demangled_name": "::hello", + "mcdc_records": [], + "name": "_RNvXs0_CslINASTaKc5F_4implNtB5_3BarNtB5_5Hello5hello" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 38, + 5, + 40, + 6 + ] + } + ], + "demangled_name": "::hello", + "mcdc_records": [], + "name": "_RNvXs_CslINASTaKc5F_4implNtB4_3FooNtB4_5Hello5hello" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 5, + 26, + 6 + ] + } + ], + "demangled_name": "::say_hello", + "mcdc_records": [], + "name": "_RNvYNtCslINASTaKc5F_4impl3BarNtB4_5Hello9say_helloB4_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 28, + 5, + 30, + 6 + ] + } + ], + "demangled_name": "::say_bye", + "mcdc_records": [], + "name": "_RNvYNtCslINASTaKc5F_4impl3FooNtB4_5Hello7say_byeB4_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 5, + 26, + 6 + ] + } + ], + "demangled_name": "::say_hello", + "mcdc_records": [], + "name": "_RNvYNtCslINASTaKc5F_4impl3FooNtB4_5Hello9say_helloB4_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 32, + 5, + 34, + 6 + ] + } + ], + "demangled_name": "<_ as impl::Hello>::say_nothing", + "mcdc_records": [], + "name": "_RNvYpNtCslINASTaKc5F_4impl5Hello11say_nothingB5_" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/impl/src/impl.rs b/testsuite/tests/llvm/rust-llvm-reports/impl/src/impl.rs new file mode 100644 index 000000000..cb5d0c392 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/impl/src/impl.rs @@ -0,0 +1,59 @@ +use std::hint::black_box; + +struct Foo { + x: u32 +} + +impl Foo { + fn new(x: u32) -> Self { + Self { + x + } + } + + fn print(&self) { + black_box(self.x); + } +} + +struct Bar; + +trait Hello { + fn hello(&self) -> &'static str; + + fn say_hello(&self) { + black_box(self.hello()); + } + + fn say_bye(&self) { + black_box("Bye"); + } + + fn say_nothing(&self) { + black_box("nothing"); + } +} + +impl Hello for Foo { + fn hello(&self) -> &'static str { + "Hola" + } +} + +impl Hello for Bar { + fn hello(&self) -> &'static str { + "Hallo" + } +} + +fn main() { + let foo = Foo::new(15); + foo.print(); + + foo.say_hello(); + Bar.say_hello(); + + foo.say_bye(); + +} + diff --git a/testsuite/tests/llvm/rust-llvm-reports/impl/test.py b/testsuite/tests/llvm/rust-llvm-reports/impl/test.py new file mode 100644 index 000000000..64d8aa8aa --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/impl/test.py @@ -0,0 +1,38 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of struct impls and trait implementations. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {} + +uncovered = multi_range((32, 34)) + +expected_report = { + "impl.rs.xcov": { + "+": multi_range( + (8, 12), # Foo::new + (14, 16), # Foo::print + (24, 26), # Trait::say_hello + (28, 30), # Trait::say_bye + (38, 40), # ::hello + (44, 46), # ::hello + (49, 51), + 53, + 54, + 56, + 58, # main + ), + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report) + +thistest.result() diff --git a/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/coverage.json new file mode 100644 index 000000000..d6ebd152d --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/coverage.json @@ -0,0 +1,846 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/mcdc_nested/src/mcdc_nested.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 8, + 20, + 9 + ], + "true_count": 3 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 13, + 20, + 46 + ], + "true_count": 2 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 16, + 20, + 17 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 21, + 20, + 22 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 19, + 1, + 20, + 9 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 20, + 16, + 20, + 17 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 20, + 21, + 20, + 22 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 20, + 25, + 20, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 20, + 39, + 20, + 44 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 20, + 47, + 22, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 22, + 12, + 24, + 6 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 25, + 1, + 25, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::foo_uncovered_root", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 20, + 8, + 20, + 46 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 20, + 16, + 20, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested18foo_uncovered_root" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 8, + 12, + 9 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 13, + 12, + 46 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 16, + 12, + 17 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 21, + 12, + 22 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 11, + 1, + 12, + 9 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 12, + 16, + 12, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 21, + 12, + 22 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 25, + 12, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 39, + 12, + 44 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 47, + 14, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 14, + 12, + 16, + 6 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 17, + 1, + 17, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::foo_uncovered_nested", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 12, + 8, + 12, + 46 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 12, + 16, + 12, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested20foo_uncovered_nested" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 8, + 4, + 9 + ], + "true_count": 3 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 13, + 4, + 46 + ], + "true_count": 2 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 16, + 4, + 17 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 21, + 4, + 22 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 4, + 9 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 4, + 16, + 4, + 17 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 21, + 4, + 22 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 25, + 4, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 4, + 39, + 4, + 44 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 47, + 6, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 6, + 12, + 8, + 6 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 9, + 1, + 9, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::foo", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 4, + 8, + 4, + 46 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 4, + 16, + 4, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested3foo" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 51, + 1, + 75, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::main", + "mcdc_records": [], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested4main" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 28, + 8, + 28, + 9 + ], + "true_count": 4 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 29, + 9, + 32, + 32 + ], + "true_count": 4 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 29, + 12, + 29, + 13 + ], + "true_count": 4 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 30, + 13, + 31, + 36 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 30, + 16, + 30, + 17 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 30, + 21, + 30, + 22 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 27, + 1, + 28, + 9 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 29, + 12, + 29, + 13 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 30, + 16, + 30, + 17 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 30, + 21, + 30, + 22 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 31, + 15, + 31, + 19 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 31, + 29, + 31, + 34 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 32, + 11, + 32, + 15 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 32, + 25, + 32, + 30 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 33, + 5, + 35, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 35, + 12, + 37, + 6 + ] + }, + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 38, + 1, + 38, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::nested_3", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 28, + 8, + 32, + 32 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 29, + 12, + 31, + 36 + ], + "test_vectors": [ + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 30, + 16, + 30, + 22 + ], + "test_vectors": [] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested8nested_3" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/src/mcdc_nested.rs b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/src/mcdc_nested.rs new file mode 100644 index 000000000..7a23627ac --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/src/mcdc_nested.rs @@ -0,0 +1,75 @@ +use std::hint::black_box; + +fn foo(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn foo_uncovered_nested(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn foo_uncovered_root(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn nested_3(a: bool, b: bool, c: bool, d: bool) { + if a && + if b || + if c && d + { true } else { false } + { true } else { false } + { + black_box("yes"); + } else { + black_box("no"); + } +} + +// This test currently make llvm utility functions fail. +// (See https://github.com/llvm/llvm-project/pull/91600) +// +// fn nested_first(a: bool, b: bool, c: bool) { +// if if b || c { true } else { false } && a { +// black_box("yes"); +// } else { +// black_box("no"); +// } +// } + +fn main() { + foo(true, false, false); + foo(true, true, true); + foo(true, false, true); + foo(false, true, true); + + foo_uncovered_nested(false, true, true); + foo_uncovered_nested(true, true, false); + foo_uncovered_nested(true, false, false); + + foo_uncovered_root(true, false, false); + foo_uncovered_root(true, true, false); + foo_uncovered_root(true, false, true); + + nested_3(true, true, true, true); + nested_3(false, true, true, true); + nested_3(true, true, false, true); + nested_3(true, true, false, false); + nested_3(true, true, true, false); + + // nested_first(true, false, false); + // nested_first(true, true, true); + // nested_first(true, false, true); + // nested_first(false, true, true); +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/test.py b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/test.py new file mode 100644 index 000000000..042a00e20 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/test.py @@ -0,0 +1,35 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of MCDC instrumentation of nested decisions. + +Note: For now, there is a construct (see mcdc_nested.rs) that make the trace\ +adapter crash when trying to build the mappings' representation from the +profdata file. +This is an LLVM issue, see https://github.com/llvm/llvm-project/pull/91600 +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +uncovered_mcdc_decisions = multi_range(12, 20, (28, 32)) # nested_3 + +expected_report = { + "mcdc_nested.rs.xcov": { + "+": multi_range( + (3, 9), # foo + (11, 17), # foo_uncovered_nested + (19, 25), # foo_uncovered_root + (27, 38), # nested_3 + (51, 75), # main + ) + - uncovered_mcdc_decisions, + "!": uncovered_mcdc_decisions, + } +} + +check_llvm_reports("coverage.json", expected_report, cov_level="stmt+mcdc") + +thistest.result() diff --git a/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/coverage.json new file mode 100644 index 000000000..b98b3b5de --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/coverage.json @@ -0,0 +1,822 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/mcdc_non_control_flow/src/mcdc_assign.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 13, + 4, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 18, + 4, + 19 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 3, + 33 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 4, + 9, + 4, + 10 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 4, + 13, + 4, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 18, + 4, + 19 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 5, + 5, + 6, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_and", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 4, + 13, + 4, + 19 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign10assign_and" + }, + { + "branch_regions": [ + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 19, + 13, + 19, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 19, + 18, + 19, + 19 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 19, + 23, + 19, + 24 + ], + "true_count": 2 + } + ], + "code_regions": [ + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 18, + 1, + 18, + 44 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 19, + 9, + 19, + 10 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 19, + 13, + 19, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 19, + 18, + 19, + 19 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 19, + 23, + 19, + 24 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 20, + 5, + 21, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_3_bis", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 19, + 13, + 19, + 24 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + -1, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign12assign_3_bis" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 13, + 24, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 19, + 24, + 20 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 25, + 24, + 26 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 31, + 24, + 32 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 36, + 24, + 39 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 23, + 1, + 23, + 65 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 24, + 9, + 24, + 10 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 24, + 13, + 24, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 24, + 19, + 24, + 20 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 25, + 24, + 26 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 31, + 24, + 32 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 36, + 24, + 39 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 25, + 5, + 26, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::right_comb_tree", + "mcdc_records": [ + { + "num_conditions": 5, + "span": [ + 24, + 13, + 24, + 42 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1, + -1, + -1, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + -1, + -1, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + 1, + 1, + 1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign15right_comb_tree" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 28, + 1, + 30, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::foo", + "mcdc_records": [], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign3foo" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 36, + 1, + 62, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::main", + "mcdc_records": [], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign4main" + }, + { + "branch_regions": [ + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 14, + 13, + 14, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 14, + 18, + 14, + 19 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 14, + 23, + 14, + 24 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 13, + 1, + 13, + 40 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 14, + 9, + 14, + 10 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 14, + 13, + 14, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 14, + 18, + 14, + 19 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 23, + 14, + 24 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 15, + 5, + 16, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_3", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 14, + 13, + 14, + 24 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign8assign_3" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 9, + 13, + 9, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 9, + 18, + 9, + 19 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 8, + 1, + 8, + 32 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 9, + 9, + 9, + 10 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 9, + 13, + 9, + 14 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 9, + 18, + 9, + 19 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 10, + 5, + 11, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_or", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 9, + 13, + 9, + 19 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign9assign_or" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 33, + 9, + 33, + 10 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 33, + 14, + 33, + 15 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 32, + 1, + 33, + 10 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 33, + 14, + 33, + 15 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 34, + 1, + 34, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::func_call", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 33, + 9, + 33, + 15 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign9func_call" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/src/mcdc_assign.rs b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/src/mcdc_assign.rs new file mode 100644 index 000000000..85aa5e4d4 --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/src/mcdc_assign.rs @@ -0,0 +1,63 @@ +use std::hint::black_box; + +fn assign_and(a: bool, b: bool) { + let x = a && b; + black_box(x); +} + +fn assign_or(a: bool, b: bool) { + let x = a || b; + black_box(x); +} + +fn assign_3(a: bool, b: bool, c: bool) { + let x = a || b && c; + black_box(x); +} + +fn assign_3_bis(a: bool, b: bool, c: bool) { + let x = a && b || c; + black_box(x); +} + +fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + let x = a && (b && (c && (d && (e)))); + black_box(x); +} + +fn foo(a: bool) -> bool { + black_box(a) +} + +fn func_call(a: bool, b: bool) { + foo(a && b); +} + +fn main() { + assign_and(true, false); + assign_and(true, true); + assign_and(false, false); + + assign_or(true, false); + assign_or(true, true); + assign_or(false, false); + + assign_3(true, false, false); + assign_3(true, true, false); + assign_3(false, false, true); + assign_3(false, true, true); + + assign_3_bis(true, false, false); + assign_3_bis(true, true, false); + assign_3_bis(false, false, true); + assign_3_bis(false, true, true); + + right_comb_tree(false, false, false, true, true); + right_comb_tree(true, false, false, true, true); + right_comb_tree(true, true, true, true, true); + + func_call(true, false); + func_call(true, true); + func_call(false, false); +} + diff --git a/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/test.py b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/test.py new file mode 100644 index 000000000..73e1ba32f --- /dev/null +++ b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/test.py @@ -0,0 +1,40 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checksthe handling of MCDC instrumentation in non-control flow +decisions. +Specifically, it checks that the last operand was successfully instrumented. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +uncovered_mcdc_decisions = { + 9, # assign_or + 14, # assign_3 + 19, # assign_3_bis + 24, # right_comb_tree +} + +expected_report = { + "mcdc_assign.rs.xcov": { + "+": multi_range( + (3, 6), # assign_and + (8, 11), # assign_or + (13, 16), # assign_3 + (18, 21), # assign_3_bis + (23, 26), # right_comb_tree + (28, 30), # foo + (32, 34), # func_call + (36, 62), # main + ) + - uncovered_mcdc_decisions, + "!": uncovered_mcdc_decisions, + } +} + +check_llvm_reports("coverage.json", expected_report, cov_level="stmt+mcdc") + +thistest.result() diff --git a/testsuite/tests/llvm/rust/extra.opt b/testsuite/tests/llvm/rust/extra.opt new file mode 100644 index 000000000..fa8e9e274 --- /dev/null +++ b/testsuite/tests/llvm/rust/extra.opt @@ -0,0 +1,2 @@ +!rust DEAD Rust support not available in this configuration +windows XFAIL Infra. issues investigated under eng/das/cov/gnatcoverage#416 diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs b/testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs new file mode 100644 index 000000000..9cbe62183 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs @@ -0,0 +1,15 @@ +pub fn let_else(input: Option) { + + // Let statements is covered if the assignement happens, meaning it was not + // short-circuited by a an error in the expression evaluation. + // + // In the `let-else` case, the statement is covered if the pattern matching + // succeeds. In that case, it means the else block is not executed, thus + // not covered. In the other case, the else block shall be executed (and + // covered), whereas the let statement won't. + + let Some(_x) = input else { // # let + println!("No input"); // # in-else-1 + return; // # in-else + }; +} diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs new file mode 100644 index 000000000..dd691d9fd --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::let_else(Some(42)); +} + +//# foo.rs +// /in-else-1/ l= ## s- +// /in-else/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs new file mode 100644 index 000000000..19cadd2c4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::let_else(None); +} + +//# foo.rs +// /let/ l! ## s- +// /in-else/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/test.py b/testsuite/tests/llvm/rust/stmt/block-expr/test.py new file mode 100644 index 000000000..51f041da9 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for a simple code block +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs b/testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs new file mode 100644 index 000000000..133060596 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs @@ -0,0 +1,12 @@ +use std::hint::black_box; + +pub fn foo(input: u32) { + 'named_block: { + let _ = black_box(1); + if input == 42 { + break 'named_block; // # break + } // # bb2-1 + let _ = black_box(2); // # bb2 + } + let _ = black_box(3); +} diff --git a/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs new file mode 100644 index 000000000..14796a87d --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); +} + +//# foo.rs +// /break/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs new file mode 100644 index 000000000..e5b75ad07 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::foo(42); +} + +//# foo.rs +// /bb2-1/ l= ## s- +// /bb2/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/break-block/test.py b/testsuite/tests/llvm/rust/stmt/break-block/test.py new file mode 100644 index 000000000..86e6827eb --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for break in named blocks +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/closure/src/foo.rs b/testsuite/tests/llvm/rust/stmt/closure/src/foo.rs new file mode 100644 index 000000000..22ab0c56c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/src/foo.rs @@ -0,0 +1,14 @@ +use std::hint::black_box; + +pub fn foo(input: u32) { + let print_even = // # var + |i| { // # closure-arg + if i % 2 == 0 { // # closure-if-guard + black_box(i); // # closure-body + } // # closure-else + }; // # closure-end + + if input < 10 { // # if-guard + print_even(input); // # call + } // # else +} diff --git a/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs new file mode 100644 index 000000000..a947c51fb --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs @@ -0,0 +1,12 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); +} + +//# foo.rs +// /closure-arg/ l= ## 0 +// /closure-if-guard/ l! ## s- +// /closure-else/ l! ## 0 +// /closure-body/ l- ## 0 +// /else/ l! ## s- diff --git a/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs new file mode 100644 index 000000000..2461f06a9 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs @@ -0,0 +1,15 @@ +mod foo; + +fn main() { + let _ = foo::foo(42); +} + +//# foo.rs +// /closure-arg/ l= ## s- +// /closure-if-guard/ l= ## s- +// /closure-else/ l= ## s- +// /closure-end/ l= ## s- +// /closure/ l- ## 0 +// /if-guard/ l! ## s- +// /call/ l- ## 0 +// /else/ l! ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/closure/test.py b/testsuite/tests/llvm/rust/stmt/closure/test.py new file mode 100644 index 000000000..8455ea09c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for closures +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs new file mode 100644 index 000000000..a3da6ddb3 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs @@ -0,0 +1,12 @@ +use std::hint::black_box; + +pub fn foo(b: bool) { // # decl-1 + if b // # condition + { // # if-1 + black_box(1); // # if + } // # if + else + { // # else-1 + black_box(2); // # else + } // # else +} // # end-1 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs new file mode 100644 index 000000000..2b33a73a6 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + foo::foo(true); + foo::foo(false); +} + +//# foo.rs +// /.*/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs new file mode 100644 index 000000000..6f8a2029e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + foo::foo(false); +} + +//# foo.rs +// /if-1/ l= ## s- +// /if/ l- ## 0 +// /(?!if)/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs new file mode 100644 index 000000000..628a3c822 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs @@ -0,0 +1,7 @@ +mod foo; + +fn main() {} + +//# foo.rs +// /.*-1/ l= ## s- +// /.*/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs new file mode 100644 index 000000000..984ee261c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + foo::foo(true); +} + +//# foo.rs +// /else-1/ l= ## s- +// /else/ l- ## 0 +// /(?!else)/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/test.py b/testsuite/tests/llvm/rust/stmt/if-expr/test.py new file mode 100644 index 000000000..1fd448fe8 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/test.py @@ -0,0 +1,9 @@ +""" +Check behavior for the coverage of an if expression +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs b/testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs new file mode 100644 index 000000000..421926f79 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs @@ -0,0 +1,19 @@ +use std::hint::black_box; + +pub fn let_else(input: Option) { + + // Let statements is covered if the assignement happens, meaning it was not + // short-circuited by a an error in the expression evaluation. + // + // In the `let-else` case, the statement is covered if the pattern matching + // succeeds. In that case, it means the else block is not executed, thus + // not covered. In the other case, the else block shall be executed (and + // covered), whereas the let statement won't. + + let Some(x) = input else { // # let + println!("No input"); // # in-else-1 + return; // # in-else + }; + + black_box(x); // # black-box +} diff --git a/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs new file mode 100644 index 000000000..dd691d9fd --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::let_else(Some(42)); +} + +//# foo.rs +// /in-else-1/ l= ## s- +// /in-else/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs new file mode 100644 index 000000000..a5e897e5a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::let_else(None); +} + +//# foo.rs +// /let/ l! ## s- +// /in-else/ l+ ## 0 +// /black-box/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/let-else/test.py b/testsuite/tests/llvm/rust/stmt/let-else/test.py new file mode 100644 index 000000000..faf4bd337 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for let-else construct +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs b/testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs new file mode 100644 index 000000000..e54e7764e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs @@ -0,0 +1,3 @@ +pub fn let_stmt() { // # let_stmt-1 + let x: u32 = 42; // # let_stmt +} // # let_stmt diff --git a/testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs b/testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs new file mode 100644 index 000000000..d397e0681 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + foo::let_stmt(); +} + +//# foo.rs +// /let_stmt/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/let-stmt/test.py b/testsuite/tests/llvm/rust/stmt/let-stmt/test.py new file mode 100644 index 000000000..8e5fc2289 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-stmt/test.py @@ -0,0 +1,9 @@ +""" +Ensure a simple 1 statement function is correctly covered. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs new file mode 100644 index 000000000..adad1d1f8 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs @@ -0,0 +1,32 @@ +use std::hint::black_box; + +// In for loops, the variable has its own SCO, which is covered by assignment. +// In case the iterator given to the loop is empty, this SCO is never covered. +// However, if the variable name is `_`, meaning the value produced by the +// iterator is unbound, there is no associated SCO. +// Additionally, if the variable is bound, a SCO is made for the iterator. +// Otherwise, it is attached in the SCO preceding the for loop. + +pub fn foo(input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + for // # after-if + _ // # after-if + in 0 .. input // # after-if + { // # body-1 + black_box(1); // # body + } // # body +} + +pub fn bar(input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + for + i // # var + in 0 .. input // # guard + { // # body-1 + black_box(i); // # body + } // # body +} diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs new file mode 100644 index 000000000..939da805a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); + let _ = foo::bar(5); +} + +//# foo.rs +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs new file mode 100644 index 000000000..5a1eb05a7 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs @@ -0,0 +1,12 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); + let _ = foo::bar(0); +} + +//# foo.rs +// /return/ l- ## s- +// /var/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs new file mode 100644 index 000000000..86997058a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs @@ -0,0 +1,14 @@ +mod foo; + +fn main() { + let _ = foo::foo(11); + let _ = foo::bar(11); +} + +//# foo.rs +// /after-if-1/ l= ## s- +// /after-if/ l- ## 0 +// /var/ l- ## s- +// /guard/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py b/testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py new file mode 100644 index 000000000..2345940f4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for for loops +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs new file mode 100644 index 000000000..0d37caf90 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs @@ -0,0 +1,14 @@ +use std::hint::black_box; + +pub fn foo(mut input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + 'named: loop { + if input == 0 { // # if + break 'named; // # break + } // # body-1 + black_box(input); // # body + input -= 1; // # body + } +} diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs new file mode 100644 index 000000000..f7a8f120e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); +} + +//# foo.rs +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs new file mode 100644 index 000000000..78b042904 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); +} + +//# foo.rs +// /return/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs new file mode 100644 index 000000000..3a94065c4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs @@ -0,0 +1,12 @@ +mod foo; + +fn main() { + let _ = foo::foo(11); +} + +//# foo.rs +// /after-if-1/ l- ## s- +// /if/ l- ## s- +// /break/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py b/testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py new file mode 100644 index 000000000..47d14d5b7 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for named loops +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs new file mode 100644 index 000000000..305030ffb --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs @@ -0,0 +1,12 @@ +use std::hint::black_box; + +pub fn foo(mut input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + while input > 0 // # guard + { // # body-1 + black_box(input); // # body + input -= 1; // # body + } // # body +} diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs new file mode 100644 index 000000000..f7a8f120e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); +} + +//# foo.rs +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs new file mode 100644 index 000000000..78b042904 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); +} + +//# foo.rs +// /return/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs new file mode 100644 index 000000000..6a7930c41 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs @@ -0,0 +1,11 @@ +mod foo; + +fn main() { + let _ = foo::foo(11); +} + +//# foo.rs +// /after-if-1/ l- ## s- +// /guard/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py b/testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py new file mode 100644 index 000000000..9af6a8dc1 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for while loops +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs new file mode 100644 index 000000000..33634a1f0 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs @@ -0,0 +1,14 @@ +use std::hint::black_box; + +pub fn foo(input: Option) { + let _ = match input { + Some(5) => // # some-5 + black_box(5), // # body-some-5 + Some(0..=4) => // # some-range + black_box(1), // # body-some-range + Some(i) => // # some-i + black_box(i), // # body-some-i + None => // # none + black_box(1) // # body-none + }; +} diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs new file mode 100644 index 000000000..664437e0c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(30)); +} + +//# foo.rs +// /body-some-[^i]/ l- ## s- +// /body-none/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs new file mode 100644 index 000000000..436f55e01 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs @@ -0,0 +1,11 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(5)); +} + +//# foo.rs +// /some-\D/ l- ## s- +// /body-some-range/ l- ## s- +// /body-some-i/ l- ## 0 +// /body-none/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs new file mode 100644 index 000000000..68e63c35e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(None); +} + +//# foo.rs +// /some-\D/ l- ## s- +// /body-some-[^i]/ l= ## s- +// /body-some/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs new file mode 100644 index 000000000..89b823df8 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs @@ -0,0 +1,11 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(3)); +} + +//# foo.rs +// /body-some-5/ l- ## s- +// /some-i/ l- ## s- +// /body-some-i/ l- ## 0 +// /body-none/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/test.py b/testsuite/tests/llvm/rust/stmt/match-expr/test.py new file mode 100644 index 000000000..5cbbdbdd4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for match expressions +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/simple-stmt/src/foo.rs b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/foo.rs new file mode 100644 index 000000000..81f164b05 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/foo.rs @@ -0,0 +1,3 @@ +pub fn foo() { // # foo-1 + println!("hello-world"); // # foo-2 +} // # foo-3 diff --git a/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_call_foo.rs b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_call_foo.rs new file mode 100644 index 000000000..81fc88849 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_call_foo.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + foo::foo(); +} + +//# foo.rs +// /foo/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_no_call_foo.rs b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_no_call_foo.rs new file mode 100644 index 000000000..6aa5c3c1e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_no_call_foo.rs @@ -0,0 +1,7 @@ +mod foo; + +fn main() {} + +//# foo.rs +// /foo-1/ l- ## s- +// /foo-[23]/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/simple-stmt/test.py b/testsuite/tests/llvm/rust/stmt/simple-stmt/test.py new file mode 100644 index 000000000..8e5fc2289 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/simple-stmt/test.py @@ -0,0 +1,9 @@ +""" +Ensure a simple 1 statement function is correctly covered. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs b/testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs new file mode 100644 index 000000000..a0db67940 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs @@ -0,0 +1,9 @@ +// The try '?' operator induces an implicit break of the control flow. +// Therefore, at instrumentation, Rust inserts a counter at the beginning of +// the function, one for the short-circuit of `?`, and one after the evaluation +// of '?'. + +pub fn foo(input: Option) -> Option { // # fn + let number = input?; // # try + return Some(number.to_string()); // # return +} diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs new file mode 100644 index 000000000..fa7ab7c5e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(None); +} + +//# foo.rs +// /fn/ l+ ## 0 +// /try/ l! ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs new file mode 100644 index 000000000..1b1b49e4a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(42)); +} + +//# foo.rs +// /try/ l! ## s- diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/test.py b/testsuite/tests/llvm/rust/stmt/try-operator/test.py new file mode 100644 index 000000000..bd7d9d3fd --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for try operators +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb new file mode 100644 index 000000000..201838d3a --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb @@ -0,0 +1,9 @@ +package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end; +end; diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads new file mode 100644 index 000000000..ec1a7e9ed --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + type Op_Kind is (Increment, Decrement); + + procedure Apply (Op : Op_Kind; X : in out Integer); +end; diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py new file mode 100644 index 000000000..2c6899406 --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py @@ -0,0 +1,62 @@ +""" +Test the behaviour of the --relocate-build-tree and --root-dir option. +""" + +import os + +from e3.fs import sync_tree + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +expected_reports = { + "ops.adb.xcov": {"+": {4, 5}, "-": {6}}, + "ops.ads.xcov": {}, +} + +# To avoid source repository pollution, copy source material to a temporary +# directory. +Wdir("tmp_") +for filename in ["opslib", "tests"]: + sync_tree(os.path.join("..", filename), filename) + +project_root = os.path.abspath(".") + +# Create ops project file +extra = """ + for Library_Dir use "lib-opslib"; + for Library_Name use "opslib"; +""" +gprfor([], prjid="ops", extra=extra, cwd="opslib") + +# Create tests project file +tests_gpr = os.path.abspath( + gprfor( + ["test_inc.adb"], + prjid="tests", + deps=["../opslib/ops.gpr"], + cwd="tests", + ) +) + +# Build directory is relocated in tmp +build_run_and_coverage( + gprsw=GPRswitches( + tests_gpr, + units=["ops"], + root_dir=project_root + os.sep, + relocate_build_tree=True, + ), + covlevel="stmt", + gpr_exe_dir=os.path.join(project_root, "tests"), + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) + +check_xcov_reports("out-instr", expected_reports, discard_empty=False) + +thistest.result() diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb b/testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb new file mode 100644 index 000000000..d3c3ce1f2 --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb @@ -0,0 +1,7 @@ +with Ops; +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb new file mode 100644 index 000000000..201838d3a --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb @@ -0,0 +1,9 @@ +package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end; +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads new file mode 100644 index 000000000..ec1a7e9ed --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + type Op_Kind is (Increment, Decrement); + + procedure Apply (Op : Op_Kind; X : in out Integer); +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb b/testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb new file mode 100644 index 000000000..d3c3ce1f2 --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb @@ -0,0 +1,7 @@ +with Ops; +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py new file mode 100644 index 000000000..a384542cb --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -0,0 +1,73 @@ +""" +Test the behaviour of the --relocate-build-tree option. +""" + +import os + +from e3.fs import sync_tree + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +expected_reports = { + "ops.adb.xcov": {"+": {4, 5}, "-": {6}}, + "ops.ads.xcov": {}, +} + +# To avoid source repository pollution, copy source material to a temporary +# directory. +Wdir("tmp_") +for filename in ["opslib", "src"]: + sync_tree(os.path.join("..", filename), filename) + +# Create ops project file +extra = """ + for Library_Dir use "lib-opslib"; + for Library_Name use "opslib"; +""" +ops_gpr = gprfor([], prjid="ops", extra=extra, cwd="opslib") + +# Create tests project file +tests_gpr = os.path.abspath( + gprfor( + ["test_inc.adb"], + prjid="tests", + deps=["opslib/ops.gpr"], + ) +) + +# Build directory is relocated in tmp +build_run_and_coverage( + gprsw=GPRswitches(tests_gpr, units=["ops"], relocate_build_tree=True), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) + +check_xcov_reports("out-instr", expected_reports, discard_empty=False) + +# Check if relative path for GPR works correctly +build_run_and_coverage( + gprsw=GPRswitches(tests_gpr, units=["ops"], relocate_build_tree=True), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) + +check_xcov_reports("out-instr", expected_reports, discard_empty=False) + +os.environ["GPR_PROJECT_PATH"] += os.pathsep + os.path.dirname(tests_gpr) +build_run_and_coverage( + gprsw=GPRswitches(tests_gpr, units=["ops"], relocate_build_tree=True), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) + +check_xcov_reports("out-instr", expected_reports, discard_empty=False) + +thistest.result() diff --git a/testsuite/tests/scos-overlap/test.c b/testsuite/tests/scos-overlap/test.c new file mode 100644 index 000000000..abd162711 --- /dev/null +++ b/testsuite/tests/scos-overlap/test.c @@ -0,0 +1,13 @@ +extern void foo (void (*f) (const char *str)); + +static void +callback (const char *str) +{ +} + +int +main (void) +{ + foo (callback); + return 0; +} diff --git a/testsuite/tests/scos-overlap/test.py b/testsuite/tests/scos-overlap/test.py new file mode 100644 index 000000000..eac3ca1c8 --- /dev/null +++ b/testsuite/tests/scos-overlap/test.py @@ -0,0 +1,103 @@ +""" +Check that gnatcov rejects invalid configurations for overlapping SCO +statements. +""" + +from dataclasses import dataclass + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import thistest, gprfor + + +@dataclass +class W: + """Helper to represent expected warnings.""" + + col: str + sco_num: str + col_range: str + + def __str__(self): + return ( + f"!!! foo.c:5:{self.col}:" + f" unexpected SCO overlapping with SCO {self.sco_num}:" + f" STATEMENT at foo.c:5:{self.col_range}," + " discarding overlapping SCO" + ) + + +def run_variant(label, col_ranges, expected_warnings): + """ + Generate C code that will generate SCOS for the column number ranges in + ``col_ranges``, instrument it and check that gnatcov emits the given + expected warnings. + """ + thistest.log(f"== {label} ==") + wd = Wdir("tmp_" + label) + + # Generate C code and instrument it + + with open("foo.c", "w") as f: + f.write("void\n") + f.write("foo (void (*f) (const char *str))\n") + f.write("{\n") + for start, end in col_ranges: + # Add an empty line after line directive to prevent the + # postprocessing step in gnatcov from merging the lines together + # (thus undoing the SCO nesting). + f.write("#line 4\n\n") + + # Make sure the range is wide enough for us to insert a statement + # (a call to the "f" function with a string literal argument). + range_length = end - start + 1 + arg_length = range_length - 6 + assert arg_length >= 0 + + f.write(" " * (start - 1)) + f.write('f("') + f.write("A" * arg_length) + f.write('");') + f.write("\n") + f.write("}\n") + + log = "instr.log" + mkdir("obj") + xcov_instrument( + gprsw=GPRswitches( + root_project=gprfor(mains=["test.c"], srcdirs=["..", "."]), + units=["foo.c"], + ), + covlevel="stmt", + out=log, + tolerate_messages="unexpected SCO overlap", + ) + + # Check that the instrumenter emits the expected warnings. For convenience + # and platform independence, harmonize line terminators in the output. + thistest.fail_if_not_equal( + '"gnatcov instrument" warnings', + "\n".join(str(w) for w in expected_warnings), + "\n".join(line.rstrip() for line in contents_of(log).splitlines()), + ) + + wd.to_homedir() + + +run_variant("no-overlap", [(1, 10), (11, 20)], []) +run_variant("simple-nesting", [(1, 20), (2, 19)], []) +run_variant("contiguous-nesting", [(1, 20), (2, 10), (11, 19)], []) +run_variant("reverse-contiguous-nesting", [(11, 19), (2, 10), (1, 20)], []) + +run_variant("nok-nesting-left", [(1, 20), (1, 19)], [W("1", "#1", "1-20")]) +run_variant("nok-nesting-right", [(1, 20), (2, 20)], [W("2", "#1", "1-20")]) +run_variant("overlap-left", [(1, 10), (5, 15)], [W("5", "#1", "1-10")]) +run_variant("overlap-right", [(5, 15), (1, 10)], [W("1", "#1", "5-15")]) +run_variant( + "nested-overlap", [(1, 20), (10, 19), (2, 10)], [W("2", "#2", "10-19")] +) + +thistest.result() diff --git a/testsuite/tests/shared-libs/ada-main/src-main/main.adb b/testsuite/tests/shared-libs/ada-main/src-main/main.adb new file mode 100644 index 000000000..42da3e81b --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/src-main/main.adb @@ -0,0 +1,7 @@ +with Mylib; + +procedure Main is + Dummy : constant Natural := Mylib.Fact (1); +begin + null; +end Main; diff --git a/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb new file mode 100644 index 000000000..8ffae146d --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; + +end Mylib; diff --git a/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads new file mode 100644 index 000000000..6d5364017 --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads @@ -0,0 +1,5 @@ +package Mylib is + + function Fact (N : Natural) return Natural; + +end Mylib; diff --git a/testsuite/tests/shared-libs/ada-main/test.py b/testsuite/tests/shared-libs/ada-main/test.py new file mode 100644 index 000000000..6aec67df9 --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/test.py @@ -0,0 +1,64 @@ +""" +Test that we can compute code coverage on Ada code located in a shared library. +Beyond the library, the program is composed of an Ada unit. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir("tmp_") + + +# Create one project file to build the pure Ada library to test +mylib_gpr = gprfor( + mains=[], + prjid="mylib", + langs=["Ada"], + srcdirs="../src-mylib", + objdir="obj-mylib", + extra='for Library_Name use "mylib";' + '\nfor Library_Kind use "relocatable";' + '\nfor Library_Dir use "lib-mylib";', +) + +# Create another project to build Ada program to test the library +main_gpr = gprfor( + mains=["main.adb"], + prjid="main", + langs=["Ada"], + deps=["mylib"], + srcdirs="../src-main", + objdir="obj-main", +) + +# Make sure that subprocesses can import the shared library for mylib. On Unix +# systems, there is nothing specific to do thanks to RPATH magic, but on +# Windows we need to add its directory to PATH. +lib_dir = os.path.abspath("lib-mylib") +os.environ["PATH"] = "{}{}{}".format( + lib_dir, os.path.pathsep, os.environ["PATH"] +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr, projects=["mylib"]), + covlevel="stmt", + gpr_obj_dir="obj-main", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=."], + # There are several projects in the closure: main_gpr, mylib_gpr and + # gnatcov_rts_full. GPRbuild will complain if one library does not have the + # same kind as the others, so force relocatable. + extra_gprbuild_args=["-XLIBRARY_TYPE=relocatable"], +) + +check_xcov_reports( + ".", {"mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, "mylib.ads.xcov": {}} +) + +thistest.result() diff --git a/testsuite/tests/shared-libs/c-main/src-main/main.c b/testsuite/tests/shared-libs/c-main/src-main/main.c new file mode 100644 index 000000000..ed6af4b93 --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/src-main/main.c @@ -0,0 +1,14 @@ +extern void adainit (void); +extern int mylib__fact (int); + +int +main (int argc, const char **argv) +{ + /* Run elaboration for both the runtime and our Ada units. */ + adainit (); + + /* Run the code to cover. */ + mylib__fact (1); + + return 0; +} diff --git a/testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb new file mode 100644 index 000000000..8ffae146d --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; + +end Mylib; diff --git a/testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads new file mode 100644 index 000000000..deb270a99 --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads @@ -0,0 +1,6 @@ +package Mylib is + + function Fact (N : Natural) return Natural; + pragma Export (C, Fact, "mylib__fact"); + +end Mylib; diff --git a/testsuite/tests/shared-libs/c-main/test.py b/testsuite/tests/shared-libs/c-main/test.py new file mode 100644 index 000000000..b476eea27 --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/test.py @@ -0,0 +1,61 @@ +""" +Test that we can compute code coverage on Ada code located in a shared library. +Beyond the library, the program is composed of a C unit. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir("tmp_") + + +# Create one project file to build the pure Ada library to test +mylib_gpr = gprfor( + mains=[], + prjid="mylib", + langs=["Ada"], + srcdirs="../src-mylib", + objdir="obj-mylib", + extra='for Library_Name use "mylib";' + '\nfor Library_Kind use "relocatable";' + '\nfor Library_Dir use "lib-mylib";', +) + +# Create another project to build the mixed C/Ada program to test the library. +main_gpr = gprfor( + mains=["main.c"], + prjid="main", + langs=["C"], + deps=["mylib"], + srcdirs="../src-main", + objdir="obj-main", +) + +# Make sure that subprocesses can import the shared library for mylib. On Unix +# systems, there is nothing specific to do thanks to RPATH magic, but on +# Windows we need to add its directory to PATH. +lib_dir = os.path.abspath("lib-mylib") +os.environ["PATH"] = "{}{}{}".format( + lib_dir, os.path.pathsep, os.environ["PATH"] +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr, projects=["mylib"]), + covlevel="stmt", + gpr_obj_dir="obj-main", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=."], + extra_gprbuild_args=["-XLIBRARY_TYPE=relocatable"], +) + +check_xcov_reports( + ".", {"mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, "mylib.ads.xcov": {}} +) + +thistest.result() diff --git a/testsuite/tests/shared-libs/extra.opt b/testsuite/tests/shared-libs/extra.opt new file mode 100644 index 000000000..2057bb8c4 --- /dev/null +++ b/testsuite/tests/shared-libs/extra.opt @@ -0,0 +1,3 @@ +!native DEAD Shared libraries exist only for native platforms +bin-traces XFAIL OA05-051: bin-traces and shared libs +RTS_ZFP DEAD can't build shared gnatcov_rts with light runtime diff --git a/testsuite/tests/subp_of_interest/src/main.adb b/testsuite/tests/subp_of_interest/src/main.adb new file mode 100644 index 000000000..d83413451 --- /dev/null +++ b/testsuite/tests/subp_of_interest/src/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo (1); + Pkg.Bar; +end Main; diff --git a/testsuite/tests/subp_of_interest/src/pkg.adb b/testsuite/tests/subp_of_interest/src/pkg.adb new file mode 100644 index 000000000..bbe2ebc38 --- /dev/null +++ b/testsuite/tests/subp_of_interest/src/pkg.adb @@ -0,0 +1,38 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + --------- + -- Foo -- + --------- + + procedure Foo (I : Integer) is + begin + Put_Line ("Hello from Foo!"); + end Foo; + + --------- + -- Bar -- + --------- + + procedure Bar is + procedure Nested_Bar_1 is null; + procedure Nested_Bar_2; + + Dummy_Decl : Boolean; + + ------------------ + -- Nested_Bar_2 -- + ------------------ + + procedure Nested_Bar_2 is + begin + Put_Line ("Hello from Nested_Bar_2!"); + end Nested_Bar_2; + begin + Nested_Bar_1; + Nested_Bar_2; + Put_Line ("Hello from Bar!"); + end Bar; + +end Pkg; diff --git a/testsuite/tests/subp_of_interest/src/pkg.ads b/testsuite/tests/subp_of_interest/src/pkg.ads new file mode 100644 index 000000000..0845bfade --- /dev/null +++ b/testsuite/tests/subp_of_interest/src/pkg.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pkg is + procedure Foo (I : Integer) with Pre => I > 0; + procedure Bar; + + I : Integer; +end Pkg; diff --git a/testsuite/tests/subp_of_interest/test.opt b/testsuite/tests/subp_of_interest/test.opt new file mode 100644 index 000000000..fc0b26792 --- /dev/null +++ b/testsuite/tests/subp_of_interest/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Uses Ada_2012 code constructs (aspects) diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py new file mode 100644 index 000000000..e931adb22 --- /dev/null +++ b/testsuite/tests/subp_of_interest/test.py @@ -0,0 +1,180 @@ +""" +Check that the subprograms of interest mechanism works as expected, i.e. +produces the right coverage expectations for source traces, and the right error +message for binary traces. +""" + +import os +import os.path +import re + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +src_traces = thistest.options.trace_mode == "src" + + +def check_xcov(label, args, expected_output=""): + """ + Run xcov with the given aruments and check its output. + + Also pass it --output-dir={label}, and create that directory beforehand. + """ + log = f"{label}.log" + os.mkdir(label) + xcov(args + [f"--output-dir={label}"], out=log) + thistest.fail_if_not_equal( + "'gnatcov coverage' output", + expected_output, + contents_of(log).strip(), + ) + + +tmp = Wdir("tmp_") + +pkg_spec = os.path.join("..", "src", "pkg.ads") +pkg_body = os.path.join("..", "src", "pkg.adb") + +thistest.log("== Checkpoint creation ==") +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor(srcdirs=os.path.join("..", "src"), mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +# Produce a coverage report and a checkpoint with the subprogram switch. Check +# that the coverage report contains only coverage data for the specified +# subprograms for source traces. For binary traces, simply check that the +# gnatcov coverage invocation yields the expected warning. +ckpt_filename = "trace.ckpt" +check_xcov( + "xcov_subp", + cov_args + + [ + "--save-checkpoint", + ckpt_filename, + f"--subprograms={pkg_spec}:4", + f"--subprograms={pkg_body}:19", + f"--subprograms={pkg_body}:20", + ], + expected_output=( + "" + if src_traces + else "warning: Ignoring --subprograms switches as this is not" + " supported with binary traces." + ), +) +cov_ckpt_args = cov_args[:-1] + ["--checkpoint", ckpt_filename] +if src_traces: + check_xcov_reports( + "xcov_subp", + { + "main.adb.xcov": {}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {11, 19, 30}}, + }, + ) + + # Then check that the checkpoint contains only coverage data for the + # specific subprogram. To do this, produce a new coverage report from the + # checkpoint without using the --subprograms switch. + thistest.log("== xcov_no_subp ==") + check_xcov("xcov_no_subp", cov_ckpt_args) + check_xcov_reports( + "xcov_no_subp", + { + "main.adb.xcov": {"-": {5, 6}}, + "pkg.ads.xcov": {"-": {7}}, + "pkg.adb.xcov": {"+": {11, 19, 30}, "-": {22, 33, 34, 35}}, + }, + ) + + # Check that we can still select subprograms of interest declared in the + # package body, when the package specification is ignored through + # --ignored-source-files. + thistest.log("== xcov_ignore ==") + check_xcov( + "xcov_ignore", + cov_args + + [ + f"--subprograms={pkg_body}:20", + "--ignore-source-files=pkg.ads", + ], + ) + check_xcov_reports( + "xcov_ignore", + { + "main.adb.xcov": {}, + "pkg.adb.xcov": {"+": {30}}, + }, + ) + + # Also check the warnings when the subprogram switch is ill-formed + + # Case 1: missing colon in the argument + thistest.log("== Missing colon ==") + xcov( + cov_args + ["--subprograms", "no-colon"], + out="xcov-wrong1.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=r".*Wrong argument passed to --subprograms: .*", + actual=contents_of("xcov-wrong1.txt"), + ) + + # Case 2: line number is not a number + thistest.log("== Bad line number ==") + xcov( + cov_args + ["--subprograms", f"{pkg_spec}:b"], + out="xcov-wrong2.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=r".*Wrong argument passed to --subprograms: .*", + actual=contents_of("xcov-wrong2.txt"), + ) + + # Case 3: file does not exist + thistest.log("== No such file ==") + xcov( + cov_args + ["--subprograms", "dumb-file-name:4"], + out="xcov-wrong3.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=( + r".*Error when parsing --subprograms argument dumb-file-name:4:" + r" unknown source file" + ), + actual=contents_of("xcov-wrong3.txt"), + ) + + # Case 4: scope does not exist + thistest.log("== No such scope ==") + xcov( + cov_args + [f"--subprograms={pkg_body}:14"], + out="xcov-wrong3.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=( + ".*Error when parsing --subprograms argument" + f" {re.escape(pkg_body)}:14: unknown subprogram" + ), + actual=contents_of("xcov-wrong3.txt"), + ) + + +thistest.result() diff --git a/testsuite/tests/subp_of_interest_c/src/bar.h b/testsuite/tests/subp_of_interest_c/src/bar.h new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/bar.h @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/subp_of_interest_c/src/main.c b/testsuite/tests/subp_of_interest_c/src/main.c new file mode 100644 index 000000000..18f907090 --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/main.c @@ -0,0 +1,10 @@ +#include "bar.h" +#include "pkg.h" + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/subp_of_interest_c/src/pkg.c b/testsuite/tests/subp_of_interest_c/src/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/subp_of_interest_c/src/pkg.h b/testsuite/tests/subp_of_interest_c/src/pkg.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/pkg.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py new file mode 100644 index 000000000..e909bd915 --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -0,0 +1,43 @@ +""" +Check that the subprograms of interest mechanism works as expected on a C +example. It also acts as a regression testcase as gnatcov used to crash when +instrumenting a source including multiple headers, with at last one of them +not having any coverage obligation. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +cov_args = build_run_and_coverage( + gprsw=GPRswitches( + gprfor(srcdirs=os.path.join("..", "src"), mains=["main.c"]) + ), + covlevel="stmt", + mains=["main"], + trace_mode="src", + extra_coverage_args=[ + "-axcov", + "--subprograms", + f"{os.path.join('..', 'src', 'pkg.c')}:1", + ], +) + +check_xcov_reports( + "obj", + { + "main.c.xcov": {}, + "bar.h.xcov": {}, + "pkg.c.xcov": {"+": {4}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/trace_name/main.adb b/testsuite/tests/trace_name/main.adb new file mode 100644 index 000000000..57d139b4a --- /dev/null +++ b/testsuite/tests/trace_name/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world!"); +end Main; diff --git a/testsuite/tests/trace_name/test.opt b/testsuite/tests/trace_name/test.opt new file mode 100644 index 000000000..2eb62c7a9 --- /dev/null +++ b/testsuite/tests/trace_name/test.opt @@ -0,0 +1,2 @@ +!native,src-traces DEAD Check default trace file name (dump-channel=bin-file) +native,RTS_ZFP DEAD Check default trace file name (dump-channel=bin-file) diff --git a/testsuite/tests/trace_name/test.py b/testsuite/tests/trace_name/test.py new file mode 100644 index 000000000..f56e6aacc --- /dev/null +++ b/testsuite/tests/trace_name/test.py @@ -0,0 +1,54 @@ +""" +Check that the source trace produced by gnatcov matches the executable name, +and not the unit name. The two can be different when the executable name is +specified in the project file, or when the unit name and the filename are +mismatching. Test both cases. +""" + +from SCOV.minicheck import build_and_run +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +import os + + +def check_srctrace_name(gprsw, main): + build_and_run( + gprsw=gprsw, + covlevel="stmt", + mains=[main], + extra_instr_args=["--dump-filename-simple"], + extra_coverage_args=[], + ) + # Check the name of the trace + trace_ext = ( + ".srctrace" if thistest.options.trace_mode == "src" else ".trace" + ) + trace_name = f"{main}{env.target.os.exeext}{trace_ext}" + thistest.fail_if( + not os.path.exists(trace_name), + f"Could not find {trace_name}", + ) + + +# Check when the executable name is left unspecified +tmp = Wdir("tmp_no_exec_attr") +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) +check_srctrace_name(gprsw, "main") + +# Check when the executable name is specified in the project +tmp.to_subdir("tmp_exec_attr") +gprsw = GPRswitches( + root_project=gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra="""package Builder is + for Executable ("main.adb") use "bar"; + end Builder;""", + ) +) +check_srctrace_name(gprsw, "bar") + +thistest.result() diff --git a/testsuite/tests/xml-check/src/andthen.adb b/testsuite/tests/xml-check/src/andthen.adb new file mode 100644 index 000000000..49cba2788 --- /dev/null +++ b/testsuite/tests/xml-check/src/andthen.adb @@ -0,0 +1,4 @@ +function Andthen (A, B : Boolean) return Boolean is +begin + return A and then B; +end; diff --git a/testsuite/tests/xml-check/src/test_andthen_t.adb b/testsuite/tests/xml-check/src/test_andthen_t.adb new file mode 100644 index 000000000..29949cd9b --- /dev/null +++ b/testsuite/tests/xml-check/src/test_andthen_t.adb @@ -0,0 +1,6 @@ +with Support, Andthen; use Support; + +procedure Test_Andthen_T is +begin + Assert (Andthen (True, True) = True); +end; diff --git a/testsuite/tests/xml-check/test.py b/testsuite/tests/xml-check/test.py new file mode 100644 index 000000000..952fef99f --- /dev/null +++ b/testsuite/tests/xml-check/test.py @@ -0,0 +1,30 @@ +"""Sanity check our ability to produce XML reports.""" + +from xml.dom import minidom + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor("test_andthen_t.adb", srcdirs="../src") + ), + covlevel="stmt+mcdc", + mains=["test_andthen_t"], + extra_coverage_args=["--annotate=xml", "--output-dir=."], + scos=["obj/andthen"], +) + +xmldoc = minidom.parse("andthen.adb.xml") +print(xmldoc.toxml()) + +xmldoc = minidom.parse("index.xml") +print(xmldoc.toxml()) + +thistest.result() diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 391fda3fd..23fa5531e 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -7,6 +7,7 @@ See ./testsuite.py -h for more help """ +import logging import time import os import re @@ -14,7 +15,7 @@ import itertools from e3.fs import mkdir, rm, cp -from e3.os.fs import which +from e3.os.fs import which, unixpath from e3.os.process import Run, quote_arg import e3.testsuite from e3.testsuite.control import AdaCoreLegacyTestControlCreator @@ -40,17 +41,10 @@ import SUITE.control as control -from SUITE.control import BUILDER +from SUITE.control import BUILDER, _runtime_info from SUITE.control import altrun_opt_for, altrun_attr_for from SUITE.control import cargs_opt_for, cargs_attr_for - -DEFAULT_TIMEOUT = 600 -""" -Default timeout to use (in seconds) to run testcases. Users can override this -using gnatpython.main's --timeout command-line option. -""" - VALGRIND_TIMEOUT_FACTOR = 2 """ When the testsuite runs with Valgrind (--enable-valgrind), the default timeout @@ -101,7 +95,7 @@ class QlevelInfo(object): def __init__(self, levelid, subtrees, xcovlevel): - self.levelid = levelid # string identifier + self.levelid = levelid # string identifier # regexp of directory subtrees: testdirs that match this # hold qualification tests for this level @@ -117,11 +111,14 @@ def hosts(self, test_dir): provided test directory, which may be relative to a testsuite root or absolute. """ - return re.search(pattern=self.subtrees, string=test_dir) + + # Expect filtering subtrees using forward slashes, so make + # sure the provided test_dir is amenable so such patterns. + return re.search(pattern=self.subtrees, string=unixpath(test_dir)) RE_QCOMMON = "(Common|Appendix)" -RE_QLANG = "(%s)" % '|'.join(QLANGUAGES) +RE_QLANG = "(%s)" % "|".join(QLANGUAGES) # A regular expression that matches subdirs of qualification tests # that should apply for coverage criteria RE_CRIT. @@ -129,9 +126,11 @@ def hosts(self, test_dir): def RE_SUBTREE(re_crit): return "%(root)s/((%(common)s)|(%(lang)s/(%(crit)s)))" % { - "root": QROOTDIR, "common": RE_QCOMMON, - "lang": RE_QLANG, "crit": re_crit - } + "root": QROOTDIR, + "common": RE_QCOMMON, + "lang": RE_QLANG, + "crit": re_crit, + } # Note that we expect test directory names to be in unix form here. @@ -142,21 +141,18 @@ def RE_SUBTREE(re_crit): "doA": QlevelInfo( levelid="doA", subtrees=RE_SUBTREE(re_crit="stmt|decision|mcdc"), - xcovlevel="stmt+mcdc" - ), - + xcovlevel="stmt+mcdc", + ), "doB": QlevelInfo( levelid="doB", subtrees=RE_SUBTREE(re_crit="stmt|decision"), - xcovlevel="stmt+decision" - ), - + xcovlevel="stmt+decision", + ), "doC": QlevelInfo( - levelid="doC", - subtrees=RE_SUBTREE(re_crit="stmt"), - xcovlevel="stmt" - ) - } + levelid="doC", subtrees=RE_SUBTREE(re_crit="stmt"), xcovlevel="stmt" + ), +} + # =============================== # == Compilation Flags Control == @@ -275,12 +271,12 @@ def RE_SUBTREE(re_crit): # option. -def maybe_exec(log, bin, args=None, edir=None): +def maybe_exec(log, binfile, args=None, edir=None): """ - Execute the provided BIN program file, if any. + Execute the provided BINFILE program file, if any. Run this program in the current working directory EDIR is None. Otherwise, - run it in the location where BIN resides if EDIR is "...", or in EDIR's + run it in the location where BINFILE resides if EDIR is "...", or in EDIR's value otherwise. Pass the provided list of ARGS, if any, on the command line. Skip possible @@ -292,20 +288,22 @@ def maybe_exec(log, bin, args=None, edir=None): Return the process object. """ - if not bin: + if not binfile: return - to_run = [sys.executable, bin] if bin.endswith('.py') else [bin] + to_run = ( + [sys.executable, binfile] if binfile.endswith(".py") else [binfile] + ) if args: to_run.extend([arg for arg in args if arg]) if edir == "...": - edir = os.path.dirname(bin) + edir = os.path.dirname(binfile) p = Run(to_run, cwd=edir) - log += "\nRunning hook: {}\n".format(bin) + log += "\nRunning hook: {}\n".format(binfile) log += p.out return p @@ -314,7 +312,7 @@ def maybe_exec(log, bin, args=None, edir=None): class TestPyRunner: """Helper to run a "test.py" test script.""" - filename = 'test.py' + filename = "test.py" def __init__(self, driver, result, test_prefix, working_prefix): """ @@ -341,7 +339,7 @@ def __init__(self, driver, result, test_prefix, working_prefix): # Create a "canonical" directory name for this testcase, useful to # simplify some platform-independent processings. - self.unix_test_dir = self.test_dir().replace('\\', '/') + self.unix_test_dir = unixpath(self.test_dir()) # Load all relevant *.opt files to control the execution of this test self.test_control_creator = self.parse_opt() @@ -366,21 +364,21 @@ def outf(self): Same location as the test source script, with same name + a .out extra suffix extension. """ - return self.test_dir(self.filename + '.out') + return self.test_dir(self.filename + ".out") def logf(self): """ Similar to outfile, for the file where logs of the commands executed by the provided test object should go. """ - return self.test_dir(self.filename + '.log') + return self.test_dir(self.filename + ".log") def errf(self): """ Similar to outf, for the file where diffs of the provided test object should go. """ - return self.test_dir(self.filename + '.err') + return self.test_dir(self.filename + ".err") def qdaf(self): return qdaf_in(self.test_dir()) @@ -390,7 +388,7 @@ def ctxf(self): The file containing a SUITE_context describing the testcase run (the file is in pickle format). """ - return self.test_dir('ctx.dump') + return self.test_dir("ctx.dump") # -------------------------------------- # -- Testscase specific discriminants -- @@ -406,14 +404,14 @@ def discriminants(self): lang = self.lang() if lang: - discs.append('LANG_%s' % lang.upper()) + discs.append("LANG_%s" % lang.upper()) return discs def lang(self): """The language specific subtree SELF pertains to.""" for lang in control.KNOWN_LANGUAGES: - if '/{}/'.format(lang) in self.unix_test_dir: + if "/{}/".format(lang) in self.unix_test_dir: return lang return None @@ -428,16 +426,16 @@ def lookup_extra_opt(self): # world, this would be the tessuite root directory, but in practice we # often run the testsuite on "Qualif/ ../extra/tests/", so if there is # an "extra" directory above the root directory, allow one level up. - root_dir = self.driver.test_env['testsuite_root_dir'] - up_root = os.path.abspath(os.path.join(root_dir, '..')) - if os.path.exists(os.path.join(up_root, 'extra')): + root_dir = self.driver.test_env["testsuite_root_dir"] + up_root = os.path.abspath(os.path.join(root_dir, "..")) + if os.path.exists(os.path.join(up_root, "extra")): root_dir = up_root # Climb up from the testcase directory to the testsuite root directory # and gather all extra.opt files found in the way. - d = self.test_dir('..') + d = self.test_dir("..") while d.startswith(root_dir): - extra_opt = os.path.join(d, 'extra.opt') + extra_opt = os.path.join(d, "extra.opt") if os.path.exists(extra_opt): result.append(extra_opt) d = os.path.dirname(d) @@ -456,7 +454,7 @@ def parse_opt(self): # directory tree order, then feed that to the opt file parser. opt_files = [] - test_opt = self.test_dir('test.opt') + test_opt = self.test_dir("test.opt") if os.path.exists(test_opt): opt_files.append(test_opt) @@ -465,14 +463,15 @@ def parse_opt(self): opt_lines = sum((lines_of(f) for f in opt_files), []) # Create a single "control.opt" file to contain all control directives - control_opt = self.working_dir('control.opt') - with open(control_opt, 'w') as f: + control_opt = self.working_dir("control.opt") + with open(control_opt, "w") as f: for line in opt_lines: - f.write(line + '\n') + f.write(line + "\n") return AdaCoreLegacyTestControlCreator( system_tags=self.env.suite_discriminants + self.discriminants(), - opt_filename=control_opt) + opt_filename=control_opt, + ) def set_up(self): mopt = self.env.main_options @@ -499,13 +498,15 @@ def set_up(self): # Construct the test command line - testcase_cmd = [sys.executable, - self.test_dir(self.filename), - '--report-file=' + outf, - '--log-file=' + logf] + testcase_cmd = [ + sys.executable, + self.test_dir(self.filename), + "--report-file=" + outf, + "--log-file=" + logf, + ] if mopt.enable_valgrind: - testcase_cmd.append('--enable-valgrind=' + mopt.enable_valgrind) + testcase_cmd.append("--enable-valgrind=" + mopt.enable_valgrind) # Propagate our command line arguments as testcase options. # @@ -518,74 +519,109 @@ def set_up(self): # the requested level (validated by GNATcovTestFinder.probe): if mopt.qualif_level: - testcase_cmd.append('--qualif-level=%s' % mopt.qualif_level) + testcase_cmd.append("--qualif-level=%s" % mopt.qualif_level) testcase_cmd.append( - '--xcov-level=%s' % QLEVEL_INFO[mopt.qualif_level].xcovlevel) + "--xcov-level=%s" % QLEVEL_INFO[mopt.qualif_level].xcovlevel + ) if mopt.build: - testcase_cmd.append('--build=%s' % mopt.build) + testcase_cmd.append("--build=%s" % mopt.build) if mopt.target: - testcase_cmd.append('--target=%s' % mopt.target) + testcase_cmd.append("--target=%s" % mopt.target) if mopt.board: - testcase_cmd.append('--board=%s' % mopt.board) + testcase_cmd.append("--board=%s" % mopt.board) if mopt.gprmode: - testcase_cmd.append('--gprmode') + testcase_cmd.append("--gprmode") if mopt.trace_mode: - testcase_cmd.append('--trace-mode=%s' % mopt.trace_mode) + testcase_cmd.append("--trace-mode=%s" % mopt.trace_mode) if mopt.kernel: - testcase_cmd.append('--kernel=%s' % mopt.kernel) + testcase_cmd.append("--kernel=%s" % mopt.kernel) if mopt.trace_size_limit: testcase_cmd.append( - '--trace-size-limit=%s' % mopt.trace_size_limit) + "--trace-size-limit=%s" % mopt.trace_size_limit + ) if mopt.RTS: - testcase_cmd.append('--RTS=%s' % mopt.RTS) + testcase_cmd.append("--RTS=%s" % mopt.RTS) if mopt.largs: - testcase_cmd.append('--largs=%s' % mopt.largs.strip()) + testcase_cmd.append("--largs=%s" % mopt.largs.strip()) - testcase_cmd.append('--tags=@%s' % self.env.discr_file) + testcase_cmd.append("--tags=@%s" % self.env.discr_file) if mopt.auto_arch: - testcase_cmd.append('--auto-arch') + testcase_cmd.append("--auto-arch") if mopt.consolidate: - testcase_cmd.append('--consolidate=%s' % mopt.consolidate) + testcase_cmd.append("--consolidate=%s" % mopt.consolidate) if mopt.pretty_print: - testcase_cmd.append('--pretty-print') + testcase_cmd.append("--pretty-print") if mopt.spark_tests: - testcase_cmd.append('--spark-tests=%s' % mopt.spark_tests) + testcase_cmd.append("--spark-tests=%s" % mopt.spark_tests) if mopt.all_warnings: - testcase_cmd.append('--all-warnings') + testcase_cmd.append("--all-warnings") + + if mopt.default_dump_trigger: + testcase_cmd.append( + f"--default-dump-trigger={mopt.default_dump_trigger}" + ) + + if mopt.default_dump_channel: + testcase_cmd.append( + f"--default-dump-channel={mopt.default_dump_channel}" + ) + + if mopt.block: + testcase_cmd.append("--block") + + if mopt.ada_version: + testcase_cmd.append(f"--ada-version={mopt.ada_version}") # --gnatcov_ family for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: if getattr(mopt, altrun_attr_for(pgm, cmd)) is None: continue - testcase_cmd.append('--%(opt)s=%(val)s' % { - 'opt': altrun_opt_for(pgm, cmd), - 'val': getattr(mopt, altrun_attr_for(pgm, cmd))}) + testcase_cmd.append( + "--%(opt)s=%(val)s" + % { + "opt": altrun_opt_for(pgm, cmd), + "val": getattr(mopt, altrun_attr_for(pgm, cmd)), + } + ) + + # --gpr family + for pgm in control.ALTRUN_GPR: + if getattr(mopt, altrun_attr_for(pgm)) is None: + continue + testcase_cmd.append( + f"--{altrun_opt_for(pgm)}=" + f"{getattr(mopt, altrun_attr_for(pgm))}" + ) # --cargs family for lang in [None] + control.KNOWN_LANGUAGES: - testcase_cmd.append('--%(opt)s=%(val)s' % { - "opt": cargs_opt_for(lang), - "val": getattr(mopt, cargs_attr_for(lang))}) + testcase_cmd.append( + "--%(opt)s=%(val)s" + % { + "opt": cargs_opt_for(lang), + "val": getattr(mopt, cargs_attr_for(lang)), + } + ) # Compute the testcase timeout, whose default vary depending on whether # we use Valgrind. - timeout = DEFAULT_TIMEOUT + timeout = int(self.test_control.opt_results["RLIMIT"]) if mopt.enable_valgrind: timeout = VALGRIND_TIMEOUT_FACTOR * timeout @@ -595,22 +631,23 @@ def set_up(self): self.testcase_cmd = testcase_cmd self.testcase_timeout = timeout - def maybe_exec(self, bin, args=None, edir=None): + def maybe_exec(self, binfile, args=None, edir=None): """ Shortcut for the global maybe_exec. Log the result in ``self.result.log`` and abort the testcase on failure. """ - if not bin: + if not binfile: return - if maybe_exec(self.result.log, bin, args, edir).status != 0: - raise TestAbortWithError("Altrun hook failed ({})".format(bin)) + if maybe_exec(self.result.log, binfile, args, edir).status != 0: + raise TestAbortWithError("Altrun hook failed ({})".format(binfile)) def run(self): mopt = self.env.main_options - self.maybe_exec(mopt.pre_testcase, args=[mopt.altrun], - edir=self.test_dir()) + self.maybe_exec( + mopt.pre_testcase, args=[mopt.altrun], edir=self.test_dir() + ) # Run the "test.py" script in the testsuite root directory (as # expected: the script will change its own CWD later). @@ -618,14 +655,15 @@ def run(self): self.test_py_process = Run( self.testcase_cmd, cwd=self.env.root_dir, - timeout=self.testcase_timeout) + timeout=self.testcase_timeout, + ) end_time = time.time() self.result.time = end_time - start_time # To ease debugging, copy the consolidated standard outputs (stdout + # stderr) to the "test.py.err" file. - with open(self.errf(), 'w') as f: + with open(self.errf(), "w") as f: f.write(self.test_py_process.out) # If the script exitted with an error status code, consider that the @@ -648,17 +686,15 @@ def tear_down(self): # Execute a post-testcase action if requested so, before the test # artifacts might be cleared by a post-run cleanup: - self.maybe_exec(args.post_testcase, args=[args.altrun], - edir=self.test_dir()) + self.maybe_exec( + args.post_testcase, args=[args.altrun], edir=self.test_dir() + ) # Perform post-run cleanups if requested so. Note that this may # alter the test execution status to make sure that unexpected cleanup # failures get visibility: - if ( - self.result.status != TestStatus.FAIL - and args.do_post_run_cleanups - ): + if self.result.status != TestStatus.FAIL and args.do_post_run_cleanups: self.do_post_run_cleanups(ts_options=args) if args.qualif_level: @@ -666,20 +702,24 @@ def tear_down(self): def analyze(self): if self.test_py_failed: - self.push_failure("test.py exitted with status code {}" - .format(self.test_py_process.status)) + self.push_failure( + "test.py exitted with status code {}".format( + self.test_py_process.status + ) + ) elif cutils.match("==== PASSED ==================", self.outf()): self.push_success() else: self.push_failure("Missing PASSED tag in output file") - def run_test(self, previous_values, slot): + def run_test(self, previous_values, slot): """Run the testcase, analyze its result and push the result.""" try: self.test_control = self.test_control_creator.create(self.driver) except ValueError as exc: return self.push_error( - "Error while interpreting control: {}".format(exc)) + "Error while interpreting control: {}".format(exc) + ) # If test control tells us to skip the test, stop right here if self.test_control.skip: @@ -746,10 +786,13 @@ def latch_status(self): r = self.result pdump_to( self.stdf(), - o=TC_status(passed=r.status in (TestStatus.PASS, TestStatus.XPASS), - xfail=self.test_control.xfail, - status=r.status.name, - comment=self.test_control.message)) + o=TC_status( + passed=r.status in (TestStatus.PASS, TestStatus.XPASS), + xfail=self.test_control.xfail, + status=r.status.name, + comment=self.test_control.message, + ), + ) def latched_status(self): return pload_from(self.stdf()) @@ -759,20 +802,29 @@ def _handle_info_for(self, path): the provided PATH, such as the output of the "handle" sysinternal on Windows.""" - if sys.platform != 'win32': + if sys.platform != "win32": return "No handle info on non-windows platform" # Adjust the provided path to something - path = re.sub('^[a-zA-Z]:(.*)', r'\1', path).replace('/', '\\') + path = re.sub("^[a-zA-Z]:(.*)", r"\1", path).replace("/", "\\") gpdir = os.path.dirname(sys.executable) handle_path = os.path.abspath( - os.path.join(gpdir, 'Lib', 'site-packages', - 'gnatpython', 'internal', 'data', 'libexec', - 'x86-windows', 'handle.exe')) + os.path.join( + gpdir, + "Lib", + "site-packages", + "gnatpython", + "internal", + "data", + "libexec", + "x86-windows", + "handle.exe", + ) + ) - return Run([handle_path, '/AcceptEULA', '-a', '-u', path]).out + return Run([handle_path, "/AcceptEULA", "-a", "-u", path]).out def do_post_run_cleanups(self, ts_options): """Cleanup temporary artifacts from the testcase directory. @@ -815,24 +867,24 @@ def cleanup_on_match(subdirs, prefixes, parent): # Perform a filesystem walk to craft the list of items we # can/should remove. Make it topdown so we can arrange not to # recurse within subirectories we cleanup as a whole. - for dirpath, dirnames, filenames in ( - os.walk(self.test_dir(), topdown=True)): - + for dirpath, dirnames, filenames in os.walk( + self.test_dir(), topdown=True + ): # Nothing in "obj" dirs ever needs to be preserved cleanup_on_match( - subdirs=dirnames, prefixes=['tmp', 'obj'], - parent=dirpath) + subdirs=dirnames, prefixes=["tmp", "obj"], parent=dirpath + ) # We can also always get rid of all the pure binary artifacts, # wherever they are produced. Files without extension, most often # executables, are considered never of interest. for fn in filenames: if ( - fn.endswith('.trace') - or fn.endswith('.obj') - or fn.endswith('.o') - or fn.endswith('.exe') - or '.' not in fn + fn.endswith(".trace") + or fn.endswith(".obj") + or fn.endswith(".o") + or fn.endswith(".exe") + or "." not in fn ): cleanup_q.append(os.path.join(dirpath, fn)) @@ -843,13 +895,14 @@ def cleanup_on_match(subdirs, prefixes, parent): # packages. if not ts_options.qualif_level: for fn in filenames: - if (fn == 'test.py.log'): + if fn == "test.py.log": cleanup_q.append(os.path.join(dirpath, fn)) cleanup_on_match( subdirs=dirnames, - prefixes=['st_', 'dc_', 'mc_', 'uc_'], - parent=dirpath) + prefixes=["st_", "dc_", "mc_", "uc_"], + parent=dirpath, + ) # Deal with occasional removal failures presumably caused by stray # handles. Expand glob patterns locally, issue separate rm requests @@ -861,31 +914,34 @@ def cleanup_on_match(subdirs, prefixes, parent): except Exception: handle_comment = self._handle_info_for(path) self.passed = False - self.status = 'RMFAILED' + self.status = "RMFAILED" comments.append( - "Removal of %s failed\nHandle info follows:" % path) + "Removal of %s failed\nHandle info follows:" % path + ) comments.append(handle_comment) - with open(self.errf(), 'a') as f: - f.write('\n'.join(comments)) + with open(self.errf(), "a") as f: + f.write("\n".join(comments)) class TestPyDriver(TestDriver): """ Test driver that runs "test.py" scripts. """ + def add_test(self, dag): self.runner = TestPyRunner( self, self.result, self.test_dir(), self.working_dir() ) - self.add_fragment(dag, 'run', self.runner.run_test) + self.add_fragment(dag, "run", self.runner.run_test) class GroupPyDriver(TestDriver): """ Test driver that runs "group.py" scripts. """ + def add_test(self, dag): # Generator of unique indexes for generated testcases indexes = itertools.count(1) @@ -900,7 +956,7 @@ def add_test(self, dag): ) # Look for all "test.py" that were generated under this test directory - for dirpath, dirnames, filenames in os.walk(self.test_dir()): + for dirpath, _, filenames in os.walk(self.test_dir()): if "test.py" in filenames: self.add_test_py_run(dag, dirpath, next(indexes)) @@ -909,8 +965,7 @@ def add_test_py_run(self, dag, test_dir, index): # as for regular tests. test_rel_dir = os.path.relpath(test_dir, self.test_dir()) test_name = "{}-{}".format( - self.test_name, - test_rel_dir.replace("\\", "/").replace("/", "-") + self.test_name, unixpath(test_rel_dir).replace("/", "-") ) # For debuggability, derive the group.py test environment @@ -926,9 +981,7 @@ def add_test_py_run(self, dag, test_dir, index): class GNATcovTestFinder(TestFinder): - def probe(self, testsuite, dirpath, dirnames, filenames): - # If we are running in qualification mode, punt if this test # is not within the subtrees attached to the requested level. qlevel = testsuite.main.args.qualif_level @@ -937,12 +990,12 @@ def probe(self, testsuite, dirpath, dirnames, filenames): # If directory contains a "test.py" file *and* not a ".generated" # one, this this is a regular testcase. - if 'test.py' in filenames and '.generated' not in filenames: + if "test.py" in filenames and ".generated" not in filenames: driver_cls = TestPyDriver # If it contains a "group.py" file, then this is a special test that # generates several actual testcases. - elif 'group.py' in filenames: + elif "group.py" in filenames: driver_cls = GroupPyDriver # Otherwise, there is no testcase @@ -953,7 +1006,7 @@ def probe(self, testsuite, dirpath, dirnames, filenames): return ParsedTest( test_name=testsuite.test_name(dirpath), driver_cls=driver_cls, - test_env={'testsuite_root_dir': testsuite.root_dir}, + test_env={"testsuite_root_dir": testsuite.root_dir}, test_dir=dirpath, ) @@ -964,7 +1017,6 @@ def probe(self, testsuite, dirpath, dirnames, filenames): class TestSuite(e3.testsuite.Testsuite): - enable_cross_support = True @property @@ -979,16 +1031,16 @@ def test_name(self, test_dir): # strip leading "..". pattern = os.path.pardir + os.path.sep while result.startswith(pattern): - result = result[len(pattern):] + result = result[len(pattern) :] # Run some name canonicalization and replace directory separators with # dashes. - result = result.replace("\\", "/").rstrip("/").replace("/", "-") + result = unixpath(result).rstrip("/").replace("/", "-") # Tests from the internal testsuite used to be located in the "tests" # subdirectory. They are now in "../extra/tests", but we want the GAIA # name to remain the same. - return strip_prefix('extra-', result) + return strip_prefix("extra-", result) # -------------------------- # -- GAIA file facilities -- @@ -1002,24 +1054,24 @@ def _push_log(self, textlist, filename): # consecutive failures. We must be careful not to dump a possibly # invalid empty line in the output file in such a case. if textlist: - with open(os.path.join(self.output_dir, filename), mode='a') as fd: - fd.write('\n'.join(textlist) + '\n') + with open(os.path.join(self.output_dir, filename), mode="a") as fd: + fd.write("\n".join(textlist) + "\n") def _push_comments(self, textlist): - self._push_log(textlist=textlist, filename='comment') + self._push_log(textlist=textlist, filename="comment") self._comment_lines.extend(textlist) def _push_results(self, textlist): - self._push_log(textlist=textlist, filename='results') + self._push_log(textlist=textlist, filename="results") def _push_altrun(self, textlist): - self._push_log(textlist=textlist, filename='altrun') + self._push_log(textlist=textlist, filename="altrun") def _discriminants_log(self): - return os.path.join(self.output_dir, 'discs') + return os.path.join(self.output_dir, "discs") def write_comment_file(self, f): - f.write('\n'.join(self._comment_lines) + '\n') + f.write("\n".join(self._comment_lines) + "\n") # ------------------------------- # -- STR production facilities -- @@ -1038,10 +1090,9 @@ def _dump_ctxdata(self): if self.main.args.other_tool_info: (toolname, version_info) = Run( [sys.executable, self.main.args.other_tool_info], timeout=20 - ).out.split('##') + ).out.split("##") - other_tool_info = TOOL_info( - exename=toolname, ver=version_info) + other_tool_info = TOOL_info(exename=toolname, ver=version_info) else: other_tool_info = None @@ -1056,9 +1107,9 @@ def _dump_ctxdata(self): gnatpro=TOOL_info(self.tool("gcc")), gnatemu=TOOL_info(self.tool("gnatemu")), gnatcov=TOOL_info("gnatcov"), - other=other_tool_info - ) - ) + other=other_tool_info, + ), + ) # ----------------------- # -- Common facilities -- @@ -1073,10 +1124,53 @@ def tool(self, name): :rtype: str """ if self.env.is_cross: - return self.env.target.triplet + '-' + name + return self.env.target.triplet + "-" + name else: return name + def _build_libsupport(self): + args = self.main.args + + libsup_vars = [] + + if self.env.is_cross: + # Beware that the TARGET variable set here is used as the + # --target switch to gprbuild calls from the Makefile, and + # the args.target value we receive might have os-version + # or machine extensions that aren't appropriate for that + # (e.g. aarch64-elf,unknown). + libsup_vars.append("TARGET={}".format(self.env.target.triplet)) + + # The BOARD variable is used to fill the Emulator package Board + # attribute, so convert the argument to a gnatemu name. + board = control.gnatemu_board_name(args.board) + if board: + libsup_vars.append("BOARD={}".format(board)) + + if args.RTS: + libsup_vars.append("RTS={}".format(args.RTS)) + + # QNX + run-cross2 will report an abort as an abnormal program + # termination, which is not the point of the silent last chance + # handler. QNX however does provide the exit function, so use that + # instead. + if args.target and ("qnx" in args.target or "morello" in args.target): + libsup_vars.append("SILENT_LCH=exit") + + logfile = os.path.join(self.output_dir, "build_support.out") + + p = Run( + ["make", "--debug", "-C", "support", "-f", "Makefile.libsupport"] + + libsup_vars, + output=logfile, + ) + + if p.status != 0: + raise FatalError( + ("Problem during libsupport construction. %s:\n" % logfile) + + contents_of(logfile) + ) + def set_up(self): """ Prepare the testsuite run: compute and dump discriminants, run @@ -1093,39 +1187,86 @@ def set_up(self): # running for qualification, making sure we know what target language # we're qualifying for. + def _get_canonical_ada_version(ada_ver: str) -> str: + if ada_ver in ["83", "95"]: + # For Ada 1983 and 1995, only -gnatYY is correct + return ada_ver + elif ada_ver in ["05", "2005"]: + # For Ada 2005, use "05" to make sure all compilers get it. + return "05" + elif ada_ver[-2:] in ["12", "22"]: + # Since Ada 2012, -gnatYY and -gnatYYYY are accepted + # For Ada 2022, -gnatYYYY is mandatory + return "20" + ada_ver[-2:] + raise FatalError(f"Unable to retrieve Ada version from {ada_ver}") + attr_cargs_ada = cargs_attr_for("Ada") cargs_ada = getattr(args, attr_cargs_ada) attr_cargs = cargs_attr_for("") cargs = getattr(args, attr_cargs) - if not re.search("-gnat95|-gnat05|-gnat12", cargs_ada + cargs): + + gnatcov_instr_ada_version = None + qualifiable_ada_versions = ["95", "05", "12"] + qav_str = "|".join(qualifiable_ada_versions) + ada_version_match = re.search( + r"-gnat(95|(?:20)?(?:05|12)|2022)", cargs_ada + cargs + ) + + if ada_version_match: + ada_version = _get_canonical_ada_version( + ada_version_match.groups()[0] + ) + + if ( + args.qualif_level + and ada_version[-2:] not in qualifiable_ada_versions + ): + raise FatalError( + f"-gnat{ada_version} is invalid for qualification. " + f"Allowed versions are -gnat<{qav_str}>" + ) + + logging.debug( + f"Setting Ada version to Ada {ada_version} from cargs" + ) + gnatcov_instr_ada_version = ada_version + else: if args.qualif_level: raise FatalError( - "Missing -gnat<95|05|12> in cargs:Ada for qualification") + f"Missing -gnat<{qav_str}> in cargs:Ada for qualification" + ) else: + logging.debug("Setting default Ada version to Ada 05") + gnatcov_instr_ada_version = "05" setattr(args, attr_cargs_ada, cargs_ada + " -gnat05") - # Most SPARK testcases require Ada 2012 + # Most SPARK testcases require Ada 2022 + + if args.spark_tests: + logging.debug("Setting Ada version to Ada 2022 for SPARK") + gnatcov_instr_ada_version = "2022" + setattr(args, attr_cargs_ada, cargs_ada + " -gnat2022") - if getattr(args, "spark_tests"): - setattr(args, attr_cargs_ada, cargs_ada + " -gnat12") + # Make sure gnatcov instrument is called with the same Ada version as + # the one passed to gnat afterwards + args.ada_version = gnatcov_instr_ada_version # Expect an explicit -gnatec if we're running for qualification if args.qualif_level and "-gnatec" not in cargs_ada: - raise FatalError( - "Missing -gnatec in cargs:Ada for qualification") + raise FatalError("Missing -gnatec in cargs:Ada for qualification") # Source traces require the use of project files to convey units of # interest, which --gprmode will do: - if args.trace_mode == 'src': + if args.trace_mode == "src": args.gprmode = True # On some targets, we need to link with -lgnat for any executable # to run and the toolchain doesn't do it automatically in some cases # (e.g. C only programs). This is a workaround: - if args.target and '-elf' in args.target: + if args.target and "-elf" in args.target: args.largs += " -lgnat" # e3.testsuite forces the writing of the "comment" file at the end of @@ -1135,12 +1276,12 @@ def set_up(self): # Initialize the GAIA log files. We need to do that before setting up # the altrun hooks, as their execution may dump output logs. - for f in ('comment', 'results', 'discs', 'altrun'): - open(os.path.join(self.output_dir, f), 'w').close() + for f in ("comment", "results", "discs", "altrun"): + open(os.path.join(self.output_dir, f), "w").close() # Add current directory in PYTHONPATH, allowing Python testcase scripts # to find the SUITE and SCOV packages: - self.env.add_search_path('PYTHONPATH', self.root_dir) + self.env.add_search_path("PYTHONPATH", self.root_dir) # Generate the discs list for test.opt parsing, and dump the list in # a file that we can then to determine which discriminants were set @@ -1148,7 +1289,8 @@ def set_up(self): self.env.suite_discriminants = self._discriminants() self._push_log( textlist=[" ".join(self.env.suite_discriminants)], - filename=self._discriminants_log()) + filename=self._discriminants_log(), + ) # Setup the alternate run hooks, if any self._setup_altrun_hooks() @@ -1165,7 +1307,7 @@ def set_up(self): self._init_strbox() self._dump_ctxdata() - with open('python_bin.dump', 'w') as f: + with open("python_bin.dump", "w") as f: f.write(sys.executable) # Dump useful comments about this run for starters @@ -1185,32 +1327,17 @@ def set_up(self): toolchain_discriminants = self._toolchain_discriminants() toolchain_discriminant = ( - toolchain_discriminants[0] if toolchain_discriminants - else None) + toolchain_discriminants[0] if toolchain_discriminants else None + ) BUILDER.RUN_CONFIG_SEQUENCE( toplev_options=self.main.args, - toolchain_discriminant=toolchain_discriminant) + toolchain_discriminant=toolchain_discriminant, + ) # Build support library as needed - if control.runtime_info().need_libsupport: - - targetargs = ["TARGET=%s" % self.env.target.triplet] - if self.main.args.board: - targetargs.append("BOARD=%s" % self.main.args.board) - - logfile = os.path.join(self.output_dir, 'build_support.out') - - p = Run(['make', '-C', 'support', '-f', 'Makefile.libsupport'] + - targetargs + ["RTS=%s" % self.main.args.RTS], - output=logfile) - - if p.status != 0: - raise FatalError( - ("Problem during libsupport construction. %s:\n" % - logfile) + - contents_of(logfile)) + self._build_libsupport() # Initialize counter of consecutive failures, to stop the run # when it is visibly useless to keep going. @@ -1218,7 +1345,7 @@ def set_up(self): # TODO: re-implement this feature self.n_consecutive_failures = 0 - self.maybe_exec(bin=self.main.args.pre_testsuite, edir="...") + self.maybe_exec(binfile=self.main.args.pre_testsuite, edir="...") # Make testsuite options and the discriminants file available from # testcases. @@ -1226,28 +1353,31 @@ def set_up(self): self.env.discr_file = self._discriminants_log() def tear_down(self): - self.maybe_exec(bin=self.main.args.post_testsuite, edir="...") + self.maybe_exec(binfile=self.main.args.post_testsuite, edir="...") # ----------------------------------- # -- Early comments about this run -- # ----------------------------------- def _options_comment(self): - return "Testsuite options:\n" + " ".join(quote_arg(arg) - for arg in sys.argv[1:]) + return "Testsuite options:\n" + " ".join( + quote_arg(arg) for arg in sys.argv[1:] + ) def _versions_comment(self): all_versions = [ - version("gnatcov") + ", " + version(self.tool("gnatls"))] + version("gnatcov") + ", " + version(self.tool("gnatls")) + ] if self.main.args.target: all_versions.append(version(self.tool("gnatemu"), nlines=2)) - return '\n'.join(["Running versions:"] + all_versions) + '\n' + return "\n".join(["Running versions:"] + all_versions) + "\n" def _early_comments(self): - return ['\n\n'.join([self._options_comment(), - self._versions_comment()])] + return [ + "\n\n".join([self._options_comment(), self._versions_comment()]) + ] # ------------------------------- # -- Discriminant computations -- @@ -1257,41 +1387,51 @@ def _discriminants(self): """Full set of discriminants that apply to this test""" return ( - self._base_discriminants() + - self._board_discriminants() + - self._qualif_level_discriminants() + - self._cargs_discriminants() + - self._rts_discriminants() + - self._toolchain_discriminants()) + self._base_discriminants() + + self._board_discriminants() + + self._qualif_level_discriminants() + + self._cargs_discriminants() + + self._rts_discriminants() + + self._toolchain_discriminants() + + self._gnatcov_discriminants() + + self._rust_toolchain_discriminants() + ) def _base_discriminants(self): - # List of toolchain discriminants for which we don't want to run # C++ tests, due to lack of compatibility with modern hosts. unsupported_cpp_toolchains = ["7.1.2", "5.04a1"] - result = ['ALL'] + self.env.discriminants + result = ["ALL"] + self.env.discriminants toolchain_discrs = self._toolchain_discriminants() # Only enable C++ tests if we have a C++ compiler that is not # blacklisted. - if which(self.tool('g++')) and ( + if which(self.tool("g++")) and ( not toolchain_discrs or toolchain_discrs[0] not in unsupported_cpp_toolchains ): - result.append('C++') + result.append("C++") # Add a discriminant to track the current trace mode - result.append('src-traces' - if self.main.args.trace_mode == 'src' - else 'bin-traces') + result.append( + "src-traces" + if self.main.args.trace_mode == "src" + else "bin-traces" + ) if self.main.args.spark_tests: - result.append('spark-tests') + result.append("spark-tests") if self.main.args.all_warnings: - result.append('all-warnings') + result.append("all-warnings") + + if self.main.args.block: + result.append("block") + + if self.main.args.community: + result.append("community") return result @@ -1307,11 +1447,12 @@ def _board_discriminants(self): # board was requested are good enough: boardname = ( - self.main.args.board if self.main.args.board - else self.env.target.machine if self.env.target.machine - else None) + self.main.args.board + if self.main.args.board + else self.env.target.machine if self.env.target.machine else None + ) - return ['board', boardname] if boardname else [] + return ["board", boardname] if boardname else [] def _cargs_discriminants(self): """ @@ -1326,12 +1467,16 @@ def _cargs_discriminants(self): Return an empty list if --cargs was not used. """ - allopts = ' '.join( - [getattr(self.main.args, attr) - for attr in (cargs_attr_for(lang) - for lang in [None] + control.KNOWN_LANGUAGES)] - ) - return ["CARGS_%s" % arg.lstrip('-') for arg in allopts.split()] + allopts = " ".join( + [ + getattr(self.main.args, attr) + for attr in ( + cargs_attr_for(lang) + for lang in [None] + control.KNOWN_LANGUAGES + ) + ] + ) + return ["CARGS_%s" % arg.lstrip("-") for arg in allopts.split()] def _qualif_level_discriminants(self): """ @@ -1341,9 +1486,10 @@ def _qualif_level_discriminants(self): """ return ( - [] if not self.main.args.qualif_level + [] + if not self.main.args.qualif_level else [self.main.args.qualif_level.upper()] - ) + ) def _rts_discriminants(self): """ @@ -1351,31 +1497,9 @@ def _rts_discriminants(self): support library in use, as conveyed by the --RTS command-line option. """ - - # Match light-tasking before light otherwise the wrong discriminant - # will be selected. - - # ex --RTS=powerpc-elf/light-tasking or --RTS=light-tasking - - if "light-tasking" in self.main.args.RTS: - return ["RTS_RAVENSCAR", "RTS_LIGHT_TASKING"] - - # --RTS=light- or --RTS=light (e.g. for VxWorks) correspond to - # the former zfp- variants - - elif "light" in self.main.args.RTS or "zfp" in self.main.args.RTS: - return ["RTS_ZFP"] - - # ex --RTS=powerpc-elf/embedded or --RTS=embedded or --RTS=ravenscar - - elif ("embedded" in self.main.args.RTS - or "ravenscar" in self.main.args.RTS): - return ["RTS_RAVENSCAR", "RTS_EMBEDDED"] - - # ex --RTS=native or --RTS=kernel, or no --RTS at all - - else: - return ["RTS_FULL"] + return _runtime_info( + self.main.args.RTS, self.env.target.platform + ).discrs def _toolchain_discriminants(self): """ @@ -1385,44 +1509,89 @@ def _toolchain_discriminants(self): gcc_version = version(self.tool("gcc")) # Different version numbering for old GNAT versions - m = (re.search(r"GNAT Pro (\d\.\d\.\d)", gcc_version) or - re.search(r"GNAT Pro (5.04a1)", gcc_version)) + m = re.search(r"GNAT Pro (\d\.\d\.\d)", gcc_version) or re.search( + r"GNAT Pro (5.04a1)", gcc_version + ) return [m.group(1)] if m else [] + def _gnatcov_discriminants(self): + """ + Compute the discriminant that reflects the version of the + particular gnatcov in use. + """ + gnatcov_info = control.gnatcov_info() + + return ( + ["gnatcov-{}".format(gnatcov_info.major())] + if gnatcov_info.major() + else [] + ) + + def _rust_toolchain_discriminants(self): + """ + Compute the discriminant that reflects the presence of a rust + toolchain. + """ + + # Enable the rust discriminant when: + # * targeting a native platform; + # * gcc is recent enough (>= 4.2); + # * a Rust toolchain is found. + return ( + ["rust"] + if ( + not self.env.is_cross + and "5.04a1" not in self._toolchain_discriminants() + and which("cargo") + ) + else [] + ) + # -------------------------- # -- Command-line options -- # -------------------------- def add_options(self, parser): parser.add_argument( - '--post-run-cleanups', dest='do_post_run_cleanups', - action='store_true', - help='Request post-run cleanup of temporary artifacts.') + "--post-run-cleanups", + dest="do_post_run_cleanups", + action="store_true", + help="Request post-run cleanup of temporary artifacts.", + ) parser.add_argument( - '--qualif-level', choices=list(QLEVEL_INFO), - metavar='QUALIF_LEVEL', - help='State we are running in qualification mode for a' - ' QUALIF_LEVEL target. This selects a set of applicable tests' - ' for that level.') + "--qualif-level", + choices=list(QLEVEL_INFO), + metavar="QUALIF_LEVEL", + help="State we are running in qualification mode for a" + " QUALIF_LEVEL target. This selects a set of applicable tests" + " for that level.", + ) parser.add_argument( - '--other-tool-info', dest='other_tool_info', - metavar='OTHER_TOOL_INFO', default="", - help='Name of a python script outputing other tool##version info') + "--other-tool-info", + dest="other_tool_info", + metavar="OTHER_TOOL_INFO", + default="", + help="Name of a python script outputing other tool##version info", + ) # --pre|post family for when, what in control.ALTRUN_HOOK_PAIRS: parser.add_argument( - '--%s' % altrun_opt_for(when, what), + "--%s" % altrun_opt_for(when, what), dest=altrun_attr_for(when, what), - help='Run CMD %s to %s run' % (when, what), metavar="CMD") + help="Run CMD %s to %s run" % (when, what), + metavar="CMD", + ) parser.add_argument( - '--altrun', metavar="ALTRUN_SUBDIR", - help='Name of custom hooks directory.') + "--altrun", + metavar="ALTRUN_SUBDIR", + help="Name of custom hooks directory.", + ) # Options shared with testcase scripts @@ -1441,10 +1610,15 @@ def _resolve_paths(self): # First deal with options accepting filenames per se: attributes_to_resolve = ( - ["kernel", "altrun"] + - [altrun_attr_for(p0, p1) - for p0, p1 in (control.ALTRUN_HOOK_PAIRS - + control.ALTRUN_GNATCOV_PAIRS)]) + ["kernel", "altrun"] + + [ + altrun_attr_for(p0, p1) + for p0, p1 in ( + control.ALTRUN_HOOK_PAIRS + control.ALTRUN_GNATCOV_PAIRS + ) + ] + + [altrun_attr_for(p0) for p0 in control.ALTRUN_GPR] + ) for attr in attributes_to_resolve: current_value = getattr(self.main.args, attr) @@ -1465,11 +1639,12 @@ def resolve(carg): """ carg_needs_resolution = any( - carg.startswith(prefix) for prefix in prefixes_to_resolve) + carg.startswith(prefix) for prefix in prefixes_to_resolve + ) if carg_needs_resolution: - (opt, path) = carg.split('=') - return '='.join((opt, os.path.abspath(path))) + (opt, path) = carg.split("=") + return "=".join((opt, os.path.abspath(path))) else: return carg @@ -1477,25 +1652,27 @@ def resolve(carg): cargs_attr = cargs_attr_for(lang) current_cargs = getattr(self.main.args, cargs_attr).split() new_cargs = [resolve(carg) for carg in current_cargs] - setattr(self.main.args, cargs_attr, ' '.join(new_cargs)) + setattr(self.main.args, cargs_attr, " ".join(new_cargs)) # ----------------------------- # -- altrun hooks & friends -- # ----------------------------- - def maybe_exec(self, bin, args=None, edir=None): + def maybe_exec(self, binfile, args=None, edir=None): """ Shortcut for the global maybe_exec. Log the result in the altrun log file, and abort the testsuite on failure. """ - if not bin: + if not binfile: return log = Log("") - p = maybe_exec(log, bin, args, edir) + p = maybe_exec(log, binfile, args, edir) self._push_altrun(log.log.splitlines()) - exit_if(p.status != 0, - "Altrun hook failed ({}):\n{}".format(bin, p.out)) + exit_if( + p.status != 0, + "Altrun hook failed ({}):\n{}".format(binfile, p.out), + ) def _bin_for(self, base, indir=None): """For a provided BASE filename (directory path allowed), return @@ -1513,21 +1690,21 @@ def _bin_for(self, base, indir=None): if there is more than one possibility. """ - candidate_exe = ( - base + (self.env.host.os.exeext - if self.env.host.os.exeext else "")) - candidates = [candidate_exe, base+".py"] + candidate_exe = base + ( + self.env.host.os.exeext if self.env.host.os.exeext else "" + ) + candidates = [candidate_exe, base + ".py"] def relative_for(p): return p if indir is None else os.path.join(indir, p) - programs = [ - p for p in candidates if os.path.exists(relative_for(p))] + programs = [p for p in candidates if os.path.exists(relative_for(p))] exit_if( len(programs) > 1, - "from %s, too many binaries for %s:\n%s" % - (os.getcwd(), base, '\n'.join(programs))) + "from %s, too many binaries for %s:\n%s" + % (os.getcwd(), base, "\n".join(programs)), + ) return programs[0] if programs else None def _setup_altrun_hooks(self): @@ -1544,33 +1721,35 @@ def _setup_altrun_hooks(self): # designed for local operations: self.maybe_exec( - bin=self._bin_for("setup", indir=ctldir), edir=ctldir) + binfile=self._bin_for("setup", indir=ctldir), edir=ctldir + ) - def install_altrun_for(p0, p1, binbase): + def install_altrun_for(p0, p1=None, binbase=None): """Establish an implicit value for the --P0_P1 command line option if we find a matching binary program in the altrun subdir we are processing. BINBASE provides the binary base name to use.""" - bin = self._bin_for(os.path.join(ctldir, binbase)) + binfile = self._bin_for(os.path.join(ctldir, binbase)) - if not bin: + if not binfile: return attr = altrun_attr_for(p0, p1) exit_if( getattr(self.main.args, attr), - "%s altrun conflicts with explicit --%s" % (bin, attr) - ) + "%s altrun conflicts with explicit --%s" % (binfile, attr), + ) - self._push_altrun(["hooking %s to %s" % (attr, bin)]) - setattr(self.main.args, attr, bin) + self._push_altrun(["hooking %s to %s" % (attr, binfile)]) + setattr(self.main.args, attr, binfile) # For the toplevel testsuite driver hooks, map on binaries # matching the command line option names: for when, what in control.ALTRUN_HOOK_PAIRS: install_altrun_for( - p0=when, p1=what, binbase=altrun_opt_for(when, what)) + p0=when, p1=what, binbase=altrun_opt_for(when, what) + ) # For the gnatcov replacements, map on binaries called # 'c': @@ -1578,6 +1757,10 @@ def install_altrun_for(p0, p1, binbase): for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: install_altrun_for(p0=pgm, p1=cmd, binbase="c%s" % cmd) + # For the gpr replacements, map on binaries called cgpr: + for pgm in control.ALTRUN_GPR: + install_altrun_for(p0=pgm, p1=None, binbase=f"c{pgm}") + if __name__ == "__main__": sys.exit(TestSuite().testsuite_main()) diff --git a/tools/gnatcov/.vscode/settings.json b/tools/gnatcov/.vscode/settings.json new file mode 100644 index 000000000..a41a48f6c --- /dev/null +++ b/tools/gnatcov/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "ada.projectFile": "gnatcov.gpr", + "ada.scenarioVariables": { + "BUILD_MODE": "dev", + "PART": "gnatcov64", + "C_SUPPORT": "True" + } +} diff --git a/tools/gnatcov/LICENSE.dhtml b/tools/gnatcov/LICENSE.dhtml index 772898263..162c3ba4f 100644 --- a/tools/gnatcov/LICENSE.dhtml +++ b/tools/gnatcov/LICENSE.dhtml @@ -1,184 +1,2 @@ GNATcoverage as a whole is licensed under the terms of the General Public License version 3 (see LICENSE). - -However, the gnatcov-dhtml.min.js file used in dynamic html reports -incorporates code from the Google Closure library -(http://code.google.com/p/closure-library/) licensed under the Apache 2.0 -license reproduced below: - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 1282b82fb..49eecb466 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -12,7 +12,7 @@ # # all # bin <- default -# adapters [ADAPTERS_LIST=dynamorio|valgrind|...] +# adapters [ADAPTERS_LIST=trace32|...] # ---------------- # -- To install -- @@ -22,7 +22,7 @@ # install-bin # install-examples # -# install-adapters [ADAPTERS_LIST=dynamorio|valgrind|...] +# install-adapters [ADAPTERS_LIST=trace32|...] # # All working with the PREFIX variable, that users may specify: @@ -31,32 +31,6 @@ # on possibly case-insensitive filesystems. PREFIX=$(PWD)/local -# By default, assume that the binutils dependency was built in the source tree. -BINUTILS_BUILD_DIR?=$(BINUTILS_SRC_DIR) - -# Note for the trace adapters: -# ---------------------------- - -# When *building* adapters for native configurations, we usually need to know -# the execution engine "prefix" to get access to e.g. header files (valgrind) -# or cmake artifacts (dynamoRIO). - -# By default, we infer that prefix from the location of "valgrind" or "drrun" -# on the PATH, and users may specify an alternate location by setting the -# VALGRIND_PREFIX or DYNRIO_PREFIX Makefile variable. - -# When *installing* adapters, we need the location of the valgrind install -# tree where the valgrind adapter needs to go. By default, we infer that from -# the location of "valgrind" on the PATH. Users may alter that choice by -# setting the VALGRIND_PREFIX variable. - -# dynamorio doesn't need the client to be installed within it's own tree, so -# we install within the bundled install tree, rooted at PREFIX and gnatcov -# passes the complete client path to dynamorio. - -# Alternatively, users may specify a final location by setting the -# VALGRIND_TOOL_INSTALL_DIR or DYNRIO_CLIENT_INSTALL_DIR variable. - # ---------------- # -- To cleanup -- # ---------------- @@ -74,9 +48,10 @@ GPRINSTALL=gprinstall # Binary program name PGMNAME=gnatcov -PGMPATH=obj64/$(BUILD_MODE)/$(PGMNAME) +PGMPATH=obj32/$(BUILD_MODE)/$(PGMNAME) PGM32PATH=obj32/$(BUILD_MODE)/gnatcov32 PGM64PATH=obj64/$(BUILD_MODE)/gnatcov64 +COMPILERPATH=obj32/$(BUILD_MODE)/compiler_wrappers-gcc # Directory name in the install tree DIRNAME=gnatcoverage @@ -106,11 +81,11 @@ endif # users get the core only by default in case they don't need the # adapters for their host, e.g. when building for gnatemu targets. -# For example, a user who needs to build gnatcov on linux to perform -# ppc-elf coverage only doesn't need the valgrind adapter for native -# coverage. He might moreover be on a system where the adapter build -# would fail (e.g. missing header files), so we really shouldn't try -# to build these adapters by default. +# For example, a user who needs to build gnatcov on linux to perform ppc-elf +# coverage only doesn't need the trace32 adapter for the corresponding probe. +# He might moreover be on a system where the adapter build would fail (e.g. +# missing probe-specific files), so we really shouldn't try to build these +# adapters by default. # So ... # @@ -130,87 +105,90 @@ include architecture.mk ifeq ($(HOST_OS), windows) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = nexus dynamorio trace32 +DEFAULT_ADAPTERS = trace32 llvm_json else -DEFAULT_ADAPTERS = dynamorio +DEFAULT_ADAPTERS = endif endif ifeq ($(HOST_OS), linux) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = valgrind trace32 +DEFAULT_ADAPTERS = else -DEFAULT_ADAPTERS = valgrind +DEFAULT_ADAPTERS = trace32 llvm_json endif endif -ADAPTERS_LIST=$(DEFAULT_ADAPTERS) +ADAPTERS_LIST ?= $(DEFAULT_ADAPTERS) -PARALLEL_BUILD=0 +PROCESSORS=0 BUILD_MODE=dev # ================================================================ # == Variables to pass down to sub-makefiles for trace adapters == # ================================================================ -# For valgrind, we need a prefix indication at build time to find header -# files, and at install time to place the "tool" within the valgrind install -# tree. - -VALGRIND_PREFIX?=$(shell dirname `which valgrind`)/.. - -valgrind_ADAPTER_BUILD_VARS=\ - VALGRIND_PREFIX?=$(VALGRIND_PREFIX) - -valgrind_ADAPTER_INSTALL_VARS=\ - VALGRIND_TOOL_INSTALL_DIR?=$(VALGRIND_PREFIX)/libexec/valgrind - -# For dynamorio, we need a prefix indication at build time to find header -# files and cmake artifacts, and can always install within the gnatcov install -# tree. - -DYNRIO_PREFIX?=$(shell dirname `which drrun`)/.. - -dynamorio_ADAPTER_BUILD_VARS=\ - DYNRIO_PREFIX?=$(DYNRIO_PREFIX) - -dynamorio_ADAPTER_INSTALL_VARS=\ - DYNRIO_CLIENT_INSTALL_DIR?=$(PREFIX)/libexec/gnatcoverage/lib$(BITS_ARCH) - -# Trace32 and Nexus (iSystem) adapters use the same prefix as GNATcov +# The trace adapters use the same prefix as GNATcov trace32_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) -nexus_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) +llvm_json_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) .PHONY: default all adapters bin $(PGMPATH) default: bin all: bin adapters -bin: -# Unlike BINUTILS_BUILD_DIR for which we have a default fallback, -# BINUTILS_SRC_DIR must be defined explicitely. - @if [ -z "$(BINUTILS_SRC_DIR)" ]; then \ - echo "Please define the BINUTILS_SRC_DIR and" \ - " BINUTILS_BUILD_DIR variables to point to the binutils" \ - " source and build directories."; \ - exit 1; \ - fi +# Here we build gnatcov32, gnatcov64 and the "gnatcov" driver that spawns +# one or the other of the first two depending on the operation to perform +# and the kind of binary item at hand, if any. Source instrumentation is +# unconditionally directed to gnatcov64, so this is the only program where +# "instrument" support is needed. + +BIN_COMMON_BUILD_ARGS=\ + -Pgnatcov.gpr -p -j$(PROCESSORS) \ + -XBUILD_MODE=$(BUILD_MODE) \ + -XC_SUPPORT=$(C_SUPPORT) \ + $(EXTRA_ADAFLAGS) \ + -largs $(LD_FLAGS) \ + -cargs:c++ $(CXXFLAGS) \ + -gargs +INSTR_COMMON_ARGS=\ + -j$(PROCESSORS) \ + -P gnatcov.gpr \ + --c++-opts=$(CXXFLAGS) +INSTR_BIN_BUILD_ARGS=\ + $(BIN_COMMON_BUILD_ARGS) \ + --src-subdirs=gnatcov-instr \ + --implicit-with=gnatcov_rts -# Use "set -e" not to start the second build if the first one failed. Also -# start with the 64-bit one so that errors in the "gnatcov" main closure show -# up as soon as possible. - set -e && for bits in 64 32; \ - do \ - $(GPRBUILD) -Pgnatcov -p -j$(PARALLEL_BUILD) \ - -XARCH=$$bits \ - -XBUILD_MODE=$(BUILD_MODE) \ - -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ - -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ - -XC_SUPPORT=$(C_SUPPORT) \ - $(EXTRA_ADAFLAGS) \ - -largs $(LD_FLAGS) \ - -cargs:c++ $(CXXFLAGS); \ - done +bin: +ifdef INSTRUMENTED + # We need to instrument and build at the same time: the driver and + # gnatcov32 builds share the same object directory, meaning that + # gnatcov will remove files resulting from the instrumentation of + # gnatcov32 when instrumenting the driver. This will be a problem: in + # the former case, gnatcov_bits_specific.adb is instrumented as a main + # but not in the latter case (gnatcov.adb is). This means that if we + # use the version that was not instrumented as a main to compile + # gnatcov32, running gnatcov32 will not dump execution traces. + + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=gnatcov64 + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=gnatcov64 + + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=gnatcov32 + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=gnatcov32 + + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=driver + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=driver + + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=compiler + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=compiler +else + # Start with the 64-bit gnatcov, which has the largest closure + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler +endif ADAPTER_TARGETS=$(foreach a, $(ADAPTERS_LIST), adapter-$(a)) .PHONY: $(ADAPTERS_TARGETS) @@ -230,7 +208,7 @@ adapters: $(ADAPTER_TARGETS) ####################### ppc_genopc: - $(GPRBUILD) -j$(PARALLEL_BUILD) -Pgnatcov $(EXTRA_ADAFLAGS) $@ + $(GPRBUILD) -j$(PROCESSORS) -Pgnatcov $(EXTRA_ADAFLAGS) $@ ppc_disopc.ads: ppc_genopc ppc_disopc.tmpl ./ppc_genopc > $@ @@ -269,6 +247,7 @@ install-bin: $(CP) \ $(PGM32PATH)$(exeext) \ $(PGM64PATH)$(exeext) \ + $(COMPILERPATH)$(exeext) \ $(PREFIX)/libexec/gnatcoverage install-examples: @@ -278,8 +257,15 @@ install-examples: install-gnatcov_rts: $(RM) -r $(PREFIX)/share/$(DIRNAME)/gnatcov_rts $(MKDIR) $(PREFIX)/share/$(DIRNAME)/gnatcov_rts + $(RM) -r $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts + $(MKDIR) $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts $(CP) -r rts/*.gpr rts/*.ads rts/*.adb rts/*.c rts/*.h \ $(PREFIX)/share/$(DIRNAME)/gnatcov_rts + $(CP) -r ada-rts/*.gpr ada-rts/*.ads ada-rts/*.adb \ + $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts + # Copy gnatcov_rts.ads from the regular runtime to the Ada only one to make + # sure we keep the runtime versions in sync + $(CP) rts/gnatcov_rts.ads $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts # Create library/object directories for gnatcov_rts in the installed tree. # This is necessary for out-of-tree builds of gnatcov_rts to work, as # gnatcov_rts may be read-only after final installation, and gprbuild @@ -290,10 +276,12 @@ install-gnatcov_rts: mkdir $(PREFIX)/share/$(DIRNAME)/gnatcov_rts/$$d-$$lt; \ done; \ done + $(MKDIR) $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts/obj-gnatcov_rts install-lib: $(MKDIR) $(PREFIX)/lib/gnatcoverage $(CP) gnatcov-xml-report.xsd $(PREFIX)/lib/gnatcoverage + $(CP) cobertura.dtd $(PREFIX)/lib/gnatcoverage install-common: install-bin install-examples install-gnatcov_rts install-lib install-without-doc: install-common @@ -376,6 +364,31 @@ gnat_util.gpr: @echo " for source_dirs use (\"$(GU_SUBDIR)\");" >> $@ @echo "end gnat_util;" >> $@ +# GNATsas + +# This is equivalent to the default run performed during CI +GNATSAS_ARGS=-XBUILD_MODE=$(BUILD_MODE) -XPART=gnatcov64 +GNATSAS_OBJ_DIR=obj64/$(BUILD_MODE) +gnatsas: + rm -f $(OBJ_DIR)/results + gnatsas analyze -P gnatcov.gpr $(GNATSAS_ARGS) + gnatsas report text -P gnatcov.gpr $(GNATSAS_ARGS) + if gnatsas report exit-code -P gnatcov.gpr $(GNATSAS_ARGS); then \ + echo "gnatsas:PASSED" >> $(GNATSAS_OBJ_DIR)/results ; \ + else \ + echo "gnatsas:FAILED:unexpected messages" >> $(GNATSAS_OBJ_DIR)/results ; \ + gnatsas report -P gnatcov.gpr -o $(GNATSAS_OBJ_DIR)/gnatsas.out \ + $(GNATSAS_ARGS) ; \ + fi + # GNAT SAS report root should be the repository root so file URIs are + # correctly resolved in GitLab. This is executed from tools/gnatcov in the + # CI. + gnatsas report code-climate -P gnatcov.gpr --root ../.. \ + -o $(GNATSAS_OBJ_DIR)/gnatsas/gnatsas.json $(GNATSAS_ARGS) ; + +bump_baseline: + gnatsas baseline --bump-baseline -P gnatcov.gpr $(GNATSAS_ARGS) + .PHONY: force force: diff --git a/tools/gnatcov/README.md b/tools/gnatcov/README.md index 18a5fd896..38b7be9d3 100644 --- a/tools/gnatcov/README.md +++ b/tools/gnatcov/README.md @@ -32,7 +32,7 @@ exercise it by just switching to share/examples/gnatcoverage/starter and typing: ```shell -engines $ make [TARGET=powerpc-elf] [RTS=zfp-mpc8641] +engines $ make [TARGET=powerpc-elf] [RTS=light-mpc8641] ``` The local Makefile includes a generic Makefile common to all the examples, and @@ -59,24 +59,29 @@ environment variable designating the GNAT installation root. gnatcoll-core $ make install ``` -2. Build libopcodes, libbfd and libiberty libraries from Binutils, which - gnatcov needs to support object code disassembling on all platforms. +2. Build static libraries provided by Binutils, which gnatcov needs to support + object code disassembling on all platforms. - Best is to use a Binutils release for this, such as 2.35 which + Binutils libraries are statically linked into gnatcov, so binutils can be + installed in a temporary directory (`$prefix_binutils` in the commands below) + just for gnatcov’s build. + + Best is to use a Binutils release for this, such as 2.42 which is known to work. ```shell - binutils-2.35 $ ./configure --enable-targets=all \ + binutils-2.42 $ ./configure --enable-targets=all \ + --prefix=$prefix_binutils \ + --enable-install-libiberty \ --disable-werror --disable-gdb \ --disable-sim --disable-ld --disable-libquadmath \ --disable-readline - binutils-2.35 $ make + binutils-2.42 $ make + binutils-2.42 $ make install + binutils-2.42 $ export LIBRARY_PATH=$prefix_binutils/lib64:$prefix_binutils/lib:$LIBRARY_PATH + binutils-2.42 $ export C_INCLUDE_PATH=$prefix_binutils/include:$C_INCLUDE_PATH ``` - These libraries are statically linked, so installation is not required: the - gnatcov build process only needs access to the source+build directory (no - need to run `make install`). - 3. Build or install Libadalang: please refer to [Libadalang's instructions](https://github.com/adacore/libadalang#quick-guide-to-use-libadalang). Note that when building GNATcoverage's `master` branch, you should use @@ -95,6 +100,6 @@ environment variable designating the GNAT installation root. ```shell gnatcoverage/tools/gnatcov $ - make BINUTILS_SRC_DIR= C_SUPPORT=False bin + make C_SUPPORT=False bin make PREFIX=$prefix install-bin install-examples ``` diff --git a/tools/gnatcov/ada-rts/gcvrt.ads b/tools/gnatcov/ada-rts/gcvrt.ads new file mode 100644 index 000000000..7233b13a7 --- /dev/null +++ b/tools/gnatcov/ada-rts/gcvrt.ads @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023-2024, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with this software; see file -- +-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- +-- of the license. -- +------------------------------------------------------------------------------ + +-- Namespace for units generated for instrumentation purposes +-- +-- This unit needs to be compilable with Ada 95 compilers + +package GCVRT is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); + +end GCVRT; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb new file mode 100644 index 000000000..b1df4896f --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb @@ -0,0 +1,115 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2024, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with System; use System; + +package body GNATcov_RTS.Buffers.Lists is + + procedure Reset_Buffer + (Buffer_Address : System.Address; Last_Bit_Id : Any_Bit_Id); + -- Reset a coverage buffer + + procedure Reset_Buffers (C_Buffers : Coverage_Buffers_Access); + -- Reset statement, decision, and mcdc coverage buffers + + procedure Reset_Buffers_Group + (C_Buffers_Group : Coverage_Buffers_Group_Access); + -- Reset a buffers group, which consists of all the buffers for a unit, + -- i.e. for its specification, its body, and its separates. + + ------------------ + -- Reset_Buffer -- + ------------------ + + procedure Reset_Buffer + (Buffer_Address : System.Address; Last_Bit_Id : Any_Bit_Id) + is + Buffer : Coverage_Buffer_Type (1 .. Last_Bit_Id); + for Buffer'Address use Buffer_Address; + begin + for I in Buffer'Range loop + Buffer (I) := False; + end loop; + end Reset_Buffer; + + ------------------- + -- Reset_Buffers -- + ------------------- + + procedure Reset_Buffers (C_Buffers : Coverage_Buffers_Access) is + begin + if C_Buffers = null then + return; + end if; + if C_Buffers.Statement /= System.Null_Address then + Reset_Buffer (C_Buffers.Statement, C_Buffers.Statement_Last_Bit); + end if; + if C_Buffers.Decision /= System.Null_Address then + Reset_Buffer (C_Buffers.Decision, C_Buffers.Decision_Last_Bit); + end if; + if C_Buffers.MCDC /= System.Null_Address then + Reset_Buffer (C_Buffers.Statement, C_Buffers.MCDC_Last_Bit); + end if; + end Reset_Buffers; + + ------------------------- + -- Reset_Buffers_Group -- + ------------------------- + + procedure Reset_Buffers_Group + (C_Buffers_Group : Coverage_Buffers_Group_Access) is + begin + if C_Buffers_Group = null then + return; + end if; + declare + Buffers_Group : + Coverage_Buffers_Group (1 .. Integer (C_Buffers_Group.Length)); + pragma Import (C, Buffers_Group); + for Buffers_Group'Address use C_Buffers_Group.Buffers; + begin + for I in Buffers_Group'Range loop + Reset_Buffers (Buffers_Group (I)); + end loop; + end; + end Reset_Buffers_Group; + + ------------------------------- + -- Reset_Group_Array_Buffers -- + ------------------------------- + + procedure Reset_Group_Array_Buffers + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array) + is + Buffers_Groups : + Coverage_Buffers_Group_Array (1 .. Integer (Arr.Length)); + pragma Import (C, Buffers_Groups); + for Buffers_Groups'Address use Arr.Groups; + begin + for I in Buffers_Groups'Range loop + Reset_Buffers_Group (Buffers_Groups (I)); + end loop; + end Reset_Group_Array_Buffers; + +end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads new file mode 100644 index 000000000..ce01651ca --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Parent package to host lists of buffers for units of interest + +-- This unit needs to be compilable with Ada 95 compilers + +package GNATcov_RTS.Buffers.Lists is + + pragma Preelaborate; + + type Coverage_Buffers_Access is + access constant GNATcov_RTS_Coverage_Buffers; + pragma Convention (C, Coverage_Buffers_Access); + + type Coverage_Buffers_Group is + array (Positive range <>) of Coverage_Buffers_Access; + pragma Convention (C, Coverage_Buffers_Group); + + type GNATcov_RTS_Coverage_Buffers_Group is record + Length : aliased unsigned; + Buffers : System.Address; + -- Address of a Coverage_Buffers_Group array of Length items + end record; + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group); + + type Coverage_Buffers_Group_Access is + access constant GNATcov_RTS_Coverage_Buffers_Group; + + type Coverage_Buffers_Group_Array is + array (Positive range <>) of Coverage_Buffers_Group_Access; + pragma Convention (C, Coverage_Buffers_Group_Array); + + type GNATcov_RTS_Coverage_Buffers_Group_Array is record + Length : aliased unsigned; + Groups : System.Address; + -- Address of a Coverage_Buffers_Group_Array array of Length items + end record; + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group_Array); + + procedure Reset_Group_Array_Buffers + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array); + -- Set the components of all the buffers in each group to zero, effectively + -- resetting the coverage state of all obligations to "not covered". + +end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb new file mode 100644 index 000000000..c6e607d4e --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb @@ -0,0 +1,107 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package body GNATcov_RTS.Buffers is + + ------------- + -- Witness -- + ------------- + + procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id) is + Buffer : Coverage_Buffer_Type (0 .. Bit); + for Buffer'Address use Buffer_Address; + pragma Import (Ada, Buffer); + begin + Buffer (Bit) := True; + end Witness; + + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Witness_Dummy_Type + is + begin + Witness (Buffer_Address, Bit); + return (Data => False); + end Witness; + + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean is + begin + Witness (Buffer_Address, Bit); + return False; + end Witness; + + function Witness + (Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + Value : Boolean) return Boolean is + begin + if Value then + Witness (Buffer_Address, True_Bit); + else + Witness (Buffer_Address, False_Bit); + end if; + return Value; + end Witness; + + function Witness + (Decision_Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + MCDC_Buffer_Address : System.Address; + MCDC_Base : Bit_Id; + MCDC_Path_Address : System.Address; + Value : Boolean) return Boolean + is + MCDC_Path_Index : Any_Bit_Id; + for MCDC_Path_Index'Address use MCDC_Path_Address; + pragma Import (Ada, MCDC_Path_Index); + + begin + Witness (MCDC_Buffer_Address, MCDC_Base + MCDC_Path_Index); + return Witness (Decision_Buffer_Address, False_Bit, True_Bit, Value); + end Witness; + + function Witness + (Buffer_Address : System.Address; + Offset_For_True : Any_Bit_Id; + First : Boolean; + Value : Boolean) return Boolean + is + MCDC_Path_Index : Any_Bit_Id; + for MCDC_Path_Index'Address use Buffer_Address; + pragma Import (Ada, MCDC_Path_Index); + begin + if First then + MCDC_Path_Index := 0; + end if; + + if Value then + MCDC_Path_Index := MCDC_Path_Index + Offset_For_True; + end if; + + return Value; + end Witness; + +end GNATcov_RTS.Buffers; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads new file mode 100644 index 000000000..4801a6c61 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads @@ -0,0 +1,216 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This package provides types and subprograms to maintain data about the +-- satisfaction of coverage obligations. + +-- This unit needs to be compilable with Ada 95 compilers + +with Interfaces; +with System; + +with GNATcov_RTS.Types; use GNATcov_RTS.Types; +with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; + +package GNATcov_RTS.Buffers is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code; + pragma Warnings (On); + + -- Any_Bit_Id is declared volatile here, as in order to instrument declare + -- expressions we need to declare a constant MC_DC_State (a subtype of + -- Any_Bit_Id) object, but prevent the compiler from optimizing out the + -- variable. + + type Any_Bit_Id is new int; + pragma Volatile (Any_Bit_Id); + + No_Bit_Id : constant Any_Bit_Id := -1; + + subtype Bit_Id is Any_Bit_Id range 0 .. Any_Bit_Id'Last; + -- Unique identifier for a boolean in a coverage buffer + + type Coverage_Buffer_Type is array (Bit_Id range <>) of Boolean; + -- Even though it is tempting to pack this array to save memory, we must + -- avoid bit packing to allow concurrent writes to coverage buffers. + + Fingerprint_Size : constant := 20; + + type GNATcov_RTS_Bool is new unsigned; + + type Any_Unit_Part is + (Not_Applicable_Part, Unit_Body, Unit_Spec, Unit_Separate); + pragma Convention (C, Any_Unit_Part); + + type Any_Language_Kind is (Unit_Based_Language, File_Based_Language); + pragma Convention (C, Any_Language_Kind); + + type Fingerprint_Type is array (1 .. 20) of Unsigned_8; + for Fingerprint_Type'Component_Size use 8; + for Fingerprint_Type'Size use 20 * 8; + pragma Universal_Aliasing (Fingerprint_Type); + + type GNATcov_RTS_Coverage_Buffers is record + Fingerprint : Fingerprint_Type; + -- Hash of SCO info for this unit, as gnatcov computes it (see + -- SC_Obligations). Used a fast way to check that coverage obligations + -- and coverage data are consistent. Specific hash values are computed + -- during instrumentation. + + Language : Any_Language_Kind; + -- Language kind for this unit + + Unit_Part : Any_Unit_Part; + Unit_Name : GNATcov_RTS_String; + -- Unit kind and name for the instrumented unit. The Unit_Name field + -- accounts both for unit-based languages (such as Ada) and file-based + -- languages such as C. + -- + -- The Unit_Part field is only there for unit-based languages and is set + -- to Not_Applicable_Part for file-based languages. + -- + -- More specifically, for unit-based languages, Unit_Name is the fully + -- qualified name of the compilation unit (or subunit) in lower case. + -- For instance: "foo", "ada.text_io" or "foo.bar.my_subunit". + -- + -- For file-based languages, Unit_Name is the simple filename, e.g. + -- "foo.c". + + Bit_Maps_Fingerprint : Fingerprint_Type; + -- Hash of buffer bit mappings for this unit, as gnatcov computes it + -- (see SC_Obligations). Used as a fast way to check that gnatcov will + -- be able to interpret buffer bits from a source traces using buffer + -- bit mappings from SID files. + + Annotations_Fingerprint : Fingerprint_Type; + -- Hash of annotations for this unit, as gnatcov computes it (see + -- SC_Obligations). Used as a fast way to check that source traces and + -- coverage data are consistent. + + Statement, Decision, MCDC : System.Address; + -- Addresses of coverage buffers for statement obligations, decision + -- obligations and MC/DC obligations. The address refer to + -- Coverage_Buffer_Type arrays whose bounds go from + -- 0 to Unit_Coverage_Buffers.*_Last_Bit. + + Statement_Last_Bit, Decision_Last_Bit, MCDC_Last_Bit : Any_Bit_Id; + -- Index for the last bits in coverage buffers for statements, decisions + -- and MC/DC. + end record; + + ------------------------- + -- Witness subprograms -- + ------------------------- + + -- The following subprograms are called by generated code to record + -- the execution of constructs. + + -- Note that the Buffer_Address parameters below are required so that: + -- + -- * functions don't have IN OUT formals, which are illegal before Ada + -- 2012; + -- + -- * our hack for pure units to be able to reference coverage buffers + -- (which are global state, i.e. unreachable from pure units) works. + + -- Statements and declarations + + -- The following Witness subprograms set the Boolean corresponding to Bit + -- to True in Buffer in various context. + + procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id); + -- This variant is used as part of sequence of statements, to witness + -- that we have reached a specific point in the sequence. + + type Witness_Dummy_Type is record + Data : Boolean; + end record; + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Witness_Dummy_Type; + -- This variant is used in contexts where statements are not allowed + -- but declarations are, for example ahead of library level declarations + -- to witness their elaboration. + + -- Use a dummy type of minimal but non-zero size to prevent the compiler + -- from optimizing calls away, as this unit is Pure. Use a composite type + -- to prevent ambiguities in contexts where the Boolean variant below + -- might be used, for example in constructs like + -- + -- case Witness (Buffer, Bit) is + -- when others => ... + -- end case; + -- + -- used for some kinds of expression functions. + + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean; + -- This variant is used in Boolean expression contexts and always returns + -- True. + + -- Decisions + + subtype MCDC_State_Type is Any_Bit_Id; + + -- When instrumenting expression functions, we need to conjure up storage + -- for MC/DC state as limited aggregates. The following type provides for + -- this use case. + + type MCDC_State_Holder is limited record + State : aliased MCDC_State_Type; + end record; + + function Witness + (Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + Value : Boolean) return Boolean; + -- If Value is False, set the Boolean corresponding to False_Bit to True in + -- Buffer. Set the one corresponding to True_Bit otherwise. + + function Witness + (Decision_Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + MCDC_Buffer_Address : System.Address; + MCDC_Base : Bit_Id; + MCDC_Path_Address : System.Address; + Value : Boolean) return Boolean; + -- Same as above, and also set the bit determined by MCDC_Base and the + -- Bit_Id value at MCDC_Path_Address in the buffer at MCDC_Buffer_Address. + -- Note that MCDC_Path may not be passed by value, because it is not known + -- until the side effects of the actual for the Value formal have been + -- evaluated. + + -- Conditions + + function Witness + (Buffer_Address : System.Address; + Offset_For_True : Any_Bit_Id; + First : Boolean; + Value : Boolean) return Boolean; + -- Buffer_Address is the address of an MCDC_State_Type local variable. + -- If First is True, first reset it to 0. + -- If Value is True, add Offset_For_True. + +end GNATcov_RTS.Buffers; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-strings.ads b/tools/gnatcov/ada-rts/gnatcov_rts-strings.ads new file mode 100644 index 000000000..3a7c102be --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-strings.ads @@ -0,0 +1,44 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021-2024, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Ada bindings for gnatcov_rts_c-strings.h +-- +-- This unit needs to be compilable with Ada 95 compilers + +with GNATcov_RTS.Types; use GNATcov_RTS.Types; + +package GNATcov_RTS.Strings is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); + + type GNATcov_RTS_String is record + Str : System.Address; + Length : size_t; + end record; + pragma Convention (C_Pass_By_Copy, GNATcov_RTS_String); + +end GNATcov_RTS.Strings; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb new file mode 100644 index 000000000..deab9df34 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb @@ -0,0 +1,175 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with GNATcov_RTS.Traces.Output.Text_IO; + +package body GNATcov_RTS.Traces.Output.Base64 is + + package TIO renames Output.Text_IO; -- Just a shorthand + + -- Base64-over-stdout stream + + type Uint6 is mod 2**6; + Base64_Alphabet : constant array (Uint6) of Character := + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + & "abcdefghijklmnopqrstuvwxyz" + & "0123456789" + & "+/"; + Base64_Padding : constant Character := '='; + + type Base64_Buffer_Index is range 1 .. 4; + subtype Valid_Base64_Buffer_Index is Base64_Buffer_Index range 1 .. 3; + type Base64_Buffer_Array is array (Valid_Base64_Buffer_Index) of Unsigned_8; + + type Base64_Buffer is record + Bytes : Base64_Buffer_Array := (others => 0); + -- We output base64 content by groups of 4 digits, which encode for 3 + -- input bytes. This buffer is used to accumulate input bytes. + + Next : Base64_Buffer_Index := 1; + -- Index of the next cell in Bytes where to store an input byte. This + -- means that a given time, only the Bytes (1 .. Next - 1) slice contain + -- input bytes. + + Columns : Natural := 0; + -- Number of output digits on the current line. We keep track of this to + -- break lines at 80 digits. + end record; + + procedure Write_Bytes (Output : in out Base64_Buffer; Bytes : Uint8_Array); + -- Callback for Generic_Write_Trace_File + + procedure Flush (Output : in out Base64_Buffer); + -- Flush the remaining bytes in Output to the standard output. If the + -- buffer is not full, this means it's the end of the content: pad with + -- '=' bytes as needed. + + ----------------- + -- Write_Bytes -- + ----------------- + + procedure Write_Bytes (Output : in out Base64_Buffer; Bytes : Uint8_Array) + is + begin + for I in Bytes'Range loop + Output.Bytes (Output.Next) := Bytes (I); + Output.Next := Output.Next + 1; + if Output.Next = Base64_Buffer_Index'Last then + Flush (Output); + end if; + end loop; + end Write_Bytes; + + ----------- + -- Flush -- + ----------- + + procedure Flush (Output : in out Base64_Buffer) is + + function "+" (Bits : Uint6) return Character; + -- Shortcut to get the ASCII representation of the given 6 bits + + --------- + -- "+" -- + --------- + + function "+" (Bits : Uint6) return Character is + begin + return Base64_Alphabet (Bits); + end "+"; + + -- Split input bytes (3 bytes = 24 bits) into 4 groups of 6 bits + + In_Bytes : Base64_Buffer_Array renames Output.Bytes; + Out_Digits : String (1 .. 4); + begin + case Output.Next is + when 1 => + return; + + when 2 => + Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); + Out_Digits (2) := +(Uint6 (In_Bytes (1) mod 4) * 16); + Out_Digits (3) := Base64_Padding; + Out_Digits (4) := Base64_Padding; + + when 3 => + Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); + Out_Digits (2) := + +(Uint6 (In_Bytes (1) mod 4) * 16 or Uint6 (In_Bytes (2) / 16)); + Out_Digits (3) := +(Uint6 (In_Bytes (2) mod 16) * 4); + Out_Digits (4) := Base64_Padding; + + when 4 => + Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); + Out_Digits (2) := + +(Uint6 (In_Bytes (1) mod 4) * 16 or Uint6 (In_Bytes (2) / 16)); + Out_Digits (3) := + +(Uint6 (In_Bytes (2) mod 16) * 4 or Uint6 (In_Bytes (3) / 64)); + Out_Digits (4) := +(Uint6 (In_Bytes (3) mod 64)); + end case; + + -- Output the 4 characters corresponding to each group of 6 bits. + -- Introduce a newline when needed in order to avoid exceeding 80 + -- characters per line. + + TIO.Put (Out_Digits); + Output.Columns := Output.Columns + 4; + if Output.Columns >= 80 then + Output.Columns := 0; + TIO.New_Line; + end if; + + Output.Bytes := (others => 0); + Output.Next := 1; + end Flush; + + ---------------------- + -- Write_Trace_File -- + ---------------------- + + procedure Write_Trace_File + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := "") + is + procedure Helper is new Generic_Write_Trace_File (Base64_Buffer); + Buffer : Base64_Buffer := + (Bytes => (others => 0), Next => 1, Columns => 0); + begin + TIO.New_Line; + TIO.Put_Line ("== GNATcoverage source trace file =="); + Helper (Buffer, Buffers_Groups, Program_Name, Exec_Date, User_Data); + Flush (Buffer); + if Buffer.Columns /= 0 then + TIO.New_Line; + end if; + TIO.Put_Line ("== End =="); + TIO.New_Line; + end Write_Trace_File; + +end GNATcov_RTS.Traces.Output.Base64; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads new file mode 100644 index 000000000..051048cd0 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package GNATcov_RTS.Traces.Output.Base64 is + + pragma Preelaborate; + + procedure Write_Trace_File + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := ""); + -- Write a Base64-encoded trace file to the standard output + -- (Ada.Text_IO.Standard_Output). + +end GNATcov_RTS.Traces.Output.Base64; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb new file mode 100644 index 000000000..df9288908 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb @@ -0,0 +1,63 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package body GNATcov_RTS.Traces.Output.Bytes_IO is + + ------------ + -- Close -- + ------------ + + procedure Close (File : in out File_Type) is + begin + OSLIB.Close (FD => File.FD); + end Close; + + ------------- + -- Create -- + ------------- + + procedure Create (File : in out File_Type; Name : String) is + begin + File.FD := OSLIB.Create_File (Name => Name, Fmode => OSLIB.Binary); + if File.FD = OSLIB.Invalid_FD then + raise IO_Error; + end if; + end Create; + + ------------ + -- Write -- + ------------ + + procedure Write (File : File_Type; Byte : U8) is + N : Integer; + begin + N := OSLIB.Write (FD => File.FD, A => Byte'Address, N => 1); + if N /= 1 then + raise IO_Error; + end if; + end Write; + +end GNATcov_RTS.Traces.Output.Bytes_IO; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads new file mode 100644 index 000000000..b31751672 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +-- This provides the base IO interface for use by the "bin-file" trace +-- dumper, restricted to configurations where we can assume that a full +-- GNAT RTS is available. +-- +-- The interface is devised as a simple subset of Ada.Direct_IO. It may +-- be used from "atexit" handlers though, so may only resort to low level +-- mechanisms as this triggers after the runtime has been finalized. + +-- The base IO interface exposed by GNAT.OS_Lib, going through elementary +-- int file descriptors, is well suited for our purpose. + +with Interfaces; +with GNAT.OS_Lib; + +private package GNATcov_RTS.Traces.Output.Bytes_IO is + + pragma Preelaborate; + + package OSLIB renames GNAT.OS_Lib; + use type OSLIB.File_Descriptor; + + -- Expose File_Type as a limited record type with implicit + -- initializers so clients can simply declare a F : File_Type; + -- object and call Create as with Direct_IO. + + type File_Type is limited record + FD : OSLIB.File_Descriptor := OSLIB.Invalid_FD; + end record; + + subtype U8 is Interfaces.Unsigned_8; + + IO_Error : exception; + -- Exception we raise in case of errors reported by the underlying + -- IO engine. + + procedure Close (File : in out File_Type); + + procedure Create (File : in out File_Type; Name : String); + -- Create or reset a file of the requested Name, ready for writing + -- in binary mode. Raise IO_Error if the operation somehow fails and + -- would yield an invalid File descriptor. + + procedure Write (File : File_Type; Byte : U8); + +end GNATcov_RTS.Traces.Output.Bytes_IO; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads new file mode 100644 index 000000000..e5f9bd6b2 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +-- This provides the base IO interface for use by the "base64-stdout" trace +-- dumper, available in all configurations. +-- +-- The interface is devised as a simple subset of Ada.Text_IO. It may +-- be used from "atexit" handlers though, so may only resort to low level +-- mechanisms as this triggers after the runtime has been finalized. + +-- GNAT.IO provides the low level services we need and is available from +-- most if not all the GNAT runtime profiles so is a good common ground for +-- our use. + +with GNAT.IO; + +private package GNATcov_RTS.Traces.Output.Text_IO is + + pragma Preelaborate; + + procedure New_Line (N : Positive := 1) renames GNAT.IO.New_Line; + procedure Put (S : String) renames GNAT.IO.Put; + procedure Put_Line (S : String) renames GNAT.IO.Put_Line; + +end GNATcov_RTS.Traces.Output.Text_IO; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb new file mode 100644 index 000000000..f74eccc13 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -0,0 +1,339 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with Ada.Unchecked_Conversion; + +with System; + +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; + +package body GNATcov_RTS.Traces.Output is + + ------------------------------ + -- Generic_Write_Trace_File -- + ------------------------------ + + procedure Generic_Write_Trace_File + (Output : in out Output_Stream; + Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := "") + is + + Alignment : constant Unsigned_8 := 8; + -- Alignment (in bytes) to use when writing trace files. It is used + -- to align record types / strings written in the trace. + + generic + type T is mod <>; + with + function Shift_Right (Value : T; Amount : Natural) return T is <>; + procedure Write_Unsigned (Output : in out Output_Stream; U : T); + -- Generic implementation for Write_U8, Write_U16 and Write_U32. + -- Write the bytes in little-endian order. + + procedure Write_Padding (Output : in out Output_Stream; Count : Natural); + -- Write X bytes of padding to Output so that Count + X is a multiple of + -- Alignment. + + procedure Write_Header (Output : in out Output_Stream); + -- Write a trace file header to Output + + procedure Write_Info + (Output : in out Output_Stream; + Kind : Supported_Info_Kind; + Data : String); + -- Write a trace info entry to Output + + procedure Write_Entry + (Output : in out Output_Stream; + Buffers : GNATcov_RTS_Coverage_Buffers); + -- Write a whole trace entry (header, unit name and buffers) for Buffers + -- to Output. + + procedure Write_Buffer + (Output : in out Output_Stream; Buffer : Coverage_Buffer_Type); + -- Write the Buffer coverage buffer to Output + + procedure Write_Buffer + (Output : in out Output_Stream; + Buffer_Address : System.Address; + Last_Bit : Any_Bit_Id); + -- Wrapper for Write_Buffer to use a buffer from its address and upper + -- bound. + + -------------------- + -- Write_Unsigned -- + -------------------- + + procedure Write_Unsigned (Output : in out Output_Stream; U : T) is + Bytes : Uint8_Array (1 .. T'Size / 8); + Value : T := U; + begin + for I in Bytes'Range loop + Bytes (I) := Unsigned_8 (Value and 16#FF#); + Value := Shift_Right (Value, 8); + end loop; + Write_Bytes (Output, Bytes); + end Write_Unsigned; + + procedure Write_U8 is new Write_Unsigned (T => Unsigned_8); + procedure Write_U16 is new Write_Unsigned (T => Unsigned_16); + procedure Write_U32 is new Write_Unsigned (T => Unsigned_32); + procedure Write_U64 is new Write_Unsigned (T => Unsigned_64); + + Padding_Constant : constant Uint8_Array (1 .. 16) := (others => 0); + -- Contant to avoid a local array declaration every time we need to do + -- padding, as it uses the secondary stack on the aamp platform. + + ------------------- + -- Write_Padding -- + ------------------- + + procedure Write_Padding (Output : in out Output_Stream; Count : Natural) + is + Alignment : constant Natural := + Natural (Generic_Write_Trace_File.Alignment); + Pad_Count : constant Natural := Alignment - Count mod Alignment; + begin + if Pad_Count /= Alignment then + declare + Bytes : Uint8_Array (1 .. Pad_Count); + for Bytes'Address use Padding_Constant'Address; + pragma Import (Ada, Bytes); + begin + Write_Bytes (Output, Bytes); + end; + end if; + end Write_Padding; + + ------------------ + -- Write_Header -- + ------------------ + + procedure Write_Header (Output : in out Output_Stream) is + Trace_File_Magic_Bytes : + constant Uint8_Array (1 .. Trace_File_Magic'Length); + for Trace_File_Magic_Bytes'Address use Trace_File_Magic'Address; + pragma Import (Ada, Trace_File_Magic_Bytes); + begin + Write_Bytes (Output, Trace_File_Magic_Bytes); + Write_U32 (Output, Unsigned_32 (Current_Version)); + Write_U8 (Output, Alignment); + + -- The Write_Unsigned subprogram (which is used to write bytes) + -- writes the bytes in the little endian order. + + Write_U8 (Output, Unsigned_8 (Little_Endian)); + Write_U16 (Output, 0); + end Write_Header; + + ---------------- + -- Write_Info -- + ---------------- + + procedure Write_Info + (Output : in out Output_Stream; + Kind : Supported_Info_Kind; + Data : String) + is + Data_Bytes : constant Uint8_Array (1 .. Data'Length); + for Data_Bytes'Address use Data'Address; + pragma Import (Ada, Data_Bytes); + begin + Write_U32 (Output, Unsigned_32 (Kind)); + Write_U32 (Output, Unsigned_32 (Data'Length)); + Write_Bytes (Output, Data_Bytes); + Write_Padding (Output, Data'Length); + end Write_Info; + + ----------------- + -- Write_Entry -- + ----------------- + + procedure Write_Entry + (Output : in out Output_Stream; Buffers : GNATcov_RTS_Coverage_Buffers) + is + Unit_Name_Bytes : + Uint8_Array (1 .. Integer (Buffers.Unit_Name.Length)); + for Unit_Name_Bytes'Address use Buffers.Unit_Name.Str; + pragma Import (Ada, Unit_Name_Bytes); + + subtype Bounded_Uint8_Array is Uint8_Array (1 .. 20); + function To_Uint8_Array is new + Ada.Unchecked_Conversion (Fingerprint_Type, Bounded_Uint8_Array); + begin + -- Write trace entry header + + Write_U32 (Output, Unsigned_32 (Buffers.Unit_Name.Length)); + Write_U32 (Output, Unsigned_32 (Buffers.Statement_Last_Bit + 1)); + Write_U32 (Output, Unsigned_32 (Buffers.Decision_Last_Bit + 1)); + Write_U32 (Output, Unsigned_32 (Buffers.MCDC_Last_Bit + 1)); + Write_U8 + (Output, Unsigned_8 (Any_Language_Kind_Map (Buffers.Language))); + Write_U8 + (Output, + Unsigned_8 + (GNATcov_RTS.Buffers.Any_Unit_Part'Pos (Buffers.Unit_Part))); + Write_U8 (Output, Unsigned_8 (LSB_First_Bytes)); + Write_Bytes (Output, To_Uint8_Array (Buffers.Fingerprint)); + Write_Bytes (Output, To_Uint8_Array (Buffers.Bit_Maps_Fingerprint)); + Write_Bytes + (Output, To_Uint8_Array (Buffers.Annotations_Fingerprint)); + Write_Bytes (Output, (1 .. 1 => 0)); + + -- Write the unit name + + Write_Bytes (Output, Unit_Name_Bytes); + Write_Padding (Output, Integer (Buffers.Unit_Name.Length)); + + -- Write coverage buffers + + Write_Buffer (Output, Buffers.Statement, Buffers.Statement_Last_Bit); + Write_Buffer (Output, Buffers.Decision, Buffers.Decision_Last_Bit); + Write_Buffer (Output, Buffers.MCDC, Buffers.MCDC_Last_Bit); + end Write_Entry; + + ------------------ + -- Write_Buffer -- + ------------------ + + procedure Write_Buffer + (Output : in out Output_Stream; Buffer : Coverage_Buffer_Type) + is + + procedure Append_Bit (Value : Boolean); + procedure Flush; + + Current_Byte : Interfaces.Unsigned_8 := 0; + Bit_Mask : Interfaces.Unsigned_8 := 1; + Bytes_Count : Natural := 0; + + ---------------- + -- Append_Bit -- + ---------------- + + procedure Append_Bit (Value : Boolean) is + begin + if Value then + Current_Byte := Current_Byte or Bit_Mask; + end if; + Bit_Mask := 2 * Bit_Mask; + if Bit_Mask = 2**8 then + Flush; + end if; + end Append_Bit; + + ----------- + -- Flush -- + ----------- + + procedure Flush is + begin + if Bit_Mask /= 1 then + Write_Bytes (Output, (1 => Current_Byte)); + Current_Byte := 0; + Bit_Mask := 1; + Bytes_Count := Bytes_Count + 1; + end if; + end Flush; + + -- Start of processing for Write_Buffer + + begin + -- Write bytes that are included in the coverage buffer + + for J in Buffer'Range loop + Append_Bit (Buffer (J)); + end loop; + Flush; + + -- Complete with the required padding + + Write_Padding (Output, Bytes_Count); + end Write_Buffer; + + ------------------ + -- Write_Buffer -- + ------------------ + + procedure Write_Buffer + (Output : in out Output_Stream; + Buffer_Address : System.Address; + Last_Bit : Any_Bit_Id) + is + Buffer : Coverage_Buffer_Type (0 .. Last_Bit); + for Buffer'Address use Buffer_Address; + pragma Import (Ada, Buffer); + + -- Buffer could be declared constant in theory, but would then be + -- wrongly flagged as an incorrectly placed deferred constant + -- declaration by some old toolchains (as observed with 5.04). + begin + Write_Buffer (Output, Buffer); + end Write_Buffer; + + -- Start of processing for Generic_Write_Trace_File + + begin + Write_Header (Output); + Write_Info (Output, Info_Program_Name, Program_Name); + + -- Write the exec date + + declare + Timestamp : Interfaces.Unsigned_64 := Exec_Date; + Bytes : Uint8_Array (1 .. 8); + Bytes_Str : String (1 .. 8); + for Bytes_Str'Address use Bytes'Address; + pragma Import (Ada, Bytes_Str); + begin + for I in 1 .. 8 loop + Bytes (I) := Interfaces.Unsigned_8 (Timestamp mod 8); + Timestamp := Shift_Right (Timestamp, 8); + end loop; + Write_Info (Output, Info_Exec_Date, Bytes_Str); + end; + + Write_Info (Output, Info_User_Data, User_Data); + Write_Info (Output, Info_End, ""); + for I in Buffers_Groups'Range loop + declare + Buffers : + Coverage_Buffers_Group + (1 .. Integer (Buffers_Groups (I).Length)); + for Buffers'Address use Buffers_Groups (I).Buffers; + pragma Import (C, Buffers); + begin + for J in Buffers'Range loop + Write_Entry (Output, Buffers (J).all); + end loop; + end; + end loop; + end Generic_Write_Trace_File; + +end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads new file mode 100644 index 000000000..06b161ec0 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads @@ -0,0 +1,58 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; + +package GNATcov_RTS.Traces.Output is + + pragma Preelaborate; + + subtype Serialized_Timestamp is String (1 .. 8); + -- Little-endian 64-bit unsigned integer. Represents a date/time as the + -- number of seconds that passed since the Unix Epoch. In other words, a + -- 64-bit Unix timestamp. + + generic + type Output_Stream (<>) is limited private; + -- Entity where the trace file is written + + with + procedure Write_Bytes + (Stream : in out Output_Stream; Bytes : Uint8_Array) is <>; + -- Write Bytes to the given Stream + + procedure Generic_Write_Trace_File + (Output : in out Output_Stream; + Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := ""); + -- Write a trace file to Output to contain the coverage data in Buffers. + -- + -- Program_Name, Exec_Date, and User_Data are used to fill the + -- corresponding metadata in the written trace file. + +end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces.adb new file mode 100644 index 000000000..2c3496a1f --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.adb @@ -0,0 +1,45 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with System; + +package body GNATcov_RTS.Traces is + + ---------------------- + -- Native_Endianity -- + ---------------------- + + function Native_Endianity return Supported_Endianity is + use type System.Bit_Order; + begin + if System.Default_Bit_Order = System.Low_Order_First then + return Little_Endian; + else + return Big_Endian; + end if; + end Native_Endianity; + +end GNATcov_RTS.Traces; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads new file mode 100644 index 000000000..3304f60c2 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads @@ -0,0 +1,251 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Trace file format for instrumented programs + +-- This unit needs to be compilable with Ada 95 compilers + +with Interfaces; use Interfaces; + +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; + +package GNATcov_RTS.Traces is + + pragma Preelaborate; + + type Uint8_Array is array (Positive range <>) of Interfaces.Unsigned_8; + pragma Pack (Uint8_Array); + + -- Execution of an instrumented program sets bits in its coverage buffers. + -- These bits convey information that GNATcov will later on use to + -- discharge coverage obligations. + -- + -- This unit describes a file format for an instrumented program to + -- communicate these coverage buffers to GNATcov. + + -- This format expects bytes/Characters to be 8-bit values. + + -- Each trace file starts with a header (see Trace_File_Header), followed + -- by a sequence of trace info entries (see Trace_Entry_Header) ending with + -- a Info_End entry, and then contains zero or several trace entries, + -- typically one per instrumented unit. Each trace entry is padded so that + -- trace entries start and end on byte/half word/word/long word boundaries. + + type Trace_File_Format_Version is new Unsigned_32; + Current_Version : Trace_File_Format_Version := 4; + -- Expected value of the Trace_File_Header.Format_Version field. + -- + -- 0 -- initial version + -- 1 -- extend trace entry model to account for C files + -- 2 -- introduce fingerprints for bit maps + -- 3 -- remove the project name from trace entries + -- 4 -- introduce fingerprints for annotations + + type Any_Alignment is new Unsigned_8; + subtype Supported_Alignment is Any_Alignment; + -- Number of bytes the trace file writer used to pad trace entries. The + -- size of the trace file is supposed to be a multiple of this value. + -- Supported alignments are: 1, 2, 4 and 8. + + type Any_Endianity is new Unsigned_8; + Little_Endian : constant Any_Endianity := 0; + Big_Endian : constant Any_Endianity := 1; + subtype Supported_Endianity is + Any_Endianity range Little_Endian .. Big_Endian; + -- Endianity to decode multi-byte scalars + + function Native_Endianity return Supported_Endianity; + -- Return the native endianity + + type Any_Unit_Part is new Unsigned_8; + Not_Applicable_Part : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Not_Applicable_Part); + Unit_Body : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Body); + Unit_Spec : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Spec); + Unit_Separate : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Separate); + subtype All_Unit_Part is + Any_Unit_Part range Not_Applicable_Part .. Unit_Separate; + subtype Supported_Unit_Part is + Any_Unit_Part range Unit_Body .. Unit_Separate; + -- Describe the kind of unit referenced by a trace entry + + Unit_Part_Map : constant array (Buffers.Any_Unit_Part) of All_Unit_Part := + (Buffers.Not_Applicable_Part => Not_Applicable_Part, + Buffers.Unit_Body => Unit_Body, + Buffers.Unit_Spec => Unit_Spec, + Buffers.Unit_Separate => Unit_Separate); + + type Any_Bit_Count is new Unsigned_32; + -- Number of bits contained in a coverage buffer + + type Any_Language_Kind is new Unsigned_8; + Unit_Based_Language : constant Any_Language_Kind := + Buffers.Any_Language_Kind'Pos (Buffers.Unit_Based_Language); + File_Based_Language : constant Any_Language_Kind := + Buffers.Any_Language_Kind'Pos (Buffers.File_Based_Language); + subtype Supported_Language_Kind is + Any_Language_Kind range Unit_Based_Language .. File_Based_Language; + -- Language kind for a compilation unit + + Any_Language_Kind_Map : + constant array (Buffers.Any_Language_Kind) of Supported_Language_Kind := + (Buffers.Unit_Based_Language => Unit_Based_Language, + Buffers.File_Based_Language => File_Based_Language); + + ----------------------- + -- Trace file header -- + ----------------------- + + Trace_File_Magic : constant String (1 .. 32) := + "GNATcov source trace file" & (26 .. 32 => ASCII.NUL); + -- Expected value of the Trace_File_Header.Magic field (32 bytes) + + type Trace_File_Header is record + Magic : Uint8_Array (1 .. 32); + + Format_Version : Trace_File_Format_Version; + Alignment : Any_Alignment; + Endianity : Any_Endianity; + + Padding : Unsigned_16; + -- Padding used only to make the size of the trace file header a + -- multiple of 8 bytes. Must be zero. + end record; + pragma Pack (Trace_File_Header); + + ----------------------- + -- Trace information -- + ----------------------- + + -- Each trace info entry starts with the following header. Then goes the + -- bytes for the entry content, NUL-padded according to the trace file + -- alignment. + + type Any_Info_Kind is new Unsigned_32; + + Info_End : constant Any_Info_Kind := 0; + -- Special trace info entry: indicates the end of a sequence of entries. No + -- data is associated to this trace info entry. + + Info_Program_Name : constant Any_Info_Kind := 1; + -- Name of the program that produced this trace + + Info_Exec_Date : constant Any_Info_Kind := 2; + -- Date for the program execution that produced this trace + + Info_User_Data : constant Any_Info_Kind := 3; + -- Arbitrary storage for user data. This is exposed to users as the trace + -- "tag". + + subtype Supported_Info_Kind is + Any_Info_Kind range Info_End .. Info_User_Data; + + type Trace_Info_Header is record + Kind : Any_Info_Kind; + -- Kind for this trace info entry + + Length : Unsigned_32; + -- Length of the data associated to this entry + end record; + pragma Pack (Trace_Info_Header); + + ------------------------ + -- Trace entry header -- + ------------------------ + + -- Each trace entry starts with the following header. Then goes: + -- + -- * The name of the unit describes. It is NUL-padded according to the + -- trace file alignment. + -- + -- * The statement coverage buffer. It is also NUL-padded. + -- + -- * The decision coverage buffer. It is also NUL-padded. + -- + -- * The MC/DC coverage buffer. It is also NUL-padded. + + type Any_Bit_Buffer_Encoding is new Unsigned_8; + -- Encoding used to store coverage buffers + + LSB_First_Bytes : constant Any_Bit_Buffer_Encoding := 0; + -- LSB_First_Bytes: bit buffers are encoded as sequences of bytes. + -- + -- * Booleans are encoded with bits the usual way: 0 for False and 1 for + -- True. + -- + -- * Byte X contains bits for bits 8 * Y to 8 * Y + 7. For instance, byte + -- 1 contains bits 8 to 15. + -- + -- * Inside byte X, least significant bit maps to bit 8 * Y while the most + -- significant bit maps to bit 8 * Y + 7. + + subtype Supported_Bit_Buffer_Encoding is + Any_Bit_Buffer_Encoding range LSB_First_Bytes .. LSB_First_Bytes; + + type Trace_Entry_Header is record + Unit_Name_Length : Unsigned_32; + -- Length of the unit name / filename for the unit this trace entry + -- describes. + + Statement_Bit_Count : Any_Bit_Count; + Decision_Bit_Count : Any_Bit_Count; + MCDC_Bit_Count : Any_Bit_Count; + -- Number of bits in the statement, decision and MC/DC coverage buffers + + Language_Kind : Any_Language_Kind; + -- Language for this unit + + Unit_Part : Any_Unit_Part; + -- Part of the unit this trace entry describes. Not_Applicable_Part for + -- file-based languages. + + Bit_Buffer_Encoding : Any_Bit_Buffer_Encoding; + -- Encoding used to represent statement and decision coverage buffers + + Fingerprint : Buffers.Fingerprint_Type; + -- Hash of SCO info for this unit. Useds a fast way to check that + -- coverage obligations and coverage data are consistent. Specific hash + -- values are computed during instrumentation. + + Bit_Maps_Fingerprint : Buffers.Fingerprint_Type; + -- Hash of buffer bit mappings for this unit, as gnatcov computes it + -- (see SC_Obligations). Used as a fast way to check that gnatcov will + -- be able to interpret buffer bits from a source traces using buffer + -- bit mappings from SID files. + + Annotations_Fingerprint : Fingerprint_Type; + -- Hash of annotations for this unit, as gnatcov computes it (see + -- SC_Obligations). Used as a fast way to check that source traces and + -- coverage data are consistent. + + Padding : Uint8_Array (1 .. 1); + -- Padding used only to make the size of this trace entry header a + -- multiple of 8 bytes. Must be zero. + end record; + pragma Pack (Trace_Entry_Header); + +end GNATcov_RTS.Traces; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-types.ads b/tools/gnatcov/ada-rts/gnatcov_rts-types.ads new file mode 100644 index 000000000..40767cd9a --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-types.ads @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021-2024, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Basic types to use in source trace buffers. We try to avoid using types +-- from Interfaces and Interfaces.C, and in general to minimize the set of +-- dependencies of GNATcov_RTS on the Ada runtime, so that we can compute code +-- coverage for these runtime units. +-- +-- This unit needs to be compilable with Ada 95 compilers + +with System; + +package GNATcov_RTS.Types is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); + + type Unsigned_8 is mod 2**8; + type Unsigned_64 is mod 2**64; + + -- We assume here that Integer (Ada) is a correct mapping for int (C) + + type int is new Integer; + type unsigned is mod 2**int'Size; + type size_t is mod System.Memory_Size; + +end GNATcov_RTS.Types; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts.gpr b/tools/gnatcov/ada-rts/gnatcov_rts.gpr new file mode 100644 index 000000000..5c919b3ef --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts.gpr @@ -0,0 +1,17 @@ +-- Ada Instrumentation runtime for gnatcov. It is an Ada-only version of +-- the instrumentation runtime, and is equivalent to the gnatcov_rts.gpr +-- under /share/gnatcoverage/gnatcov_rts. +-- +-- This project is meant to be built and installed before instrumenting +-- projects with "gnatcov instrument", and then to be used when building +-- instrumented programs thanks to gprbuild's --implicit-with option. + +project GNATcov_RTS is + for Source_Dirs use ("."); + for Object_Dir use "obj-gnatcov_rts"; + for Languages use ("Ada"); + + package Compiler is + for Default_Switches ("Ada") use ("-O2"); + end Compiler; +end GNATcov_RTS; diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb deleted file mode 100644 index 649787f5a..000000000 --- a/tools/gnatcov/ali_files.adb +++ /dev/null @@ -1,653 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2009-2022, AdaCore -- --- -- --- GNATcoverage is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This software is distributed in the hope that it will be useful -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- --- License for more details. You should have received a copy of the GNU -- --- General Public License distributed with this software; see file -- --- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- --- of the license. -- ------------------------------------------------------------------------------- - -with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Strings.Unbounded; -with Ada.Text_IO; use Ada.Text_IO; - -with GNAT.Regpat; use GNAT.Regpat; -with SCOs; - -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Get_SCOs; -with Inputs; use Inputs; -with Outputs; use Outputs; -with Switches; use Switches; - -package body ALI_Files is - - ----------------------------------------------- - -- Regular expressions for ALI files parsing -- - ----------------------------------------------- - - D_Regexp : constant String := "(([^""\t ]+)|(""([^""]|"""")+""))[\t ]"; - D_Matcher : constant Pattern_Matcher := Compile (D_Regexp); - - N_Regexp : constant String := - "A([0-9]*):([0-9]*)(:[^ ]*)? xcov ([^ ]*)( ""(.*)"")?"; - N_Matcher : constant Pattern_Matcher := Compile (N_Regexp); - - U_Regexp : constant String := "^[^\t ]*[\t ]+([^\t ]*)"; - U_Matcher : constant Pattern_Matcher := Compile (U_Regexp); - - V_Regexp : constant String := "^V ""(.*)""$"; - V_Matcher : constant Pattern_Matcher := Compile (V_Regexp); - - function Unquote (Filename : String) return String; - -- If needed, unquote a filename, such as the ones that can be found on D - -- lines. - - procedure Mark_Ignored_Units - (Ignored_Source_Files : access GNAT.Regexp.Regexp; - Deps : SFI_Vector); - -- Mark SCOs.SCO_Unit_Table entries to be ignored by setting their Dep_Num - -- to Missing_Dep_Num. - - ------------- - -- Unquote -- - ------------- - - function Unquote (Filename : String) return String is - use Ada.Strings.Unbounded; - - Result : Unbounded_String; - In_Quote : Boolean := False; - -- True when we just met a double quote inside a quoted filename. False - -- otherwise. - - begin - if Filename (Filename'First) /= '"' then - return Filename; - else - -- To unquote, just copy the string removing consecutive double - -- quotes. - - for C of Filename (Filename'First + 1 .. Filename'Last - 1) loop - if C = '"' then - if not In_Quote then - Append (Result, C); - end if; - In_Quote := not In_Quote; - else - Append (Result, C); - end if; - end loop; - return To_String (Result); - end if; - end Unquote; - - ------------------------ - -- Mark_Ignored_Units -- - ------------------------ - - procedure Mark_Ignored_Units - (Ignored_Source_Files : access GNAT.Regexp.Regexp; - Deps : SFI_Vector) - is - use SCOs; - Deps_Present : constant Boolean := not Deps.Is_Empty; - begin - if Ignored_Source_Files = null then - return; - end if; - - for J in SCO_Unit_Table.First + 1 .. SCO_Unit_Table.Last loop - declare - U : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J); - Name : constant String := - (if Deps_Present - then Get_Simple_Name (Deps.Element (U.Dep_Num)) - else U.File_Name.all); - SFI : constant Source_File_Index := - Get_Index_From_Generic_Name (Name, Source_File); - begin - if GNAT.Regexp.Match (Name, Ignored_Source_Files.all) then - Consolidate_Ignore_Status (SFI, Always); - U.Dep_Num := Missing_Dep_Num; - else - Consolidate_Ignore_Status (SFI, Never); - end if; - end; - end loop; - end Mark_Ignored_Units; - - -------------- - -- Load_ALI -- - -------------- - - procedure Load_ALI (ALI_Filename : String) is - Discard_ALI : Source_File_Index; - Discard_Units, Discard_Deps : SFI_Vector; - - pragma Unreferenced (Discard_ALI); - pragma Warnings (Off, Discard_Units); - pragma Warnings (Off, Discard_Deps); - - begin - Discard_ALI := - Load_ALI (ALI_Filename => ALI_Filename, - Ignored_Source_Files => null, - Units => Discard_Units, - Deps => Discard_Deps, - ALI_Annotations => ALI_Annotations, - With_SCOs => False); - end Load_ALI; - - -------------- - -- Load_ALI -- - -------------- - - function Load_ALI - (ALI_Filename : String; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Units : out SFI_Vector; - Deps : out SFI_Vector; - ALI_Annotations : in out ALI_Annotation_Maps.Map; - With_SCOs : Boolean) return Source_File_Index - is - ALI_File : File_Type; - ALI_Index : Source_File_Index; - - Line : String_Access; - Index : Natural; - - Matches : Match_Array (0 .. 10); - -- For regex matching - - function Match (Index : Integer) return String; - -- Return Index'th match in Line - - function Get_Stripped_Line (F : File_Type) return String; - -- Like Get_Line but strip trailing CR, to allow for processing Windows - -- LI files on a UNIX host. - - function Getc return Character; - -- Consume and return next character from Line. - -- Load next line if at end of line. Return ^Z if at end of file. - - function Nextc return Character; - -- Peek at next character in Line. Return ^Z if at end of file. - - procedure Skipc; - -- Skip one character in Line - - function Check_Message (M1, M2 : String_Access) return Boolean; - -- Return True if either M1 or M2 is null or designates an empty string, - -- else return True if M1 and M2 designate identical strings. - - ------------------- - -- Check_Message -- - ------------------- - - function Check_Message (M1, M2 : String_Access) return Boolean is - begin - return False - or else M1 = null or else M1.all = "" - or else M2 = null or else M2.all = "" - or else M1.all = M2.all; - end Check_Message; - - ---------- - -- Getc -- - ---------- - - function Getc return Character is - Next_Char : constant Character := Nextc; - begin - Index := Index + 1; - if Index > Line'Last + 1 then - - -- Note: normally we should just read the next line from ALI_File - -- and reset Index. However some older versions of the compiler - -- generated duplicated SCOs in some cases, so if we get two - -- successive identical lines, we ignore them and keep reading. - - while not End_Of_File (ALI_File) loop - declare - Next_Line : constant String := Get_Stripped_Line (ALI_File); - begin - if Next_Line = Line.all then - Report - ("ignoring duplicate line in ALI file " - & ALI_Filename, Kind => Warning); - - else - Free (Line); - Line := new String'(Next_Line); - Index := 1; - - exit; - end if; - end; - end loop; - end if; - return Next_Char; - end Getc; - - ----------------------- - -- Get_Stripped_Line -- - ----------------------- - - function Get_Stripped_Line (F : File_Type) return String is - Line : constant String := Get_Line (F); - Last : Integer := Line'Last; - begin - if Last in Line'Range and then Line (Last) = ASCII.CR then - Last := Last - 1; - end if; - return Line (Line'First .. Last); - end Get_Stripped_Line; - - ----------- - -- Match -- - ----------- - - function Match (Index : Integer) return String is - begin - if Matches (Index) = No_Match then - return ""; - else - return Line (Matches (Index).First .. Matches (Index).Last); - end if; - end Match; - - ----------- - -- Nextc -- - ----------- - - function Nextc return Character is - begin - if Index = Line'Last + 1 then - return ASCII.LF; - - elsif Index in Line'Range then - return Line (Index); - - else - return Character'Val (16#1a#); - end if; - end Nextc; - - ----------- - -- Skipc -- - ----------- - - procedure Skipc is - C : Character; - pragma Unreferenced (C); - begin - C := Getc; - end Skipc; - - procedure Get_SCOs_From_ALI is new Get_SCOs; - - -- Local variables - - No_Object : Boolean := False; - -- Set True if the P line contains the NO flag - - Preserve_Control_Flow_Seen : Boolean := False; - -- Set True if unit has been compiled with -fpreserve-control-flow - - Dump_SCOs_Seen : Boolean := False; - -- Set True if unit has been compiled with -fdump-scos (or -gnateS) - - Debug_Seen : Boolean := False; - -- Set True if unit has been compiled with -g - - Profile_Arcs_Seen : Boolean := False; - -- Set True if unit has been compiled with -fprofile-arcs - - Expected_Annotation_Kind : ALI_Annotation_Kind; - Expected_Annotation_Msg : String_Access; - -- Variables for checking of annotation validity: annotations must - -- come in (Exempt_On, Exempt_Off) pairs, nesting forbidden, and - -- the Exempt_Off message must be either empty or identical to the - -- Exempt_On one. - - -- Start of processing for Load_ALI - - begin - pragma Assert (Deps.Last_Index = 0); - - -- First check whether this ALI has been already loaded. We identify - -- this by the fact that it already has an assigned Source_File_Index. - - ALI_Index := Get_Index_From_Full_Name - (ALI_Filename, Library_File, Insert => False); - if ALI_Index /= No_Source_File then - Report - ("ignoring duplicate ALI file " & ALI_Filename, Kind => Warning); - return No_Source_File; - end if; - - ALI_Index := Get_Index_From_Full_Name - (ALI_Filename, Library_File, Insert => True); - Log_File_Open (ALI_Filename); - Open (ALI_File, In_File, ALI_Filename); - - -- Check that the first line is a valid ALI V line. - - declare - use Ada.Strings.Unbounded; - - V_Line : constant String := Get_Stripped_Line (ALI_File); - - Error_Msg : Unbounded_String; - begin - Match (V_Matcher, V_Line, Matches); - if Matches (0) = No_Match then - Error_Msg := - To_Unbounded_String - ("malformed ALI file """ & ALI_Filename & """"); - - if V_Line'Length > 3 - and then - To_Lower (V_Line (V_Line'Last - 3 .. V_Line'Last)) = ".ali" - then - Append - (Error_Msg, - ASCII.LF - & "to load ALIs from list use ""--scos=@" - & ALI_Filename & """"); - end if; - Fatal_Error (To_String (Error_Msg)); - end if; - end; - - -- Here once the ALI file has been succesfully opened - - if Verbose then - Put_Line ("Loading SCOs from " & ALI_Filename); - end if; - - Expected_Annotation_Kind := Exempt_On; - Expected_Annotation_Msg := null; - - Scan_ALI : while not End_Of_File (ALI_File) loop - loop - Free (Line); - Line := new String'(Get_Stripped_Line (ALI_File)); - exit when Line'Length > 0; - end loop; - - case Line (1) is - when 'A' => - if Line.all = "A -fpreserve-control-flow" then - Preserve_Control_Flow_Seen := True; - - elsif Line.all = "A -fdump-scos" - or else - Line.all = "A -gnateS" - then - Dump_SCOs_Seen := True; - - elsif Line.all = "A -g" then - Debug_Seen := True; - - elsif Line.all = "A -fprofile-arcs" then - Profile_Arcs_Seen := True; - end if; - - when 'P' => - declare - P_Start : Integer; - begin - P_Start := 2; - loop - while P_Start <= Line'Last - and then Line (P_Start) = ' ' - loop - P_Start := P_Start + 1; - end loop; - exit when P_Start > Line'Last - 1; - - declare - Param : constant String (1 .. 2) := - Line (P_Start .. P_Start + 1); - begin - if Param = "NO" then - No_Object := True; - end if; - end; - - P_Start := P_Start + 2; - end loop; - end; - - when 'U' => - Match (U_Matcher, Line (3 .. Line'Last), Matches); - if Matches (0) /= No_Match then - Units.Append (Get_Index_From_Generic_Name (Match (1), - Source_File)); - end if; - - when 'D' => - Match (D_Matcher, Line (3 .. Line'Last), Matches); - if Matches (0) /= No_Match then - - -- Dependency files are source files. However, in order to - -- avoid unnecessary conflicts at consolidation time, we - -- don't want to consider them for coverage analysis unless - -- they are in the units of interest. So consider them as - -- stubs at this stage. - - Deps.Append (Get_Index_From_Generic_Name - (Unquote (Match (1)), Stub_File)); - end if; - - when 'N' => - declare - Annotation : ALI_Annotation; - Valid : Boolean; - Sloc : Source_Location; - begin - Match (N_Matcher, Line (3 .. Line'Last), Matches); - if Matches (0) /= No_Match then - declare - Note_SFN : constant String := Match (3); - Note_SFI : Source_File_Index := Units.Last_Element; - - begin - if Note_SFN'Length > 0 then - - -- Case of a separate: the source file is not the - -- current compilation unit but some other one - -- identified explicitly. - - Note_SFI := Get_Index_From_Generic_Name - (Note_SFN (Note_SFN'First + 1 - .. Note_SFN'Last), - Source_File); - end if; - - Sloc := - (Source_File => Note_SFI, - L => (Line => - Integer'Value (Match (1)), - Column => - Integer'Value (Match (2)))); - end; - - Valid := True; - - declare - Msg : constant String := Match (6); - begin - Annotation := - (CU => No_CU_Id, - Kind => ALI_Annotation_Kind'Value (Match (4)), - Message => (if Msg'Length > 0 - then new String'(Msg) - else null), - others => <>); - exception - when Constraint_Error => - Report (Sloc, "bad annotation " & Match (4)); - Valid := False; - end; - - if Valid then - if Annotation.Kind /= Expected_Annotation_Kind then - Report (Sloc, "unexpected " - & Annotation.Kind'Img & " " - & Annotation.Message.all - & " (expected " - & Expected_Annotation_Kind'Img - & ")"); - elsif not Check_Message - (Annotation.Message, Expected_Annotation_Msg) - then - Report (Sloc, "unexpected EXEMPT_OFF " - & Annotation.Message.all - & " (expected " - & Expected_Annotation_Msg.all - & ")"); - end if; - - if Annotation.Kind = Exempt_On then - if Annotation.Message = null then - Report (Sloc, "empty message for EXEMPT_ON"); - end if; - - Expected_Annotation_Kind := Exempt_Off; - Expected_Annotation_Msg := Annotation.Message; - - else - Expected_Annotation_Kind := Exempt_On; - Expected_Annotation_Msg := null; - end if; - - ALI_Annotations.Insert - (Key => Sloc, New_Item => Annotation); - end if; - end if; - end; - - when 'C' => - exit Scan_ALI; - - when others => - null; - end case; - end loop Scan_ALI; - - if Expected_Annotation_Kind = Exempt_Off then - declare - use ALI_Annotation_Maps; - Last_Ann_Cursor : constant Cursor := ALI_Annotations.Last; - Last_Ann_Sloc : constant Source_Location := - Key (Last_Ann_Cursor); - Last_Ann : constant ALI_Annotation := - Element (Last_Ann_Cursor); - begin - Report (Last_Ann_Sloc, - "missing Exempt_Off " & Last_Ann.Message.all); - end; - end if; - - if With_SCOs then - if No_Object then - Put_Line ("warning: no object generated for " & ALI_Filename); - - else - if not Preserve_Control_Flow_Seen then - Put_Line - ("warning: " & ALI_Filename - & ": unit compiled without -fpreserve-control-flow"); - end if; - - if not Dump_SCOs_Seen then - Put_Line - ("warning: " & ALI_Filename - & ": unit compiled without SCO generation (-fdump-scos)"); - end if; - - if not Debug_Seen then - Put_Line - ("warning: " & ALI_Filename - & ": unit compiled without debug information (-g)"); - end if; - - if Profile_Arcs_Seen then - Put_Line - ("warning: " & ALI_Filename - & ": unit compiled with instrumentation (-fprofile-arcs)"); - end if; - end if; - - if not End_Of_File (ALI_File) - and then Dump_SCOs_Seen - and then not No_Object - then - Index := 1; - Get_SCOs_From_ALI; - Mark_Ignored_Units (Ignored_Source_Files, Deps); - - else - -- In this case, we will not parse SCOs: reset parsing tables so - -- that further processing don't start using stale SCO entries. - - SCOs.Initialize; - end if; - end if; - - Close (ALI_File); - return ALI_Index; - end Load_ALI; - - ---------- - -- Read -- - ---------- - - procedure Read - (S : access Root_Stream_Type'Class; - V : out ALI_Annotation) - is - begin - CU_Id'Read (S, V.CU); - ALI_Annotation_Kind'Read (S, V.Kind); - - declare - Msg : constant String := String'Input (S); - begin - if Msg'Length > 0 then - V.Message := new String'(Msg); - end if; - end; - V.Violation_Count := 0; - V.Undetermined_Cov_Count := 0; - end Read; - - ----------- - -- Write -- - ----------- - - procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation) is - begin - CU_Id'Write (S, V.CU); - ALI_Annotation_Kind'Write (S, V.Kind); - if V.Message /= null then - String'Output (S, V.Message.all); - else - String'Output (S, ""); - end if; - end Write; - -end ALI_Files; diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads deleted file mode 100644 index daa60d041..000000000 --- a/tools/gnatcov/ali_files.ads +++ /dev/null @@ -1,103 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2009-2022, AdaCore -- --- -- --- GNATcoverage is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This software is distributed in the hope that it will be useful -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- --- License for more details. You should have received a copy of the GNU -- --- General Public License distributed with this software; see file -- --- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- --- of the license. -- ------------------------------------------------------------------------------- - --- ALI files reader - -with Ada.Containers.Ordered_Maps; -with Ada.Streams; use Ada.Streams; - -with GNAT.Regexp; -with GNAT.Strings; use GNAT.Strings; - -with SC_Obligations; use SC_Obligations; -with Slocs; use Slocs; -with Types; use Types; - -package ALI_Files is - - -- This unit instantiates containers and we want to avoid too much - -- performance cost when using references to their elements, so suppress - -- tampering checks. - - pragma Suppress (Tampering_Check); - - type ALI_Annotation_Kind is (Exempt_On, Exempt_Off); - - type ALI_Annotation is record - CU : CU_Id; - -- Compilation unit whose LI file this annotation comes from - - Kind : ALI_Annotation_Kind; - -- On or Off - - Message : String_Access; - -- When Kind = Exempt_On, justification message for the exemption. - -- This is null if no justification is given (i.e. this is never an - -- access to an empty string). - - Violation_Count : Natural := 0; - -- When Kind = Exempt_On, this counts the violation "hits" on this - -- exemption: - -- - -- * exempted violation messages if generating a report, - -- - -- * exempted non/partially covered lines otherwise. - - Undetermined_Cov_Count : Natural := 0; - -- When Kind = Exempt_On, this counts the number of "hits" for - -- undetermined coverage items: currently exempted non-instrumented - -- messages when generating a report, or lines marked as - -- non instrumented otherwise. - -- - -- This is relevant only for source trace based coverage analysis. - end record; - - procedure Read (S : access Root_Stream_Type'Class; V : out ALI_Annotation); - procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation); - for ALI_Annotation'Read use Read; - for ALI_Annotation'Write use Write; - - package ALI_Annotation_Maps is - new Ada.Containers.Ordered_Maps - (Key_Type => Source_Location, - Element_Type => ALI_Annotation); - - ALI_Annotations : ALI_Annotation_Maps.Map; - - function Load_ALI - (ALI_Filename : String; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Units : out SFI_Vector; - Deps : out SFI_Vector; - ALI_Annotations : in out ALI_Annotation_Maps.Map; - With_SCOs : Boolean) return Types.Source_File_Index; - -- Load coverage related information (coverage exemptions and, if With_SCOs - -- is True, source coverage obligations) from ALI_Filename. Returns the - -- source file index for the ALI file. Subsequent calls for the same ALI - -- file will return No_Source_File immediately, without reloading the file. - -- Units are the units contained in this compilation. - -- - -- Ignore all source obligations according to Ignored_Source_Files (see - -- SC_Obligations.Load_SCOs' documentation). - -- - -- Deps are the dependencies of the compilation. - - procedure Load_ALI (ALI_Filename : String); - -- Load ALI information for Filename, without SCOs - -end ALI_Files; diff --git a/tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam b/tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam new file mode 100644 index 000000000..6a6fe5b40 --- /dev/null +++ b/tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam @@ -0,0 +1,2501 @@ +{ + "info": { + "sam_version": 1, + "host": "Unix", + "sar_checksum": [ "db3236eab36625b745cfd5f42eb879d4" ], + "gnatsas_version": "GNATSAS 26.0w (20241010)", + "date": "2024-10-22 16:32:37", + "root_project_name": "gnatcov", + "tools": [ + { + "tool": "Gnat", + "command_line": "codepeer-gprbuild -Pgnatcov.gpr -XPART=gnatcov64 -XBUILD_MODE=dev -ws -j2 -k -s --unchecked-shared-lib-imports -m --db /home/eyraud/sbx/wave/x86_64-linux/gnatsas-edge/install/share/gnatsas/config --target=gnatsas --complete-output --no-object-check --restricted-to-languages=Ada --subdirs=gnatsas/gnatcov.gnat/obj -c -u -gnatc -gnatd.M -gnatef -gnatw.d -gnatj10000 -gnatw.ab.bxwq.r.ir.m.pvm -gnatwn -cargs -fdiagnostics-format=json" + }, + { + "tool": "Infer", + "command_line": "infer --reactive --incremental-analysis --quiet --scheduler=components --no-default-checkers --value --pulse --force-delete-results-dir --results-dir=/home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.infer/infer.out --report-force-relative-path --project-root=/home/eyraud/gnatcoverage/tools/gnatcov/ --backtrack-level=1000 --jobs=2 --changed-files-index=/home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/infer_changed_files_index --report-changed-files-only --progress-bar-style plain -- gprbuild -P /home/eyraud/gnatcoverage/tools/gnatcov/gnatcov.gpr -XPART=gnatcov64 -XBUILD_MODE=dev --target gnatsas --files-from /home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.gnatsas/capture_sources.txt" + }, + { + "tool": "Gnatcheck", + "command_line": "gnatcheck -m0 -q -j2 -l -o /home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.gnatcheck/gnatcheck.out -ox /home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.gnatcheck/gnatcheck.xml --subdirs=gnatsas/gnatcov.gnatcheck -Pgnatcov.gpr --no-subprojects -XPART=gnatcov64 -XBUILD_MODE=dev -rules +Rduplicate_branches +Rsame_logic +Rsame_operands +Rsame_tests +Rsuspicious_equalities" + } + ], + "baseline": { + "file": "gnatcov._no_sub.baseline.sam", + "date": "2024-10-15 14:56:39", + "command_line": "gnatsas analyze -P gnatcov.gpr -XBUILD_MODE=dev -XPART=gnatcov64", + "project_switches": "-j0 --incrementality-method=minimal --no-subprojects --no-inspector", + "checksum": "68a94303edb91a387b0c82d7bed2c11d" + }, + "command_line": "gnatsas analyze -P gnatcov.gpr -XBUILD_MODE=dev -XPART=gnatcov64", + "project_switches": "-j2 --incrementality-method=minimal --no-subprojects --no-inspector", + "review_statuses": { + "Uncategorized": "Uncategorized", + "Pending": "Pending", + "Not A Bug": "Not_a_bug", + "Intentional": "Not_a_bug", + "False Positive": "Not_a_bug", + "Bug": "Bug" + } + }, + "prjs": { + "gnatcov.gpr": [ + { + "file_info": { + "basename": "annotations-cobertura.adb", + "path": "annotations-cobertura.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-cobertura.ads", + "path": "annotations-cobertura.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-dynamic_html.adb", + "path": "annotations-dynamic_html.adb" + }, + "subps": { + "annotations.dynamic_html.set_sco_fields": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "8c1b8f3b9d7ab0555d88e7537d6e38be", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_image` on line 930 is not freed after the last access at line 937, column 23", + "sloc": { "line": 937, "column": 23 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-dynamic_html.adb", + "loc": { "line": 930, "column": 30 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-dynamic_html.adb", + "loc": { "line": 930, "column": 30 }, + "text": "when calling `annotations.sco_image` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 808, "column": 21 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 3, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 7, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 8, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-dynamic_html.adb", + "loc": { "line": 937, "column": 23 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "annotations-dynamic_html.ads", + "path": "annotations-dynamic_html.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-html.adb", + "path": "annotations-html.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-html.ads", + "path": "annotations-html.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-index.adb", + "path": "annotations-index.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-index.ads", + "path": "annotations-index.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-report.adb", + "path": "annotations-report.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-report.ads", + "path": "annotations-report.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-sarif.adb", + "path": "annotations-sarif.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-sarif.ads", + "path": "annotations-sarif.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-xcov.adb", + "path": "annotations-xcov.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-xcov.ads", + "path": "annotations-xcov.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-xml.adb", + "path": "annotations-xml.adb" + }, + "subps": { + "annotations.xml.pretty_print_condition": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "ea6cd8676ded724f682f2698efcd1bcb", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_text` on line 327 is not freed after the last access at line 334, column 31", + "sloc": { "line": 334, "column": 31 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 327, "column": 27 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-xml.adb", + "loc": { "line": 327, "column": 27 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 334, "column": 31 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ], + "annotations.xml.pretty_print_start_decision": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "ea6cd8676ded724f682f2698efcd1bcb", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_text` on line 521 is not freed after the last access at line 527, column 36", + "sloc": { "line": 527, "column": 36 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 521, "column": 27 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-xml.adb", + "loc": { "line": 521, "column": 27 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 527, "column": 36 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ], + "annotations.xml.pretty_print_statement": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "ea6cd8676ded724f682f2698efcd1bcb", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_text` on line 680 is not freed after the last access at line 687, column 31", + "sloc": { "line": 687, "column": 31 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 680, "column": 27 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-xml.adb", + "loc": { "line": 680, "column": 27 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 687, "column": 31 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "annotations-xml.ads", + "path": "annotations-xml.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations.adb", + "path": "annotations.adb" + }, + "subps": { + "annotations.disp_scos": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "bfc277166e3f1cab1c98959e46a65727", + "key_seq": 1 + }, + "data": { + "msg": "SCO_State might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 326, "column": 22 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Removed" + } + } + ], + "annotations.sco_text": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "8a8bd52eff4074034eb037a2eaee1d92", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `files_table.end_lex_element` on line 652 is not freed after the last access at line 751, column 17", + "sloc": { "line": 751, "column": 17 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations.adb", + "loc": { "line": 652, "column": 39 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations.adb", + "loc": { "line": 652, "column": 39 }, + "text": "when calling `files_table.end_lex_element` here" + }, + { + "level": 2, + "file": "files_table.adb", + "loc": { "line": 433, "column": 35 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations.adb", + "loc": { "line": 751, "column": 17 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "annotations.ads", + "path": "annotations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "arch__64.ads", "path": "arch__64.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "argparse.adb", "path": "argparse.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "argparse.ads", "path": "argparse.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "binary_files.adb", + "path": "binary_files.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "binary_files.ads", + "path": "binary_files.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "calendar_utils.adb", + "path": "calendar_utils.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "calendar_utils.ads", + "path": "calendar_utils.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "cfg_dump.adb", "path": "cfg_dump.adb" }, + "subps": { + "cfg_dump.collect_instructions": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 1 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 528, "column": 26 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 2 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 536, "column": 25 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 3 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 544, "column": 19 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 4 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 642, "column": 56 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 5 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 666, "column": 28 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "86f20cfc6181c4829e56de57edad9d59", + "key_seq": 1 + }, + "data": { + "msg": "Last_Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 528, "column": 49 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "86f20cfc6181c4829e56de57edad9d59", + "key_seq": 2 + }, + "data": { + "msg": "Last_Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 536, "column": 52 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "e3cfb48b116277ba65fdd7a8bee8c0f6", + "key_seq": 1 + }, + "data": { + "msg": "Old_PC might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 717, "column": 20 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Removed" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "08c65a49805954c02d01890fdb7e9c5d", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new` on line 443 is not freed after the last access at line 717, column 20", + "sloc": { "line": 717, "column": 20 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "cfg_dump.adb", + "loc": { "line": 443, "column": 21 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "cfg_dump.adb", + "loc": { "line": 443, "column": 21 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "cfg_dump.adb", + "loc": { "line": 717, "column": 20 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ], + "cfg_dump.collect_instructions(cfg_dump.context_access, traces_elf.address_info_acc)": [] + } + }, + { + "file_info": { "basename": "cfg_dump.ads", "path": "cfg_dump.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "check_scos.adb", + "path": "check_scos.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "check_scos.ads", + "path": "check_scos.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "checkpoints.adb", + "path": "checkpoints.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "checkpoints.ads", + "path": "checkpoints.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "clang-extensions.adb", + "path": "clang-extensions.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "clang-extensions.ads", + "path": "clang-extensions.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "coff.ads", "path": "coff.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "command_line.adb", + "path": "command_line.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "command_line.ads", + "path": "command_line.ads" + }, + "subps": { + "command_line": [ + { + "msg_id": { + "tool_kind": [ "Gnat", "Default_gnat_warnings" ], + "key": "32f47d5e89e388b8a6f8fcc6dbeb5e9a", + "key_seq": 1 + }, + "data": { + "msg": "in instantiation at argparse.ads:200, component of \"Bool_Option_Info_Array\" padded by 8 bits", + "sloc": { "line": 208, "column": 4 }, + "rank": "Medium", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { "basename": "commands.adb", "path": "commands.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "commands.ads", "path": "commands.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "compiler_wrappers-gcc.adb", + "path": "compiler_wrappers-gcc.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "compiler_wrappers.ads", + "path": "compiler_wrappers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "convert.adb", "path": "convert.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "convert.ads", "path": "convert.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-object.adb", + "path": "coverage-object.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-object.ads", + "path": "coverage-object.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-source.adb", + "path": "coverage-source.adb" + }, + "subps": { + "coverage.source.compute_atcc_state": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "fbd69b2f7f0cd8aa93f7b5a68c529d73", + "key_seq": 1 + }, + "data": { + "msg": "Last_Cond_Not_Evaluated might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 1474, "column": 24 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ], + "coverage.source.compute_mcdc_state": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "18eb84a06439c4349d5e2227f9e6b1f9", + "key_seq": 1 + }, + "data": { + "msg": "Last_Cond_No_Pair might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 1350, "column": 24 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "coverage-source.ads", + "path": "coverage-source.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-tags.adb", + "path": "coverage-tags.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-tags.ads", + "path": "coverage-tags.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "coverage.adb", "path": "coverage.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "coverage.ads", "path": "coverage.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage_options.adb", + "path": "coverage_options.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage_options.ads", + "path": "coverage_options.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "decision_map.adb", + "path": "decision_map.adb" + }, + "subps": { + "decision_map.analyze_routine": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "90d4f86d18540ad03e69f32cf8b264e9", + "key_seq": 1 + }, + "data": { + "msg": "Insn_Len might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2794, "column": 22 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "decision_map.ads", + "path": "decision_map.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "diagnostics.adb", + "path": "diagnostics.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "diagnostics.ads", + "path": "diagnostics.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "dis_opcodes.ads", + "path": "libopcodes_bind/dis_opcodes.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_aarch64.adb", + "path": "disa_aarch64.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_aarch64.ads", + "path": "disa_aarch64.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "disa_arm.adb", "path": "disa_arm.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_arm.ads", "path": "disa_arm.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_common.adb", + "path": "disa_common.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_common.ads", + "path": "disa_common.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "disa_lmp.adb", "path": "disa_lmp.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_lmp.ads", "path": "disa_lmp.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_ppc.adb", "path": "disa_ppc.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_ppc.ads", "path": "disa_ppc.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_sparc.adb", + "path": "disa_sparc.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_sparc.ads", + "path": "disa_sparc.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_symbolize.adb", + "path": "disa_symbolize.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_symbolize.ads", + "path": "disa_symbolize.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_thumb.adb", + "path": "disa_thumb.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_thumb.ads", + "path": "disa_thumb.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "disa_x86.adb", "path": "disa_x86.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_x86.ads", "path": "disa_x86.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemble_insn_properties.adb", + "path": "disassemble_insn_properties.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemble_insn_properties.ads", + "path": "disassemble_insn_properties.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemblers.adb", + "path": "disassemblers.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemblers.ads", + "path": "disassemblers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "display.adb", "path": "display.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "display.ads", "path": "display.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "dwarf.ads", "path": "dwarf.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "dwarf_handling.adb", + "path": "dwarf_handling.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "dwarf_handling.ads", + "path": "dwarf_handling.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "elf32.adb", "path": "elf32.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "elf32.ads", "path": "elf32.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "elf64.adb", "path": "elf64.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "elf64.ads", "path": "elf64.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "elf_common.adb", + "path": "elf_common.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "elf_common.ads", + "path": "elf_common.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "elf_disassemblers.adb", + "path": "elf_disassemblers.adb" + }, + "subps": { + "elf_disassemblers.go_to_next_insn": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "87dc423edec3358707a253916c1fcbb9", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Insn_Set might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 225, "column": 7 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Removed" + } + } + ] + } + }, + { + "file_info": { + "basename": "elf_disassemblers.ads", + "path": "elf_disassemblers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "elf_files.adb", "path": "elf_files.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "elf_files.ads", "path": "elf_files.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "execs_dbase.adb", + "path": "execs_dbase.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "execs_dbase.ads", + "path": "execs_dbase.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "factory_registry.adb", + "path": "factory_registry.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "factory_registry.ads", + "path": "factory_registry.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "files_handling.adb", + "path": "files_handling.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "files_handling.ads", + "path": "files_handling.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "files_table.adb", + "path": "files_table.adb" + }, + "subps": { + "files_table.checkpoint_clear": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Access_check" ], + "key": "a5ab61ae4c450e2549d54916852c2df2", + "key_seq": 1 + }, + "data": { + "msg": "`FI.all` could be null (null value originating from line 1969) and is dereferenced", + "cwe": [ [ 476 ] ], + "sloc": { "line": 1960, "column": 10 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 1, + "file": "files_table.adb", + "loc": { "line": 1969, "column": 10 }, + "text": "is assigned to the null pointer" + }, + { + "level": 1, + "file": "files_table.adb", + "loc": { "line": 1960, "column": 10 }, + "text": "invalid access occurs here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "files_table.ads", + "path": "files_table.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "gnatcov.adb", "path": "gnatcov.adb" }, + "subps": {} + }, + { + "file_info": { + "basename": "gnatcov_bits_specific.adb", + "path": "gnatcov_bits_specific.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "hex_images.adb", + "path": "hex_images.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "hex_images.ads", + "path": "hex_images.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "highlighting.adb", + "path": "highlighting.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "highlighting.ads", + "path": "highlighting.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "inputs.adb", "path": "inputs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "inputs.ads", "path": "inputs.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_preprocessing.adb", + "path": "instrument-ada_preprocessing.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_preprocessing.ads", + "path": "instrument-ada_preprocessing.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit.adb", + "path": "instrument-ada_unit.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit.ads", + "path": "instrument-ada_unit.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit_provider.adb", + "path": "instrument-ada_unit_provider.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit_provider.ads", + "path": "instrument-ada_unit_provider.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c.adb", + "path": "instrument-c.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c.ads", + "path": "instrument-c.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c_utils.adb", + "path": "instrument-c_utils.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c_utils.ads", + "path": "instrument-c_utils.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-checkpoints.adb", + "path": "instrument-checkpoints.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-checkpoints.ads", + "path": "instrument-checkpoints.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-clean_objdirs.adb", + "path": "instrument-clean_objdirs.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-clean_objdirs.ads", + "path": "instrument-clean_objdirs.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-common.adb", + "path": "instrument-common.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-common.ads", + "path": "instrument-common.ads" + }, + "subps": { + "instrument.common.replace_manual_indications": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "59287a3a858ba0f412ab294538006a2c", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Has_Reset_Indication` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 531, "column": 52 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "instrument-common.ads", + "loc": { "line": 526, "column": 4 }, + "text": "parameter `Has_Reset_Indication` of instrument.common.replace_manual_indications" + }, + { + "level": 0, + "file": "instrument-common.ads", + "loc": { "line": 531, "column": 52 }, + "text": "end of the subprogram is here" + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "f6825e9f92414db4f641a38556d8ee02", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Has_Reset_Indication might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 531, "column": 52 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "instrument.common.replace_manual_indications", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "59287a3a858ba0f412ab294538006a2c", + "key_seq": 1 + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "instrument-config.adb", + "path": "instrument-config.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-gcc_wrapper.adb", + "path": "instrument-gcc_wrapper.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-input_traces.adb", + "path": "instrument-input_traces.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-input_traces.ads", + "path": "instrument-input_traces.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-main.adb", + "path": "instrument-main.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-projects.adb", + "path": "instrument-projects.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-setup_config.adb", + "path": "instrument-setup_config.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-setup_config.ads", + "path": "instrument-setup_config.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-source.adb", + "path": "instrument-source.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument.adb", + "path": "instrument.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument.ads", + "path": "instrument.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "json.adb", "path": "json.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "json.ads", "path": "json.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "logging.adb", "path": "logging.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "logging.ads", "path": "logging.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "mc_dc.adb", "path": "mc_dc.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "mc_dc.ads", "path": "mc_dc.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "object_locations.adb", + "path": "object_locations.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "object_locations.ads", + "path": "object_locations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "outputs.adb", "path": "outputs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "outputs.ads", "path": "outputs.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "paths.adb", "path": "paths.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "paths.ads", "path": "paths.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "pecoff_files.adb", + "path": "pecoff_files.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "pecoff_files.ads", + "path": "pecoff_files.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "perf_counters.adb", + "path": "perf_counters.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "perf_counters.ads", + "path": "perf_counters.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "ppc_descs.adb", "path": "ppc_descs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "ppc_descs.ads", "path": "ppc_descs.ads" }, + "subps": { + "ppc_descs": [ + { + "msg_id": { + "tool_kind": [ "Gnatcheck", "Same_operands" ], + "key": "772dd957dd1b5c22c9cc7789b160385a", + "key_seq": 1 + }, + "data": { + "msg": "same operands", + "sloc": { "line": 101, "column": 30 }, + "rank": "Medium", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Gnatcheck", "Same_operands" ], + "key": "772dd957dd1b5c22c9cc7789b160385a", + "key_seq": 2 + }, + "data": { + "msg": "same operands", + "sloc": { "line": 103, "column": 30 }, + "rank": "Medium", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { "basename": "project.adb", "path": "project.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "project.ads", "path": "project.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "qemu_traces.ads", + "path": "qemu_traces.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "qemu_traces_entries__64.ads", + "path": "qemu_traces_entries__64.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "rundrv-config.adb", + "path": "rundrv-config.adb" + }, + "subps": { + "rundrv.config.get_builtin_driver": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "07450640bbbf2f6ae0bf9b8d2ec66542", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Native might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 111, "column": 27 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "rundrv.config.get_builtin_driver", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Native` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 111, "column": 27 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "rundrv-config.adb", + "loc": { "line": 84, "column": 4 }, + "text": "parameter `Native` of rundrv.config.get_builtin_driver" + }, + { + "level": 0, + "file": "rundrv-config.adb", + "loc": { "line": 111, "column": 27 }, + "text": "end of the subprogram is here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "rundrv-config.ads", + "path": "rundrv-config.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "rundrv-handlers.adb", + "path": "rundrv-handlers.adb" + }, + "subps": { + "rundrv.handlers.get_gnatemu_driver": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "07450640bbbf2f6ae0bf9b8d2ec66542", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Native might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 229, "column": 10 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "rundrv.handlers.get_gnatemu_driver", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Native` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 229, "column": 10 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "rundrv-handlers.adb", + "loc": { "line": 218, "column": 4 }, + "text": "parameter `Native` of rundrv.handlers.get_gnatemu_driver" + }, + { + "level": 0, + "file": "rundrv-handlers.adb", + "loc": { "line": 229, "column": 10 }, + "text": "end of the subprogram is here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "rundrv-handlers.ads", + "path": "rundrv-handlers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "rundrv.adb", "path": "rundrv.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "rundrv.ads", "path": "rundrv.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "sc_obligations-bdd.adb", + "path": "sc_obligations-bdd.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "sc_obligations-bdd.ads", + "path": "sc_obligations-bdd.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "sc_obligations.adb", + "path": "sc_obligations.adb" + }, + "subps": { + "sc_obligations.get_origin": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "52cde9cc70750fefd8280ae1fa662e63", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Prev_Value might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2676, "column": 19 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "sc_obligations.get_origin", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "52f2e1bd10d09e4e51f8afdfc4ded607", + "key_seq": 1 + } + ], + "age": "Removed" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "52f2e1bd10d09e4e51f8afdfc4ded607", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Prev_Value` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2676, "column": 19 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 2660, "column": 4 }, + "text": "parameter `Prev_Value` of sc_obligations.get_origin" + }, + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 2676, "column": 19 }, + "text": "end of the subprogram is here" + } + ], + "age": "Removed" + } + } + ], + "sc_obligations.next_bdd_node((sc_obligations.sco_id, standard.boolean) -> sc_obligations.bdd_node_id)": [ + { + "msg_id": { + "tool_kind": [ "Gnat", "Unused_entity" ], + "key": "6418215abbab1632bf5ce16178874fcd", + "key_seq": 1 + }, + "data": { + "msg": "use clause for package \"BDD\" has no effect", + "sloc": { "line": 4585, "column": 7 }, + "rank": "Low", + "age": "Unchanged" + } + } + ], + "sc_obligations.offset_for_true((sc_obligations.sco_id) -> standard.natural)": [ + { + "msg_id": { + "tool_kind": [ "Gnat", "Unused_entity" ], + "key": "6418215abbab1632bf5ce16178874fcd", + "key_seq": 1 + }, + "data": { + "msg": "use clause for package \"BDD\" has no effect", + "sloc": { "line": 4612, "column": 7 }, + "rank": "Low", + "age": "Unchanged" + } + } + ], + "sc_obligations.sloc_to_sco": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "d735d81c314d0204dd60007ccce00fd4", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `files_table.sloc_to_sco_map` on line 5994 is not freed after the last access at line 6076, column 20", + "sloc": { "line": 6076, "column": 20 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 5994, "column": 14 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "sc_obligations.adb", + "loc": { "line": 5994, "column": 14 }, + "text": "when calling `files_table.sloc_to_sco_map` here" + }, + { + "level": 2, + "file": "files_table.adb", + "loc": { "line": 1719, "column": 17 }, + "text": "when calling `files_table.writeable_sloc_to_sco_map` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 1705, "column": 33 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 6076, "column": 20 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "d735d81c314d0204dd60007ccce00fd4", + "key_seq": 2 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `files_table.sloc_to_sco_map` on line 6004 is not freed after the last access at line 6076, column 20", + "sloc": { "line": 6076, "column": 20 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 6004, "column": 14 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "sc_obligations.adb", + "loc": { "line": 6004, "column": 14 }, + "text": "when calling `files_table.sloc_to_sco_map` here" + }, + { + "level": 2, + "file": "files_table.adb", + "loc": { "line": 1719, "column": 17 }, + "text": "when calling `files_table.writeable_sloc_to_sco_map` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 1705, "column": 33 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 6076, "column": 20 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "sc_obligations.ads", + "path": "sc_obligations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "setup_rts.adb", "path": "setup_rts.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "setup_rts.ads", "path": "setup_rts.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "slocs.adb", "path": "slocs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "slocs.ads", "path": "slocs.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "sparc_descs.ads", + "path": "sparc_descs.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "ss_annotations.adb", + "path": "ss_annotations.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "ss_annotations.ads", + "path": "ss_annotations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "strings.adb", "path": "strings.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "strings.ads", "path": "strings.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "subprocesses.adb", + "path": "subprocesses.adb" + }, + "subps": { + "subprocesses.wait_and_finalize": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "c174c2d3c4d06c9d38c3c19bc5f73688", + "key_seq": 1 + }, + "data": { + "msg": "Id might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 382, "column": 38 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "subprocesses.ads", + "path": "subprocesses.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "support_files.ads", + "path": "support_files.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "swaps.adb", "path": "swaps.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "swaps.ads", "path": "swaps.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "switches.adb", "path": "switches.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "switches.ads", "path": "switches.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "symbols.adb", "path": "symbols.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "symbols.ads", "path": "symbols.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "temp_dirs.adb", "path": "temp_dirs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "temp_dirs.ads", "path": "temp_dirs.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "text_files.adb", + "path": "text_files.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "text_files.ads", + "path": "text_files.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "traces.adb", "path": "traces.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "traces.ads", "path": "traces.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dbase.adb", + "path": "traces_dbase.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dbase.ads", + "path": "traces_dbase.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_disa.adb", + "path": "traces_disa.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_disa.ads", + "path": "traces_disa.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dump.adb", + "path": "traces_dump.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dump.ads", + "path": "traces_dump.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_elf.adb", + "path": "traces_elf.adb" + }, + "subps": { + "traces_elf.read_debug_lines.close_source_line": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "e8031aaabc82b6a3ac7d1dbb070dc6bb", + "key_seq": 1 + }, + "data": { + "msg": "Insn_1_Last_PC might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2401, "column": 35 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "e8031aaabc82b6a3ac7d1dbb070dc6bb", + "key_seq": 2 + }, + "data": { + "msg": "Insn_1_Last_PC might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2408, "column": 45 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ], + "traces_elf.set_insn_state": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "74bcf79a584b32bc3a3b1e2b4235a049", + "key_seq": 1 + }, + "data": { + "msg": "Last_Insn_1_Len might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 3817, "column": 34 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "traces_elf.ads", + "path": "traces_elf.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_files.adb", + "path": "traces_files.adb" + }, + "subps": { + "traces_files.read_so_info": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "251d35eeb8dc5fb3d9304dd9e82f5c1f", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `traces_files.read_so_info.read_info_entries` on line 649 is not freed after the last access at line 650, column 10", + "sloc": { "line": 650, "column": 10 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "traces_files.adb", + "loc": { "line": 649, "column": 7 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "traces_files.adb", + "loc": { "line": 649, "column": 7 }, + "text": "when calling `traces_files.read_so_info.read_info_entries` here" + }, + { + "level": 2, + "file": "traces_files.adb", + "loc": { "line": 847, "column": 13 }, + "text": "when calling `traces_files.read_so_info.process_info_entry` here" + }, + { + "level": 3, + "file": "traces_files.adb", + "loc": { "line": 635, "column": 43 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "traces_files.adb", + "loc": { "line": 650, "column": 10 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "traces_files.ads", + "path": "traces_files.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_files_registry.adb", + "path": "traces_files_registry.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_files_registry.ads", + "path": "traces_files_registry.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_lines.adb", + "path": "traces_lines.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_lines.ads", + "path": "traces_lines.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_names.adb", + "path": "traces_names.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_names.ads", + "path": "traces_names.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_source.adb", + "path": "traces_source.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_source.ads", + "path": "traces_source.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_stats.adb", + "path": "traces_stats.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_stats.ads", + "path": "traces_stats.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "version.ads", "path": "version.ads" }, + "subps": {} + } + ] + } +} diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb new file mode 100644 index 000000000..28c4136a4 --- /dev/null +++ b/tools/gnatcov/annotations-cobertura.adb @@ -0,0 +1,652 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023-2024, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with this software; see file -- +-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- +-- of the license. -- +------------------------------------------------------------------------------ + +with Ada.Calendar.Conversions; use Ada.Calendar.Conversions; +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Ordered_Maps; +with Ada.Directories; +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Fixed; +with Ada.Unchecked_Deallocation; + +with GNAT.OS_Lib; +with GNAT.Regpat; use GNAT.Regpat; + +with Interfaces.C; use Interfaces.C; + +with Annotations.Xml; use Annotations.Xml; +with Command_Line; use Command_Line; +with Coverage; use Coverage; +with Coverage.Source; use Coverage.Source; +with Outputs; use Outputs; +with Paths; +with Support_Files; +with Switches; use Switches; +with Version; + +package body Annotations.Cobertura is + + DTD_Basename : constant String := "cobertura.dtd"; + DTD_Filename : constant String := Support_Files.In_Lib_Dir (DTD_Basename); + + type Pattern_Matcher_Acc is access all Pattern_Matcher; + procedure Free is new + Ada.Unchecked_Deallocation (Pattern_Matcher, Pattern_Matcher_Acc); + + type Cobertura_Pretty_Printer is new Pretty_Printer with record + Report_Filename : Unbounded_String; + Report_File : File_Type; + -- "cobertura.xml" file + + Indentation : Natural := 0; + -- Indentation for the next XML items to write + + Source_Prefix_Pattern : Pattern_Matcher_Acc; + -- Regexp matching a source filename prefix to remove in the report. + -- + -- This is needed to support coverage reports in GitLab pipelines, which + -- require filenames to be relative to the root of the tested + -- repository. GNATcoverage users are supposed to pass the root of this + -- repository through the --source-root option. + end record; + -- Pretty printer type for the Cobertura annotation format + + overriding + function Format + (Pp : Cobertura_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Cobertura); + + type Rate_Type is digits 3; + + function Img (R : Rate_Type) return String; + -- Return a string representation of the rate without an exponent suffix + -- and without a leading space. + + -------------------- + -- XML generation -- + -------------------- + + Xml_Header : constant String := ""; + + function A (Name : String; Value : String) return String; + -- Return a string representing an xml attribute whose name and value are + -- given in parameter, i.e. Name = "Value". + + procedure T + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String); + -- Print a string representing an empty tag whose name and attributes are + -- given in parameter, i.e. . + + procedure ST + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String); + -- Print a string representing a start tag whose name and attributes are + -- given in parameter, i.e. . + + procedure ST (Pp : in out Cobertura_Pretty_Printer'Class; Name : String); + -- Same as ST, with no attributes + + procedure ET (Pp : in out Cobertura_Pretty_Printer'Class; Name : String); + -- Print a string representing an end tag whose name is given in parameter, + -- i.e. . + + ----------------------------------------------------- + -- Cobertura_Pretty_Printer's primitive operations -- + -- (inherited from Pretty_Printer) -- + ----------------------------------------------------- + + overriding + procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer); + + overriding + procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer); + + overriding + procedure Pretty_Print_Start_File + (Pp : in out Cobertura_Pretty_Printer; + File : Source_File_Index; + Skip : out Boolean); + + overriding + procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer); + + overriding + procedure Pretty_Print_Start_Line + (Pp : in out Cobertura_Pretty_Printer; + Line_Num : Natural; + Info : Line_Info_Access; + Line : String); + + ----------------------------- + -- Shortcut for Put_Line's -- + ----------------------------- + + procedure P (Pp : Cobertura_Pretty_Printer'Class; S : String); + -- Put_Line S in the destination file + + ----------------------------- + -- Statistics computations -- + ----------------------------- + + procedure Compute_Line_Stats + (Li_Stat : Li_Stat_Array; + Lines_Valid : out Natural; + Lines_Covered : out Natural; + Line_Rate : out Rate_Type); + -- Compute line statistics. This does not account for exempted / non- + -- instrumented / non-coverable lines. + + procedure Compute_Branch_Stats + (Ob_Stats : Ob_Stat_Array; + Branches_Valid : out Natural; + Branches_Covered : out Natural; + Branch_Rate : out Rate_Type); + -- Compute branch statistics. This does not account exempted / non- + -- instrumented / non-coverable obligations. + -- + -- We choose to represent decisions in the branch terminology that + -- cobertura uses: a decision yields two branches. If it is not covered, + -- neither branch is covered; if it is partially covered, one of the branch + -- is; if it is fully covered, the two branches are. + + --------------- + -- Installed -- + --------------- + + function Installed return Boolean is + begin + return Ada.Directories.Exists (DTD_Filename); + end Installed; + + --------- + -- Img -- + --------- + + function Img (R : Rate_Type) return String is + package Float_IO is new Ada.Text_IO.Float_IO (Rate_Type); + Result : String (1 .. 8); + begin + Float_IO.Put + (To => Result, Item => R, Aft => Rate_Type'Digits - 1, Exp => 0); + return Ada.Strings.Fixed.Trim (Result, Side => Ada.Strings.Both); + end Img; + + ------- + -- A -- + ------- + + function A (Name : String; Value : String) return String is + begin + return " " & Name & "=" & '"' & To_Xml_String (Value) & '"'; + end A; + + -------- + -- ET -- + -------- + + procedure ET (Pp : in out Cobertura_Pretty_Printer'Class; Name : String) is + begin + Pp.Indentation := Pp.Indentation - 1; + Pp.P (""); + New_Line (Pp.Report_File); + end ET; + + --------------------- + -- Generate_Report -- + --------------------- + + procedure Generate_Report (Context : Coverage.Context_Access) is + Pp : Cobertura_Pretty_Printer := + (Need_Sources => True, + Context => Context, + Source_Prefix_Pattern => null, + others => <>); + + -- If --source-root was passed, turn it into the corresponding prefix + -- matcher. Append a directory separator so that "/prefix/basename" + -- always becomes "basename" instead of "/basename" regardless of + -- whether the prefix is "/prefix" or "/prefix/". + + Source_Root_Opt : Parser.String_Option renames + Args.String_Args (Opt_Source_Root); + Output_Opt : Parser.String_Option renames + Args.String_Args (Opt_Output); + begin + if Source_Root_Opt.Present then + declare + Prefix : constant String := +Source_Root_Opt.Value & "/"; + begin + Pp.Source_Prefix_Pattern := + new Pattern_Matcher'(Compile (Paths.Glob_To_Regexp (Prefix))); + end; + end if; + + if Output_Opt.Present then + Pp.Report_Filename := Output_Opt.Value; + else + Pp.Report_Filename := +"cobertura.xml"; + end if; + + Pp.Need_Sources := False; + + Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); + Free (Pp.Source_Prefix_Pattern); + end Generate_Report; + + ------- + -- P -- + ------- + + procedure P (Pp : Cobertura_Pretty_Printer'Class; S : String) is + Spaces : constant String (1 .. Pp.Indentation) := (others => ' '); + begin + Put_Line (Pp.Report_File, Spaces & S); + end P; + + ---------------------- + -- Pretty_Print_End -- + ---------------------- + + overriding + procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer) is + begin + Pp.ET ("packages"); + Pp.ET ("coverage"); + Close (Pp.Report_File); + end Pretty_Print_End; + + --------------------------- + -- Pretty_Print_End_File -- + --------------------------- + + overriding + procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer) is + begin + Pp.ET ("lines"); + Pp.ET ("class"); + Pp.ET ("classes"); + Pp.ET ("package"); + end Pretty_Print_End_File; + + ------------------------ + -- Compute_Line_Stats -- + ------------------------ + + procedure Compute_Line_Stats + (Li_Stat : Li_Stat_Array; + Lines_Valid : out Natural; + Lines_Covered : out Natural; + Line_Rate : out Rate_Type) is + begin + Lines_Valid := + Li_Stat (Covered) + + Li_Stat (Not_Covered) + + Li_Stat (Partially_Covered); + Lines_Covered := Li_Stat (Covered) + Li_Stat (Partially_Covered); + Line_Rate := Rate_Type (Lines_Covered) / Rate_Type (Lines_Valid); + end Compute_Line_Stats; + + -------------------------- + -- Compute_Branch_Stats -- + -------------------------- + + procedure Compute_Branch_Stats + (Ob_Stats : Ob_Stat_Array; + Branches_Valid : out Natural; + Branches_Covered : out Natural; + Branch_Rate : out Rate_Type) is + begin + Branches_Valid := + Ob_Stats (Decision).Stats (Covered) + + Ob_Stats (Decision).Stats (Not_Covered) + + Ob_Stats (Decision).Stats (Partially_Covered); + Branches_Covered := + 2 + * Ob_Stats (Decision).Stats (Covered) + + Ob_Stats (Decision).Stats (Partially_Covered); + if Branches_Valid = 0 then + Branch_Rate := 1.0; + else + Branch_Rate := + Rate_Type (Branches_Covered) / Rate_Type (Branches_Valid); + end if; + end Compute_Branch_Stats; + + ------------------------ + -- Pretty_Print_Start -- + ------------------------ + + overriding + procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer) is + Success : Boolean; + Timestamp : constant String := + Ada.Strings.Fixed.Trim + (long_long'Image (To_Unix_Time_64 (Pp.Context.Timestamp)), + Ada.Strings.Left); + begin + -- Copy the DTD Schema to the output directory + + GNAT.OS_Lib.Copy_File + (Name => DTD_Filename, + Pathname => Get_Output_Dir, + Success => Success, + Mode => GNAT.OS_Lib.Overwrite); + if not Success then + Fatal_Error + ("Error while copying " + & DTD_Filename + & " to the output directory"); + end if; + + Create_Output_File (Pp.Report_File, +Pp.Report_Filename); + + Pp.P (Xml_Header); + Pp.P (""); + + -- Compute statistics + + declare + Lines_Valid, Lines_Covered : Natural; + Line_Rate : Rate_Type; + + Branches_Valid, Branches_Covered : Natural; + Branch_Rate : Rate_Type; + begin + Compute_Line_Stats + (Global_Stats, Lines_Valid, Lines_Covered, Line_Rate); + Compute_Branch_Stats + (Global_Ob_Stats, Branches_Valid, Branches_Covered, Branch_Rate); + + Pp.ST + ("coverage", + A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("lines-covered", Img (Lines_Covered)) + & A ("lines-valid", Img (Lines_Valid)) + & A ("branches-covered", Img (Branches_Covered)) + & A ("branches-valid", Img (Branches_Valid)) + + -- Cobertura also provides the cyclomatic complexity number. + -- As we don't compute this, print an arbitrary invalid value. + + & A ("complexity", "-1") + & A ("version", Version.Xcov_Version) + & A ("timestamp", Timestamp)); + + Pp.ST ("sources"); + Pp.ET ("sources"); + Pp.ST ("packages"); + end; + end Pretty_Print_Start; + + ----------------------------- + -- Pretty_Print_Start_File -- + ----------------------------- + + overriding + procedure Pretty_Print_Start_File + (Pp : in out Cobertura_Pretty_Printer; + File : Source_File_Index; + Skip : out Boolean) + is + Info : constant File_Info_Access := Get_File (File); + + Simple_Source_Filename : constant String := Info.Simple_Name.all; + + Lines_Valid, Lines_Covered : Natural; + Line_Rate : Rate_Type; + + Branches_Valid, Branches_Covered : Natural; + Branch_Rate : Rate_Type; + + Filename : Unbounded_String := +Info.Full_Name.all; + -- Filename to mention in the coverage report. Use the full name, unless + -- we can remove the prefix according to the --source-root option. + begin + Skip := False; + + -- Compute line and branch statistics + + Compute_Line_Stats + (Info.Li_Stats, Lines_Valid, Lines_Covered, Line_Rate); + Compute_Branch_Stats + (Info.Ob_Stats, Branches_Valid, Branches_Covered, Branch_Rate); + + -- Remove the source root prefix (if present) from Filename so that, if + -- Filename designates a source file that is inside the directory + -- referenced by --source-root, Filename is set to a pathname relative + -- to the source root. + -- + -- Note that the pattern matcher in Pp.Source_Prefix_Pattern expects + -- "normalized" filename with: + -- + -- 1) casing folded for case insensitive systems, + -- 2) forward slashes instead of backslashes. + -- + -- So normalize first into Normalized_Filename, then turn Filename into + -- a slice of it. + + if Pp.Source_Prefix_Pattern /= null then + declare + Matches : GNAT.Regpat.Match_Array (0 .. 0); + First, Last : Natural; + Normalized_Filename : constant String := + Paths.Normalize_For_Regexp (+Filename); + begin + GNAT.Regpat.Match + (Pp.Source_Prefix_Pattern.all, Normalized_Filename, Matches); + if Matches (0) /= GNAT.Regpat.No_Match then + First := Matches (0).Last + 1; + Last := Normalized_Filename'Last; + Filename := +Normalized_Filename (First .. Last); + end if; + end; + end if; + + Pp.ST + ("package", + A ("name", Simple_Source_Filename) + & A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("complexity", "-1")); + Pp.ST ("classes"); + Pp.ST + ("class", + A ("name", Simple_Source_Filename) + & A ("filename", +Filename) + & A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("complexity", "-1")); + Pp.ST ("methods"); + Pp.ET ("methods"); + Pp.ST ("lines"); + end Pretty_Print_Start_File; + + ----------------------------- + -- Pretty_Print_Start_Line -- + ----------------------------- + + overriding + procedure Pretty_Print_Start_Line + (Pp : in out Cobertura_Pretty_Printer; + Line_Num : Natural; + Info : Line_Info_Access; + Line : String) + is + Coverage_State : constant Any_Line_State := Aggregated_State (Info.all); + Exempted : constant Boolean := Info.Exemption /= Slocs.No_Location; + begin + if not Exempted and then Coverage_State /= No_Code then + declare + subtype Coverage_Line_State is + Any_Line_State range Not_Covered .. Covered; + package SCOs_State_Maps is new + Ada.Containers.Ordered_Maps + (Key_Type => SCO_Id, + Element_Type => Coverage_Line_State); + + Hit : Natural := 0; + -- Whether the line was covered or not. Cobertura enables counting + -- the number of coverage hits; we don't. + + Has_Decision : Boolean := False; + -- Whether there is a decision on the current line + + State_Decisions : SCOs_State_Maps.Map; + -- List of decisions at the current line and their coverage state + + Branches_Covered, Branches_Valid : Natural := 0; + begin + if Coverage_State /= Not_Covered then + Hit := 1; + end if; + + -- Express decision coverage in cobertura notion of condition + -- coverage: in Cobertura terminology, a condition is represented + -- as a two-valuation expression: either 0, 1 or 2 of its + -- valuation are covered. + + -- Start by getting all of the decisions present on this line. + -- Note that there can be no SCOs for the line if using binary + -- traces with the insn coverage level. TODO??? Is this really + -- something we want to support? + + if Info.SCOs /= null then + for SCO of Info.SCOs.all loop + if Kind (SCO) /= Removed + and then First_Sloc (SCO).L.Line = Line_Num + and then SCO_Kind (Kind (SCO)) = Decision + and then (Coverage.Enabled (Decision) + or else Coverage.MCDC_Coverage_Enabled) + then + declare + Line_State : constant Any_Line_State := + Get_Line_State (SCO, Decision); + begin + if Line_State in Coverage_Line_State then + Has_Decision := True; + State_Decisions.Insert (SCO, Line_State); + end if; + end; + end if; + end loop; + end if; + + -- Compute the decision coverage rate if any + + if not State_Decisions.Is_Empty then + for State_Decision of State_Decisions loop + Branches_Valid := Branches_Valid + 2; + if State_Decision = Covered then + Branches_Covered := Branches_Covered + 2; + elsif State_Decision = Partially_Covered then + Branches_Covered := Branches_Covered + 1; + end if; + end loop; + end if; + + -- Emit the xml line node. Here is an example: + -- + -- + + declare + Line_Attributes : Unbounded_String; + begin + Append (Line_Attributes, A ("number", Img (Line_Num))); + Append (Line_Attributes, A ("hits", Img (Hit))); + if Has_Decision then + Append (Line_Attributes, A ("branch", "true")); + Append + (Line_Attributes, + A + ("condition-coverage", + Img (Ratio (Branches_Covered, Branches_Valid)) + & "%" + & "(" + & Img (Branches_Covered) + & "/" + & Img (Branches_Valid) + & ")")); + else + Append (Line_Attributes, A ("branch", "false")); + end if; + Pp.ST ("line", +Line_Attributes); + + Pp.ST ("conditions"); + declare + I : Integer := 0; + Coverage_Ratio : Integer; + begin + for State_Decision of State_Decisions loop + Coverage_Ratio := + (case State_Decision is + when Not_Covered => 0, + when Partially_Covered => 50, + when Covered => 100); + Pp.T + ("condition", + A ("number", Img (I)) + & A ("type", "jump") + & A ("coverage", Img (Coverage_Ratio) & "%")); + I := I + 1; + end loop; + end; + Pp.ET ("conditions"); + + Pp.ET ("line"); + end; + end; + end if; + end Pretty_Print_Start_Line; + + ------- + -- T -- + ------- + + procedure T + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String) is + begin + Pp.P ("<" & Name & Attributes & "/>"); + end T; + + -------- + -- ST -- + -------- + + procedure ST + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String) is + begin + Pp.P ("<" & Name & Attributes & ">"); + Pp.Indentation := Pp.Indentation + 1; + end ST; + + procedure ST (Pp : in out Cobertura_Pretty_Printer'Class; Name : String) is + begin + Pp.P ("<" & Name & ">"); + Pp.Indentation := Pp.Indentation + 1; + end ST; + +end Annotations.Cobertura; diff --git a/tools/gnatcov/annotations-cobertura.ads b/tools/gnatcov/annotations-cobertura.ads new file mode 100644 index 000000000..8e567be1e --- /dev/null +++ b/tools/gnatcov/annotations-cobertura.ads @@ -0,0 +1,59 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023-2024, AdaCore -- +-- -- +-- GNATcoverage is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This software is distributed in the hope that it will be useful -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- +-- License for more details. You should have received a copy of the GNU -- +-- General Public License distributed with this software; see file -- +-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- +-- of the license. -- +------------------------------------------------------------------------------ + +with Coverage; + +package Annotations.Cobertura is + + -- Generate a report in the Cobertura report format. This report format + -- is designed for integration with standard continuous integration + -- systems, e.g. gitlab CI, which do not support standard gnatcov report + -- formats. The only specification for this format is a document type + -- definition found there: + -- https://github.com/cobertura/web/blob/master/htdocs/xml/coverage-04.dtd + -- + -- This is a partial report in the sense that gnatcov coverage metrics + -- can't be specified accurately in the Cobertura report format. This + -- format provides + -- + -- * Line coverage metrics: whether a line was covered, and the number + -- of coverage hits. + -- + -- * Condition coverage metrics: whether a line is branching (talking + -- Cobertura terminology, which means whether it has any condition). + -- For each condition, whether its true / false / both valuation(s) + -- were covered. + -- + -- Obviously, neither decision and MC/DC coverage can be expressed using + -- the aforementioned metrics without little tweaks. We actually chose + -- to represent decision coverage in the condition coverage metrics: + -- a decision (gnatcov) is represented as a condition (cobertura). We drop + -- the MC/DC coverage as we can't express it. + -- + -- Note that for now, at least some of the continuous integration systems + -- (this is the case for gitlab at least) do not integrate condition + -- coverage results, which means that users won't have decision coverage + -- results over their code if they use it with gitlab. + + procedure Generate_Report (Context : Coverage.Context_Access); + + function Installed return Boolean; + -- Return whether the DTD is installed, i.e. the required resource files + -- are installed in lib/gnatcoverage/. + +end Annotations.Cobertura; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index f52c48030..b37aa450f 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2013-2022, AdaCore -- +-- Copyright (C) 2013-2024, AdaCore -- -- -- -- GNATcoverage is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -16,15 +16,11 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Characters.Handling; +with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Exceptions; use Ada.Exceptions; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; - -pragma Warnings (Off, "* is an internal GNAT unit"); - with Ada.Strings.Unbounded.Aux; -pragma Warnings (On, "* is an internal GNAT unit"); +with Ada.Text_IO.Unbounded_IO; with GNATCOLL.JSON; use GNATCOLL.JSON; @@ -32,15 +28,14 @@ with GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; with Annotations.Html; -with Coverage_Options; use Coverage_Options; with Hex_Images; with Interfaces; with Outputs; with Project; -with Support_Files; use Support_Files; -with Switches; +with Support_Files; use Support_Files; +with Switches; use Switches; with Traces_Disa; -with Traces_Files; use Traces_Files; +with Traces_Files; use Traces_Files; -- This package generates a dynamic HTML report, i.e. an HTML document heavily -- relying on JavaScript for presenting advanced graphical components. @@ -70,42 +65,36 @@ package body Annotations.Dynamic_Html is -- this node with children. It will then be written into a