xref: /aosp_15_r20/external/skia/modules/pathkit/tests/testReporter.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Workerconst REPORT_URL = 'http://localhost:8081/report_gold_data'
2*c8dee2aaSAndroid Build Coastguard Worker// Set this to enforce that the gold server must be up.
3*c8dee2aaSAndroid Build Coastguard Worker// Typically used for debugging.
4*c8dee2aaSAndroid Build Coastguard Workerconst fail_on_no_gold = false;
5*c8dee2aaSAndroid Build Coastguard Worker
6*c8dee2aaSAndroid Build Coastguard Workerfunction reportCanvas(canvas, testname, outputType='canvas') {
7*c8dee2aaSAndroid Build Coastguard Worker    let b64 = canvas.toDataURL('image/png');
8*c8dee2aaSAndroid Build Coastguard Worker    return _report(b64, outputType, testname);
9*c8dee2aaSAndroid Build Coastguard Worker}
10*c8dee2aaSAndroid Build Coastguard Worker
11*c8dee2aaSAndroid Build Coastguard Workerfunction reportSVG(svg, testname) {
12*c8dee2aaSAndroid Build Coastguard Worker    // This converts an SVG to a base64 encoded PNG. It basically creates an
13*c8dee2aaSAndroid Build Coastguard Worker    // <img> element that takes the inlined SVG and draws it on a canvas.
14*c8dee2aaSAndroid Build Coastguard Worker    // The trick is we have to wait until the image is loaded, thus the Promise
15*c8dee2aaSAndroid Build Coastguard Worker    // wrapping below.
16*c8dee2aaSAndroid Build Coastguard Worker    let svgStr = svg.outerHTML;
17*c8dee2aaSAndroid Build Coastguard Worker    let tempImg = document.createElement('img');
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker    let tempCanvas = document.createElement('canvas');
20*c8dee2aaSAndroid Build Coastguard Worker    let canvasCtx = tempCanvas.getContext('2d');
21*c8dee2aaSAndroid Build Coastguard Worker    setCanvasSize(canvasCtx, svg.getAttribute('width'), svg.getAttribute('height'));
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker    return new Promise(function(resolve, reject) {
24*c8dee2aaSAndroid Build Coastguard Worker        tempImg.onload = () => {
25*c8dee2aaSAndroid Build Coastguard Worker            canvasCtx.drawImage(tempImg, 0, 0);
26*c8dee2aaSAndroid Build Coastguard Worker            let b64 = tempCanvas.toDataURL('image/png');
27*c8dee2aaSAndroid Build Coastguard Worker            _report(b64, 'svg', testname).then(() => {
28*c8dee2aaSAndroid Build Coastguard Worker                resolve();
29*c8dee2aaSAndroid Build Coastguard Worker            }).catch((e) => reject(e));
30*c8dee2aaSAndroid Build Coastguard Worker        };
31*c8dee2aaSAndroid Build Coastguard Worker        tempImg.setAttribute('src', 'data:image/svg+xml;,' + svgStr);
32*c8dee2aaSAndroid Build Coastguard Worker    });
33*c8dee2aaSAndroid Build Coastguard Worker}
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker// For tests that just do a simple path and return it as a string, wrap it in
36*c8dee2aaSAndroid Build Coastguard Worker// a proper svg and send it off.  Supports fill (nofill means just stroke it).
37*c8dee2aaSAndroid Build Coastguard Worker// This uses the "standard" size of 600x600.
38*c8dee2aaSAndroid Build Coastguard Workerfunction reportSVGString(svgstr, testname, fillRule='nofill') {
39*c8dee2aaSAndroid Build Coastguard Worker    let newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
40*c8dee2aaSAndroid Build Coastguard Worker    newPath.setAttribute('stroke', 'black');
41*c8dee2aaSAndroid Build Coastguard Worker    if (fillRule !== 'nofill') {
42*c8dee2aaSAndroid Build Coastguard Worker        newPath.setAttribute('fill', 'orange');
43*c8dee2aaSAndroid Build Coastguard Worker        newPath.setAttribute('fill-rule', fillRule);
44*c8dee2aaSAndroid Build Coastguard Worker    } else {
45*c8dee2aaSAndroid Build Coastguard Worker        newPath.setAttribute('fill', 'rgba(255,255,255,0.0)');
46*c8dee2aaSAndroid Build Coastguard Worker    }
47*c8dee2aaSAndroid Build Coastguard Worker    newPath.setAttribute('d', svgstr);
48*c8dee2aaSAndroid Build Coastguard Worker    let newSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
49*c8dee2aaSAndroid Build Coastguard Worker    newSVG.appendChild(newPath);
50*c8dee2aaSAndroid Build Coastguard Worker    // helps with the conversion to PNG.
51*c8dee2aaSAndroid Build Coastguard Worker    newSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
52*c8dee2aaSAndroid Build Coastguard Worker    newSVG.setAttribute('width', 600);
53*c8dee2aaSAndroid Build Coastguard Worker    newSVG.setAttribute('height', 600);
54*c8dee2aaSAndroid Build Coastguard Worker    return reportSVG(newSVG, testname);
55*c8dee2aaSAndroid Build Coastguard Worker}
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker// Reports a canvas and then an SVG of this path. Puts it on a standard size canvas.
58*c8dee2aaSAndroid Build Coastguard Workerfunction reportPath(path, testname, done) {
59*c8dee2aaSAndroid Build Coastguard Worker    let canvas = document.createElement('canvas');
60*c8dee2aaSAndroid Build Coastguard Worker    let canvasCtx = canvas.getContext('2d');
61*c8dee2aaSAndroid Build Coastguard Worker    // Set canvas size and make it a bit bigger to zoom in on the lines
62*c8dee2aaSAndroid Build Coastguard Worker    standardizedCanvasSize(canvasCtx);
63*c8dee2aaSAndroid Build Coastguard Worker    canvasCtx.stroke(path.toPath2D());
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker    let svgStr = path.toSVGString();
66*c8dee2aaSAndroid Build Coastguard Worker
67*c8dee2aaSAndroid Build Coastguard Worker    return reportCanvas(canvas, testname).then(() => {
68*c8dee2aaSAndroid Build Coastguard Worker                reportSVGString(svgStr, testname).then(() => {
69*c8dee2aaSAndroid Build Coastguard Worker                    done();
70*c8dee2aaSAndroid Build Coastguard Worker                }).catch(reportError(done));
71*c8dee2aaSAndroid Build Coastguard Worker            }).catch(reportError(done));
72*c8dee2aaSAndroid Build Coastguard Worker}
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker// data is a base64 encoded png, outputType is the value that goes with the
75*c8dee2aaSAndroid Build Coastguard Worker// key 'config' when reporting.
76*c8dee2aaSAndroid Build Coastguard Workerfunction _report(data, outputType, testname) {
77*c8dee2aaSAndroid Build Coastguard Worker    return fetch(REPORT_URL, {
78*c8dee2aaSAndroid Build Coastguard Worker        method: 'POST',
79*c8dee2aaSAndroid Build Coastguard Worker        mode: 'no-cors',
80*c8dee2aaSAndroid Build Coastguard Worker        headers: {
81*c8dee2aaSAndroid Build Coastguard Worker            'Content-Type': 'application/json',
82*c8dee2aaSAndroid Build Coastguard Worker        },
83*c8dee2aaSAndroid Build Coastguard Worker        body: JSON.stringify({
84*c8dee2aaSAndroid Build Coastguard Worker            'output_type': outputType,
85*c8dee2aaSAndroid Build Coastguard Worker            'data': data,
86*c8dee2aaSAndroid Build Coastguard Worker            'test_name': testname,
87*c8dee2aaSAndroid Build Coastguard Worker        })
88*c8dee2aaSAndroid Build Coastguard Worker    }).then(() => console.log(`Successfully reported ${testname} to gold aggregator`));
89*c8dee2aaSAndroid Build Coastguard Worker}
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Workerfunction reportError(done) {
92*c8dee2aaSAndroid Build Coastguard Worker    return (e) => {
93*c8dee2aaSAndroid Build Coastguard Worker        console.log("Error with fetching. Likely could not connect to aggregator server", e.message);
94*c8dee2aaSAndroid Build Coastguard Worker        if (fail_on_no_gold) {
95*c8dee2aaSAndroid Build Coastguard Worker            expect(e).toBeUndefined();
96*c8dee2aaSAndroid Build Coastguard Worker        }
97*c8dee2aaSAndroid Build Coastguard Worker        done();
98*c8dee2aaSAndroid Build Coastguard Worker    };
99*c8dee2aaSAndroid Build Coastguard Worker}
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Workerfunction setCanvasSize(ctx, width, height) {
102*c8dee2aaSAndroid Build Coastguard Worker    ctx.canvas.width = width;
103*c8dee2aaSAndroid Build Coastguard Worker    ctx.canvas.height = height;
104*c8dee2aaSAndroid Build Coastguard Worker}
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Workerfunction standardizedCanvasSize(ctx) {
107*c8dee2aaSAndroid Build Coastguard Worker    setCanvasSize(ctx, 600, 600);
108*c8dee2aaSAndroid Build Coastguard Worker}
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker// A wrapper to catch and print a stacktrace to the logs.
111*c8dee2aaSAndroid Build Coastguard Worker// Exceptions normally shows up in the browser console,
112*c8dee2aaSAndroid Build Coastguard Worker// but not in the logs that appear on the bots AND a thrown
113*c8dee2aaSAndroid Build Coastguard Worker// exception will normally cause a test to time out.
114*c8dee2aaSAndroid Build Coastguard Worker// This wrapper mitigates both those pain points.
115*c8dee2aaSAndroid Build Coastguard Workerfunction catchException(done, fn) {
116*c8dee2aaSAndroid Build Coastguard Worker    return () => {
117*c8dee2aaSAndroid Build Coastguard Worker        try {
118*c8dee2aaSAndroid Build Coastguard Worker            fn()
119*c8dee2aaSAndroid Build Coastguard Worker        } catch (e) {
120*c8dee2aaSAndroid Build Coastguard Worker            console.log('Failed with the following error', e);
121*c8dee2aaSAndroid Build Coastguard Worker            expect(e).toBeFalsy();
122*c8dee2aaSAndroid Build Coastguard Worker            debugger;
123*c8dee2aaSAndroid Build Coastguard Worker            done();
124*c8dee2aaSAndroid Build Coastguard Worker        }
125*c8dee2aaSAndroid Build Coastguard Worker        // We don't call done with finally because
126*c8dee2aaSAndroid Build Coastguard Worker        // that would make the break the asynchronous nature
127*c8dee2aaSAndroid Build Coastguard Worker        // of fn().
128*c8dee2aaSAndroid Build Coastguard Worker    }
129*c8dee2aaSAndroid Build Coastguard Worker}
130