mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-26 22:35:43 +00:00
### Description <!-- Describe your changes. --> This PR tries to fix #22615. (see detailed description in the issue) A perfect solution would be too difficult to make, because there are a huge number of combinations of usage scenarios, including combinations of development framework, bundler, dev/prod mode, and so on. This PR is using the following approach: - Introduce a new type of end to end test: export test. This type of tests are complete web apps that use popular web development frameworks, and the tests are using puppeteer to run the apps and check if the apps can run without error. - added one nextjs based web app and one vite based web app. - In the test, perform the following test steps: - `npm install` for packages built locally - `npm run dev` to start dev server and use puppeteer to launch the browser to test - `npm run build && npm run start` to test prod build and use puppeteer to launch the browser to test - Make changes to ort-web, including: - special handling on Webpack's behavior of rewriting `import.meta.url` to a `file://` string - revise build definitions - fix wasm URL for proxy, if used in a bundled build
127 lines
4.2 KiB
JavaScript
127 lines
4.2 KiB
JavaScript
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
'use strict';
|
|
|
|
const EventEmitter = require('node:events');
|
|
const path = require('path');
|
|
const { runShellCmd } = require('./utils');
|
|
|
|
const launchBrowserAndRunTests = async (logPrefix, port) => {
|
|
const testResults = [];
|
|
const puppeteer = require('puppeteer-core');
|
|
let browser;
|
|
try {
|
|
browser = await puppeteer.launch({
|
|
executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
browser: 'chrome',
|
|
headless: true,
|
|
args: ['--enable-features=SharedArrayBuffer', '--no-sandbox', '--disable-setuid-sandbox'],
|
|
});
|
|
|
|
for await (const flags of [
|
|
[false, false],
|
|
[false, true],
|
|
[true, false],
|
|
[true, true],
|
|
]) {
|
|
const [multiThread, proxy] = flags;
|
|
console.log(`[${logPrefix}] Running test with multi-thread: ${multiThread}, proxy: ${proxy}...`);
|
|
|
|
const page = await browser.newPage();
|
|
await page.goto(`http://localhost:${port}`);
|
|
// wait for the page to load
|
|
await page.waitForSelector('#ortstate', { visible: true });
|
|
// if multi-thread is enabled, check the checkbox
|
|
if (multiThread) {
|
|
await page.locator('#cb-mt').click();
|
|
}
|
|
// if proxy is enabled, check the checkbox
|
|
if (proxy) {
|
|
await page.locator('#cb-px').click();
|
|
}
|
|
// click the load model button
|
|
await page.locator('#btn-load').click();
|
|
// wait for the model to load or fail
|
|
await page.waitForFunction("['2','3'].includes(document.getElementById('ortstate').innerText)");
|
|
// verify the model is loaded
|
|
const modelLoadState = await page.$eval('#ortstate', (el) => el.innerText);
|
|
if (modelLoadState !== '2') {
|
|
const ortLog = await page.$eval('#ortlog', (el) => el.innerText);
|
|
testResults.push({ multiThread, proxy, success: false, message: `Failed to load model: ${ortLog}` });
|
|
continue;
|
|
}
|
|
|
|
// click the run test button
|
|
await page.locator('#btn-run').click();
|
|
// wait for the inference run to complete or fail
|
|
await page.waitForFunction("['5','6'].includes(document.getElementById('ortstate').innerText)");
|
|
// verify the inference run result
|
|
const runState = await page.$eval('#ortstate', (el) => el.innerText);
|
|
if (runState !== '5') {
|
|
const ortLog = await page.$eval('#ortlog', (el) => el.innerText);
|
|
testResults.push({ multiThread, proxy, success: false, message: `Failed to run model: ${ortLog}` });
|
|
continue;
|
|
}
|
|
|
|
testResults.push({ multiThread, proxy, success: true });
|
|
}
|
|
|
|
return testResults;
|
|
} finally {
|
|
console.log(`[${logPrefix}] Closing the browser...`);
|
|
// close the browser
|
|
if (browser) {
|
|
await browser.close();
|
|
}
|
|
}
|
|
};
|
|
|
|
async function runTest(testCaseName, logPrefix, ready, cmd, port) {
|
|
const wd = path.join(__dirname, 'testcases', testCaseName);
|
|
logPrefix = [testCaseName, ...logPrefix].join(':');
|
|
|
|
console.log(`[${logPrefix}] Testing...`);
|
|
const npmRunDevEvent = new EventEmitter();
|
|
const npmRunDev = runShellCmd(cmd, {
|
|
wd,
|
|
event: npmRunDevEvent,
|
|
ready,
|
|
ignoreExitCode: true,
|
|
});
|
|
|
|
let testResults;
|
|
npmRunDevEvent.on('serverReady', async () => {
|
|
try {
|
|
testResults = await launchBrowserAndRunTests(logPrefix, port);
|
|
} finally {
|
|
console.log(`[${logPrefix}] Killing the server...`);
|
|
// kill the server as the last step
|
|
npmRunDevEvent.emit('kill');
|
|
}
|
|
});
|
|
|
|
await npmRunDev;
|
|
|
|
console.log(`[${logPrefix}] test result:`, testResults);
|
|
if (testResults.some((r) => !r.success)) {
|
|
throw new Error(`[${logPrefix}] test failed.`);
|
|
}
|
|
}
|
|
|
|
async function runDevTest(testCaseName, ready, port, logPrefix = '', cmd = 'npm run dev') {
|
|
return runTest(testCaseName, logPrefix ? ['dev', logPrefix] : ['dev'], ready, cmd, port);
|
|
}
|
|
|
|
async function runProdTest(testCaseName, ready, port) {
|
|
const wd = path.join(__dirname, 'testcases', testCaseName);
|
|
|
|
console.log(`[${testCaseName}:prod] Building...`);
|
|
await runShellCmd('npm run build', { wd });
|
|
await runTest(testCaseName, ['prod'], ready, 'npm run start', port);
|
|
}
|
|
|
|
module.exports = {
|
|
runDevTest,
|
|
runProdTest,
|
|
};
|