[pathkit] Clean up perf/test init

This will hopefully help with flakiness.

Bug: skia:8810
Change-Id: Id2fa9abcc0e95f0cf8b08557215766b4f9c57478
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/200047
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
diff --git a/modules/pathkit/karma.bench.conf.js b/modules/pathkit/karma.bench.conf.js
index a2808a6..315903b 100644
--- a/modules/pathkit/karma.bench.conf.js
+++ b/modules/pathkit/karma.bench.conf.js
@@ -13,6 +13,7 @@
       { pattern: 'npm-wasm/bin/pathkit.wasm', included:false, served:true},
       'perf/perfReporter.js',
       'npm-wasm/bin/pathkit.js',
+      'tests/pathkitinit.js',
       'perf/*.bench.js'
     ],
 
@@ -38,8 +39,8 @@
     // enable / disable watching file and executing tests whenever any file changes
     autoWatch: true,
 
-    browserDisconnectTimeout: 10000,
-    browserNoActivityTimeout: 10000,
+    browserDisconnectTimeout: 20000,
+    browserNoActivityTimeout: 20000,
 
     // start these browsers
     browsers: ['Chrome'],
@@ -74,6 +75,7 @@
       { pattern: 'npm-asmjs/bin/pathkit.js.mem', included:false, served:true},
       'perf/perfReporter.js',
       'npm-asmjs/bin/pathkit.js',
+      'tests/pathkitinit.js',
       'perf/*.bench.js'
     ];
 
diff --git a/modules/pathkit/karma.conf.js b/modules/pathkit/karma.conf.js
index 649d21d..47ff2d2 100644
--- a/modules/pathkit/karma.conf.js
+++ b/modules/pathkit/karma.conf.js
@@ -14,6 +14,7 @@
       { pattern: 'tests/*.json', included:false, served:true},
       'tests/testReporter.js',
       'npm-wasm/bin/test/pathkit.js',
+      'tests/pathkitinit.js',
       'tests/*.spec.js'
     ],
 
@@ -39,8 +40,8 @@
     // enable / disable watching file and executing tests whenever any file changes
     autoWatch: true,
 
-    browserDisconnectTimeout: 15000,
-    browserNoActivityTimeout: 15000,
+    browserDisconnectTimeout: 20000,
+    browserNoActivityTimeout: 20000,
 
     // start these browsers
     browsers: ['Chrome'],
@@ -76,6 +77,7 @@
       { pattern: 'tests/*.json', included:false, served:true},
       'tests/testReporter.js',
       'npm-asmjs/bin/test/pathkit.js',
+      'tests/pathkitinit.js',
       'tests/*.spec.js'
     ];
 
diff --git a/modules/pathkit/perf/effects.bench.js b/modules/pathkit/perf/effects.bench.js
index cf73fd4..30d6e35 100644
--- a/modules/pathkit/perf/effects.bench.js
+++ b/modules/pathkit/perf/effects.bench.js
@@ -1,20 +1,4 @@
-
-
 describe('PathKit\'s Effects', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
 
     // see https://fiddle.skia.org/c/@discrete_path
     function drawStar(X=128, Y=128, R=116) {
diff --git a/modules/pathkit/perf/path.bench.js b/modules/pathkit/perf/path.bench.js
index d8dc47e..01fd6f9 100644
--- a/modules/pathkit/perf/path.bench.js
+++ b/modules/pathkit/perf/path.bench.js
@@ -1,21 +1,4 @@
-
-
 describe('PathKit\'s Path Behavior', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
-
     function drawPath() {
         let path = PathKit.NewPath();
         path.moveTo(20, 5);
diff --git a/modules/pathkit/perf/pathops.bench.js b/modules/pathkit/perf/pathops.bench.js
index aa105a4..31d7e05 100644
--- a/modules/pathkit/perf/pathops.bench.js
+++ b/modules/pathkit/perf/pathops.bench.js
@@ -1,21 +1,4 @@
-
-
 describe('PathKit\'s Pathops', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
-
     // see https://fiddle.skia.org/c/@discrete_path
     function drawStar(X=128, Y=128, R=116) {
         let p = PathKit.NewPath();
diff --git a/modules/pathkit/perf/perfReporter.js b/modules/pathkit/perf/perfReporter.js
index d74110c..c60cfbc 100644
--- a/modules/pathkit/perf/perfReporter.js
+++ b/modules/pathkit/perf/perfReporter.js
@@ -3,47 +3,52 @@
 // Typically used for debugging.
 const fail_on_no_perf = false;
 
-
 function benchmarkAndReport(benchName, setupFn, testFn, teardownFn) {
-    let ctx = {};
-    // warmup 3 times (arbitrary choice)
-    setupFn(ctx);
-    testFn(ctx);
-    testFn(ctx);
-    testFn(ctx);
-    teardownFn(ctx);
-
-    ctx = {};
-    setupFn(ctx);
-    let start = Date.now();
-    let now = start;
-    times = 0;
-    // See how many times we can do it in 100ms (arbitrary choice)
-    while (now - start < 100) {
+    try {
+        let ctx = {};
+        // warmup 3 times (arbitrary choice)
+        setupFn(ctx);
         testFn(ctx);
-        now = Date.now();
-        times++;
-    }
-
-    teardownFn(ctx);
-
-    // Try to make it go for 2 seconds (arbitrarily chosen)
-    // Since the pre-try took 100ms, multiply by 20 to get
-    // approximate tries in 2s
-    let goalTimes = times * 20;
-    setupFn(ctx);
-    start = Date.now();
-    times = 0;
-    while (times < goalTimes) {
         testFn(ctx);
-        times++;
-    }
-    let end = Date.now();
-    teardownFn(ctx);
+        testFn(ctx);
+        teardownFn(ctx);
 
-    let us = (end - start) * 1000 / times;
-    console.log(benchName, `${us} microseconds`)
-    return _report(us, benchName);
+        ctx = {};
+        setupFn(ctx);
+        let start = Date.now();
+        let now = start;
+        times = 0;
+        // See how many times we can do it in 100ms (arbitrary choice)
+        while (now - start < 100) {
+            testFn(ctx);
+            now = Date.now();
+            times++;
+        }
+
+        teardownFn(ctx);
+
+        // Try to make it go for 2 seconds (arbitrarily chosen)
+        // Since the pre-try took 100ms, multiply by 20 to get
+        // approximate tries in 2s (unless now - start >> 100 ms)
+        let goalTimes = times * 20;
+        ctx = {};
+        setupFn(ctx);
+        times = 0;
+        start = Date.now();
+        while (times < goalTimes) {
+            testFn(ctx);
+            times++;
+        }
+        const end = Date.now();
+        teardownFn(ctx);
+
+        const us = (end - start) * 1000 / times;
+        console.log(benchName, `${us} microseconds`)
+        return _report(us, benchName);
+    } catch(e) {
+        console.error('caught error', e);
+        return Promise.reject(e);
+    }
 }
 
 
diff --git a/modules/pathkit/tests/effects.spec.js b/modules/pathkit/tests/effects.spec.js
index 29cdbd5..575c95a 100644
--- a/modules/pathkit/tests/effects.spec.js
+++ b/modules/pathkit/tests/effects.spec.js
@@ -1,21 +1,5 @@
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
 
 describe('PathKit\'s Path Behavior', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
-
     // see https://fiddle.skia.org/c/@discrete_path
     function drawStar() {
         let path = PathKit.NewPath();
diff --git a/modules/pathkit/tests/path.spec.js b/modules/pathkit/tests/path.spec.js
index 80a779a..aa674ba 100644
--- a/modules/pathkit/tests/path.spec.js
+++ b/modules/pathkit/tests/path.spec.js
@@ -1,20 +1,4 @@
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
-
 describe('PathKit\'s Path Behavior', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
 
     describe('Basic Path Features', function() {
         function drawSimplePath() {
diff --git a/modules/pathkit/tests/path2d.spec.js b/modules/pathkit/tests/path2d.spec.js
index 6c2b3ef..b60db85 100644
--- a/modules/pathkit/tests/path2d.spec.js
+++ b/modules/pathkit/tests/path2d.spec.js
@@ -1,21 +1,4 @@
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
-
 describe('PathKit\'s Path2D API', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
-
     it('can do everything in the Path2D API w/o crashing', function(done) {
         LoadPathKit.then(catchException(done, () => {
             // This is taken from example.html
diff --git a/modules/pathkit/tests/pathkitinit.js b/modules/pathkit/tests/pathkitinit.js
new file mode 100644
index 0000000..0fc9b71
--- /dev/null
+++ b/modules/pathkit/tests/pathkitinit.js
@@ -0,0 +1,16 @@
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
+
+let PathKit = null;
+const LoadPathKit = new Promise(function(resolve, reject) {
+    console.log('pathkit loading', new Date());
+    PathKitInit({
+        locateFile: (file) => '/pathkit/'+file,
+    }).ready().then((_PathKit) => {
+        console.log('pathkit loaded', new Date());
+        PathKit = _PathKit;
+        resolve();
+    }).catch((e) => {
+        console.error('pathkit failed to load', new Date(), e);
+        reject();
+    });
+});
\ No newline at end of file
diff --git a/modules/pathkit/tests/pathops.spec.js b/modules/pathkit/tests/pathops.spec.js
index 720bd8c..089f9bc 100644
--- a/modules/pathkit/tests/pathops.spec.js
+++ b/modules/pathkit/tests/pathops.spec.js
@@ -1,5 +1,3 @@
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
-
 var dumpErrors = false;
 var container;
 
@@ -74,36 +72,27 @@
 }
 
 describe('PathKit\'s PathOps Behavior', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
     var PATHOP_MAP = {};
     var FILLTYPE_MAP = {};
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                PATHOP_MAP = {
-                    'kIntersect_SkPathOp':         PathKit.PathOp.INTERSECT,
-                    'kDifference_SkPathOp':        PathKit.PathOp.DIFFERENCE,
-                    'kUnion_SkPathOp':             PathKit.PathOp.UNION,
-                    'kXOR_SkPathOp':               PathKit.PathOp.XOR,
-                    'kXOR_PathOp':                 PathKit.PathOp.XOR,
-                    'kReverseDifference_SkPathOp': PathKit.PathOp.REVERSE_DIFFERENCE,
-                };
-                FILLTYPE_MAP = {
-                    'kWinding_FillType':        PathKit.FillType.WINDING,
-                    'kEvenOdd_FillType':        PathKit.FillType.EVENODD,
-                    'kInverseWinding_FillType': PathKit.FillType.INVERSE_WINDING,
-                    'kInverseEvenOdd_FillType': PathKit.FillType.INVERSE_EVENODD,
-                };
-                resolve();
-            });
+
+    function init() {
+        if (PathKit && !PATHOP_MAP['kIntersect_SkPathOp']) {
+            PATHOP_MAP = {
+                'kIntersect_SkPathOp':         PathKit.PathOp.INTERSECT,
+                'kDifference_SkPathOp':        PathKit.PathOp.DIFFERENCE,
+                'kUnion_SkPathOp':             PathKit.PathOp.UNION,
+                'kXOR_SkPathOp':               PathKit.PathOp.XOR,
+                'kXOR_PathOp':                 PathKit.PathOp.XOR,
+                'kReverseDifference_SkPathOp': PathKit.PathOp.REVERSE_DIFFERENCE,
+            };
+            FILLTYPE_MAP = {
+                'kWinding_FillType':        PathKit.FillType.WINDING,
+                'kEvenOdd_FillType':        PathKit.FillType.EVENODD,
+                'kInverseWinding_FillType': PathKit.FillType.INVERSE_WINDING,
+                'kInverseEvenOdd_FillType': PathKit.FillType.INVERSE_EVENODD,
+            };
         }
-    });
+    }
 
     function getFillType(str) {
         let e = FILLTYPE_MAP[str];
@@ -119,6 +108,7 @@
 
     it('combines two paths with .op() and matches what we see from C++', function(done) {
         LoadPathKit.then(catchException(done, () => {
+            init();
             // Test JSON created with:
             // ./out/Clang/pathops_unittest -J ./modules/pathkit/tests/PathOpsOp.json -m PathOpsOp$
             fetch('/base/tests/PathOpsOp.json').then((r) => {
@@ -177,6 +167,7 @@
 
     it('simplifies a path with .simplify() and matches what we see from C++', function(done) {
         LoadPathKit.then(catchException(done, () => {
+            init();
             // Test JSON created with:
             // ./out/Clang/pathops_unittest -J ./modules/pathkit/tests/PathOpsSimplify.json -m PathOpsSimplify$
             fetch('/base/tests/PathOpsSimplify.json').then((r) => {
diff --git a/modules/pathkit/tests/svg.spec.js b/modules/pathkit/tests/svg.spec.js
index 02cfa4e..f1d75dd 100644
--- a/modules/pathkit/tests/svg.spec.js
+++ b/modules/pathkit/tests/svg.spec.js
@@ -1,20 +1,4 @@
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
 describe('PathKit\'s SVG Behavior', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
-
     it('can create a path from an SVG string', function(done) {
         LoadPathKit.then(catchException(done, () => {
             //.This is a parallelagram from
diff --git a/modules/pathkit/tests/util.spec.js b/modules/pathkit/tests/util.spec.js
index ed65dc5..3e7f5c9 100644
--- a/modules/pathkit/tests/util.spec.js
+++ b/modules/pathkit/tests/util.spec.js
@@ -1,21 +1,5 @@
 // Tests for util-related things
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
 describe('PathKit\'s CubicMap Behavior', function() {
-    // Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
-    var PathKit = null;
-    const LoadPathKit = new Promise(function(resolve, reject) {
-        if (PathKit) {
-            resolve();
-        } else {
-            PathKitInit({
-                locateFile: (file) => '/pathkit/'+file,
-            }).ready().then((_PathKit) => {
-                PathKit = _PathKit;
-                resolve();
-            });
-        }
-    });
-
     it('computes YFromX correctly', function(done) {
         LoadPathKit.then(catchException(done, () => {
             // Spot check a few points