test/TestRunner.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <string> | ||
| 5 | #include <unordered_set> | ||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | #include <gtest/gtest.h> | ||
| 9 | |||
| 10 | #include <SourceFile.h> | ||
| 11 | #include <driver/Driver.h> | ||
| 12 | #include <exception/CompilerError.h> | ||
| 13 | #include <exception/LexerError.h> | ||
| 14 | #include <exception/LinkerError.h> | ||
| 15 | #include <exception/ParserError.h> | ||
| 16 | #include <exception/SemanticError.h> | ||
| 17 | #include <global/GlobalResourceManager.h> | ||
| 18 | #include <global/TypeRegistry.h> | ||
| 19 | #include <llvm/IR/Module.h> | ||
| 20 | #include <llvm/TargetParser/Host.h> | ||
| 21 | #include <llvm/TargetParser/Triple.h> | ||
| 22 | #include <symboltablebuilder/Scope.h> | ||
| 23 | #include <symboltablebuilder/SymbolTable.h> | ||
| 24 | #include <typechecker/FunctionManager.h> | ||
| 25 | #include <typechecker/InterfaceManager.h> | ||
| 26 | #include <typechecker/StructManager.h> | ||
| 27 | #include <util/FileUtil.h> | ||
| 28 | #include <util/SystemUtil.h> | ||
| 29 | |||
| 30 | #include "driver/TestDriver.h" | ||
| 31 | #include "util/BootstrapUtil.h" | ||
| 32 | #include "util/TestUtil.h" | ||
| 33 | |||
| 34 | using namespace spice::compiler; | ||
| 35 | |||
| 36 | namespace spice::testing { | ||
| 37 | |||
| 38 | extern TestDriverCliOptions testDriverCliOptions; | ||
| 39 | |||
| 40 | namespace { | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Re-run the IR generator for the given source file, discarding the module that was built for it before. | ||
| 44 | * | ||
| 45 | * Since the IR generator emits parts of the IR depending on the selected opt level, a module can only be used to check | ||
| 46 | * the dump of the opt level it was generated for. | ||
| 47 | * | ||
| 48 | * @param sourceFile Source file to re-generate the IR for | ||
| 49 | */ | ||
| 50 | 80 | void reGenerateIR(SourceFile *sourceFile) { | |
| 51 | // Rewind the stage marker, so that the IR generator does not consider this file as already done | ||
| 52 | 80 | sourceFile->previousStage = DEP_GRAPH_VISUALIZER; | |
| 53 | 80 | sourceFile->runIRGenerator(); | |
| 54 | 80 | } | |
| 55 | |||
| 56 | /** | ||
| 57 | * Re-run the IR generator for the given source file and all its (transitive) dependencies, dependencies first. | ||
| 58 | * | ||
| 59 | * This is only required for LTO builds, where the modules of all source files are merged into the LTO module, which is | ||
| 60 | * the one that gets dumped. Without LTO, only the module of the main source file ends up in the dump, so re-generating | ||
| 61 | * the dependencies would be wasted work. | ||
| 62 | * | ||
| 63 | * @param sourceFile Source file to re-generate the IR for | ||
| 64 | * @param visitedSet Already visited source files (guards against cycles, caused by circular imports) | ||
| 65 | */ | ||
| 66 | 2 | void reGenerateIRForLTO(SourceFile *sourceFile, std::unordered_set<const SourceFile *> &visitedSet) { // NOLINT(misc-no-recursion) | |
| 67 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
|
2 | if (!visitedSet.insert(sourceFile).second) |
| 68 | ✗ | return; | |
| 69 | |||
| 70 | // Re-generate the dependencies first, mirroring the order of SourceFile::runBackEnd() | ||
| 71 |
5/8✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 18 not taken.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 18 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 18 not taken.
✓ Branch 13 → 9 taken 1 time.
✓ Branch 13 → 14 taken 2 times.
|
3 | for (SourceFile *dependency : sourceFile->dependencies | std::views::values) |
| 72 |
1/2✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 18 not taken.
|
1 | reGenerateIRForLTO(dependency, visitedSet); |
| 73 | |||
| 74 | 2 | reGenerateIR(sourceFile); | |
| 75 | |||
| 76 | // The optimizer stages of the main source file are driven by the test runner itself. All other files run their | ||
| 77 | // pre-link optimization as part of their own back end, so it has to be repeated here. | ||
| 78 |
2/2✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 17 taken 1 time.
|
2 | if (!sourceFile->isMainFile) |
| 79 | 1 | sourceFile->runPreLinkIROptimizer(); | |
| 80 | } | ||
| 81 | |||
| 82 | } // namespace | ||
| 83 | |||
| 84 | 1342 | static void execTestCase(const TestCase &testCase) { | |
| 85 | // Check if test is disabled | ||
| 86 |
3/4✓ Branch 2 → 3 taken 1342 times.
✗ Branch 2 → 741 not taken.
✓ Branch 3 → 4 taken 27 times.
✓ Branch 3 → 10 taken 1315 times.
|
1342 | if (TestUtil::isDisabled(testCase)) |
| 87 |
3/6✓ Branch 4 → 5 taken 27 times.
✗ Branch 4 → 388 not taken.
✓ Branch 5 → 6 taken 27 times.
✗ Branch 5 → 385 not taken.
✓ Branch 6 → 7 taken 27 times.
✗ Branch 6 → 383 not taken.
|
27 | GTEST_SKIP(); |
| 88 | |||
| 89 | // Create fake cli options | ||
| 90 |
2/4✓ Branch 10 → 11 taken 1315 times.
✗ Branch 10 → 391 not taken.
✓ Branch 11 → 12 taken 1315 times.
✗ Branch 11 → 389 not taken.
|
1315 | const std::filesystem::path mainSourceFilePath = testCase.testPath / REF_NAME_SOURCE; |
| 91 | 1315 | CliOptions cliOptions = { | |
| 92 | /* mainSourceFile= */ mainSourceFilePath, | ||
| 93 | /* targetTriple= */ {}, | ||
| 94 | − | /* targetArch= */ TARGET_UNKNOWN, // GCOV_EXCL_LINE - coverage tool bug | |
| 95 | ✗ | /* targetVendor= */ TARGET_UNKNOWN, | |
| 96 | ✗ | /* targetOs= */ TARGET_UNKNOWN, | |
| 97 | /* isNativeTarget= */ true, | ||
| 98 | /* useCPUFeatures*/ false, // Disabled because it makes the refs differ on different machines | ||
| 99 | /* execute= */ false, // If we set this to 'true', the compiler will not emit object files | ||
| 100 | /* cacheDir= */ "./cache", | ||
| 101 | /* outputDir= */ "./", | ||
| 102 | /* outputPath= */ "", | ||
| 103 | /* buildMode= */ BuildMode::DEBUG, | ||
| 104 | /* outputContainer= */ OutputContainer::EXECUTABLE, | ||
| 105 | // Compile serially: the test cases are already spread over processes by gtest-parallel, so a parallel back end | ||
| 106 | // would only oversubscribe the machine, and the reference outputs stay strictly deterministic this way. | ||
| 107 | /* compileJobCount= */ 1, | ||
| 108 | /* ignoreCache */ true, | ||
| 109 | ✗ | /* llvmArgs= */ "", | |
| 110 | /* printDebugOutput= */ false, | ||
| 111 | CliOptions::DumpSettings{ | ||
| 112 | /* dumpAST= */ false, | ||
| 113 | /* dumpSymbolTables= */ false, | ||
| 114 | /* dumpTypes= */ false, | ||
| 115 | /* dumpCacheStats= */ false, | ||
| 116 | /* dumpDependencyGraph= */ false, | ||
| 117 | /* dumpIR= */ false, | ||
| 118 | /* dumpAssembly= */ false, | ||
| 119 | /* dumpObjectFile= */ false, | ||
| 120 | /* dumpToFiles= */ false, | ||
| 121 | /* abortAfterDump */ false, | ||
| 122 | }, | ||
| 123 | /* namesForIRValues= */ true, | ||
| 124 | /* useLifetimeMarkers= */ false, | ||
| 125 | /* useTBAAMetadata */ false, | ||
| 126 | /* optLevel= */ OptLevel::O0, | ||
| 127 | /* useLTO= */ false, | ||
| 128 | /* backend= */ Backend::LLVM, | ||
| 129 |
2/4✓ Branch 31 → 32 taken 1315 times.
✗ Branch 31 → 400 not taken.
✓ Branch 32 → 33 taken 1315 times.
✗ Branch 32 → 398 not taken.
|
2630 | /* noEntryFct= */ exists(testCase.testPath / CTL_RUN_BUILTIN_TESTS), |
| 130 |
2/4✓ Branch 34 → 35 taken 1315 times.
✗ Branch 34 → 394 not taken.
✓ Branch 35 → 36 taken 1315 times.
✗ Branch 35 → 392 not taken.
|
2630 | /* generateTestMain= */ exists(testCase.testPath / CTL_RUN_BUILTIN_TESTS), |
| 131 | /* staticLinking= */ false, | ||
| 132 | CliOptions::InstrumentationSettings{ | ||
| 133 | /* debugInfoLevel= */ DebugInfoLevel::NONE, | ||
| 134 | 1315 | /* codeCoverage= */ testDriverCliOptions.enableCoverage, | |
| 135 | /* sanitizer= */ Sanitizer::NONE, | ||
| 136 | }, | ||
| 137 | /* disableVerifier= */ false, | ||
| 138 | /* testMode= */ true, | ||
| 139 | /* comparableOutput= */ true, | ||
| 140 | /* buildVars= */ {}, | ||
| 141 |
20/58✓ Branch 13 → 14 taken 1315 times.
✗ Branch 13 → 739 not taken.
✓ Branch 17 → 18 taken 1315 times.
✗ Branch 17 → 434 not taken.
✓ Branch 20 → 21 taken 1315 times.
✗ Branch 20 → 428 not taken.
✓ Branch 23 → 24 taken 1315 times.
✗ Branch 23 → 422 not taken.
✓ Branch 24 → 25 taken 1315 times.
✗ Branch 24 → 419 not taken.
✓ Branch 25 → 26 taken 1315 times.
✗ Branch 25 → 416 not taken.
✓ Branch 26 → 27 taken 1315 times.
✗ Branch 26 → 413 not taken.
✓ Branch 29 → 30 taken 1315 times.
✗ Branch 29 → 407 not taken.
✓ Branch 30 → 31 taken 1315 times.
✗ Branch 30 → 402 not taken.
✓ Branch 33 → 34 taken 1315 times.
✗ Branch 33 → 396 not taken.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 1315 times.
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 45 taken 1315 times.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 1315 times.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 1315 times.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 1315 times.
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 1315 times.
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 57 taken 1315 times.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 60 taken 1315 times.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 63 taken 1315 times.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 65 taken 1315 times.
✗ Branch 404 → 405 not taken.
✗ Branch 404 → 406 not taken.
✗ Branch 410 → 411 not taken.
✗ Branch 410 → 412 not taken.
✗ Branch 413 → 414 not taken.
✗ Branch 413 → 415 not taken.
✗ Branch 416 → 417 not taken.
✗ Branch 416 → 418 not taken.
✗ Branch 419 → 420 not taken.
✗ Branch 419 → 421 not taken.
✗ Branch 425 → 426 not taken.
✗ Branch 425 → 427 not taken.
✗ Branch 431 → 432 not taken.
✗ Branch 431 → 433 not taken.
✗ Branch 437 → 438 not taken.
✗ Branch 437 → 439 not taken.
✗ Branch 440 → 441 not taken.
✗ Branch 440 → 442 not taken.
|
15780 | }; |
| 142 | static_assert(sizeof(CliOptions::DumpSettings) == 10, "CliOptions::DumpSettings struct size changed"); | ||
| 143 | static_assert(sizeof(CliOptions::InstrumentationSettings) == 3, "CliOptions::InstrumentationSettings struct size changed"); | ||
| 144 | #if defined(__clang__) && defined(__apple_build_version__) | ||
| 145 | // some std types for Apple Clang are smaller than for GCC and Clang | ||
| 146 | static_assert(sizeof(CliOptions) == 320, "CliOptions struct size changed"); | ||
| 147 | #else | ||
| 148 | static_assert(sizeof(CliOptions) == 448, "CliOptions struct size changed"); | ||
| 149 | #endif | ||
| 150 | |||
| 151 | // Parse test args | ||
| 152 |
1/2✓ Branch 67 → 68 taken 1315 times.
✗ Branch 67 → 443 not taken.
|
2630 | std::vector<std::string> args = {"spice", "build"}; |
| 153 |
1/2✓ Branch 69 → 70 taken 1315 times.
✗ Branch 69 → 735 not taken.
|
1315 | TestUtil::parseTestArgs(cliOptions.mainSourceFile, args); |
| 154 |
2/4✓ Branch 70 → 71 taken 1315 times.
✗ Branch 70 → 448 not taken.
✓ Branch 71 → 72 taken 1315 times.
✗ Branch 71 → 446 not taken.
|
1315 | args.push_back(mainSourceFilePath.string()); |
| 155 | |||
| 156 | 1315 | bool explicitlySelectedTarget = false; | |
| 157 | 1315 | std::vector<const char *> argv; | |
| 158 |
1/2✓ Branch 74 → 75 taken 1315 times.
✗ Branch 74 → 733 not taken.
|
1315 | argv.reserve(args.size()); |
| 159 |
2/2✓ Branch 93 → 77 taken 4042 times.
✓ Branch 93 → 94 taken 1315 times.
|
6672 | for (const std::string &arg : args) { |
| 160 |
2/2✓ Branch 80 → 81 taken 10 times.
✓ Branch 80 → 82 taken 4032 times.
|
4042 | if (arg.starts_with("--target")) |
| 161 | 10 | explicitlySelectedTarget = true; | |
| 162 |
1/2✓ Branch 83 → 84 taken 4042 times.
✗ Branch 83 → 449 not taken.
|
4042 | argv.push_back(arg.c_str()); |
| 163 | } | ||
| 164 |
1/2✓ Branch 94 → 95 taken 1315 times.
✗ Branch 94 → 733 not taken.
|
1315 | Driver driver(cliOptions, true); |
| 165 |
1/2✓ Branch 97 → 98 taken 1315 times.
✗ Branch 97 → 731 not taken.
|
1315 | driver.parse(static_cast<int>(argv.size()), argv.data()); |
| 166 |
1/2✓ Branch 98 → 99 taken 1315 times.
✗ Branch 98 → 731 not taken.
|
1315 | driver.enrich(); |
| 167 | |||
| 168 | // If this is a cross-compilation test, we want to emit the target information in IR. For this we need to set native to false | ||
| 169 |
2/2✓ Branch 99 → 100 taken 10 times.
✓ Branch 99 → 101 taken 1305 times.
|
1315 | if (explicitlySelectedTarget) |
| 170 | 10 | cliOptions.isNativeTarget = false; | |
| 171 | |||
| 172 | // Redirect all build artifacts to a per-test directory. Driver::enrich() resets these to shared paths (e.g. "./" and a | ||
| 173 | // shared temp cache dir), which would cause concurrently running test processes to clobber each other's object files and | ||
| 174 | // executables. Using a unique directory per test keeps parallel runs (e.g. via gtest-parallel) collision-free. | ||
| 175 |
1/2✓ Branch 101 → 102 taken 1315 times.
✗ Branch 101 → 731 not taken.
|
1315 | const std::filesystem::path artifactDir = TestUtil::prepareArtifactDir(testCase); |
| 176 |
1/2✓ Branch 102 → 103 taken 1315 times.
✗ Branch 102 → 729 not taken.
|
1315 | const std::filesystem::path executablePath = TestUtil::getExecutablePath(artifactDir); |
| 177 |
1/2✓ Branch 103 → 104 taken 1315 times.
✗ Branch 103 → 727 not taken.
|
1315 | cliOptions.outputDir = artifactDir; |
| 178 |
2/4✓ Branch 104 → 105 taken 1315 times.
✗ Branch 104 → 453 not taken.
✓ Branch 105 → 106 taken 1315 times.
✗ Branch 105 → 451 not taken.
|
1315 | cliOptions.cacheDir = artifactDir / "cache"; |
| 179 |
1/2✓ Branch 109 → 110 taken 1315 times.
✗ Branch 109 → 727 not taken.
|
1315 | std::filesystem::create_directories(cliOptions.cacheDir); |
| 180 | |||
| 181 | // Instantiate GlobalResourceManager | ||
| 182 |
1/2✓ Branch 110 → 111 taken 1315 times.
✗ Branch 110 → 727 not taken.
|
1315 | GlobalResourceManager resourceManager(cliOptions); |
| 183 | |||
| 184 | try { | ||
| 185 | // Create source file instance for main source file | ||
| 186 |
2/4✓ Branch 113 → 114 taken 1315 times.
✗ Branch 113 → 457 not taken.
✓ Branch 114 → 115 taken 1315 times.
✗ Branch 114 → 455 not taken.
|
1315 | SourceFile *mainSourceFile = resourceManager.createSourceFile(nullptr, MAIN_FILE_NAME, cliOptions.mainSourceFile, false); |
| 187 | |||
| 188 | // Run Lexer and Parser | ||
| 189 |
2/2✓ Branch 117 → 118 taken 1311 times.
✓ Branch 117 → 686 taken 4 times.
|
1315 | mainSourceFile->runLexer(); |
| 190 |
1/2✓ Branch 118 → 119 taken 1311 times.
✗ Branch 118 → 686 not taken.
|
1311 | mainSourceFile->runParser(); |
| 191 | |||
| 192 | // Build and optimize AST | ||
| 193 |
2/2✓ Branch 119 → 120 taken 1295 times.
✓ Branch 119 → 686 taken 16 times.
|
1311 | mainSourceFile->runASTBuilder(); |
| 194 | |||
| 195 | // Check AST | ||
| 196 |
3/6✓ Branch 122 → 123 taken 1295 times.
✗ Branch 122 → 465 not taken.
✓ Branch 123 → 124 taken 1295 times.
✗ Branch 123 → 463 not taken.
✓ Branch 124 → 125 taken 1295 times.
✗ Branch 124 → 461 not taken.
|
1295 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_SYNTAX_TREE, [&] { |
| 197 | 14 | mainSourceFile->runASTVisualizer(); | |
| 198 | 14 | return mainSourceFile->compilerOutput.astString; | |
| 199 | }); | ||
| 200 | |||
| 201 | // Execute import collector and semantic analysis stages | ||
| 202 |
2/2✓ Branch 129 → 130 taken 1283 times.
✓ Branch 129 → 686 taken 12 times.
|
1295 | mainSourceFile->runImportCollector(); |
| 203 |
2/2✓ Branch 130 → 131 taken 1241 times.
✓ Branch 130 → 686 taken 42 times.
|
1283 | mainSourceFile->runSymbolTableBuilder(); |
| 204 |
2/2✓ Branch 131 → 132 taken 859 times.
✓ Branch 131 → 686 taken 382 times.
|
1241 | mainSourceFile->runMiddleEnd(); // TypeChecker pre + post |
| 205 | |||
| 206 | // Check symbol table output (check happens here to include updates from type checker) | ||
| 207 |
3/6✓ Branch 134 → 135 taken 859 times.
✗ Branch 134 → 479 not taken.
✓ Branch 135 → 136 taken 859 times.
✗ Branch 135 → 477 not taken.
✓ Branch 136 → 137 taken 859 times.
✗ Branch 136 → 475 not taken.
|
1718 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_SYMBOL_TABLE, |
| 208 |
2/4✓ Branch 3 → 4 taken 16 times.
✗ Branch 3 → 11 not taken.
✓ Branch 4 → 5 taken 16 times.
✗ Branch 4 → 9 not taken.
|
1750 | [&] { return mainSourceFile->globalScope->getSymbolTableJSON().dump(/*indent=*/2); }); |
| 209 | |||
| 210 | // Fail if an error was expected | ||
| 211 | − | if (TestUtil::doesRefExist(testCase.testPath / REF_NAME_ERROR_OUTPUT)) // GCOV_EXCL_LINE | |
| 212 | − | FAIL() << "Expected error, but got no error"; // GCOV_EXCL_LINE | |
| 213 | |||
| 214 | // Check dependency graph | ||
| 215 |
3/6✓ Branch 156 → 157 taken 859 times.
✗ Branch 156 → 505 not taken.
✓ Branch 157 → 158 taken 859 times.
✗ Branch 157 → 503 not taken.
✓ Branch 158 → 159 taken 859 times.
✗ Branch 158 → 501 not taken.
|
859 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_DEP_GRAPH, [&] { |
| 216 | 4 | mainSourceFile->runDependencyGraphVisualizer(); | |
| 217 | 4 | return mainSourceFile->compilerOutput.depGraphString; | |
| 218 | }); | ||
| 219 | |||
| 220 | // Run backend for all dependencies | ||
| 221 |
5/8✓ Branch 163 → 164 taken 859 times.
✗ Branch 163 → 515 not taken.
✓ Branch 164 → 165 taken 859 times.
✗ Branch 164 → 515 not taken.
✓ Branch 165 → 166 taken 859 times.
✗ Branch 165 → 515 not taken.
✓ Branch 171 → 167 taken 923 times.
✓ Branch 171 → 172 taken 859 times.
|
1782 | for (SourceFile *sourceFile : mainSourceFile->dependencies | std::views::values) |
| 222 |
1/2✓ Branch 168 → 169 taken 923 times.
✗ Branch 168 → 515 not taken.
|
923 | sourceFile->runBackEnd(); |
| 223 | |||
| 224 | // Keep track of the opt level the IR in the module was generated with | ||
| 225 | 859 | OptLevel generatedOptLevel = cliOptions.optLevel; | |
| 226 | // Execute IR generator in normal or debug mode | ||
| 227 |
1/2✓ Branch 172 → 173 taken 859 times.
✗ Branch 172 → 686 not taken.
|
859 | mainSourceFile->runIRGenerator(); |
| 228 | |||
| 229 | // Coverage counters are woven in by the optimizer pipeline, which the IR-check loop below only runs for opt levels | ||
| 230 | // that have a reference file to compare against. Most test cases only check execution output and have no IR | ||
| 231 | // reference at all, so without this, their linked binary would never actually carry the GCOV counters. Force one | ||
| 232 | // optimizer run at the default opt level in that case. | ||
| 233 |
2/2✓ Branch 173 → 174 taken 421 times.
✓ Branch 173 → 177 taken 438 times.
|
859 | if (cliOptions.instrumentation.codeCoverage) { |
| 234 |
1/2✓ Branch 174 → 175 taken 421 times.
✗ Branch 174 → 686 not taken.
|
421 | const bool anyOptIrRefExists = std::ranges::any_of( |
| 235 |
3/6✓ Branch 2 → 3 taken 1663 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 1663 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 1663 times.
✗ Branch 4 → 10 not taken.
|
1663 | REF_NAME_OPT_IR, [&](const char *const ref) { return TestUtil::doesRefExist(testCase.testPath / ref); }); |
| 236 |
2/2✓ Branch 175 → 176 taken 247 times.
✓ Branch 175 → 177 taken 174 times.
|
421 | if (!anyOptIrRefExists) |
| 237 |
1/2✓ Branch 176 → 177 taken 247 times.
✗ Branch 176 → 686 not taken.
|
247 | mainSourceFile->runDefaultIROptimizer(); |
| 238 | } | ||
| 239 | |||
| 240 | // Check IR code | ||
| 241 |
2/2✓ Branch 188 → 178 taken 5154 times.
✓ Branch 188 → 189 taken 859 times.
|
6013 | for (uint8_t i = 0; i <= 5; i++) { |
| 242 |
1/2✓ Branch 182 → 183 taken 5154 times.
✗ Branch 182 → 516 not taken.
|
5154 | TestUtil::checkRefMatch( |
| 243 |
2/4✓ Branch 180 → 181 taken 5154 times.
✗ Branch 180 → 520 not taken.
✓ Branch 181 → 182 taken 5154 times.
✗ Branch 181 → 518 not taken.
|
10308 | testCase.testPath / REF_NAME_OPT_IR[i], |
| 244 |
1/2✓ Branch 179 → 180 taken 5154 times.
✗ Branch 179 → 524 not taken.
|
10308 | [&] { |
| 245 | 429 | cliOptions.optLevel = static_cast<OptLevel>(i); | |
| 246 | |||
| 247 | // The IR generator emits parts of the IR depending on the selected opt level, so the IR has to be | ||
| 248 | // generated from scratch whenever we check the dump of an opt level other than the one the current module | ||
| 249 | // was built for. Otherwise all dumps would show the IR for the opt level that was active when the IR | ||
| 250 | // generator ran for the first time. | ||
| 251 |
2/2✓ Branch 2 → 3 taken 79 times.
✓ Branch 2 → 13 taken 350 times.
|
429 | if (cliOptions.optLevel != generatedOptLevel) { |
| 252 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 11 taken 78 times.
|
79 | if (cliOptions.useLTO) { |
| 253 | // The bitcode linker moves the module of every source file into the LTO module, so all of them have to | ||
| 254 | // be re-generated. The LTO module itself is started from scratch to not link the same symbols twice. | ||
| 255 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 20 not taken.
|
1 | resourceManager.ltoModule = std::make_unique<llvm::Module>(LTO_FILE_NAME, resourceManager.ltoContext); |
| 256 | 1 | std::unordered_set<const SourceFile *> visitedSet; | |
| 257 |
1/2✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 21 not taken.
|
1 | reGenerateIRForLTO(mainSourceFile, visitedSet); |
| 258 | 1 | } else { | |
| 259 | 78 | reGenerateIR(mainSourceFile); | |
| 260 | } | ||
| 261 | 79 | generatedOptLevel = cliOptions.optLevel; | |
| 262 | } | ||
| 263 | |||
| 264 |
2/2✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 17 taken 428 times.
|
429 | if (cliOptions.useLTO) { |
| 265 | 1 | mainSourceFile->runPreLinkIROptimizer(); | |
| 266 | 1 | mainSourceFile->runBitcodeLinker(); | |
| 267 | 1 | mainSourceFile->runPostLinkIROptimizer(); | |
| 268 | } else { | ||
| 269 | 428 | mainSourceFile->runDefaultIROptimizer(); | |
| 270 | } | ||
| 271 | |||
| 272 | 429 | return mainSourceFile->compilerOutput.irOptString; | |
| 273 | }, | ||
| 274 | 10308 | [&](std::string &expectedOutput, std::string &actualOutput) { | |
| 275 |
2/2✓ Branch 4 → 5 taken 7 times.
✓ Branch 4 → 7 taken 212 times.
|
438 | if (cliOptions.instrumentation.emitsDebugInfo()) { |
| 276 | // Remove the lines, containing paths on the local file system | ||
| 277 | 7 | TestUtil::eraseLinesBySubstring(expectedOutput, " = !DIFile(filename:"); | |
| 278 | 7 | TestUtil::eraseLinesBySubstring(actualOutput, " = !DIFile(filename:"); | |
| 279 | } | ||
| 280 | 219 | }, | |
| 281 | true); | ||
| 282 | } | ||
| 283 | |||
| 284 | // Link the bitcode if not happened yet | ||
| 285 |
3/4✓ Branch 189 → 190 taken 1 time.
✓ Branch 189 → 192 taken 858 times.
✗ Branch 190 → 191 not taken.
✓ Branch 190 → 192 taken 1 time.
|
859 | if (cliOptions.useLTO && cliOptions.optLevel == OptLevel::O0) |
| 286 | ✗ | mainSourceFile->runBitcodeLinker(); | |
| 287 | |||
| 288 | // Check assembly code (only when not running test on GitHub Actions) | ||
| 289 | 859 | bool objectFilesEmitted = false; | |
| 290 | // GCOV_EXCL_START | ||
| 291 | − | if (!testDriverCliOptions.isGitHubActions) { | |
| 292 | − | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_ASM, [&] { | |
| 293 | − | mainSourceFile->runObjectEmitter(); | |
| 294 | − | objectFilesEmitted = true; | |
| 295 | |||
| 296 | − | return mainSourceFile->compilerOutput.asmString; | |
| 297 | }); | ||
| 298 | } | ||
| 299 | // GCOV_EXCL_STOP | ||
| 300 | |||
| 301 | // Check warnings | ||
| 302 |
1/2✓ Branch 203 → 204 taken 859 times.
✗ Branch 203 → 686 not taken.
|
859 | mainSourceFile->collectAndPrintWarnings(); |
| 303 |
3/6✓ Branch 206 → 207 taken 859 times.
✗ Branch 206 → 549 not taken.
✓ Branch 207 → 208 taken 859 times.
✗ Branch 207 → 547 not taken.
✓ Branch 208 → 209 taken 859 times.
✗ Branch 208 → 545 not taken.
|
859 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_WARNING_OUTPUT, [&] { |
| 304 |
1/2✓ Branch 2 → 3 taken 50 times.
✗ Branch 2 → 27 not taken.
|
50 | std::stringstream actualWarningString; |
| 305 |
2/2✓ Branch 18 → 5 taken 52 times.
✓ Branch 18 → 19 taken 50 times.
|
152 | for (const CompilerWarning &warning : mainSourceFile->compilerOutput.warnings) |
| 306 |
2/4✓ Branch 7 → 8 taken 52 times.
✗ Branch 7 → 24 not taken.
✓ Branch 8 → 9 taken 52 times.
✗ Branch 8 → 24 not taken.
|
52 | actualWarningString << warning.warningMessage << "\n"; |
| 307 |
1/2✓ Branch 19 → 20 taken 50 times.
✗ Branch 19 → 25 not taken.
|
100 | return actualWarningString.str(); |
| 308 | 50 | }); | |
| 309 | |||
| 310 | // Do linking and conclude compilation | ||
| 311 |
3/6✓ Branch 213 → 214 taken 859 times.
✗ Branch 213 → 563 not taken.
✓ Branch 214 → 215 taken 859 times.
✗ Branch 214 → 561 not taken.
✓ Branch 215 → 216 taken 859 times.
✗ Branch 215 → 559 not taken.
|
859 | const bool needsNormalRunForOutput = TestUtil::doesRefExist(testCase.testPath / REF_NAME_EXECUTION_OUTPUT); |
| 312 |
3/6✓ Branch 218 → 219 taken 859 times.
✗ Branch 218 → 569 not taken.
✓ Branch 219 → 220 taken 859 times.
✗ Branch 219 → 567 not taken.
✓ Branch 220 → 221 taken 859 times.
✗ Branch 220 → 565 not taken.
|
859 | const bool needsNormalRunForExitCode = TestUtil::doesRefExist(testCase.testPath / REF_NAME_EXIT_CODE); |
| 313 |
3/6✓ Branch 223 → 224 taken 859 times.
✗ Branch 223 → 575 not taken.
✓ Branch 224 → 225 taken 859 times.
✗ Branch 224 → 573 not taken.
✓ Branch 225 → 226 taken 859 times.
✗ Branch 225 → 571 not taken.
|
859 | const bool needsDebuggerRun = TestUtil::doesRefExist(testCase.testPath / REF_NAME_GDB_OUTPUT); |
| 314 |
6/6✓ Branch 228 → 229 taken 133 times.
✓ Branch 228 → 231 taken 726 times.
✓ Branch 229 → 230 taken 110 times.
✓ Branch 229 → 231 taken 23 times.
✓ Branch 230 → 231 taken 2 times.
✓ Branch 230 → 238 taken 108 times.
|
859 | if (needsNormalRunForOutput || needsNormalRunForExitCode || needsDebuggerRun) { |
| 315 | // Emit main source file object if not done already | ||
| 316 |
1/2✓ Branch 231 → 232 taken 751 times.
✗ Branch 231 → 233 not taken.
|
751 | if (!objectFilesEmitted) |
| 317 |
1/2✓ Branch 232 → 233 taken 751 times.
✗ Branch 232 → 686 not taken.
|
751 | mainSourceFile->runObjectEmitter(); |
| 318 | |||
| 319 | // Conclude the compilation | ||
| 320 |
1/2✓ Branch 233 → 234 taken 751 times.
✗ Branch 233 → 686 not taken.
|
751 | mainSourceFile->concludeCompilation(); |
| 321 | |||
| 322 | // Prepare linker | ||
| 323 |
1/2✓ Branch 234 → 235 taken 751 times.
✗ Branch 234 → 686 not taken.
|
751 | resourceManager.linker.outputPath = executablePath; |
| 324 | |||
| 325 | // Prepare and run linker | ||
| 326 |
1/2✓ Branch 235 → 236 taken 751 times.
✗ Branch 235 → 686 not taken.
|
751 | resourceManager.linker.prepare(); |
| 327 |
1/2✓ Branch 236 → 237 taken 751 times.
✗ Branch 236 → 686 not taken.
|
751 | resourceManager.linker.run(); |
| 328 |
1/2✓ Branch 237 → 238 taken 751 times.
✗ Branch 237 → 686 not taken.
|
751 | resourceManager.linker.cleanup(); |
| 329 | } | ||
| 330 | |||
| 331 | // Check type registry output | ||
| 332 |
3/6✓ Branch 240 → 241 taken 859 times.
✗ Branch 240 → 581 not taken.
✓ Branch 241 → 242 taken 859 times.
✗ Branch 241 → 579 not taken.
✓ Branch 242 → 243 taken 859 times.
✗ Branch 242 → 577 not taken.
|
871 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_TYPE_REGISTRY, [&] { return TypeRegistry::dump(); }); |
| 333 | |||
| 334 | // Check cache stats output | ||
| 335 |
3/6✓ Branch 249 → 250 taken 859 times.
✗ Branch 249 → 595 not taken.
✓ Branch 250 → 251 taken 859 times.
✗ Branch 250 → 593 not taken.
✓ Branch 251 → 252 taken 859 times.
✗ Branch 251 → 591 not taken.
|
859 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_CACHE_STATS, [&] { |
| 336 |
1/2✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 31 not taken.
|
2 | std::stringstream cacheStats; |
| 337 |
3/6✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 22 not taken.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 20 not taken.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 20 not taken.
|
2 | cacheStats << FunctionManager::dumpLookupCacheStatistics() << std::endl; |
| 338 |
3/6✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 25 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 23 not taken.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 23 not taken.
|
2 | cacheStats << StructManager::dumpLookupCacheStatistics() << std::endl; |
| 339 |
3/6✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 26 not taken.
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 26 not taken.
|
2 | cacheStats << InterfaceManager::dumpLookupCacheStatistics() << std::endl; |
| 340 |
1/2✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 29 not taken.
|
4 | return cacheStats.str(); |
| 341 | 2 | }); | |
| 342 | |||
| 343 |
3/6✓ Branch 256 → 257 taken 859 times.
✗ Branch 256 → 609 not taken.
✓ Branch 257 → 258 taken 859 times.
✗ Branch 257 → 607 not taken.
✓ Branch 258 → 259 taken 859 times.
✗ Branch 258 → 605 not taken.
|
859 | const bool checkExecutionOutput = TestUtil::doesRefExist(testCase.testPath / REF_NAME_EXECUTION_OUTPUT); |
| 344 |
3/6✓ Branch 261 → 262 taken 859 times.
✗ Branch 261 → 615 not taken.
✓ Branch 262 → 263 taken 859 times.
✗ Branch 262 → 613 not taken.
✓ Branch 263 → 264 taken 859 times.
✗ Branch 263 → 611 not taken.
|
859 | const bool checkExecutionExitCode = TestUtil::doesRefExist(testCase.testPath / REF_NAME_EXIT_CODE); |
| 345 |
4/4✓ Branch 266 → 267 taken 133 times.
✓ Branch 266 → 268 taken 726 times.
✓ Branch 267 → 268 taken 23 times.
✓ Branch 267 → 324 taken 110 times.
|
859 | if (checkExecutionOutput || checkExecutionExitCode) { |
| 346 |
2/4✓ Branch 268 → 269 taken 749 times.
✗ Branch 268 → 619 not taken.
✓ Branch 269 → 270 taken 749 times.
✗ Branch 269 → 617 not taken.
|
749 | const std::filesystem::path cliFlagsFile = testCase.testPath / INPUT_NAME_CLI_FLAGS; |
| 347 | // Execute binary | ||
| 348 |
1/2✓ Branch 271 → 272 taken 749 times.
✗ Branch 271 → 669 not taken.
|
749 | std::stringstream cmd; |
| 349 |
1/2✗ Branch 272 → 273 not taken.
✓ Branch 272 → 274 taken 749 times.
|
749 | if (testDriverCliOptions.enableLeakDetection) |
| 350 | ✗ | cmd << "valgrind -q --leak-check=full --suppressions=../../valgrind.supp --num-callers=100 --error-exitcode=1 "; | |
| 351 |
2/4✓ Branch 274 → 275 taken 749 times.
✗ Branch 274 → 622 not taken.
✓ Branch 275 → 276 taken 749 times.
✗ Branch 275 → 620 not taken.
|
749 | cmd << executablePath.string(); |
| 352 |
3/4✓ Branch 277 → 278 taken 749 times.
✗ Branch 277 → 667 not taken.
✓ Branch 278 → 279 taken 6 times.
✓ Branch 278 → 285 taken 743 times.
|
749 | if (exists(cliFlagsFile)) |
| 353 |
4/8✓ Branch 279 → 280 taken 6 times.
✗ Branch 279 → 667 not taken.
✓ Branch 280 → 281 taken 6 times.
✗ Branch 280 → 625 not taken.
✓ Branch 281 → 282 taken 6 times.
✗ Branch 281 → 623 not taken.
✓ Branch 282 → 283 taken 6 times.
✗ Branch 282 → 623 not taken.
|
6 | cmd << " " << TestUtil::getFileContentLinesVector(cliFlagsFile).at(0); |
| 354 |
2/4✓ Branch 285 → 286 taken 749 times.
✗ Branch 285 → 628 not taken.
✓ Branch 286 → 287 taken 749 times.
✗ Branch 286 → 626 not taken.
|
749 | const auto [output, exitCode] = SystemUtil::exec(cmd.str(), checkExecutionOutput); |
| 355 | |||
| 356 | // Check if the execution output matches the expected output | ||
| 357 | 726 | const auto getActualOutput = [&] { return output; }; | |
| 358 |
3/6✓ Branch 290 → 291 taken 749 times.
✗ Branch 290 → 633 not taken.
✓ Branch 291 → 292 taken 749 times.
✗ Branch 291 → 631 not taken.
✓ Branch 292 → 293 taken 749 times.
✗ Branch 292 → 629 not taken.
|
749 | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_EXECUTION_OUTPUT, getActualOutput); |
| 359 | |||
| 360 | #if not OS_WINDOWS // Windows does not give us the exit code, so we cannot check it on Windows | ||
| 361 | // Check if the exit code matches the expected one | ||
| 362 | // If no exit code ref file exists, check against 0 | ||
| 363 | 51 | const auto getActualExitCode = [&] { return std::to_string(exitCode); }; | |
| 364 |
3/6✓ Branch 299 → 300 taken 749 times.
✗ Branch 299 → 646 not taken.
✓ Branch 300 → 301 taken 749 times.
✗ Branch 300 → 644 not taken.
✓ Branch 301 → 302 taken 749 times.
✗ Branch 301 → 642 not taken.
|
749 | const bool refExists = TestUtil::checkRefMatch(testCase.testPath / REF_NAME_EXIT_CODE, getActualExitCode); |
| 365 |
2/2✓ Branch 306 → 307 taken 698 times.
✓ Branch 306 → 320 taken 51 times.
|
749 | if (!refExists) { |
| 366 |
2/12✓ Branch 307 → 308 taken 698 times.
✗ Branch 307 → 655 not taken.
✗ Branch 309 → 310 not taken.
✓ Branch 309 → 318 taken 698 times.
✗ Branch 310 → 311 not taken.
✗ Branch 310 → 661 not taken.
✗ Branch 311 → 312 not taken.
✗ Branch 311 → 659 not taken.
✗ Branch 313 → 314 not taken.
✗ Branch 313 → 658 not taken.
✗ Branch 314 → 315 not taken.
✗ Branch 314 → 656 not taken.
|
698 | EXPECT_EQ(0, exitCode) << "Program exited with non-zero exit code"; |
| 367 | } | ||
| 368 | #endif | ||
| 369 | 749 | } | |
| 370 | |||
| 371 | // Check if the debugger output matches the expected output | ||
| 372 | // GCOV_EXCL_START | ||
| 373 | − | if (!testDriverCliOptions.isGitHubActions) { // GDB tests are currently not support on GH actions | |
| 374 | − | TestUtil::checkRefMatch( | |
| 375 | − | testCase.testPath / REF_NAME_GDB_OUTPUT, | |
| 376 | − | [&] { | |
| 377 | // Execute debugger script | ||
| 378 | − | std::filesystem::path gdbScriptPath = testCase.testPath / CTL_DEBUG_SCRIPT; | |
| 379 | − | EXPECT_TRUE(std::filesystem::exists(gdbScriptPath)) << "Debug output requested, but debug script not found"; | |
| 380 | − | gdbScriptPath.make_preferred(); | |
| 381 | // -nx: ignore any local/system .gdbinit so a developer's own GDB setup (e.g. globally installed | ||
| 382 | // pretty printers) cannot change test output; tests that want the pretty printers source them | ||
| 383 | // explicitly from within their debug script instead. | ||
| 384 | − | const std::string cmd = "gdb -nx -x " + gdbScriptPath.string() + " " + executablePath.string(); | |
| 385 | − | const auto [output, exitCode] = SystemUtil::exec(cmd); | |
| 386 | |||
| 387 | #if not OS_WINDOWS // Windows does not give us the exit code, so we cannot check it on Windows | ||
| 388 | − | EXPECT_EQ(0, exitCode) << "GDB exited with non-zero exit code when running debug script"; | |
| 389 | #endif | ||
| 390 | |||
| 391 | − | return output; | |
| 392 | − | }, | |
| 393 | − | [&](std::string &expectedOutput, std::string &actualOutput) { | |
| 394 | // Do not compare against the GDB header | ||
| 395 | − | TestUtil::eraseGDBHeader(expectedOutput); | |
| 396 | − | TestUtil::eraseGDBHeader(actualOutput); | |
| 397 | − | }); | |
| 398 | } | ||
| 399 | // GCOV_EXCL_STOP | ||
| 400 |
4/7✗ Branch 687 → 688 not taken.
✓ Branch 687 → 689 taken 2 times.
✓ Branch 687 → 692 taken 16 times.
✓ Branch 687 → 695 taken 160 times.
✓ Branch 687 → 698 taken 278 times.
✗ Branch 687 → 701 not taken.
✗ Branch 687 → 704 not taken.
|
456 | } catch (LexerError &error) { |
| 401 |
1/2✓ Branch 690 → 691 taken 2 times.
✗ Branch 690 → 707 not taken.
|
2 | TestUtil::handleError(testCase, error); |
| 402 |
1/2✓ Branch 691 → 336 taken 2 times.
✗ Branch 691 → 725 not taken.
|
18 | } catch (ParserError &error) { |
| 403 |
1/2✓ Branch 693 → 694 taken 16 times.
✗ Branch 693 → 709 not taken.
|
16 | TestUtil::handleError(testCase, error); |
| 404 |
1/2✓ Branch 694 → 336 taken 16 times.
✗ Branch 694 → 725 not taken.
|
176 | } catch (SemanticError &error) { |
| 405 |
1/2✓ Branch 696 → 697 taken 160 times.
✗ Branch 696 → 711 not taken.
|
160 | TestUtil::handleError(testCase, error); |
| 406 |
1/2✓ Branch 697 → 336 taken 160 times.
✗ Branch 697 → 725 not taken.
|
438 | } catch (CompilerError &error) { |
| 407 |
1/2✓ Branch 699 → 700 taken 278 times.
✗ Branch 699 → 713 not taken.
|
278 | TestUtil::handleError(testCase, error); |
| 408 | 278 | } catch (LinkerError &error) { | |
| 409 | ✗ | TestUtil::handleError(testCase, error); | |
| 410 | − | } catch (std::exception &error) { // GCOV_EXCL_LINE | |
| 411 | − | TestUtil::handleError(testCase, error); // GCOV_EXCL_LINE | |
| 412 | − | } // GCOV_EXCL_LINE | |
| 413 | |||
| 414 |
3/6✓ Branch 336 → 337 taken 1315 times.
✗ Branch 336 → 724 not taken.
✓ Branch 337 → 338 taken 1315 times.
✗ Branch 337 → 721 not taken.
✓ Branch 338 → 339 taken 1315 times.
✗ Branch 338 → 719 not taken.
|
1315 | SUCCEED(); |
| 415 |
8/16✓ Branch 343 → 344 taken 1315 times.
✗ Branch 343 → 345 not taken.
✓ Branch 348 → 349 taken 1315 times.
✗ Branch 348 → 350 not taken.
✓ Branch 353 → 354 taken 1315 times.
✗ Branch 353 → 355 not taken.
✓ Branch 358 → 359 taken 1315 times.
✗ Branch 358 → 360 not taken.
✓ Branch 363 → 364 taken 1315 times.
✗ Branch 363 → 365 not taken.
✓ Branch 368 → 369 taken 1315 times.
✗ Branch 368 → 370 not taken.
✓ Branch 373 → 374 taken 1315 times.
✗ Branch 373 → 375 not taken.
✓ Branch 378 → 379 taken 1315 times.
✗ Branch 378 → 381 not taken.
|
10520 | } |
| 416 | |||
| 417 | /** | ||
| 418 | * Runs a test case against the bootstrap compiler, built at the start of the test run. The bootstrap compiler is invoked | ||
| 419 | * like the host compiler would be invoked by a user, since it cannot be driven stage by stage from here. | ||
| 420 | * | ||
| 421 | * The bootstrap compiler is still incomplete, so only the reference outputs it can already produce are checked: the | ||
| 422 | * serialized AST, the raised error, the IR code, and the execution output and exit code of the compiled program. A missing | ||
| 423 | * error only fails the test for the error kinds listed in BOOTSTRAP_SUPPORTED_ERROR_PREFIXES. Beyond that, each test case | ||
| 424 | * checks that the bootstrap compiler runs through all of its implemented stages without crashing or raising an unexpected | ||
| 425 | * error. | ||
| 426 | */ | ||
| 427 | ✗ | static void execBootstrapTestCase(const TestCase &testCase) { | |
| 428 | // Check if test is disabled | ||
| 429 | ✗ | if (TestUtil::isDisabled(testCase)) | |
| 430 | ✗ | GTEST_SKIP(); | |
| 431 | |||
| 432 | ✗ | const std::filesystem::path mainSourceFilePath = testCase.testPath / REF_NAME_SOURCE; | |
| 433 | ✗ | const std::filesystem::path artifactDir = TestUtil::prepareArtifactDir(testCase); | |
| 434 | ✗ | const std::filesystem::path executablePath = TestUtil::getExecutablePath(artifactDir); | |
| 435 | ✗ | const bool checkAST = TestUtil::doesRefExist(testCase.testPath / REF_NAME_SYNTAX_TREE); | |
| 436 | ✗ | const bool checkExecutionOutput = TestUtil::doesRefExist(testCase.testPath / REF_NAME_EXECUTION_OUTPUT); | |
| 437 | ✗ | const bool checkExecutionExitCode = TestUtil::doesRefExist(testCase.testPath / REF_NAME_EXIT_CODE); | |
| 438 | ✗ | const bool needsExecutable = checkExecutionOutput || checkExecutionExitCode; | |
| 439 | |||
| 440 | // Assemble the command line, mirroring the one the test runner passes to the host compiler | ||
| 441 | ✗ | const auto buildArgs = [&](const std::filesystem::path &outputPath) { | |
| 442 | ✗ | std::vector<std::string> args = {"build", "--test-mode"}; | |
| 443 | ✗ | TestUtil::parseTestArgs(mainSourceFilePath, args); | |
| 444 | ✗ | if (exists(testCase.testPath / CTL_RUN_BUILTIN_TESTS)) | |
| 445 | ✗ | args.emplace_back("--no-entry"); | |
| 446 | ✗ | args.emplace_back("--output"); | |
| 447 | ✗ | args.push_back(outputPath.string()); | |
| 448 | ✗ | return args; | |
| 449 | ✗ | }; | |
| 450 | ✗ | std::vector<std::string> args = buildArgs(executablePath); | |
| 451 | // Like the host test runner, only link an executable if it gets executed afterwards | ||
| 452 | ✗ | if (!needsExecutable) { | |
| 453 | ✗ | args.emplace_back("--output-container"); | |
| 454 | ✗ | args.emplace_back("obj"); | |
| 455 | } | ||
| 456 | ✗ | if (checkAST) | |
| 457 | ✗ | args.emplace_back("--dump-ast"); | |
| 458 | ✗ | args.push_back(mainSourceFilePath.string()); | |
| 459 | |||
| 460 | // Run the bootstrap compiler | ||
| 461 | ✗ | const auto [output, exitCode] = SystemUtil::exec(testDriverCliOptions.bootstrapCompilerPath, args, true); | |
| 462 | − | if (testDriverCliOptions.isVerbose) // GCOV_EXCL_LINE | |
| 463 | − | std::cout << "Bootstrap compiler output:\n" << output; // GCOV_EXCL_LINE | |
| 464 | |||
| 465 | // Check if the bootstrap compiler raised an error | ||
| 466 | ✗ | const std::filesystem::path errorRefPath = testCase.testPath / REF_NAME_ERROR_OUTPUT; | |
| 467 | ✗ | if (const std::optional<std::string> errorMessage = BootstrapUtil::extractErrorMessage(output)) { | |
| 468 | ✗ | if (!TestUtil::doesRefExist(errorRefPath)) | |
| 469 | ✗ | FAIL() << "Expected no error, but got: " << *errorMessage; | |
| 470 | ✗ | TestUtil::checkRefMatch(errorRefPath, [&] { return *errorMessage; }); | |
| 471 | ✗ | return; | |
| 472 | ✗ | } | |
| 473 | ✗ | if (exitCode != 0) | |
| 474 | ✗ | FAIL() << "Bootstrap compiler exited with code " << exitCode << ":\n" << output; | |
| 475 | |||
| 476 | // Check AST | ||
| 477 | ✗ | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_SYNTAX_TREE, [&] { | |
| 478 | ✗ | const std::optional<std::string> astString = BootstrapUtil::extractSerializedAST(output); | |
| 479 | ✗ | EXPECT_TRUE(astString.has_value()) << "Bootstrap compiler did not dump the AST:\n" << output; | |
| 480 | ✗ | return astString.value_or(""); | |
| 481 | ✗ | }); | |
| 482 | |||
| 483 | // Fail if an error was expected, that the bootstrap compiler is already able to raise | ||
| 484 | ✗ | if (TestUtil::doesRefExist(errorRefPath) && BootstrapUtil::isErrorSupported(errorRefPath)) | |
| 485 | ✗ | FAIL() << "Expected error, but got no error"; | |
| 486 | |||
| 487 | // Check IR code. The host checks the IR after running the optimizer pipeline of each opt level, for which a reference exists. | ||
| 488 | // The bootstrap compiler dumps the optimized IR of every source file into the output dir, so it is compiled once per opt level. | ||
| 489 | ✗ | for (uint8_t i = 0; i <= 5; i++) { | |
| 490 | ✗ | TestUtil::checkRefMatch( | |
| 491 | ✗ | testCase.testPath / REF_NAME_OPT_IR[i], | |
| 492 | ✗ | [&] { | |
| 493 | ✗ | const std::filesystem::path irArtifactDir = artifactDir / ("ir-O" + std::to_string(i)); | |
| 494 | ✗ | std::filesystem::create_directories(irArtifactDir); | |
| 495 | ✗ | std::vector<std::string> irArgs = buildArgs(irArtifactDir / "object.o"); | |
| 496 | ✗ | irArgs.emplace_back("-O" + std::string(1, BOOTSTRAP_OPT_LEVEL_NAMES[i])); | |
| 497 | ✗ | irArgs.emplace_back("--output-container"); | |
| 498 | ✗ | irArgs.emplace_back("obj"); | |
| 499 | ✗ | irArgs.emplace_back("--dump-ir"); | |
| 500 | ✗ | irArgs.emplace_back("--dump-to-files"); | |
| 501 | ✗ | irArgs.push_back(mainSourceFilePath.string()); | |
| 502 | ✗ | const auto [irOutput, irExitCode] = SystemUtil::exec(testDriverCliOptions.bootstrapCompilerPath, irArgs, true); | |
| 503 | ✗ | EXPECT_EQ(0, irExitCode) << "Bootstrap compiler exited with code " << irExitCode << ":\n" << irOutput; | |
| 504 | // With LTO, the bootstrap compiler dumps the IR of the LTO module after the post-link optimization | ||
| 505 | ✗ | const bool useLTO = std::ranges::find(irArgs, "-lto") != irArgs.end(); | |
| 506 | ✗ | const std::string irDumpName = | |
| 507 | ✗ | useLTO ? "source-ir-code-lto-post-link.ll" : "source-ir-code-O" + std::to_string(i) + ".ll"; | |
| 508 | ✗ | const std::filesystem::path irDumpPath = irArtifactDir / irDumpName; | |
| 509 | ✗ | if (!exists(irDumpPath)) | |
| 510 | ✗ | return std::string(); | |
| 511 | ✗ | return FileUtil::getFileContent(irDumpPath); | |
| 512 | ✗ | }, | |
| 513 | ✗ | [&](std::string &expectedOutput, std::string &actualOutput) { | |
| 514 | // The LLVM C API, which the bootstrap compiler uses, cannot mark global values as dso_local | ||
| 515 | ✗ | BootstrapUtil::eraseDSOLocalMarkers(expectedOutput); | |
| 516 | ✗ | BootstrapUtil::eraseDSOLocalMarkers(actualOutput); | |
| 517 | ✗ | }, | |
| 518 | true); | ||
| 519 | } | ||
| 520 | |||
| 521 | // Check execution output and exit code | ||
| 522 | ✗ | if (needsExecutable) { | |
| 523 | // Execute binary | ||
| 524 | ✗ | std::stringstream cmd; | |
| 525 | ✗ | cmd << executablePath.string(); | |
| 526 | ✗ | const std::filesystem::path cliFlagsFile = testCase.testPath / INPUT_NAME_CLI_FLAGS; | |
| 527 | ✗ | if (exists(cliFlagsFile)) | |
| 528 | ✗ | cmd << " " << TestUtil::getFileContentLinesVector(cliFlagsFile).at(0); | |
| 529 | ✗ | const auto [programOutput, programExitCode] = SystemUtil::exec(cmd.str(), checkExecutionOutput); | |
| 530 | |||
| 531 | // Check if the execution output matches the expected output | ||
| 532 | ✗ | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_EXECUTION_OUTPUT, [&] { return programOutput; }); | |
| 533 | |||
| 534 | #if not OS_WINDOWS // Windows does not give us the exit code, so we cannot check it on Windows | ||
| 535 | // Check if the exit code matches the expected one. If no exit code ref file exists, check against 0 | ||
| 536 | ✗ | const bool refExists = TestUtil::checkRefMatch(testCase.testPath / REF_NAME_EXIT_CODE, | |
| 537 | ✗ | [&] { return std::to_string(programExitCode); }); | |
| 538 | ✗ | if (!refExists) { | |
| 539 | ✗ | EXPECT_EQ(0, programExitCode) << "Program exited with non-zero exit code"; | |
| 540 | } | ||
| 541 | #endif | ||
| 542 | ✗ | } | |
| 543 | |||
| 544 | ✗ | SUCCEED(); | |
| 545 | ✗ | } | |
| 546 | |||
| 547 | /** | ||
| 548 | * Runs a test case against the host compiler or, in bootstrap mode, against the bootstrap compiler | ||
| 549 | */ | ||
| 550 | 1342 | static void runTestCase(const TestCase &testCase) { | |
| 551 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1342 times.
|
1342 | if (testDriverCliOptions.bootstrapMode) |
| 552 | ✗ | execBootstrapTestCase(testCase); | |
| 553 | else | ||
| 554 | 1342 | execTestCase(testCase); | |
| 555 | 1342 | } | |
| 556 | |||
| 557 | namespace { | ||
| 558 | |||
| 559 | /** | ||
| 560 | * Runs a lint test case against the bootstrap compiler: invokes its `lint` subcommand and compares the emitted | ||
| 561 | * findings against lint.out. The bootstrap compiler colorizes its findings, so the captured output is | ||
| 562 | * de-colorized before being matched against the plain-text reference. | ||
| 563 | */ | ||
| 564 | ✗ | void execBootstrapLinterTestCase(const TestCase &testCase) { | |
| 565 | // Check if test is disabled | ||
| 566 | ✗ | if (TestUtil::isDisabled(testCase)) | |
| 567 | ✗ | GTEST_SKIP(); | |
| 568 | |||
| 569 | ✗ | const std::filesystem::path mainSourceFilePath = testCase.testPath / REF_NAME_SOURCE; | |
| 570 | |||
| 571 | // Assemble the command line | ||
| 572 | ✗ | const std::vector<std::string> args = {"lint", mainSourceFilePath.string()}; | |
| 573 | |||
| 574 | // Run the bootstrap compiler | ||
| 575 | ✗ | const auto [output, exitCode] = SystemUtil::exec(testDriverCliOptions.bootstrapCompilerPath, args, true); | |
| 576 | − | if (testDriverCliOptions.isVerbose) // GCOV_EXCL_LINE | |
| 577 | − | std::cout << "Bootstrap compiler output:\n" << output; // GCOV_EXCL_LINE | |
| 578 | |||
| 579 | // Check if the bootstrap compiler raised an error | ||
| 580 | ✗ | const std::filesystem::path errorRefPath = testCase.testPath / REF_NAME_ERROR_OUTPUT; | |
| 581 | ✗ | if (const std::optional<std::string> errorMessage = BootstrapUtil::extractErrorMessage(output)) { | |
| 582 | ✗ | if (!TestUtil::doesRefExist(errorRefPath)) | |
| 583 | ✗ | FAIL() << "Expected no error, but got: " << *errorMessage; | |
| 584 | ✗ | TestUtil::checkRefMatch(errorRefPath, [&] { return *errorMessage; }); | |
| 585 | ✗ | return; | |
| 586 | ✗ | } | |
| 587 | ✗ | if (exitCode != 0) | |
| 588 | ✗ | FAIL() << "Bootstrap compiler exited with code " << exitCode << ":\n" << output; | |
| 589 | |||
| 590 | // Fail if an error was expected, that the bootstrap compiler is already able to raise | ||
| 591 | ✗ | if (TestUtil::doesRefExist(errorRefPath) && BootstrapUtil::isErrorSupported(errorRefPath)) | |
| 592 | ✗ | FAIL() << "Expected error, but got no error"; | |
| 593 | |||
| 594 | // Check lint findings against the reference (de-colorized) | ||
| 595 | ✗ | TestUtil::checkRefMatch(testCase.testPath / REF_NAME_LINT_OUTPUT, [&] { return BootstrapUtil::stripAnsiCodes(output); }); | |
| 596 | |||
| 597 | ✗ | SUCCEED(); | |
| 598 | ✗ | } | |
| 599 | |||
| 600 | } // namespace | ||
| 601 | |||
| 602 | class CommonTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 603 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
58 | TEST_P(CommonTests, ) { runTestCase(GetParam()); } |
| 604 |
4/14spice::testing::gtest_CommonTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_CommonTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 22 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 22 times.
✗ Branch 12 → 24 not taken.
|
48 | INSTANTIATE_TEST_SUITE_P(, CommonTests, ::testing::ValuesIn(TestUtil::collectTestCases("common", false)), |
| 605 | TestUtil::NameResolver()); | ||
| 606 | |||
| 607 | class LexerTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 608 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
18 | TEST_P(LexerTests, ) { runTestCase(GetParam()); } |
| 609 |
4/14spice::testing::gtest_LexerTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_LexerTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 2 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 24 not taken.
|
8 | INSTANTIATE_TEST_SUITE_P(, LexerTests, ::testing::ValuesIn(TestUtil::collectTestCases("lexer", false)), TestUtil::NameResolver()); |
| 610 | |||
| 611 | class ParserTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 612 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
46 | TEST_P(ParserTests, ) { runTestCase(GetParam()); } |
| 613 |
4/14spice::testing::gtest_ParserTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_ParserTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 16 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 16 times.
✗ Branch 12 → 24 not taken.
|
36 | INSTANTIATE_TEST_SUITE_P(, ParserTests, ::testing::ValuesIn(TestUtil::collectTestCases("parser", false)), |
| 614 | TestUtil::NameResolver()); | ||
| 615 | |||
| 616 | class SymbolTableBuilderTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 617 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
114 | TEST_P(SymbolTableBuilderTests, ) { runTestCase(GetParam()); } |
| 618 |
4/14spice::testing::gtest_SymbolTableBuilderTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_SymbolTableBuilderTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 50 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 50 times.
✗ Branch 12 → 24 not taken.
|
104 | INSTANTIATE_TEST_SUITE_P(, SymbolTableBuilderTests, ::testing::ValuesIn(TestUtil::collectTestCases("symboltablebuilder", true)), |
| 619 | TestUtil::NameResolver()); | ||
| 620 | |||
| 621 | class TypeCheckerTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 622 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
986 | TEST_P(TypeCheckerTests, ) { runTestCase(GetParam()); } |
| 623 |
4/14spice::testing::gtest_TypeCheckerTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_TypeCheckerTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 486 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 486 times.
✗ Branch 12 → 24 not taken.
|
976 | INSTANTIATE_TEST_SUITE_P(, TypeCheckerTests, ::testing::ValuesIn(TestUtil::collectTestCases("typechecker", true)), |
| 624 | TestUtil::NameResolver()); | ||
| 625 | |||
| 626 | class IRGeneratorTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 627 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
894 | TEST_P(IRGeneratorTests, ) { runTestCase(GetParam()); } |
| 628 |
4/14spice::testing::gtest_IRGeneratorTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_IRGeneratorTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 440 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 440 times.
✗ Branch 12 → 24 not taken.
|
884 | INSTANTIATE_TEST_SUITE_P(, IRGeneratorTests, ::testing::ValuesIn(TestUtil::collectTestCases("irgenerator", true)), |
| 629 | TestUtil::NameResolver()); | ||
| 630 | |||
| 631 | class StdTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 632 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
618 | TEST_P(StdTests, ) { runTestCase(GetParam()); } |
| 633 |
4/14spice::testing::gtest_StdTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_StdTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 302 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 302 times.
✗ Branch 12 → 24 not taken.
|
608 | INSTANTIATE_TEST_SUITE_P(, StdTests, ::testing::ValuesIn(TestUtil::collectTestCases("std", true)), TestUtil::NameResolver()); |
| 634 | |||
| 635 | class BenchmarkTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 636 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
42 | TEST_P(BenchmarkTests, ) { runTestCase(GetParam()); } |
| 637 |
4/14spice::testing::gtest_BenchmarkTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_BenchmarkTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 14 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 14 times.
✗ Branch 12 → 24 not taken.
|
32 | INSTANTIATE_TEST_SUITE_P(, BenchmarkTests, ::testing::ValuesIn(TestUtil::collectTestCases("benchmark", false)), |
| 638 | TestUtil::NameResolver()); | ||
| 639 | |||
| 640 | class ExampleTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 641 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
34 | TEST_P(ExampleTests, ) { runTestCase(GetParam()); } |
| 642 |
4/14spice::testing::gtest_ExampleTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_ExampleTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 10 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 10 times.
✗ Branch 12 → 24 not taken.
|
24 | INSTANTIATE_TEST_SUITE_P(, ExampleTests, ::testing::ValuesIn(TestUtil::collectTestCases("examples", false)), |
| 643 | TestUtil::NameResolver()); | ||
| 644 | |||
| 645 | class LinterTests : public ::testing::TestWithParam<TestCase> {}; | ||
| 646 |
7/16✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 53 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 45 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 43 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 38 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 34 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 31 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
26 | TEST_P(LinterTests, ) { |
| 647 |
1/2✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 10 not taken.
|
6 | if (!testDriverCliOptions.bootstrapMode) |
| 648 |
4/8✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 18 not taken.
✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 16 not taken.
✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 15 not taken.
✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 13 not taken.
|
6 | GTEST_SKIP() << "Linter tests run against the bootstrap compiler only"; |
| 649 | ✗ | execBootstrapLinterTestCase(GetParam()); | |
| 650 | } | ||
| 651 |
4/14spice::testing::gtest_LinterTests_EvalGenerator_():
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
spice::testing::gtest_LinterTests_EvalGenerateName_(testing::TestParamInfo<spice::testing::TestCase> const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 6 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 20 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 18 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 16 not taken.
✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 24 not taken.
|
16 | INSTANTIATE_TEST_SUITE_P(, LinterTests, ::testing::ValuesIn(TestUtil::collectTestCases("linter", false)), |
| 652 | TestUtil::NameResolver()); | ||
| 653 | |||
| 654 | } // namespace spice::testing | ||
| 655 |