1*c8dee2aaSAndroid Build Coastguard Worker<!-- This runs the GMs and unit tests which have been compiled to WASM. When this completes, 2*c8dee2aaSAndroid Build Coastguard Workereither window._error will be set or window._testsDone will be true and window._results will be an 3*c8dee2aaSAndroid Build Coastguard Workerarray of the test names and what they drew. 4*c8dee2aaSAndroid Build Coastguard Worker--> 5*c8dee2aaSAndroid Build Coastguard Worker<!DOCTYPE html> 6*c8dee2aaSAndroid Build Coastguard Worker<html> 7*c8dee2aaSAndroid Build Coastguard Worker<head> 8*c8dee2aaSAndroid Build Coastguard Worker <title>WASM Runner of GMs and Unit Tests</title> 9*c8dee2aaSAndroid Build Coastguard Worker <meta charset="utf-8" /> 10*c8dee2aaSAndroid Build Coastguard Worker <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 11*c8dee2aaSAndroid Build Coastguard Worker <meta name="viewport" content="width=device-width, initial-scale=1.0"> 12*c8dee2aaSAndroid Build Coastguard Worker <script src="/static/wasm_gm_tests.js" type="text/javascript" charset="utf-8"></script> 13*c8dee2aaSAndroid Build Coastguard Worker <style type="text/css" media="screen"> 14*c8dee2aaSAndroid Build Coastguard Worker #status_text { 15*c8dee2aaSAndroid Build Coastguard Worker min-width: 900px; 16*c8dee2aaSAndroid Build Coastguard Worker min-height: 500px; 17*c8dee2aaSAndroid Build Coastguard Worker } 18*c8dee2aaSAndroid Build Coastguard Worker </style> 19*c8dee2aaSAndroid Build Coastguard Worker</head> 20*c8dee2aaSAndroid Build Coastguard Worker<body> 21*c8dee2aaSAndroid Build Coastguard Worker<main> 22*c8dee2aaSAndroid Build Coastguard Worker <button id=start_tests>Start Tests</button> 23*c8dee2aaSAndroid Build Coastguard Worker <br> 24*c8dee2aaSAndroid Build Coastguard Worker <pre id=status_text></pre> 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker <canvas id=gm_canvas></canvas> 27*c8dee2aaSAndroid Build Coastguard Worker</main> 28*c8dee2aaSAndroid Build Coastguard Worker<script type="text/javascript" charset="utf-8"> 29*c8dee2aaSAndroid Build Coastguard Worker const loadTestsPromise = InitWasmGMTests({ 30*c8dee2aaSAndroid Build Coastguard Worker locateFile: (file) => '/static/'+file, 31*c8dee2aaSAndroid Build Coastguard Worker }); 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker const loadKnownHashesPromise = fetch('/static/hashes.txt').then((resp) => resp.text()); 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker const resourceNames = []; 36*c8dee2aaSAndroid Build Coastguard Worker const loadResourceListing = fetch('/static/resource_listing.json').then((resp) => resp.json()) 37*c8dee2aaSAndroid Build Coastguard Worker .then((json) => { 38*c8dee2aaSAndroid Build Coastguard Worker console.debug('should fetch resources', json); 39*c8dee2aaSAndroid Build Coastguard Worker const loadingPromises = []; 40*c8dee2aaSAndroid Build Coastguard Worker for (const resource of json) { 41*c8dee2aaSAndroid Build Coastguard Worker resourceNames.push(resource); 42*c8dee2aaSAndroid Build Coastguard Worker const url = `/static/resources/${resource}`; 43*c8dee2aaSAndroid Build Coastguard Worker loadingPromises.push(fetch(url).then((resp) => resp.arrayBuffer())); 44*c8dee2aaSAndroid Build Coastguard Worker } 45*c8dee2aaSAndroid Build Coastguard Worker return Promise.all(loadingPromises).catch((e) => { 46*c8dee2aaSAndroid Build Coastguard Worker console.error(e); 47*c8dee2aaSAndroid Build Coastguard Worker window._error = `Failed getting resources: ${JSON.stringify(e)}`; 48*c8dee2aaSAndroid Build Coastguard Worker }); 49*c8dee2aaSAndroid Build Coastguard Worker }); 50*c8dee2aaSAndroid Build Coastguard Worker 51*c8dee2aaSAndroid Build Coastguard Worker let attemptedPOSTs = 0; 52*c8dee2aaSAndroid Build Coastguard Worker let successfulPOSTs = 0; 53*c8dee2aaSAndroid Build Coastguard Worker Promise.all([loadTestsPromise, loadKnownHashesPromise, loadResourceListing]).then(([GM, hashes, resourceBuffers]) => { 54*c8dee2aaSAndroid Build Coastguard Worker GM.Init(); 55*c8dee2aaSAndroid Build Coastguard Worker LoadResources(GM, resourceNames, resourceBuffers); 56*c8dee2aaSAndroid Build Coastguard Worker LoadKnownHashes(GM, hashes); 57*c8dee2aaSAndroid Build Coastguard Worker document.getElementById('start_tests').addEventListener('click', async () => { 58*c8dee2aaSAndroid Build Coastguard Worker window._testsProgress = 0; 59*c8dee2aaSAndroid Build Coastguard Worker window._log = 'Starting\n'; 60*c8dee2aaSAndroid Build Coastguard Worker window._failed = []; 61*c8dee2aaSAndroid Build Coastguard Worker await RunTests(GM); 62*c8dee2aaSAndroid Build Coastguard Worker if (window._error) { 63*c8dee2aaSAndroid Build Coastguard Worker console.log(window._error); 64*c8dee2aaSAndroid Build Coastguard Worker return; 65*c8dee2aaSAndroid Build Coastguard Worker } 66*c8dee2aaSAndroid Build Coastguard Worker await RunGMs(GM); 67*c8dee2aaSAndroid Build Coastguard Worker if (attemptedPOSTs !== successfulPOSTs) { 68*c8dee2aaSAndroid Build Coastguard Worker window._error = `Failed to POST all the PNG files (expected ${attemptedPOSTs}, finished ${successfulPOSTs})`; 69*c8dee2aaSAndroid Build Coastguard Worker } else { 70*c8dee2aaSAndroid Build Coastguard Worker window._testsDone = true; 71*c8dee2aaSAndroid Build Coastguard Worker } 72*c8dee2aaSAndroid Build Coastguard Worker }); 73*c8dee2aaSAndroid Build Coastguard Worker window._testsReady = true; 74*c8dee2aaSAndroid Build Coastguard Worker }); 75*c8dee2aaSAndroid Build Coastguard Worker 76*c8dee2aaSAndroid Build Coastguard Worker const statusElement = document.getElementById('status_text'); 77*c8dee2aaSAndroid Build Coastguard Worker function log(line) { 78*c8dee2aaSAndroid Build Coastguard Worker console.log(line); 79*c8dee2aaSAndroid Build Coastguard Worker line += '\n'; 80*c8dee2aaSAndroid Build Coastguard Worker statusElement.innerText += line; 81*c8dee2aaSAndroid Build Coastguard Worker window._log += line; 82*c8dee2aaSAndroid Build Coastguard Worker } 83*c8dee2aaSAndroid Build Coastguard Worker 84*c8dee2aaSAndroid Build Coastguard Worker function LoadResources(GM, resourceNames, resourceBuffers) { 85*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < resourceNames.length; i++) { 86*c8dee2aaSAndroid Build Coastguard Worker const name = resourceNames[i]; 87*c8dee2aaSAndroid Build Coastguard Worker const buffer = resourceBuffers[i]; 88*c8dee2aaSAndroid Build Coastguard Worker GM.LoadResource(name, buffer); 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker } 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker // There's a global set of known hashes that we preload with the md5 hashes that are already 93*c8dee2aaSAndroid Build Coastguard Worker // uploaded to Gold. This saves us some time to encode them and write them to disk. 94*c8dee2aaSAndroid Build Coastguard Worker function LoadKnownHashes(GM, hashes) { 95*c8dee2aaSAndroid Build Coastguard Worker log(`Loading ${hashes.length} hashes`); 96*c8dee2aaSAndroid Build Coastguard Worker console.time('load_hashes'); 97*c8dee2aaSAndroid Build Coastguard Worker for (const hash of hashes.split('\n')) { 98*c8dee2aaSAndroid Build Coastguard Worker if (hash.length < 5) { // be sure not to add empty lines 99*c8dee2aaSAndroid Build Coastguard Worker continue; 100*c8dee2aaSAndroid Build Coastguard Worker } 101*c8dee2aaSAndroid Build Coastguard Worker GM.LoadKnownDigest(hash); 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker console.timeEnd('load_hashes'); 104*c8dee2aaSAndroid Build Coastguard Worker log('hashes loaded'); 105*c8dee2aaSAndroid Build Coastguard Worker } 106*c8dee2aaSAndroid Build Coastguard Worker 107*c8dee2aaSAndroid Build Coastguard Worker const gmSkipList = new Set([ 108*c8dee2aaSAndroid Build Coastguard Worker 'exoticformats', // Uses SkFILEStream to load resource. 109*c8dee2aaSAndroid Build Coastguard Worker ]); 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Worker async function RunGMs(GM) { 112*c8dee2aaSAndroid Build Coastguard Worker const canvas = document.getElementById('gm_canvas'); 113*c8dee2aaSAndroid Build Coastguard Worker const ctx = GM.GetWebGLContext(canvas, 2); 114*c8dee2aaSAndroid Build Coastguard Worker const grcontext = GM.MakeGrContext(ctx); 115*c8dee2aaSAndroid Build Coastguard Worker if (!grcontext) { 116*c8dee2aaSAndroid Build Coastguard Worker window._error = 'Could not make GrContext for gms'; 117*c8dee2aaSAndroid Build Coastguard Worker return; 118*c8dee2aaSAndroid Build Coastguard Worker } 119*c8dee2aaSAndroid Build Coastguard Worker window._results = []; 120*c8dee2aaSAndroid Build Coastguard Worker // We run these tests in batches so as not to lock up the main thread, which makes it easier 121*c8dee2aaSAndroid Build Coastguard Worker // to read the progress as well as making the page more responsive when debugging. 122*c8dee2aaSAndroid Build Coastguard Worker await new Promise((resolve, reject) => { 123*c8dee2aaSAndroid Build Coastguard Worker const names = GM.ListGMs(); 124*c8dee2aaSAndroid Build Coastguard Worker names.sort(); 125*c8dee2aaSAndroid Build Coastguard Worker // When debugging locally, it can be handy to skip to a certain GM by using 126*c8dee2aaSAndroid Build Coastguard Worker // names.indexOf here instead of 0. 127*c8dee2aaSAndroid Build Coastguard Worker let testIdx = 0; 128*c8dee2aaSAndroid Build Coastguard Worker const nextBatch = async () => { 129*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 10 && testIdx < names.length; i++) { 130*c8dee2aaSAndroid Build Coastguard Worker testIdx++; 131*c8dee2aaSAndroid Build Coastguard Worker const name = names[testIdx]; 132*c8dee2aaSAndroid Build Coastguard Worker if (!name) { 133*c8dee2aaSAndroid Build Coastguard Worker testIdx = names.length; 134*c8dee2aaSAndroid Build Coastguard Worker break; 135*c8dee2aaSAndroid Build Coastguard Worker } 136*c8dee2aaSAndroid Build Coastguard Worker if (gmSkipList.has(name)) { 137*c8dee2aaSAndroid Build Coastguard Worker continue; 138*c8dee2aaSAndroid Build Coastguard Worker } 139*c8dee2aaSAndroid Build Coastguard Worker log(`Starting GM ${name}`); 140*c8dee2aaSAndroid Build Coastguard Worker const pngAndMetadata = GM.RunGM(grcontext, name); 141*c8dee2aaSAndroid Build Coastguard Worker if (!pngAndMetadata || !pngAndMetadata.hash) { 142*c8dee2aaSAndroid Build Coastguard Worker log(' No output (was skipped)'); 143*c8dee2aaSAndroid Build Coastguard Worker continue; // Was skipped 144*c8dee2aaSAndroid Build Coastguard Worker } 145*c8dee2aaSAndroid Build Coastguard Worker log(` drew ${pngAndMetadata.hash}`); 146*c8dee2aaSAndroid Build Coastguard Worker window._results.push({ 147*c8dee2aaSAndroid Build Coastguard Worker name: name, 148*c8dee2aaSAndroid Build Coastguard Worker digest: pngAndMetadata.hash, 149*c8dee2aaSAndroid Build Coastguard Worker }); 150*c8dee2aaSAndroid Build Coastguard Worker if (pngAndMetadata.png) { 151*c8dee2aaSAndroid Build Coastguard Worker await postPNG(pngAndMetadata.hash, pngAndMetadata.png); 152*c8dee2aaSAndroid Build Coastguard Worker } 153*c8dee2aaSAndroid Build Coastguard Worker window._testsProgress++; 154*c8dee2aaSAndroid Build Coastguard Worker } 155*c8dee2aaSAndroid Build Coastguard Worker if (testIdx >= names.length) { 156*c8dee2aaSAndroid Build Coastguard Worker resolve(); 157*c8dee2aaSAndroid Build Coastguard Worker return; 158*c8dee2aaSAndroid Build Coastguard Worker } 159*c8dee2aaSAndroid Build Coastguard Worker setTimeout(nextBatch); 160*c8dee2aaSAndroid Build Coastguard Worker }; 161*c8dee2aaSAndroid Build Coastguard Worker setTimeout(nextBatch); 162*c8dee2aaSAndroid Build Coastguard Worker }); 163*c8dee2aaSAndroid Build Coastguard Worker grcontext.delete(); 164*c8dee2aaSAndroid Build Coastguard Worker } 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker async function postPNG(hash, data) { 167*c8dee2aaSAndroid Build Coastguard Worker attemptedPOSTs += 1; 168*c8dee2aaSAndroid Build Coastguard Worker await fetch('/write_png', { 169*c8dee2aaSAndroid Build Coastguard Worker method: 'POST', 170*c8dee2aaSAndroid Build Coastguard Worker body: data, 171*c8dee2aaSAndroid Build Coastguard Worker headers: { 172*c8dee2aaSAndroid Build Coastguard Worker 'Content-type': 'image/png', 173*c8dee2aaSAndroid Build Coastguard Worker 'X-MD5-Hash': hash, // this will be used server side to create the name of the png. 174*c8dee2aaSAndroid Build Coastguard Worker } 175*c8dee2aaSAndroid Build Coastguard Worker }).then((resp) => { 176*c8dee2aaSAndroid Build Coastguard Worker if (resp.ok) { 177*c8dee2aaSAndroid Build Coastguard Worker successfulPOSTs += 1; 178*c8dee2aaSAndroid Build Coastguard Worker } else { 179*c8dee2aaSAndroid Build Coastguard Worker console.error('not ok response', resp); 180*c8dee2aaSAndroid Build Coastguard Worker log('not ok response ' + resp.toString()); 181*c8dee2aaSAndroid Build Coastguard Worker } 182*c8dee2aaSAndroid Build Coastguard Worker }).catch((e) => { 183*c8dee2aaSAndroid Build Coastguard Worker console.error('Could not post PNG', e); 184*c8dee2aaSAndroid Build Coastguard Worker log('Could not post PNG ' + resp.toString()); 185*c8dee2aaSAndroid Build Coastguard Worker }); 186*c8dee2aaSAndroid Build Coastguard Worker } 187*c8dee2aaSAndroid Build Coastguard Worker 188*c8dee2aaSAndroid Build Coastguard Worker const testSkipList = new Set([ 189*c8dee2aaSAndroid Build Coastguard Worker // These tests all crash https://bugs.chromium.org/p/skia/issues/detail?id=10869 190*c8dee2aaSAndroid Build Coastguard Worker 191*c8dee2aaSAndroid Build Coastguard Worker 192*c8dee2aaSAndroid Build Coastguard Worker // note, to catch these crashes, you must compile a debug build, 193*c8dee2aaSAndroid Build Coastguard Worker // run with --manual_mode and open the developer console, 194*c8dee2aaSAndroid Build Coastguard Worker // and enable pause on exceptions in the sources tab, or the browser will just close 195*c8dee2aaSAndroid Build Coastguard Worker // the instant this test crashes. 196*c8dee2aaSAndroid Build Coastguard Worker 197*c8dee2aaSAndroid Build Coastguard Worker // These tests fail when doing a dlopen call 198*c8dee2aaSAndroid Build Coastguard Worker // 'To use dlopen, you need to use Emscripten's linking support' 199*c8dee2aaSAndroid Build Coastguard Worker // Some of these appear to hit the default case instead of the GLES case in GrContextFactory.cpp 200*c8dee2aaSAndroid Build Coastguard Worker // which isn't expected to work. If they had a GLES context, they'd probably pass. 201*c8dee2aaSAndroid Build Coastguard Worker 'AsyncReadPixelsContextShutdown', 202*c8dee2aaSAndroid Build Coastguard Worker 'GrContextFactory_abandon', 203*c8dee2aaSAndroid Build Coastguard Worker 'GrContext_abandonContext', 204*c8dee2aaSAndroid Build Coastguard Worker 'GrContext_oomed', 205*c8dee2aaSAndroid Build Coastguard Worker 'GrDDLImage_MakeSubset', 206*c8dee2aaSAndroid Build Coastguard Worker 'InitialTextureClear', 207*c8dee2aaSAndroid Build Coastguard Worker 'PinnedImageTest', 208*c8dee2aaSAndroid Build Coastguard Worker 'PromiseImageTextureShutdown', 209*c8dee2aaSAndroid Build Coastguard Worker 210*c8dee2aaSAndroid Build Coastguard Worker // These tests time out 211*c8dee2aaSAndroid Build Coastguard Worker 'SkTraceMemoryDump_ownedGLRenderTarget', 212*c8dee2aaSAndroid Build Coastguard Worker 'GrStyledShape', 213*c8dee2aaSAndroid Build Coastguard Worker 214*c8dee2aaSAndroid Build Coastguard Worker // wasm doesn't have threading 215*c8dee2aaSAndroid Build Coastguard Worker 'GrContextFactory_executorAndTaskGroup', 216*c8dee2aaSAndroid Build Coastguard Worker 'GrContextFactory_sharedContexts', 217*c8dee2aaSAndroid Build Coastguard Worker 'RefCnt', 218*c8dee2aaSAndroid Build Coastguard Worker 'SkRuntimeEffectThreaded', 219*c8dee2aaSAndroid Build Coastguard Worker 'SkStrikeMultiThread', 220*c8dee2aaSAndroid Build Coastguard Worker 'String_Threaded', 221*c8dee2aaSAndroid Build Coastguard Worker 222*c8dee2aaSAndroid Build Coastguard Worker // These tests are crashing for unknown reasons 223*c8dee2aaSAndroid Build Coastguard Worker 'AdvancedBlendTest', 224*c8dee2aaSAndroid Build Coastguard Worker 'Data', 225*c8dee2aaSAndroid Build Coastguard Worker 'ES2BlendWithNoTexture', 226*c8dee2aaSAndroid Build Coastguard Worker 'TextureBindingsResetTest', 227*c8dee2aaSAndroid Build Coastguard Worker 228*c8dee2aaSAndroid Build Coastguard Worker // keys invalid 229*c8dee2aaSAndroid Build Coastguard Worker 'GrPathKeys', 230*c8dee2aaSAndroid Build Coastguard Worker 231*c8dee2aaSAndroid Build Coastguard Worker // Creates only 35 of 36 expected fragment processor factories 232*c8dee2aaSAndroid Build Coastguard Worker 'ProcessorCloneTest', 233*c8dee2aaSAndroid Build Coastguard Worker 'ProcessorOptimizationValidationTest', 234*c8dee2aaSAndroid Build Coastguard Worker 'ProcessorRefTest', 235*c8dee2aaSAndroid Build Coastguard Worker 'Programs', 236*c8dee2aaSAndroid Build Coastguard Worker 237*c8dee2aaSAndroid Build Coastguard Worker // Apparently fail only on release builds / bots 238*c8dee2aaSAndroid Build Coastguard Worker 'FlushFinishedProcTest', 239*c8dee2aaSAndroid Build Coastguard Worker 'WritePixelsNonTextureMSAA_Gpu', 240*c8dee2aaSAndroid Build Coastguard Worker 241*c8dee2aaSAndroid Build Coastguard Worker // These SkSL tests fail on the Quadro P400s in the Golo 242*c8dee2aaSAndroid Build Coastguard Worker 'SkSLCommaSideEffects_Ganesh', 243*c8dee2aaSAndroid Build Coastguard Worker 'SkSLMatrixScalarNoOpFolding_Ganesh', 244*c8dee2aaSAndroid Build Coastguard Worker 'SkSLPreserveSideEffects_Ganesh', 245*c8dee2aaSAndroid Build Coastguard Worker 'SkSLStructFieldNoFolding_Ganesh', 246*c8dee2aaSAndroid Build Coastguard Worker 247*c8dee2aaSAndroid Build Coastguard Worker // These tests use files on disk, which is not supported for WASM 248*c8dee2aaSAndroid Build Coastguard Worker 'Stream', 249*c8dee2aaSAndroid Build Coastguard Worker 'StreamBuffer', 250*c8dee2aaSAndroid Build Coastguard Worker 'StreamPeek', 251*c8dee2aaSAndroid Build Coastguard Worker 'FILEStreamWithOffset', 252*c8dee2aaSAndroid Build Coastguard Worker ]); 253*c8dee2aaSAndroid Build Coastguard Worker 254*c8dee2aaSAndroid Build Coastguard Worker async function RunTests(GM) { 255*c8dee2aaSAndroid Build Coastguard Worker const canvas = document.getElementById('gm_canvas'); 256*c8dee2aaSAndroid Build Coastguard Worker const ctx = GM.GetWebGLContext(canvas, 2); 257*c8dee2aaSAndroid Build Coastguard Worker // This sets up the GL context for all tests. 258*c8dee2aaSAndroid Build Coastguard Worker const grcontext = GM.MakeGrContext(ctx); 259*c8dee2aaSAndroid Build Coastguard Worker if (!grcontext) { 260*c8dee2aaSAndroid Build Coastguard Worker window._error = 'Could not make GrContext for tests'; 261*c8dee2aaSAndroid Build Coastguard Worker return; 262*c8dee2aaSAndroid Build Coastguard Worker } 263*c8dee2aaSAndroid Build Coastguard Worker // We run these tests in batches so as not to lock up the main thread, which makes it easier 264*c8dee2aaSAndroid Build Coastguard Worker // to read the progress as well as making the page more responsive when debugging. 265*c8dee2aaSAndroid Build Coastguard Worker await new Promise((resolve, reject) => { 266*c8dee2aaSAndroid Build Coastguard Worker const names = GM.ListTests(); 267*c8dee2aaSAndroid Build Coastguard Worker names.sort(); 268*c8dee2aaSAndroid Build Coastguard Worker console.log(names); 269*c8dee2aaSAndroid Build Coastguard Worker // When debugging locally, it can be handy to skip to a certain test by using 270*c8dee2aaSAndroid Build Coastguard Worker // names.indexOf here instead of 0. 271*c8dee2aaSAndroid Build Coastguard Worker let testIdx = 0; 272*c8dee2aaSAndroid Build Coastguard Worker const nextBatch = () => { 273*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 10 && testIdx < names.length; i++) { 274*c8dee2aaSAndroid Build Coastguard Worker testIdx++; 275*c8dee2aaSAndroid Build Coastguard Worker const name = names[testIdx]; 276*c8dee2aaSAndroid Build Coastguard Worker if (!name) { 277*c8dee2aaSAndroid Build Coastguard Worker testIdx = names.length; 278*c8dee2aaSAndroid Build Coastguard Worker break; 279*c8dee2aaSAndroid Build Coastguard Worker } 280*c8dee2aaSAndroid Build Coastguard Worker if (testSkipList.has(name)) { 281*c8dee2aaSAndroid Build Coastguard Worker continue; 282*c8dee2aaSAndroid Build Coastguard Worker } 283*c8dee2aaSAndroid Build Coastguard Worker log(`Running test ${name}`); 284*c8dee2aaSAndroid Build Coastguard Worker try { 285*c8dee2aaSAndroid Build Coastguard Worker const result = GM.RunTest(name); 286*c8dee2aaSAndroid Build Coastguard Worker log(' ' + result.result, result.msg || ''); 287*c8dee2aaSAndroid Build Coastguard Worker if (result.result !== 'passed' && result.result !== 'skipped') { 288*c8dee2aaSAndroid Build Coastguard Worker window._failed.push(name); 289*c8dee2aaSAndroid Build Coastguard Worker } 290*c8dee2aaSAndroid Build Coastguard Worker } catch (e) { 291*c8dee2aaSAndroid Build Coastguard Worker log(`${name} crashed with ${e.toString()} ${e.stack}`); 292*c8dee2aaSAndroid Build Coastguard Worker window._error = e.toString(); 293*c8dee2aaSAndroid Build Coastguard Worker reject(); 294*c8dee2aaSAndroid Build Coastguard Worker return; 295*c8dee2aaSAndroid Build Coastguard Worker } 296*c8dee2aaSAndroid Build Coastguard Worker window._testsProgress++; 297*c8dee2aaSAndroid Build Coastguard Worker } 298*c8dee2aaSAndroid Build Coastguard Worker if (testIdx >= names.length) { 299*c8dee2aaSAndroid Build Coastguard Worker resolve(); 300*c8dee2aaSAndroid Build Coastguard Worker return; 301*c8dee2aaSAndroid Build Coastguard Worker } 302*c8dee2aaSAndroid Build Coastguard Worker setTimeout(nextBatch); 303*c8dee2aaSAndroid Build Coastguard Worker }; 304*c8dee2aaSAndroid Build Coastguard Worker setTimeout(nextBatch); 305*c8dee2aaSAndroid Build Coastguard Worker }); 306*c8dee2aaSAndroid Build Coastguard Worker 307*c8dee2aaSAndroid Build Coastguard Worker grcontext.delete(); 308*c8dee2aaSAndroid Build Coastguard Worker } 309*c8dee2aaSAndroid Build Coastguard Worker</script> 310*c8dee2aaSAndroid Build Coastguard Worker</body> 311*c8dee2aaSAndroid Build Coastguard Worker</html> 312