@d-es-ign/stryker-js-core 9.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +96 -0
- package/bin/stryker +2 -0
- package/bin/stryker.js +6 -0
- package/dist/src/checker/checker-child-process-proxy.d.ts +16 -0
- package/dist/src/checker/checker-child-process-proxy.d.ts.map +1 -0
- package/dist/src/checker/checker-child-process-proxy.js +22 -0
- package/dist/src/checker/checker-child-process-proxy.js.map +1 -0
- package/dist/src/checker/checker-facade.d.ts +9 -0
- package/dist/src/checker/checker-facade.d.ts.map +1 -0
- package/dist/src/checker/checker-facade.js +52 -0
- package/dist/src/checker/checker-facade.js.map +1 -0
- package/dist/src/checker/checker-factory.d.ts +10 -0
- package/dist/src/checker/checker-factory.d.ts.map +1 -0
- package/dist/src/checker/checker-factory.js +10 -0
- package/dist/src/checker/checker-factory.js.map +1 -0
- package/dist/src/checker/checker-resource.d.ts +8 -0
- package/dist/src/checker/checker-resource.d.ts.map +1 -0
- package/dist/src/checker/checker-resource.js +2 -0
- package/dist/src/checker/checker-resource.js.map +1 -0
- package/dist/src/checker/checker-retry-decorator.d.ts +12 -0
- package/dist/src/checker/checker-retry-decorator.d.ts.map +1 -0
- package/dist/src/checker/checker-retry-decorator.js +37 -0
- package/dist/src/checker/checker-retry-decorator.js.map +1 -0
- package/dist/src/checker/checker-worker.d.ts +14 -0
- package/dist/src/checker/checker-worker.d.ts.map +1 -0
- package/dist/src/checker/checker-worker.js +41 -0
- package/dist/src/checker/checker-worker.js.map +1 -0
- package/dist/src/checker/index.d.ts +4 -0
- package/dist/src/checker/index.d.ts.map +1 -0
- package/dist/src/checker/index.js +4 -0
- package/dist/src/checker/index.js.map +1 -0
- package/dist/src/child-proxy/child-process-crashed-error.d.ts +8 -0
- package/dist/src/child-proxy/child-process-crashed-error.d.ts.map +1 -0
- package/dist/src/child-proxy/child-process-crashed-error.js +16 -0
- package/dist/src/child-proxy/child-process-crashed-error.js.map +1 -0
- package/dist/src/child-proxy/child-process-proxy-worker.d.ts +32 -0
- package/dist/src/child-proxy/child-process-proxy-worker.d.ts.map +1 -0
- package/dist/src/child-proxy/child-process-proxy-worker.js +148 -0
- package/dist/src/child-proxy/child-process-proxy-worker.js.map +1 -0
- package/dist/src/child-proxy/child-process-proxy.d.ts +45 -0
- package/dist/src/child-proxy/child-process-proxy.d.ts.map +1 -0
- package/dist/src/child-proxy/child-process-proxy.js +232 -0
- package/dist/src/child-proxy/child-process-proxy.js.map +1 -0
- package/dist/src/child-proxy/id-generator.d.ts +5 -0
- package/dist/src/child-proxy/id-generator.d.ts.map +1 -0
- package/dist/src/child-proxy/id-generator.js +7 -0
- package/dist/src/child-proxy/id-generator.js.map +1 -0
- package/dist/src/child-proxy/message-protocol.d.ts +71 -0
- package/dist/src/child-proxy/message-protocol.d.ts.map +1 -0
- package/dist/src/child-proxy/message-protocol.js +34 -0
- package/dist/src/child-proxy/message-protocol.js.map +1 -0
- package/dist/src/child-proxy/out-of-memory-error.d.ts +5 -0
- package/dist/src/child-proxy/out-of-memory-error.d.ts.map +1 -0
- package/dist/src/child-proxy/out-of-memory-error.js +11 -0
- package/dist/src/child-proxy/out-of-memory-error.js.map +1 -0
- package/dist/src/concurrent/concurrency-token-provider.d.ts +20 -0
- package/dist/src/concurrent/concurrency-token-provider.d.ts.map +1 -0
- package/dist/src/concurrent/concurrency-token-provider.js +68 -0
- package/dist/src/concurrent/concurrency-token-provider.js.map +1 -0
- package/dist/src/concurrent/index.d.ts +4 -0
- package/dist/src/concurrent/index.d.ts.map +1 -0
- package/dist/src/concurrent/index.js +4 -0
- package/dist/src/concurrent/index.js.map +1 -0
- package/dist/src/concurrent/pool.d.ts +49 -0
- package/dist/src/concurrent/pool.d.ts.map +1 -0
- package/dist/src/concurrent/pool.js +137 -0
- package/dist/src/concurrent/pool.js.map +1 -0
- package/dist/src/concurrent/resource-decorator.d.ts +14 -0
- package/dist/src/concurrent/resource-decorator.d.ts.map +1 -0
- package/dist/src/concurrent/resource-decorator.js +24 -0
- package/dist/src/concurrent/resource-decorator.js.map +1 -0
- package/dist/src/config/config-file-formats.d.ts +6 -0
- package/dist/src/config/config-file-formats.d.ts.map +1 -0
- package/dist/src/config/config-file-formats.js +23 -0
- package/dist/src/config/config-file-formats.js.map +1 -0
- package/dist/src/config/config-reader.d.ts +23 -0
- package/dist/src/config/config-reader.d.ts.map +1 -0
- package/dist/src/config/config-reader.js +141 -0
- package/dist/src/config/config-reader.js.map +1 -0
- package/dist/src/config/file-matcher.d.ts +10 -0
- package/dist/src/config/file-matcher.d.ts.map +1 -0
- package/dist/src/config/file-matcher.js +31 -0
- package/dist/src/config/file-matcher.js.map +1 -0
- package/dist/src/config/index.d.ts +6 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +6 -0
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/config/meta-schema-builder.d.ts +10 -0
- package/dist/src/config/meta-schema-builder.d.ts.map +1 -0
- package/dist/src/config/meta-schema-builder.js +30 -0
- package/dist/src/config/meta-schema-builder.js.map +1 -0
- package/dist/src/config/options-validator.d.ts +28 -0
- package/dist/src/config/options-validator.d.ts.map +1 -0
- package/dist/src/config/options-validator.js +213 -0
- package/dist/src/config/options-validator.js.map +1 -0
- package/dist/src/config/validation-errors.d.ts +7 -0
- package/dist/src/config/validation-errors.d.ts.map +1 -0
- package/dist/src/config/validation-errors.js +154 -0
- package/dist/src/config/validation-errors.js.map +1 -0
- package/dist/src/di/core-tokens.d.ts +40 -0
- package/dist/src/di/core-tokens.d.ts.map +1 -0
- package/dist/src/di/core-tokens.js +40 -0
- package/dist/src/di/core-tokens.js.map +1 -0
- package/dist/src/di/index.d.ts +4 -0
- package/dist/src/di/index.d.ts.map +1 -0
- package/dist/src/di/index.js +4 -0
- package/dist/src/di/index.js.map +1 -0
- package/dist/src/di/plugin-creator.d.ts +10 -0
- package/dist/src/di/plugin-creator.d.ts.map +1 -0
- package/dist/src/di/plugin-creator.js +51 -0
- package/dist/src/di/plugin-creator.js.map +1 -0
- package/dist/src/di/plugin-loader.d.ts +41 -0
- package/dist/src/di/plugin-loader.d.ts.map +1 -0
- package/dist/src/di/plugin-loader.js +153 -0
- package/dist/src/di/plugin-loader.js.map +1 -0
- package/dist/src/errors.d.ts +5 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +13 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/fs/file-system.d.ts +19 -0
- package/dist/src/fs/file-system.d.ts.map +1 -0
- package/dist/src/fs/file-system.js +52 -0
- package/dist/src/fs/file-system.js.map +1 -0
- package/dist/src/fs/index.d.ts +5 -0
- package/dist/src/fs/index.d.ts.map +1 -0
- package/dist/src/fs/index.js +5 -0
- package/dist/src/fs/index.js.map +1 -0
- package/dist/src/fs/project-file.d.ts +26 -0
- package/dist/src/fs/project-file.d.ts.map +1 -0
- package/dist/src/fs/project-file.js +87 -0
- package/dist/src/fs/project-file.js.map +1 -0
- package/dist/src/fs/project-reader.d.ts +51 -0
- package/dist/src/fs/project-reader.d.ts.map +1 -0
- package/dist/src/fs/project-reader.js +335 -0
- package/dist/src/fs/project-reader.js.map +1 -0
- package/dist/src/fs/project.d.ts +22 -0
- package/dist/src/fs/project.d.ts.map +1 -0
- package/dist/src/fs/project.js +65 -0
- package/dist/src/fs/project.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/initializer/custom-initializers/angular-initializer.d.ts +17 -0
- package/dist/src/initializer/custom-initializers/angular-initializer.d.ts.map +1 -0
- package/dist/src/initializer/custom-initializers/angular-initializer.js +74 -0
- package/dist/src/initializer/custom-initializers/angular-initializer.js.map +1 -0
- package/dist/src/initializer/custom-initializers/custom-initializer.d.ts +13 -0
- package/dist/src/initializer/custom-initializers/custom-initializer.d.ts.map +1 -0
- package/dist/src/initializer/custom-initializers/custom-initializer.js +2 -0
- package/dist/src/initializer/custom-initializers/custom-initializer.js.map +1 -0
- package/dist/src/initializer/custom-initializers/index.d.ts +14 -0
- package/dist/src/initializer/custom-initializers/index.d.ts.map +1 -0
- package/dist/src/initializer/custom-initializers/index.js +16 -0
- package/dist/src/initializer/custom-initializers/index.js.map +1 -0
- package/dist/src/initializer/custom-initializers/react-initializer.d.ts +12 -0
- package/dist/src/initializer/custom-initializers/react-initializer.d.ts.map +1 -0
- package/dist/src/initializer/custom-initializers/react-initializer.js +25 -0
- package/dist/src/initializer/custom-initializers/react-initializer.js.map +1 -0
- package/dist/src/initializer/custom-initializers/svelte-initializer.d.ts +6 -0
- package/dist/src/initializer/custom-initializers/svelte-initializer.d.ts.map +1 -0
- package/dist/src/initializer/custom-initializers/svelte-initializer.js +33 -0
- package/dist/src/initializer/custom-initializers/svelte-initializer.js.map +1 -0
- package/dist/src/initializer/custom-initializers/vue-js-initializer.d.ts +11 -0
- package/dist/src/initializer/custom-initializers/vue-js-initializer.d.ts.map +1 -0
- package/dist/src/initializer/custom-initializers/vue-js-initializer.js +20 -0
- package/dist/src/initializer/custom-initializers/vue-js-initializer.js.map +1 -0
- package/dist/src/initializer/gitignore-writer.d.ts +7 -0
- package/dist/src/initializer/gitignore-writer.d.ts.map +1 -0
- package/dist/src/initializer/gitignore-writer.js +28 -0
- package/dist/src/initializer/gitignore-writer.js.map +1 -0
- package/dist/src/initializer/index.d.ts +6 -0
- package/dist/src/initializer/index.d.ts.map +1 -0
- package/dist/src/initializer/index.js +29 -0
- package/dist/src/initializer/index.js.map +1 -0
- package/dist/src/initializer/initializer-tokens.d.ts +9 -0
- package/dist/src/initializer/initializer-tokens.d.ts.map +1 -0
- package/dist/src/initializer/initializer-tokens.js +9 -0
- package/dist/src/initializer/initializer-tokens.js.map +1 -0
- package/dist/src/initializer/inquire.d.ts +12 -0
- package/dist/src/initializer/inquire.d.ts.map +1 -0
- package/dist/src/initializer/inquire.js +12 -0
- package/dist/src/initializer/inquire.js.map +1 -0
- package/dist/src/initializer/npm-client.d.ts +22 -0
- package/dist/src/initializer/npm-client.d.ts.map +1 -0
- package/dist/src/initializer/npm-client.js +65 -0
- package/dist/src/initializer/npm-client.js.map +1 -0
- package/dist/src/initializer/npm-registry.d.ts +13 -0
- package/dist/src/initializer/npm-registry.d.ts.map +1 -0
- package/dist/src/initializer/npm-registry.js +36 -0
- package/dist/src/initializer/npm-registry.js.map +1 -0
- package/dist/src/initializer/package-info.d.ts +10 -0
- package/dist/src/initializer/package-info.d.ts.map +1 -0
- package/dist/src/initializer/package-info.js +2 -0
- package/dist/src/initializer/package-info.js.map +1 -0
- package/dist/src/initializer/prompt-option.d.ts +6 -0
- package/dist/src/initializer/prompt-option.d.ts.map +1 -0
- package/dist/src/initializer/prompt-option.js +2 -0
- package/dist/src/initializer/prompt-option.js.map +1 -0
- package/dist/src/initializer/stryker-config-writer.d.ts +27 -0
- package/dist/src/initializer/stryker-config-writer.d.ts.map +1 -0
- package/dist/src/initializer/stryker-config-writer.js +106 -0
- package/dist/src/initializer/stryker-config-writer.js.map +1 -0
- package/dist/src/initializer/stryker-initializer.d.ts +45 -0
- package/dist/src/initializer/stryker-initializer.d.ts.map +1 -0
- package/dist/src/initializer/stryker-initializer.js +184 -0
- package/dist/src/initializer/stryker-initializer.js.map +1 -0
- package/dist/src/initializer/stryker-inquirer.d.ts +15 -0
- package/dist/src/initializer/stryker-inquirer.d.ts.map +1 -0
- package/dist/src/initializer/stryker-inquirer.js +72 -0
- package/dist/src/initializer/stryker-inquirer.js.map +1 -0
- package/dist/src/logging/index.d.ts +6 -0
- package/dist/src/logging/index.d.ts.map +1 -0
- package/dist/src/logging/index.js +5 -0
- package/dist/src/logging/index.js.map +1 -0
- package/dist/src/logging/logger-impl.d.ts +19 -0
- package/dist/src/logging/logger-impl.d.ts.map +1 -0
- package/dist/src/logging/logger-impl.js +64 -0
- package/dist/src/logging/logger-impl.js.map +1 -0
- package/dist/src/logging/logging-backend.d.ts +22 -0
- package/dist/src/logging/logging-backend.d.ts.map +1 -0
- package/dist/src/logging/logging-backend.js +65 -0
- package/dist/src/logging/logging-backend.js.map +1 -0
- package/dist/src/logging/logging-client.d.ts +16 -0
- package/dist/src/logging/logging-client.d.ts.map +1 -0
- package/dist/src/logging/logging-client.js +44 -0
- package/dist/src/logging/logging-client.js.map +1 -0
- package/dist/src/logging/logging-event.d.ts +23 -0
- package/dist/src/logging/logging-event.d.ts.map +1 -0
- package/dist/src/logging/logging-event.js +63 -0
- package/dist/src/logging/logging-event.js.map +1 -0
- package/dist/src/logging/logging-server.d.ts +15 -0
- package/dist/src/logging/logging-server.d.ts.map +1 -0
- package/dist/src/logging/logging-server.js +43 -0
- package/dist/src/logging/logging-server.js.map +1 -0
- package/dist/src/logging/logging-sink.d.ts +7 -0
- package/dist/src/logging/logging-sink.d.ts.map +1 -0
- package/dist/src/logging/logging-sink.js +2 -0
- package/dist/src/logging/logging-sink.js.map +1 -0
- package/dist/src/logging/priority.d.ts +12 -0
- package/dist/src/logging/priority.d.ts.map +1 -0
- package/dist/src/logging/priority.js +13 -0
- package/dist/src/logging/priority.js.map +1 -0
- package/dist/src/logging/provide-logging.d.ts +30 -0
- package/dist/src/logging/provide-logging.d.ts.map +1 -0
- package/dist/src/logging/provide-logging.js +45 -0
- package/dist/src/logging/provide-logging.js.map +1 -0
- package/dist/src/mutants/diff-statistics-collector.d.ts +14 -0
- package/dist/src/mutants/diff-statistics-collector.d.ts.map +1 -0
- package/dist/src/mutants/diff-statistics-collector.js +40 -0
- package/dist/src/mutants/diff-statistics-collector.js.map +1 -0
- package/dist/src/mutants/incremental-differ.d.ts +39 -0
- package/dist/src/mutants/incremental-differ.d.ts.map +1 -0
- package/dist/src/mutants/incremental-differ.js +547 -0
- package/dist/src/mutants/incremental-differ.js.map +1 -0
- package/dist/src/mutants/index.d.ts +4 -0
- package/dist/src/mutants/index.d.ts.map +1 -0
- package/dist/src/mutants/index.js +4 -0
- package/dist/src/mutants/index.js.map +1 -0
- package/dist/src/mutants/mutant-test-planner.d.ts +36 -0
- package/dist/src/mutants/mutant-test-planner.d.ts.map +1 -0
- package/dist/src/mutants/mutant-test-planner.js +237 -0
- package/dist/src/mutants/mutant-test-planner.js.map +1 -0
- package/dist/src/mutants/test-coverage.d.ts +22 -0
- package/dist/src/mutants/test-coverage.d.ts.map +1 -0
- package/dist/src/mutants/test-coverage.js +87 -0
- package/dist/src/mutants/test-coverage.js.map +1 -0
- package/dist/src/process/1-prepare-executor.d.ts +22 -0
- package/dist/src/process/1-prepare-executor.d.ts.map +1 -0
- package/dist/src/process/1-prepare-executor.js +86 -0
- package/dist/src/process/1-prepare-executor.js.map +1 -0
- package/dist/src/process/2-mutant-instrumenter-executor.d.ts +39 -0
- package/dist/src/process/2-mutant-instrumenter-executor.d.ts.map +1 -0
- package/dist/src/process/2-mutant-instrumenter-executor.js +58 -0
- package/dist/src/process/2-mutant-instrumenter-executor.js.map +1 -0
- package/dist/src/process/3-dry-run-executor.d.ts +50 -0
- package/dist/src/process/3-dry-run-executor.d.ts.map +1 -0
- package/dist/src/process/3-dry-run-executor.js +164 -0
- package/dist/src/process/3-dry-run-executor.js.map +1 -0
- package/dist/src/process/4-mutation-test-executor.d.ts +56 -0
- package/dist/src/process/4-mutation-test-executor.d.ts.map +1 -0
- package/dist/src/process/4-mutation-test-executor.js +152 -0
- package/dist/src/process/4-mutation-test-executor.js.map +1 -0
- package/dist/src/process/index.d.ts +5 -0
- package/dist/src/process/index.d.ts.map +1 -0
- package/dist/src/process/index.js +5 -0
- package/dist/src/process/index.js.map +1 -0
- package/dist/src/reporters/broadcast-reporter.d.ts +25 -0
- package/dist/src/reporters/broadcast-reporter.d.ts.map +1 -0
- package/dist/src/reporters/broadcast-reporter.js +74 -0
- package/dist/src/reporters/broadcast-reporter.js.map +1 -0
- package/dist/src/reporters/ci/circle-provider.d.ts +11 -0
- package/dist/src/reporters/ci/circle-provider.d.ts.map +1 -0
- package/dist/src/reporters/ci/circle-provider.js +33 -0
- package/dist/src/reporters/ci/circle-provider.js.map +1 -0
- package/dist/src/reporters/ci/github-actions-provider.d.ts +9 -0
- package/dist/src/reporters/ci/github-actions-provider.d.ts.map +1 -0
- package/dist/src/reporters/ci/github-actions-provider.js +21 -0
- package/dist/src/reporters/ci/github-actions-provider.js.map +1 -0
- package/dist/src/reporters/ci/provider.d.ts +22 -0
- package/dist/src/reporters/ci/provider.d.ts.map +1 -0
- package/dist/src/reporters/ci/provider.js +24 -0
- package/dist/src/reporters/ci/provider.js.map +1 -0
- package/dist/src/reporters/ci/travis-provider.d.ts +9 -0
- package/dist/src/reporters/ci/travis-provider.d.ts.map +1 -0
- package/dist/src/reporters/ci/travis-provider.js +19 -0
- package/dist/src/reporters/ci/travis-provider.js.map +1 -0
- package/dist/src/reporters/clear-text-reporter.d.ts +23 -0
- package/dist/src/reporters/clear-text-reporter.d.ts.map +1 -0
- package/dist/src/reporters/clear-text-reporter.js +174 -0
- package/dist/src/reporters/clear-text-reporter.js.map +1 -0
- package/dist/src/reporters/clear-text-score-table.d.ts +22 -0
- package/dist/src/reporters/clear-text-score-table.d.ts.map +1 -0
- package/dist/src/reporters/clear-text-score-table.js +191 -0
- package/dist/src/reporters/clear-text-score-table.js.map +1 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter-client.d.ts +19 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter-client.d.ts.map +1 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter-client.js +54 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter-client.js.map +1 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter.d.ts +21 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter.d.ts.map +1 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter.js +62 -0
- package/dist/src/reporters/dashboard-reporter/dashboard-reporter.js.map +1 -0
- package/dist/src/reporters/dashboard-reporter/index.d.ts +7 -0
- package/dist/src/reporters/dashboard-reporter/index.d.ts.map +1 -0
- package/dist/src/reporters/dashboard-reporter/index.js +15 -0
- package/dist/src/reporters/dashboard-reporter/index.js.map +1 -0
- package/dist/src/reporters/dashboard-reporter/report.d.ts +6 -0
- package/dist/src/reporters/dashboard-reporter/report.d.ts.map +1 -0
- package/dist/src/reporters/dashboard-reporter/report.js +2 -0
- package/dist/src/reporters/dashboard-reporter/report.js.map +1 -0
- package/dist/src/reporters/dashboard-reporter/tokens.d.ts +6 -0
- package/dist/src/reporters/dashboard-reporter/tokens.d.ts.map +1 -0
- package/dist/src/reporters/dashboard-reporter/tokens.js +6 -0
- package/dist/src/reporters/dashboard-reporter/tokens.js.map +1 -0
- package/dist/src/reporters/dots-reporter.d.ts +7 -0
- package/dist/src/reporters/dots-reporter.d.ts.map +1 -0
- package/dist/src/reporters/dots-reporter.js +29 -0
- package/dist/src/reporters/dots-reporter.js.map +1 -0
- package/dist/src/reporters/event-recorder-reporter.d.ts +22 -0
- package/dist/src/reporters/event-recorder-reporter.d.ts.map +1 -0
- package/dist/src/reporters/event-recorder-reporter.js +53 -0
- package/dist/src/reporters/event-recorder-reporter.js.map +1 -0
- package/dist/src/reporters/html-reporter.d.ts +14 -0
- package/dist/src/reporters/html-reporter.d.ts.map +1 -0
- package/dist/src/reporters/html-reporter.js +65 -0
- package/dist/src/reporters/html-reporter.js.map +1 -0
- package/dist/src/reporters/index.d.ts +6 -0
- package/dist/src/reporters/index.d.ts.map +1 -0
- package/dist/src/reporters/index.js +24 -0
- package/dist/src/reporters/index.js.map +1 -0
- package/dist/src/reporters/json-reporter.d.ts +15 -0
- package/dist/src/reporters/json-reporter.d.ts.map +1 -0
- package/dist/src/reporters/json-reporter.js +29 -0
- package/dist/src/reporters/json-reporter.js.map +1 -0
- package/dist/src/reporters/mutation-test-report-helper.d.ts +40 -0
- package/dist/src/reporters/mutation-test-report-helper.d.ts.map +1 -0
- package/dist/src/reporters/mutation-test-report-helper.js +298 -0
- package/dist/src/reporters/mutation-test-report-helper.js.map +1 -0
- package/dist/src/reporters/mutation-timings-reporter.d.ts +14 -0
- package/dist/src/reporters/mutation-timings-reporter.d.ts.map +1 -0
- package/dist/src/reporters/mutation-timings-reporter.js +49 -0
- package/dist/src/reporters/mutation-timings-reporter.js.map +1 -0
- package/dist/src/reporters/progress-append-only-reporter.d.ts +10 -0
- package/dist/src/reporters/progress-append-only-reporter.d.ts.map +1 -0
- package/dist/src/reporters/progress-append-only-reporter.js +25 -0
- package/dist/src/reporters/progress-append-only-reporter.js.map +1 -0
- package/dist/src/reporters/progress-bar.d.ts +8 -0
- package/dist/src/reporters/progress-bar.d.ts.map +1 -0
- package/dist/src/reporters/progress-bar.js +6 -0
- package/dist/src/reporters/progress-bar.js.map +1 -0
- package/dist/src/reporters/progress-keeper.d.ts +27 -0
- package/dist/src/reporters/progress-keeper.d.ts.map +1 -0
- package/dist/src/reporters/progress-keeper.js +77 -0
- package/dist/src/reporters/progress-keeper.js.map +1 -0
- package/dist/src/reporters/progress-reporter.d.ts +11 -0
- package/dist/src/reporters/progress-reporter.d.ts.map +1 -0
- package/dist/src/reporters/progress-reporter.js +40 -0
- package/dist/src/reporters/progress-reporter.js.map +1 -0
- package/dist/src/reporters/reporter-util.d.ts +5 -0
- package/dist/src/reporters/reporter-util.d.ts.map +1 -0
- package/dist/src/reporters/reporter-util.js +19 -0
- package/dist/src/reporters/reporter-util.js.map +1 -0
- package/dist/src/reporters/strict-reporter.d.ts +3 -0
- package/dist/src/reporters/strict-reporter.d.ts.map +1 -0
- package/dist/src/reporters/strict-reporter.js +2 -0
- package/dist/src/reporters/strict-reporter.js.map +1 -0
- package/dist/src/sandbox/create-preprocessor.d.ts +7 -0
- package/dist/src/sandbox/create-preprocessor.d.ts.map +1 -0
- package/dist/src/sandbox/create-preprocessor.js +16 -0
- package/dist/src/sandbox/create-preprocessor.js.map +1 -0
- package/dist/src/sandbox/disable-type-checks-preprocessor.d.ts +18 -0
- package/dist/src/sandbox/disable-type-checks-preprocessor.d.ts.map +1 -0
- package/dist/src/sandbox/disable-type-checks-preprocessor.js +43 -0
- package/dist/src/sandbox/disable-type-checks-preprocessor.js.map +1 -0
- package/dist/src/sandbox/file-preprocessor.d.ts +10 -0
- package/dist/src/sandbox/file-preprocessor.d.ts.map +1 -0
- package/dist/src/sandbox/file-preprocessor.js +2 -0
- package/dist/src/sandbox/file-preprocessor.js.map +1 -0
- package/dist/src/sandbox/index.d.ts +4 -0
- package/dist/src/sandbox/index.d.ts.map +1 -0
- package/dist/src/sandbox/index.js +3 -0
- package/dist/src/sandbox/index.js.map +1 -0
- package/dist/src/sandbox/multi-preprocessor.d.ts +8 -0
- package/dist/src/sandbox/multi-preprocessor.d.ts.map +1 -0
- package/dist/src/sandbox/multi-preprocessor.js +12 -0
- package/dist/src/sandbox/multi-preprocessor.js.map +1 -0
- package/dist/src/sandbox/sandbox.d.ts +43 -0
- package/dist/src/sandbox/sandbox.d.ts.map +1 -0
- package/dist/src/sandbox/sandbox.js +134 -0
- package/dist/src/sandbox/sandbox.js.map +1 -0
- package/dist/src/sandbox/ts-config-preprocessor.d.ts +46 -0
- package/dist/src/sandbox/ts-config-preprocessor.d.ts.map +1 -0
- package/dist/src/sandbox/ts-config-preprocessor.js +112 -0
- package/dist/src/sandbox/ts-config-preprocessor.js.map +1 -0
- package/dist/src/stryker-cli.d.ts +15 -0
- package/dist/src/stryker-cli.d.ts.map +1 -0
- package/dist/src/stryker-cli.js +168 -0
- package/dist/src/stryker-cli.js.map +1 -0
- package/dist/src/stryker-package.d.ts +5 -0
- package/dist/src/stryker-package.d.ts.map +1 -0
- package/dist/src/stryker-package.js +7 -0
- package/dist/src/stryker-package.js.map +1 -0
- package/dist/src/stryker-server.d.ts +40 -0
- package/dist/src/stryker-server.d.ts.map +1 -0
- package/dist/src/stryker-server.js +234 -0
- package/dist/src/stryker-server.js.map +1 -0
- package/dist/src/stryker.d.ts +31 -0
- package/dist/src/stryker.d.ts.map +1 -0
- package/dist/src/stryker.js +86 -0
- package/dist/src/stryker.js.map +1 -0
- package/dist/src/test-runner/child-process-test-runner-proxy.d.ts +19 -0
- package/dist/src/test-runner/child-process-test-runner-proxy.d.ts.map +1 -0
- package/dist/src/test-runner/child-process-test-runner-proxy.js +45 -0
- package/dist/src/test-runner/child-process-test-runner-proxy.js.map +1 -0
- package/dist/src/test-runner/child-process-test-runner-worker.d.ts +14 -0
- package/dist/src/test-runner/child-process-test-runner-worker.d.ts.map +1 -0
- package/dist/src/test-runner/child-process-test-runner-worker.js +45 -0
- package/dist/src/test-runner/child-process-test-runner-worker.js.map +1 -0
- package/dist/src/test-runner/command-test-runner.d.ts +31 -0
- package/dist/src/test-runner/command-test-runner.d.ts.map +1 -0
- package/dist/src/test-runner/command-test-runner.js +144 -0
- package/dist/src/test-runner/command-test-runner.js.map +1 -0
- package/dist/src/test-runner/index.d.ts +11 -0
- package/dist/src/test-runner/index.d.ts.map +1 -0
- package/dist/src/test-runner/index.js +18 -0
- package/dist/src/test-runner/index.js.map +1 -0
- package/dist/src/test-runner/max-test-runner-reuse-decorator.d.ts +14 -0
- package/dist/src/test-runner/max-test-runner-reuse-decorator.d.ts.map +1 -0
- package/dist/src/test-runner/max-test-runner-reuse-decorator.js +25 -0
- package/dist/src/test-runner/max-test-runner-reuse-decorator.js.map +1 -0
- package/dist/src/test-runner/reload-environment-decorator.d.ts +11 -0
- package/dist/src/test-runner/reload-environment-decorator.d.ts.map +1 -0
- package/dist/src/test-runner/reload-environment-decorator.js +56 -0
- package/dist/src/test-runner/reload-environment-decorator.js.map +1 -0
- package/dist/src/test-runner/retry-rejected-decorator.d.ts +15 -0
- package/dist/src/test-runner/retry-rejected-decorator.d.ts.map +1 -0
- package/dist/src/test-runner/retry-rejected-decorator.js +59 -0
- package/dist/src/test-runner/retry-rejected-decorator.js.map +1 -0
- package/dist/src/test-runner/test-runner-decorator.d.ts +8 -0
- package/dist/src/test-runner/test-runner-decorator.d.ts.map +1 -0
- package/dist/src/test-runner/test-runner-decorator.js +13 -0
- package/dist/src/test-runner/test-runner-decorator.js.map +1 -0
- package/dist/src/test-runner/timeout-decorator.d.ts +15 -0
- package/dist/src/test-runner/timeout-decorator.d.ts.map +1 -0
- package/dist/src/test-runner/timeout-decorator.js +51 -0
- package/dist/src/test-runner/timeout-decorator.js.map +1 -0
- package/dist/src/unexpected-exit-handler.d.ts +13 -0
- package/dist/src/unexpected-exit-handler.d.ts.map +1 -0
- package/dist/src/unexpected-exit-handler.js +28 -0
- package/dist/src/unexpected-exit-handler.js.map +1 -0
- package/dist/src/utils/file-utils.d.ts +30 -0
- package/dist/src/utils/file-utils.d.ts.map +1 -0
- package/dist/src/utils/file-utils.js +101 -0
- package/dist/src/utils/file-utils.js.map +1 -0
- package/dist/src/utils/index.d.ts +7 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +7 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/json-rpc-event-deserializer.d.ts +5 -0
- package/dist/src/utils/json-rpc-event-deserializer.d.ts.map +1 -0
- package/dist/src/utils/json-rpc-event-deserializer.js +42 -0
- package/dist/src/utils/json-rpc-event-deserializer.js.map +1 -0
- package/dist/src/utils/object-utils.d.ts +37 -0
- package/dist/src/utils/object-utils.d.ts.map +1 -0
- package/dist/src/utils/object-utils.js +91 -0
- package/dist/src/utils/object-utils.js.map +1 -0
- package/dist/src/utils/string-builder.d.ts +9 -0
- package/dist/src/utils/string-builder.d.ts.map +1 -0
- package/dist/src/utils/string-builder.js +26 -0
- package/dist/src/utils/string-builder.js.map +1 -0
- package/dist/src/utils/string-utils.d.ts +12 -0
- package/dist/src/utils/string-utils.d.ts.map +1 -0
- package/dist/src/utils/string-utils.js +54 -0
- package/dist/src/utils/string-utils.js.map +1 -0
- package/dist/src/utils/temporary-directory.d.ts +18 -0
- package/dist/src/utils/temporary-directory.d.ts.map +1 -0
- package/dist/src/utils/temporary-directory.js +63 -0
- package/dist/src/utils/temporary-directory.js.map +1 -0
- package/dist/src/utils/timer.d.ts +14 -0
- package/dist/src/utils/timer.d.ts.map +1 -0
- package/dist/src/utils/timer.js +53 -0
- package/dist/src/utils/timer.js.map +1 -0
- package/package.json +106 -0
- package/schema/stryker-schema.json +855 -0
- package/src/checker/checker-child-process-proxy.ts +67 -0
- package/src/checker/checker-facade.ts +90 -0
- package/src/checker/checker-factory.ts +46 -0
- package/src/checker/checker-resource.ts +12 -0
- package/src/checker/checker-retry-decorator.ts +57 -0
- package/src/checker/checker-worker.ts +62 -0
- package/src/checker/index.ts +3 -0
- package/src/child-proxy/child-process-crashed-error.ts +16 -0
- package/src/child-proxy/child-process-proxy-worker.ts +203 -0
- package/src/child-proxy/child-process-proxy.ts +353 -0
- package/src/child-proxy/id-generator.ts +6 -0
- package/src/child-proxy/message-protocol.ts +87 -0
- package/src/child-proxy/out-of-memory-error.ts +11 -0
- package/src/concurrent/concurrency-token-provider.ts +106 -0
- package/src/concurrent/index.ts +3 -0
- package/src/concurrent/pool.ts +209 -0
- package/src/concurrent/resource-decorator.ts +28 -0
- package/src/config/config-file-formats.ts +31 -0
- package/src/config/config-reader.ts +193 -0
- package/src/config/file-matcher.ts +36 -0
- package/src/config/index.ts +5 -0
- package/src/config/meta-schema-builder.ts +50 -0
- package/src/config/options-validator.ts +317 -0
- package/src/config/validation-errors.ts +192 -0
- package/src/di/core-tokens.ts +39 -0
- package/src/di/index.ts +4 -0
- package/src/di/plugin-creator.ts +102 -0
- package/src/di/plugin-loader.ts +245 -0
- package/src/errors.ts +12 -0
- package/src/fs/file-system.ts +63 -0
- package/src/fs/index.ts +4 -0
- package/src/fs/project-file.ts +100 -0
- package/src/fs/project-reader.ts +493 -0
- package/src/fs/project.ts +98 -0
- package/src/index.ts +7 -0
- package/src/initializer/custom-initializers/angular-initializer.ts +95 -0
- package/src/initializer/custom-initializers/custom-initializer.ts +14 -0
- package/src/initializer/custom-initializers/index.ts +31 -0
- package/src/initializer/custom-initializers/react-initializer.ts +35 -0
- package/src/initializer/custom-initializers/svelte-initializer.ts +40 -0
- package/src/initializer/custom-initializers/vue-js-initializer.ts +30 -0
- package/src/initializer/gitignore-writer.ts +33 -0
- package/src/initializer/index.ts +35 -0
- package/src/initializer/initializer-tokens.ts +8 -0
- package/src/initializer/inquire.ts +17 -0
- package/src/initializer/npm-client.ts +103 -0
- package/src/initializer/npm-registry.ts +48 -0
- package/src/initializer/package-info.ts +10 -0
- package/src/initializer/prompt-option.ts +6 -0
- package/src/initializer/stryker-config-writer.ts +158 -0
- package/src/initializer/stryker-initializer.ts +278 -0
- package/src/initializer/stryker-inquirer.ts +101 -0
- package/src/logging/index.ts +5 -0
- package/src/logging/logger-impl.ts +81 -0
- package/src/logging/logging-backend.ts +90 -0
- package/src/logging/logging-client.ts +56 -0
- package/src/logging/logging-event.ts +94 -0
- package/src/logging/logging-server.ts +56 -0
- package/src/logging/logging-sink.ts +7 -0
- package/src/logging/priority.ts +15 -0
- package/src/logging/provide-logging.ts +70 -0
- package/src/mutants/diff-statistics-collector.ts +47 -0
- package/src/mutants/incremental-differ.ts +771 -0
- package/src/mutants/index.ts +3 -0
- package/src/mutants/mutant-test-planner.ts +357 -0
- package/src/mutants/test-coverage.ts +125 -0
- package/src/process/1-prepare-executor.ts +133 -0
- package/src/process/2-mutant-instrumenter-executor.ts +122 -0
- package/src/process/3-dry-run-executor.ts +262 -0
- package/src/process/4-mutation-test-executor.ts +272 -0
- package/src/process/index.ts +4 -0
- package/src/reporters/broadcast-reporter.ts +129 -0
- package/src/reporters/ci/circle-provider.ts +50 -0
- package/src/reporters/ci/github-actions-provider.ts +22 -0
- package/src/reporters/ci/provider.ts +42 -0
- package/src/reporters/ci/travis-provider.ts +24 -0
- package/src/reporters/clear-text-reporter.ts +245 -0
- package/src/reporters/clear-text-score-table.ts +305 -0
- package/src/reporters/dashboard-reporter/dashboard-reporter-client.ts +89 -0
- package/src/reporters/dashboard-reporter/dashboard-reporter.ts +97 -0
- package/src/reporters/dashboard-reporter/index.ts +30 -0
- package/src/reporters/dashboard-reporter/report.ts +6 -0
- package/src/reporters/dashboard-reporter/tokens.ts +5 -0
- package/src/reporters/dots-reporter.ts +33 -0
- package/src/reporters/event-recorder-reporter.ts +88 -0
- package/src/reporters/html-reporter.ts +87 -0
- package/src/reporters/index.ts +48 -0
- package/src/reporters/json-reporter.ts +45 -0
- package/src/reporters/mutation-test-report-helper.ts +425 -0
- package/src/reporters/mutation-timings-reporter.ts +78 -0
- package/src/reporters/progress-append-only-reporter.ts +36 -0
- package/src/reporters/progress-bar.ts +6 -0
- package/src/reporters/progress-keeper.ts +113 -0
- package/src/reporters/progress-reporter.ts +62 -0
- package/src/reporters/reporter-util.ts +20 -0
- package/src/reporters/strict-reporter.ts +3 -0
- package/src/sandbox/create-preprocessor.ts +27 -0
- package/src/sandbox/disable-type-checks-preprocessor.ts +70 -0
- package/src/sandbox/file-preprocessor.ts +10 -0
- package/src/sandbox/index.ts +3 -0
- package/src/sandbox/multi-preprocessor.ts +13 -0
- package/src/sandbox/sandbox.ts +198 -0
- package/src/sandbox/ts-config-preprocessor.ts +168 -0
- package/src/stryker-cli.ts +363 -0
- package/src/stryker-package.ts +19 -0
- package/src/stryker-server.ts +334 -0
- package/src/stryker.ts +126 -0
- package/src/test-runner/child-process-test-runner-proxy.ts +94 -0
- package/src/test-runner/child-process-test-runner-worker.ts +66 -0
- package/src/test-runner/command-test-runner.ts +190 -0
- package/src/test-runner/index.ts +74 -0
- package/src/test-runner/max-test-runner-reuse-decorator.ts +41 -0
- package/src/test-runner/reload-environment-decorator.ts +72 -0
- package/src/test-runner/retry-rejected-decorator.ts +79 -0
- package/src/test-runner/test-runner-decorator.ts +22 -0
- package/src/test-runner/timeout-decorator.ts +71 -0
- package/src/unexpected-exit-handler.ts +36 -0
- package/src/utils/file-utils.ts +113 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/json-rpc-event-deserializer.ts +48 -0
- package/src/utils/object-utils.ts +106 -0
- package/src/utils/string-builder.ts +30 -0
- package/src/utils/string-utils.ts +61 -0
- package/src/utils/temporary-directory.ts +83 -0
- package/src/utils/timer.ts +58 -0
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { diff_match_patch as DiffMatchPatch } from 'diff-match-patch';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import {
|
|
6
|
+
schema,
|
|
7
|
+
Mutant,
|
|
8
|
+
Position,
|
|
9
|
+
Location,
|
|
10
|
+
StrykerOptions,
|
|
11
|
+
FileDescriptions,
|
|
12
|
+
MutateDescription,
|
|
13
|
+
} from '@stryker-mutator/api/core';
|
|
14
|
+
import { Logger } from '@stryker-mutator/api/logging';
|
|
15
|
+
import { TestResult, TestStatus } from '@stryker-mutator/api/test-runner';
|
|
16
|
+
import {
|
|
17
|
+
I,
|
|
18
|
+
normalizeFileName,
|
|
19
|
+
normalizeLineEndings,
|
|
20
|
+
notEmpty,
|
|
21
|
+
} from '@stryker-mutator/util';
|
|
22
|
+
import { TestDefinition } from 'mutation-testing-report-schema';
|
|
23
|
+
import { commonTokens } from '@stryker-mutator/api/plugin';
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
DiffChange,
|
|
27
|
+
DiffStatisticsCollector,
|
|
28
|
+
} from './diff-statistics-collector.js';
|
|
29
|
+
import { TestCoverage } from './test-coverage.js';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The 'diff match patch' high-performant 'diffing' of files.
|
|
33
|
+
* @see https://github.com/google/diff-match-patch
|
|
34
|
+
*/
|
|
35
|
+
const diffMatchPatch = new DiffMatchPatch();
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* This class is responsible for calculating the diff between a run and a previous run based on the incremental report.
|
|
39
|
+
*
|
|
40
|
+
* Since the ids of tests and mutants can differ across reports (they are only unique within 1 report), this class
|
|
41
|
+
* identifies mutants and tests by attributes that make them unique:
|
|
42
|
+
* - Mutant: file name, mutator name, location and replacement
|
|
43
|
+
* - Test: test name, test file name (if present) and location (if present).
|
|
44
|
+
*
|
|
45
|
+
* We're storing these identifiers in local variables (maps and sets) as strings.
|
|
46
|
+
* We should move to 'records' for these when they come available: https://github.com/tc39/proposal-record-tuple
|
|
47
|
+
*
|
|
48
|
+
* A mutant result from the previous run is reused if the following conditions were met:
|
|
49
|
+
* - The location of the mutant refers to a piece of code that didn't change
|
|
50
|
+
* - If mutant was killed:
|
|
51
|
+
* - The culprit test wasn't changed
|
|
52
|
+
* - If the mutant survived:
|
|
53
|
+
* - No test was added
|
|
54
|
+
*
|
|
55
|
+
* It uses google's "diff-match-patch" project to calculate the new locations for tests and mutants, see link.
|
|
56
|
+
* @link https://github.com/google/diff-match-patch
|
|
57
|
+
*/
|
|
58
|
+
export class IncrementalDiffer {
|
|
59
|
+
public mutantStatisticsCollector: DiffStatisticsCollector | undefined;
|
|
60
|
+
public testStatisticsCollector: DiffStatisticsCollector | undefined;
|
|
61
|
+
private readonly mutateDescriptionByRelativeFileName: Map<
|
|
62
|
+
string,
|
|
63
|
+
MutateDescription
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
public static inject = [
|
|
67
|
+
commonTokens.logger,
|
|
68
|
+
commonTokens.options,
|
|
69
|
+
commonTokens.fileDescriptions,
|
|
70
|
+
] as const;
|
|
71
|
+
constructor(
|
|
72
|
+
private readonly logger: Logger,
|
|
73
|
+
private readonly options: StrykerOptions,
|
|
74
|
+
fileDescriptions: FileDescriptions,
|
|
75
|
+
) {
|
|
76
|
+
this.mutateDescriptionByRelativeFileName = new Map(
|
|
77
|
+
Object.entries(fileDescriptions).map(([name, description]) => [
|
|
78
|
+
toRelativeNormalizedFileName(name),
|
|
79
|
+
description.mutate,
|
|
80
|
+
]),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private isInMutatedScope(
|
|
85
|
+
relativeFileName: string,
|
|
86
|
+
mutant: schema.MutantResult,
|
|
87
|
+
): boolean {
|
|
88
|
+
const mutate =
|
|
89
|
+
this.mutateDescriptionByRelativeFileName.get(relativeFileName);
|
|
90
|
+
return (
|
|
91
|
+
mutate === true ||
|
|
92
|
+
(Array.isArray(mutate) &&
|
|
93
|
+
mutate.some((range) => locationIncluded(range, mutant.location)))
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public diff(
|
|
98
|
+
currentMutants: readonly Mutant[],
|
|
99
|
+
testCoverage: I<TestCoverage>,
|
|
100
|
+
incrementalReport: schema.MutationTestResult,
|
|
101
|
+
currentRelativeFiles: Map<string, string>,
|
|
102
|
+
): readonly Mutant[] {
|
|
103
|
+
const { files, testFiles } = incrementalReport;
|
|
104
|
+
const mutantStatisticsCollector = new DiffStatisticsCollector();
|
|
105
|
+
const testStatisticsCollector = new DiffStatisticsCollector();
|
|
106
|
+
|
|
107
|
+
// Expose the collectors for unit testing purposes
|
|
108
|
+
this.mutantStatisticsCollector = mutantStatisticsCollector;
|
|
109
|
+
this.testStatisticsCollector = testStatisticsCollector;
|
|
110
|
+
|
|
111
|
+
// Collect what we can reuse, while correcting for diff in the locations
|
|
112
|
+
const reusableMutantsByKey = collectReusableMutantsByKey(this.logger);
|
|
113
|
+
const { byId: oldTestsById, byKey: oldTestInfoByKey } =
|
|
114
|
+
collectReusableTestInfo(this.logger);
|
|
115
|
+
|
|
116
|
+
// Collect some helper maps and sets
|
|
117
|
+
const {
|
|
118
|
+
oldCoverageByMutantKey: oldCoverageTestKeysByMutantKey,
|
|
119
|
+
oldKilledByMutantKey: oldKilledTestKeysByMutantKey,
|
|
120
|
+
} = collectOldKilledAndCoverageMatrix();
|
|
121
|
+
const oldTestKeys = new Set(
|
|
122
|
+
[...oldTestsById.values()].map(({ key }) => key),
|
|
123
|
+
);
|
|
124
|
+
const newTestKeys = new Set(
|
|
125
|
+
[...testCoverage.testsById].map(([, test]) =>
|
|
126
|
+
testToIdentifyingKey(test, toRelativeNormalizedFileName(test.fileName)),
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// Create a dictionary to more easily get test information
|
|
131
|
+
const testInfoByKey = collectCurrentTestInfo();
|
|
132
|
+
|
|
133
|
+
// Mark which tests are added
|
|
134
|
+
for (const [key, { relativeFileName }] of testInfoByKey) {
|
|
135
|
+
if (!oldTestKeys.has(key)) {
|
|
136
|
+
testStatisticsCollector.count(relativeFileName, 'added');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Make sure that tests that didn't run this time around aren't forgotten
|
|
141
|
+
for (const [
|
|
142
|
+
testKey,
|
|
143
|
+
{
|
|
144
|
+
test: { name, location },
|
|
145
|
+
relativeFileName,
|
|
146
|
+
},
|
|
147
|
+
] of oldTestInfoByKey) {
|
|
148
|
+
if (!testInfoByKey.has(testKey)) {
|
|
149
|
+
const test: TestResult = {
|
|
150
|
+
status: TestStatus.Success,
|
|
151
|
+
id: testKey,
|
|
152
|
+
name,
|
|
153
|
+
startPosition: location?.start,
|
|
154
|
+
timeSpentMs: 0,
|
|
155
|
+
fileName: path.resolve(relativeFileName),
|
|
156
|
+
};
|
|
157
|
+
testInfoByKey.set(testKey, {
|
|
158
|
+
test,
|
|
159
|
+
relativeFileName: relativeFileName,
|
|
160
|
+
});
|
|
161
|
+
testCoverage.addTest(test);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Done with preparations, time to map over the mutants
|
|
166
|
+
let reusedMutantCount = 0;
|
|
167
|
+
const currentMutantKeys = new Set<string>();
|
|
168
|
+
const mutants = currentMutants.map((mutant) => {
|
|
169
|
+
const relativeFileName = toRelativeNormalizedFileName(mutant.fileName);
|
|
170
|
+
const mutantKey = mutantToIdentifyingKey(mutant, relativeFileName);
|
|
171
|
+
currentMutantKeys.add(mutantKey);
|
|
172
|
+
if (!mutant.status && !this.options.force) {
|
|
173
|
+
const oldMutant = reusableMutantsByKey.get(mutantKey);
|
|
174
|
+
if (oldMutant) {
|
|
175
|
+
const coveringTests = testCoverage.forMutant(mutant.id);
|
|
176
|
+
const killedByTestKeys = oldKilledTestKeysByMutantKey.get(mutantKey);
|
|
177
|
+
if (
|
|
178
|
+
mutantCanBeReused(
|
|
179
|
+
mutant,
|
|
180
|
+
oldMutant,
|
|
181
|
+
mutantKey,
|
|
182
|
+
coveringTests,
|
|
183
|
+
killedByTestKeys,
|
|
184
|
+
)
|
|
185
|
+
) {
|
|
186
|
+
reusedMutantCount++;
|
|
187
|
+
const { status, statusReason, testsCompleted } = oldMutant;
|
|
188
|
+
const executedTests = (oldMutant as { executedTests?: unknown })
|
|
189
|
+
.executedTests;
|
|
190
|
+
return {
|
|
191
|
+
...mutant,
|
|
192
|
+
status,
|
|
193
|
+
statusReason,
|
|
194
|
+
testsCompleted,
|
|
195
|
+
executedTests,
|
|
196
|
+
coveredBy: [...(coveringTests ?? [])].map(({ id }) => id),
|
|
197
|
+
killedBy: testKeysToId(killedByTestKeys),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
mutantStatisticsCollector.count(relativeFileName, 'added');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return mutant;
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Make sure that old mutants that didn't run this time around aren't forgotten
|
|
208
|
+
|
|
209
|
+
for (const [mutantKey, oldResult] of reusableMutantsByKey) {
|
|
210
|
+
// Do an additional check to see if the mutant is in mutated range.
|
|
211
|
+
//
|
|
212
|
+
// For example:
|
|
213
|
+
// ```diff
|
|
214
|
+
// - return a || b;
|
|
215
|
+
// + return a && b;
|
|
216
|
+
// ```
|
|
217
|
+
// The conditional expression mutator here decides to _not_ mutate b to `false` the second time around. (even though the text of "b" itself didn't change)
|
|
218
|
+
// Not doing this additional check would result in a sticky mutant that is never removed
|
|
219
|
+
if (
|
|
220
|
+
!currentMutantKeys.has(mutantKey) &&
|
|
221
|
+
!this.isInMutatedScope(oldResult.relativeFileName, oldResult)
|
|
222
|
+
) {
|
|
223
|
+
const coverage = oldCoverageTestKeysByMutantKey.get(mutantKey) ?? [];
|
|
224
|
+
const killed = oldKilledTestKeysByMutantKey.get(mutantKey) ?? [];
|
|
225
|
+
const coveredBy = testKeysToId(coverage);
|
|
226
|
+
const killedBy = testKeysToId(killed);
|
|
227
|
+
const reusedMutant = {
|
|
228
|
+
...oldResult,
|
|
229
|
+
id: mutantKey,
|
|
230
|
+
fileName: path.resolve(oldResult.relativeFileName),
|
|
231
|
+
replacement: oldResult.replacement ?? oldResult.mutatorName,
|
|
232
|
+
coveredBy,
|
|
233
|
+
killedBy,
|
|
234
|
+
};
|
|
235
|
+
mutants.push(reusedMutant);
|
|
236
|
+
testCoverage.addCoverage(reusedMutant.id, coveredBy);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (this.logger.isInfoEnabled()) {
|
|
241
|
+
const testInfo = testCoverage.hasCoverage
|
|
242
|
+
? `\n\tTests:\t\t${testStatisticsCollector.createTotalsReport()}`
|
|
243
|
+
: '';
|
|
244
|
+
this.logger.info(
|
|
245
|
+
`Incremental report:\n\tMutants:\t${mutantStatisticsCollector.createTotalsReport()}` +
|
|
246
|
+
testInfo +
|
|
247
|
+
`\n\tResult:\t\t${chalk.yellowBright(reusedMutantCount)} of ${currentMutants.length} mutant result(s) are reused.`,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
if (this.logger.isDebugEnabled()) {
|
|
251
|
+
const lineSeparator = '\n\t\t';
|
|
252
|
+
const noChanges = 'No changes';
|
|
253
|
+
const detailedMutantSummary = `${lineSeparator}${mutantStatisticsCollector.createDetailedReport().join(lineSeparator) || noChanges}`;
|
|
254
|
+
const detailedTestsSummary = `${lineSeparator}${testStatisticsCollector.createDetailedReport().join(lineSeparator) || noChanges}`;
|
|
255
|
+
this.logger.debug(
|
|
256
|
+
`Detailed incremental report:\n\tMutants: ${detailedMutantSummary}\n\tTests: ${detailedTestsSummary}`,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
return mutants;
|
|
260
|
+
|
|
261
|
+
function testKeysToId(testKeys: Iterable<string> | undefined) {
|
|
262
|
+
return [...(testKeys ?? [])]
|
|
263
|
+
.map((id) => testInfoByKey.get(id))
|
|
264
|
+
.filter(notEmpty)
|
|
265
|
+
.map(({ test: { id } }) => id);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function collectReusableMutantsByKey(log: Logger) {
|
|
269
|
+
return new Map(
|
|
270
|
+
Object.entries(files).flatMap(([fileName, oldFile]) => {
|
|
271
|
+
const relativeFileName = toRelativeNormalizedFileName(fileName);
|
|
272
|
+
const currentFileSource = currentRelativeFiles.get(relativeFileName);
|
|
273
|
+
if (currentFileSource) {
|
|
274
|
+
log.trace('Diffing %s', relativeFileName);
|
|
275
|
+
const { results, removeCount } = performFileDiff(
|
|
276
|
+
oldFile.source,
|
|
277
|
+
currentFileSource,
|
|
278
|
+
oldFile.mutants,
|
|
279
|
+
);
|
|
280
|
+
mutantStatisticsCollector.count(
|
|
281
|
+
relativeFileName,
|
|
282
|
+
'removed',
|
|
283
|
+
removeCount,
|
|
284
|
+
);
|
|
285
|
+
return results.map((m) => [
|
|
286
|
+
mutantToIdentifyingKey(m, relativeFileName),
|
|
287
|
+
{
|
|
288
|
+
...m,
|
|
289
|
+
relativeFileName,
|
|
290
|
+
},
|
|
291
|
+
]);
|
|
292
|
+
}
|
|
293
|
+
mutantStatisticsCollector.count(
|
|
294
|
+
relativeFileName,
|
|
295
|
+
'removed',
|
|
296
|
+
oldFile.mutants.length,
|
|
297
|
+
);
|
|
298
|
+
// File has since been deleted, these mutants are not reused
|
|
299
|
+
return [];
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function collectReusableTestInfo(log: Logger) {
|
|
305
|
+
const byId = new Map<
|
|
306
|
+
string,
|
|
307
|
+
{ relativeFileName: string; test: TestDefinition; key: string }
|
|
308
|
+
>();
|
|
309
|
+
const byKey = new Map<string, TestInfo>();
|
|
310
|
+
|
|
311
|
+
Object.entries(testFiles ?? {}).forEach(([fileName, oldTestFile]) => {
|
|
312
|
+
const relativeFileName = toRelativeNormalizedFileName(fileName);
|
|
313
|
+
const currentFileSource = currentRelativeFiles.get(relativeFileName);
|
|
314
|
+
if (currentFileSource === undefined && fileName !== '') {
|
|
315
|
+
// An empty file name means the test runner cannot report test file locations.
|
|
316
|
+
// If the current file is undefined while the test runner can report test file locations, it means it has been deleted
|
|
317
|
+
log.debug('Test file removed: %s', relativeFileName);
|
|
318
|
+
testStatisticsCollector.count(
|
|
319
|
+
relativeFileName,
|
|
320
|
+
'removed',
|
|
321
|
+
oldTestFile.tests.length,
|
|
322
|
+
);
|
|
323
|
+
} else if (
|
|
324
|
+
currentFileSource !== undefined &&
|
|
325
|
+
oldTestFile.source !== undefined
|
|
326
|
+
) {
|
|
327
|
+
log.trace('Diffing %s', relativeFileName);
|
|
328
|
+
const locatedTests = closeLocations(oldTestFile);
|
|
329
|
+
const { results, removeCount } = performFileDiff(
|
|
330
|
+
oldTestFile.source,
|
|
331
|
+
currentFileSource,
|
|
332
|
+
locatedTests,
|
|
333
|
+
);
|
|
334
|
+
testStatisticsCollector.count(
|
|
335
|
+
relativeFileName,
|
|
336
|
+
'removed',
|
|
337
|
+
removeCount,
|
|
338
|
+
);
|
|
339
|
+
results.forEach((test) => {
|
|
340
|
+
const key = testToIdentifyingKey(test, relativeFileName);
|
|
341
|
+
const testInfo = { key, test, relativeFileName };
|
|
342
|
+
byId.set(test.id, testInfo);
|
|
343
|
+
byKey.set(key, testInfo);
|
|
344
|
+
});
|
|
345
|
+
} else {
|
|
346
|
+
// No sources to compare, we should do our best with the info we do have
|
|
347
|
+
oldTestFile.tests.map((test) => {
|
|
348
|
+
const key = testToIdentifyingKey(test, relativeFileName);
|
|
349
|
+
const testInfo = { key, test, relativeFileName };
|
|
350
|
+
byId.set(test.id, testInfo);
|
|
351
|
+
byKey.set(key, testInfo);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
return { byId, byKey };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function collectOldKilledAndCoverageMatrix() {
|
|
359
|
+
const oldCoverageByMutantKey = new Map<string, Set<string>>();
|
|
360
|
+
const oldKilledByMutantKey = new Map<string, Set<string>>();
|
|
361
|
+
|
|
362
|
+
for (const [key, mutant] of reusableMutantsByKey) {
|
|
363
|
+
const killedRow = new Set(
|
|
364
|
+
mutant.killedBy
|
|
365
|
+
?.map((testId) => oldTestsById.get(testId)?.key)
|
|
366
|
+
.filter(notEmpty),
|
|
367
|
+
);
|
|
368
|
+
const coverageRow = new Set(
|
|
369
|
+
mutant.coveredBy
|
|
370
|
+
?.map((testId) => oldTestsById.get(testId)?.key)
|
|
371
|
+
.filter(notEmpty),
|
|
372
|
+
);
|
|
373
|
+
killedRow.forEach((killed) => coverageRow.add(killed));
|
|
374
|
+
oldCoverageByMutantKey.set(key, coverageRow);
|
|
375
|
+
oldKilledByMutantKey.set(key, killedRow);
|
|
376
|
+
}
|
|
377
|
+
return { oldCoverageByMutantKey, oldKilledByMutantKey };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function collectCurrentTestInfo() {
|
|
381
|
+
const byTestKey = new Map<
|
|
382
|
+
string,
|
|
383
|
+
{ relativeFileName: string; test: TestResult }
|
|
384
|
+
>();
|
|
385
|
+
for (const testResult of testCoverage.testsById.values()) {
|
|
386
|
+
const relativeFileName = toRelativeNormalizedFileName(
|
|
387
|
+
testResult.fileName,
|
|
388
|
+
);
|
|
389
|
+
const key = testToIdentifyingKey(testResult, relativeFileName);
|
|
390
|
+
const info = { relativeFileName, test: testResult, key: key };
|
|
391
|
+
byTestKey.set(key, info);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return byTestKey;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function mutantCanBeReused(
|
|
398
|
+
mutant: Mutant,
|
|
399
|
+
oldMutant: schema.MutantResult,
|
|
400
|
+
mutantKey: string,
|
|
401
|
+
coveringTests: ReadonlySet<TestResult> | undefined,
|
|
402
|
+
oldKillingTests: Set<string> | undefined,
|
|
403
|
+
): boolean {
|
|
404
|
+
if (!testCoverage.hasCoverage) {
|
|
405
|
+
// This is the best we can do when the test runner didn't report coverage.
|
|
406
|
+
// We assume that all mutant test results can be reused,
|
|
407
|
+
// End users can use --force to force retesting of certain mutants
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
if (oldMutant.status === 'Ignored') {
|
|
411
|
+
// Was previously ignored, but not anymore, we need to run it now
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const testsDiff = diffTestCoverage(
|
|
416
|
+
mutant.id,
|
|
417
|
+
oldCoverageTestKeysByMutantKey.get(mutantKey),
|
|
418
|
+
coveringTests,
|
|
419
|
+
);
|
|
420
|
+
if (oldMutant.status === 'Killed') {
|
|
421
|
+
if (oldKillingTests) {
|
|
422
|
+
for (const killingTest of oldKillingTests) {
|
|
423
|
+
if (testsDiff.get(killingTest) === 'same') {
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// Killing tests has changed or no longer exists
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
for (const action of testsDiff.values()) {
|
|
432
|
+
if (action === 'added') {
|
|
433
|
+
// A non-killed mutant got a new test, we need to run it
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// A non-killed mutant did not get new tests, no need to rerun it
|
|
438
|
+
return true;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Determines if there is a diff between old test coverage and new test coverage.
|
|
443
|
+
*/
|
|
444
|
+
function diffTestCoverage(
|
|
445
|
+
mutantId: string,
|
|
446
|
+
oldCoveringTestKeys: Set<string> | undefined,
|
|
447
|
+
newCoveringTests: ReadonlySet<TestResult> | undefined,
|
|
448
|
+
): Map<string, DiffAction> {
|
|
449
|
+
const result = new Map<string, DiffAction>();
|
|
450
|
+
if (newCoveringTests) {
|
|
451
|
+
for (const newTest of newCoveringTests) {
|
|
452
|
+
const key = testToIdentifyingKey(
|
|
453
|
+
newTest,
|
|
454
|
+
toRelativeNormalizedFileName(newTest.fileName),
|
|
455
|
+
);
|
|
456
|
+
result.set(key, oldCoveringTestKeys?.has(key) ? 'same' : 'added');
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (oldCoveringTestKeys) {
|
|
460
|
+
const isStatic = testCoverage.hasStaticCoverage(mutantId);
|
|
461
|
+
for (const oldTestKey of oldCoveringTestKeys) {
|
|
462
|
+
if (!result.has(oldTestKey)) {
|
|
463
|
+
// Static mutants might not have covering tests, but the test might still exist
|
|
464
|
+
if (isStatic && newTestKeys.has(oldTestKey)) {
|
|
465
|
+
result.set(oldTestKey, 'same');
|
|
466
|
+
} else {
|
|
467
|
+
result.set(oldTestKey, 'removed');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Finds the diff of mutants and tests. Removes mutants / tests that no longer exist (changed or removed). Updates locations of mutants or tests that do still exist.
|
|
479
|
+
* @param oldCode The old code to use for the diff
|
|
480
|
+
* @param newCode The new (current) code to use for the diff
|
|
481
|
+
* @param items The mutants or tests to be looked . These will be treated as immutable.
|
|
482
|
+
* @returns A list of items with updated locations, without items that are changed.
|
|
483
|
+
*/
|
|
484
|
+
function performFileDiff<T extends { location: Location }>(
|
|
485
|
+
oldCode: string,
|
|
486
|
+
newCode: string,
|
|
487
|
+
items: T[],
|
|
488
|
+
): { results: T[]; removeCount: number } {
|
|
489
|
+
const oldSourceNormalized = normalizeLineEndings(oldCode);
|
|
490
|
+
const currentSrcNormalized = normalizeLineEndings(newCode);
|
|
491
|
+
const diffChanges = diffMatchPatch.diff_main(
|
|
492
|
+
oldSourceNormalized,
|
|
493
|
+
currentSrcNormalized,
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
const toDo = new Set(
|
|
497
|
+
items.map((m) => ({ ...m, location: deepClone(m.location) })),
|
|
498
|
+
);
|
|
499
|
+
const [added, removed] = [1, -1];
|
|
500
|
+
const done: T[] = [];
|
|
501
|
+
const currentPosition: Position = { column: 0, line: 0 };
|
|
502
|
+
let removeCount = 0;
|
|
503
|
+
for (const [change, text] of diffChanges) {
|
|
504
|
+
if (toDo.size === 0) {
|
|
505
|
+
// There are more changes, but nothing left to update.
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
const offset = calculateOffset(text);
|
|
509
|
+
if (change === added) {
|
|
510
|
+
for (const test of toDo) {
|
|
511
|
+
const { location } = test;
|
|
512
|
+
if (
|
|
513
|
+
gte(currentPosition, location.start) &&
|
|
514
|
+
gte(location.end, currentPosition)
|
|
515
|
+
) {
|
|
516
|
+
// This item cannot be reused, code was added here
|
|
517
|
+
removeCount++;
|
|
518
|
+
toDo.delete(test);
|
|
519
|
+
} else {
|
|
520
|
+
locationAdd(
|
|
521
|
+
location,
|
|
522
|
+
offset,
|
|
523
|
+
currentPosition.line === location.start.line,
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
positionMove(currentPosition, offset);
|
|
528
|
+
} else if (change === removed) {
|
|
529
|
+
for (const item of toDo) {
|
|
530
|
+
const {
|
|
531
|
+
location: { start },
|
|
532
|
+
} = item;
|
|
533
|
+
const endOffset = positionMove({ ...currentPosition }, offset);
|
|
534
|
+
if (gte(endOffset, start)) {
|
|
535
|
+
// This item cannot be reused, the code it covers has changed
|
|
536
|
+
removeCount++;
|
|
537
|
+
toDo.delete(item);
|
|
538
|
+
} else {
|
|
539
|
+
locationAdd(
|
|
540
|
+
item.location,
|
|
541
|
+
negate(offset),
|
|
542
|
+
currentPosition.line === start.line,
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
positionMove(currentPosition, offset);
|
|
548
|
+
toDo.forEach((item) => {
|
|
549
|
+
const { end } = item.location;
|
|
550
|
+
if (gte(currentPosition, end)) {
|
|
551
|
+
// We're done with this item, it can be reused
|
|
552
|
+
toDo.delete(item);
|
|
553
|
+
done.push(item);
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
done.push(...toDo);
|
|
559
|
+
return { results: done, removeCount };
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* A greater-than-equals implementation for positions
|
|
564
|
+
*/
|
|
565
|
+
function gte(a: Position, b: Position) {
|
|
566
|
+
return a.line > b.line || (a.line === b.line && a.column >= b.column);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function locationIncluded(haystack: Location, needle: Location) {
|
|
570
|
+
const startIncluded = gte(needle.start, haystack.start);
|
|
571
|
+
const endIncluded = gte(haystack.end, needle.end);
|
|
572
|
+
return startIncluded && endIncluded;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function deepClone(loc: Location): Location {
|
|
576
|
+
return { start: { ...loc.start }, end: { ...loc.end } };
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Reduces a mutant to a string that identifies the mutant across reports.
|
|
581
|
+
* Consists of the relative file name, mutator name, replacement, and location
|
|
582
|
+
*/
|
|
583
|
+
function mutantToIdentifyingKey(
|
|
584
|
+
{
|
|
585
|
+
mutatorName,
|
|
586
|
+
replacement,
|
|
587
|
+
location: { start, end },
|
|
588
|
+
}: Pick<Mutant, 'location' | 'mutatorName'> & { replacement?: string },
|
|
589
|
+
relativeFileName: string,
|
|
590
|
+
) {
|
|
591
|
+
return `${relativeFileName}@${start.line}:${start.column}-${end.line}:${end.column}\n${mutatorName}: ${replacement}`;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function testToIdentifyingKey(
|
|
595
|
+
{
|
|
596
|
+
name,
|
|
597
|
+
location,
|
|
598
|
+
startPosition,
|
|
599
|
+
}: Pick<schema.TestDefinition, 'location' | 'name'> &
|
|
600
|
+
Pick<TestResult, 'startPosition'>,
|
|
601
|
+
relativeFileName: string | undefined,
|
|
602
|
+
) {
|
|
603
|
+
startPosition = startPosition ?? location?.start ?? { line: 0, column: 0 };
|
|
604
|
+
return `${relativeFileName}@${startPosition.line}:${startPosition.column}\n${name}`;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export function toRelativeNormalizedFileName(
|
|
608
|
+
fileName: string | undefined,
|
|
609
|
+
): string {
|
|
610
|
+
return normalizeFileName(path.relative(process.cwd(), fileName ?? ''));
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function calculateOffset(text: string): Position {
|
|
614
|
+
const pos: Position = { line: 0, column: 0 };
|
|
615
|
+
for (const char of text) {
|
|
616
|
+
if (char === '\n') {
|
|
617
|
+
pos.line++;
|
|
618
|
+
pos.column = 0;
|
|
619
|
+
} else {
|
|
620
|
+
pos.column++;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return pos;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
function positionMove(pos: Position, diff: Position): Position {
|
|
627
|
+
pos.line += diff.line;
|
|
628
|
+
if (diff.line === 0) {
|
|
629
|
+
pos.column += diff.column;
|
|
630
|
+
} else {
|
|
631
|
+
pos.column = diff.column;
|
|
632
|
+
}
|
|
633
|
+
return pos;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function locationAdd(
|
|
637
|
+
{ start, end }: Location,
|
|
638
|
+
{ line, column }: Position,
|
|
639
|
+
currentLine: boolean,
|
|
640
|
+
) {
|
|
641
|
+
start.line += line;
|
|
642
|
+
if (currentLine) {
|
|
643
|
+
start.column += column;
|
|
644
|
+
}
|
|
645
|
+
end.line += line;
|
|
646
|
+
if (line === 0 && currentLine) {
|
|
647
|
+
end.column += column;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function negate({ line, column }: Position): Position {
|
|
652
|
+
return { line: -1 * line, column: -1 * column };
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
interface TestInfo {
|
|
656
|
+
relativeFileName: string;
|
|
657
|
+
test: TestDefinition;
|
|
658
|
+
key: string;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
type DiffAction = DiffChange | 'same';
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Sets the end position of each test to the start position of the next test.
|
|
665
|
+
* This is an educated guess and necessary.
|
|
666
|
+
* If a test has no location, it is assumed it spans the entire file (line 0 to Infinity)
|
|
667
|
+
*
|
|
668
|
+
* Knowing the end location of tests is necessary in order to know if the test was changed.
|
|
669
|
+
*/
|
|
670
|
+
function closeLocations(testFile: schema.TestFile): LocatedTest[] {
|
|
671
|
+
const locatedTests: LocatedTest[] = [];
|
|
672
|
+
const openEndedTests: OpenEndedTest[] = [];
|
|
673
|
+
|
|
674
|
+
testFile.tests.forEach((test) => {
|
|
675
|
+
if (testHasLocation(test)) {
|
|
676
|
+
if (isClosed(test)) {
|
|
677
|
+
locatedTests.push(test);
|
|
678
|
+
} else {
|
|
679
|
+
openEndedTests.push(test);
|
|
680
|
+
}
|
|
681
|
+
} else {
|
|
682
|
+
locatedTests.push({
|
|
683
|
+
...test,
|
|
684
|
+
location: {
|
|
685
|
+
start: { line: 0, column: 0 },
|
|
686
|
+
end: { line: Number.POSITIVE_INFINITY, column: 0 },
|
|
687
|
+
},
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
if (openEndedTests.length) {
|
|
693
|
+
// Sort the opened tests in order to close their locations
|
|
694
|
+
openEndedTests.sort(
|
|
695
|
+
(a, b) => a.location.start.line - b.location.start.line,
|
|
696
|
+
);
|
|
697
|
+
const openEndedTestSet = new Set(openEndedTests);
|
|
698
|
+
const startPositions = uniqueStartPositions(openEndedTests);
|
|
699
|
+
|
|
700
|
+
let currentPositionIndex = 0;
|
|
701
|
+
openEndedTestSet.forEach((test) => {
|
|
702
|
+
if (
|
|
703
|
+
eqPosition(test.location.start, startPositions[currentPositionIndex])
|
|
704
|
+
) {
|
|
705
|
+
currentPositionIndex++;
|
|
706
|
+
}
|
|
707
|
+
if (startPositions[currentPositionIndex]) {
|
|
708
|
+
locatedTests.push({
|
|
709
|
+
...test,
|
|
710
|
+
location: {
|
|
711
|
+
start: test.location.start,
|
|
712
|
+
end: startPositions[currentPositionIndex],
|
|
713
|
+
},
|
|
714
|
+
});
|
|
715
|
+
openEndedTestSet.delete(test);
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// Don't forget about the last tests
|
|
720
|
+
openEndedTestSet.forEach((lastTest) => {
|
|
721
|
+
locatedTests.push({
|
|
722
|
+
...lastTest,
|
|
723
|
+
location: {
|
|
724
|
+
start: lastTest.location.start,
|
|
725
|
+
end: { line: Number.POSITIVE_INFINITY, column: 0 },
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return locatedTests;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Determines the unique start positions of a sorted list of tests in order
|
|
736
|
+
*/
|
|
737
|
+
function uniqueStartPositions(sortedTests: OpenEndedTest[]) {
|
|
738
|
+
let current: Position | undefined;
|
|
739
|
+
const startPositions = sortedTests.reduce<Position[]>(
|
|
740
|
+
(collector, { location: { start } }) => {
|
|
741
|
+
if (
|
|
742
|
+
!current ||
|
|
743
|
+
current.line !== start.line ||
|
|
744
|
+
current.column !== start.column
|
|
745
|
+
) {
|
|
746
|
+
current = start;
|
|
747
|
+
collector.push(current);
|
|
748
|
+
}
|
|
749
|
+
return collector;
|
|
750
|
+
},
|
|
751
|
+
[],
|
|
752
|
+
);
|
|
753
|
+
return startPositions;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
function testHasLocation(test: schema.TestDefinition): test is OpenEndedTest {
|
|
757
|
+
return !!test.location?.start;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function isClosed(test: Required<schema.TestDefinition>): test is LocatedTest {
|
|
761
|
+
return !!test.location.end;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function eqPosition(start: Position, end?: Position): boolean {
|
|
765
|
+
return start.column === end?.column && start.line === end.line;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
type LocatedTest = schema.TestDefinition & { location: Location };
|
|
769
|
+
type OpenEndedTest = schema.TestDefinition & {
|
|
770
|
+
location: schema.OpenEndLocation;
|
|
771
|
+
};
|