mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-06-11 12:41:03 +02:00
Collect coverage information for the integration tests
Note that for the integration tests the coverage information ends up being processed in the Node.js context where `window` is not available, so we use `globalThis` instead for the function that merges individual test's coverage information into the global object because that is available in all contexts we support. For clarity we also rename said function since we're not exclusively dealing with `window` nor worker data anymore.
This commit is contained in:
parent
bf9ae7622f
commit
26dc195a65
21
.github/workflows/integration_tests.yml
vendored
21
.github/workflows/integration_tests.yml
vendored
@ -41,6 +41,7 @@ jobs:
|
||||
skip: --noFirefox
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: code-coverage
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@ -75,13 +76,13 @@ jobs:
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: Set-DisplayResolution -Width 1920 -Height 1080 -Force
|
||||
|
||||
- name: Run integration tests (Windows)
|
||||
- name: Run integration tests with code coverage (Windows)
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: npx gulp integrationtest ${{ matrix.skip }}
|
||||
run: npx gulp integrationtest --coverage --coverage-output build/coverage/integration ${{ matrix.skip }}
|
||||
|
||||
- name: Run integration tests (Linux)
|
||||
- name: Run integration tests with code coverage (Linux)
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
run: xvfb-run -a --server-args="-screen 0, 1920x1080x24" npx gulp integrationtest ${{ matrix.skip }}
|
||||
run: xvfb-run -a --server-args="-screen 0, 1920x1080x24" npx gulp integrationtest --coverage --coverage-output build/coverage/integration ${{ matrix.skip }}
|
||||
|
||||
- name: Save cached PDF files
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
@ -89,3 +90,15 @@ jobs:
|
||||
path: test/pdfs/*.pdf
|
||||
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
files: ./build/coverage/integration/lcov.info
|
||||
flags: integrationtest
|
||||
name: codecov-umbrella
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
verbose: true
|
||||
|
||||
@ -1036,6 +1036,9 @@ class WorkerMessageHandler {
|
||||
.getPage(data.pageIndex)
|
||||
.then(page => page.annotations.map(a => a.toString()));
|
||||
});
|
||||
handler.on("GetWorkerCoverage", function () {
|
||||
return globalThis.__coverage__ ?? {};
|
||||
});
|
||||
}
|
||||
|
||||
return workerHandlerName;
|
||||
|
||||
@ -15,15 +15,15 @@
|
||||
|
||||
// Istanbul coverage objects use s (statements), b (branches), and f (functions)
|
||||
// as shorthand keys for the hit-count maps.
|
||||
function mergeWorkerCoverageIntoWindow(coverage) {
|
||||
function mergeCoverageIntoGlobal(coverage) {
|
||||
if (!coverage || Object.keys(coverage).length === 0) {
|
||||
return;
|
||||
}
|
||||
window.__coverage__ ??= {};
|
||||
globalThis.__coverage__ ??= {};
|
||||
for (const [key, fileCoverage] of Object.entries(coverage)) {
|
||||
const existing = window.__coverage__[key];
|
||||
const existing = globalThis.__coverage__[key];
|
||||
if (!existing) {
|
||||
window.__coverage__[key] = fileCoverage;
|
||||
globalThis.__coverage__[key] = fileCoverage;
|
||||
continue;
|
||||
}
|
||||
for (const id of Object.keys(fileCoverage.s)) {
|
||||
@ -49,10 +49,10 @@ async function fetchAndMergeWorkerCoverage(pdfWorker) {
|
||||
"GetWorkerCoverage",
|
||||
null
|
||||
);
|
||||
mergeWorkerCoverageIntoWindow(coverage);
|
||||
mergeCoverageIntoGlobal(coverage);
|
||||
} catch (e) {
|
||||
console.warn(`Failed to collect worker coverage: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
export { fetchAndMergeWorkerCoverage, mergeWorkerCoverageIntoWindow };
|
||||
export { fetchAndMergeWorkerCoverage, mergeCoverageIntoGlobal };
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { mergeCoverageIntoGlobal } from "../coverage_utils.js";
|
||||
import os from "os";
|
||||
|
||||
const isMac = os.platform() === "darwin";
|
||||
@ -149,11 +150,42 @@ function closePages(pages) {
|
||||
}
|
||||
|
||||
async function closeSinglePage(page) {
|
||||
// Avoid to keep something from a previous test.
|
||||
await page.evaluate(async () => {
|
||||
const coverage = await page.evaluate(async () => {
|
||||
// Collect coverage data from the worker before the document is closed.
|
||||
let workerCoverage = null;
|
||||
const handler =
|
||||
window.PDFViewerApplication.pdfDocument?._transport?.messageHandler;
|
||||
if (handler) {
|
||||
try {
|
||||
workerCoverage = await handler.sendWithPromise(
|
||||
"GetWorkerCoverage",
|
||||
null
|
||||
);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// Close the viewer gracefully, and clear local storage to avoid state
|
||||
// leaking from one test to another.
|
||||
await window.PDFViewerApplication.testingClose();
|
||||
window.localStorage.clear();
|
||||
|
||||
// Serialize the coverage data to a JSON string because that is a lot
|
||||
// faster/cheaper to transfer from the browser to Node.js over the WebDriver
|
||||
// BiDi protocol, otherwise Puppeteer's (significantly slower) serialization
|
||||
// logic kicks in (see https://github.com/puppeteer/puppeteer/issues/2427).
|
||||
return {
|
||||
page: window.__coverage__ ? JSON.stringify(window.__coverage__) : null,
|
||||
worker: workerCoverage ? JSON.stringify(workerCoverage) : null,
|
||||
};
|
||||
});
|
||||
|
||||
if (coverage.page) {
|
||||
mergeCoverageIntoGlobal(JSON.parse(coverage.page));
|
||||
}
|
||||
if (coverage.worker) {
|
||||
mergeCoverageIntoGlobal(JSON.parse(coverage.worker));
|
||||
}
|
||||
|
||||
await page.close({ runBeforeUnload: false });
|
||||
}
|
||||
|
||||
|
||||
@ -890,6 +890,7 @@ async function startIntegrationTest() {
|
||||
sessions[0].numRuns = results.runs;
|
||||
sessions[0].numErrors = results.failures;
|
||||
sessions[0].failures = results.failureList;
|
||||
sessions[0].coverage = globalThis.__coverage__;
|
||||
await Promise.all(sessions.map(session => closeSession(session.name)));
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
import { GlobalWorkerOptions } from "pdfjs/display/worker_options.js";
|
||||
import { isNodeJS } from "../../src/shared/util.js";
|
||||
import { mergeWorkerCoverageIntoWindow } from "../coverage_utils.js";
|
||||
import { mergeCoverageIntoGlobal } from "../coverage_utils.js";
|
||||
import { MessageHandler } from "pdfjs/shared/message_handler.js";
|
||||
import { PDFWorker } from "pdfjs/display/api.js";
|
||||
import { TestReporter } from "../reporter.js";
|
||||
@ -156,7 +156,7 @@ function installWorkerCoverageHook() {
|
||||
const handler = new MessageHandler("main", "worker", webWorker);
|
||||
const promise = handler
|
||||
.sendWithPromise("GetWorkerCoverage", null)
|
||||
.then(mergeWorkerCoverageIntoWindow)
|
||||
.then(mergeCoverageIntoGlobal)
|
||||
.catch(e => {
|
||||
console.warn(`Failed to collect worker coverage: ${e}`);
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user