Skip to content
This repository was archived by the owner on Aug 1, 2024. It is now read-only.

Commit 3f5752e

Browse files
committed
Fix an async interleaving issue in MultiTestRunner.
RELNOTES: N/A ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=264503463
1 parent d1a43c1 commit 3f5752e

File tree

4 files changed

+157
-121
lines changed

4 files changed

+157
-121
lines changed

closure/goog/deps.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

closure/goog/testing/multitestrunner.js

Lines changed: 123 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ goog.require('goog.functions');
3535
goog.require('goog.object');
3636
goog.require('goog.string');
3737
goog.require('goog.testing.TestCase');
38+
goog.require('goog.testing.TestRunner');
3839
goog.require('goog.ui.Component');
3940
goog.require('goog.ui.ServerChart');
4041
goog.require('goog.ui.TableSorter');
@@ -106,11 +107,14 @@ goog.testing.MultiTestRunner.DEFAULT_TIMEOUT_MS = 45 * 1000;
106107

107108
/**
108109
* Messages corresponding to the numeric states.
109-
* @type {Array<string>}
110+
* @enum {string}
110111
*/
111-
goog.testing.MultiTestRunner.STATES = [
112-
'waiting for test runner', 'initializing tests', 'waiting for tests to finish'
113-
];
112+
goog.testing.MultiTestRunner.State = {
113+
WAITING: 'waiting for test runner',
114+
INITIALIZING: 'initializing tests',
115+
RUNNING: 'waiting for tests to finish',
116+
COMPLETE: 'tests finished',
117+
};
114118

115119

116120
/**
@@ -138,7 +142,7 @@ goog.testing.MultiTestRunner.prototype.basePath_ = '';
138142

139143
/**
140144
* A set of tests that have finished. All extant keys map to true.
141-
* @type {Object<boolean>}
145+
* @type {?Object<boolean>}
142146
* @private
143147
*/
144148
goog.testing.MultiTestRunner.prototype.finished_ = null;
@@ -250,79 +254,79 @@ goog.testing.MultiTestRunner.prototype.stats_ = null;
250254

251255
/**
252256
* Reference to the start button element.
253-
* @type {HTMLButtonElement}
257+
* @type {?HTMLButtonElement}
254258
* @private
255259
*/
256260
goog.testing.MultiTestRunner.prototype.startButtonEl_ = null;
257261

258262

259263
/**
260264
* Reference to the stop button element.
261-
* @type {HTMLButtonElement}
265+
* @type {?HTMLButtonElement}
262266
* @private
263267
*/
264268
goog.testing.MultiTestRunner.prototype.stopButtonEl_ = null;
265269

266270

267271
/**
268272
* Reference to the log element.
269-
* @type {Element}
273+
* @type {?Element}
270274
* @private
271275
*/
272276
goog.testing.MultiTestRunner.prototype.logEl_ = null;
273277

274278

275279
/**
276280
* Reference to the report element.
277-
* @type {Element}
281+
* @type {?Element}
278282
* @private
279283
*/
280284
goog.testing.MultiTestRunner.prototype.reportEl_ = null;
281285

282286

283287
/**
284288
* Reference to the stats element.
285-
* @type {Element}
289+
* @type {?Element}
286290
* @private
287291
*/
288292
goog.testing.MultiTestRunner.prototype.statsEl_ = null;
289293

290294

291295
/**
292296
* Reference to the progress bar's element.
293-
* @type {Element}
297+
* @type {?Element}
294298
* @private
295299
*/
296300
goog.testing.MultiTestRunner.prototype.progressEl_ = null;
297301

298302

299303
/**
300304
* Reference to the progress bar's inner row element.
301-
* @type {HTMLTableRowElement}
305+
* @type {?HTMLTableRowElement}
302306
* @private
303307
*/
304308
goog.testing.MultiTestRunner.prototype.progressRow_ = null;
305309

306310

307311
/**
308312
* Reference to the log tab.
309-
* @type {Element}
313+
* @type {?Element}
310314
* @private
311315
*/
312316
goog.testing.MultiTestRunner.prototype.logTabEl_ = null;
313317

314318

315319
/**
316320
* Reference to the report tab.
317-
* @type {Element}
321+
* @type {?Element}
318322
* @private
319323
*/
320324
goog.testing.MultiTestRunner.prototype.reportTabEl_ = null;
321325

322326

323327
/**
324328
* Reference to the stats tab.
325-
* @type {Element}
329+
* @type {?Element}
326330
* @private
327331
*/
328332
goog.testing.MultiTestRunner.prototype.statsTabEl_ = null;
@@ -1273,96 +1277,95 @@ goog.testing.MultiTestRunner.TestFrame = function(
12731277
* @private {!Object<string,!Array<!goog.testing.TestCase.IResult>>}
12741278
*/
12751279
this.testResults_ = {};
1276-
};
1277-
goog.inherits(goog.testing.MultiTestRunner.TestFrame, goog.ui.Component);
1278-
12791280

1280-
/**
1281-
* Reference to the iframe.
1282-
* @type {HTMLIFrameElement}
1283-
* @private
1284-
*/
1285-
goog.testing.MultiTestRunner.TestFrame.prototype.iframeEl_ = null;
1281+
/**
1282+
* Reference to the iframe.
1283+
* @type {?HTMLIFrameElement}
1284+
* @private
1285+
*/
1286+
this.iframeEl_ = null;
12861287

12871288

1288-
/**
1289-
* Whether the iframe for the current test has loaded.
1290-
* @type {boolean}
1291-
* @private
1292-
*/
1293-
goog.testing.MultiTestRunner.TestFrame.prototype.iframeLoaded_ = false;
1289+
/**
1290+
* Whether the iframe for the current test has loaded.
1291+
* @type {boolean}
1292+
* @private
1293+
*/
1294+
this.iframeLoaded_ = false;
12941295

12951296

1296-
/**
1297-
* The test file being run.
1298-
* @type {string}
1299-
* @private
1300-
*/
1301-
goog.testing.MultiTestRunner.TestFrame.prototype.testFile_ = '';
1297+
/**
1298+
* The test file being run.
1299+
* @type {string}
1300+
* @private
1301+
*/
1302+
this.testFile_ = '';
13021303

13031304

1304-
/**
1305-
* The report returned from the test.
1306-
* @type {string}
1307-
* @private
1308-
*/
1309-
goog.testing.MultiTestRunner.TestFrame.prototype.report_ = '';
1305+
/**
1306+
* The report returned from the test.
1307+
* @type {string}
1308+
* @private
1309+
*/
1310+
this.report_ = '';
13101311

13111312

1312-
/**
1313-
* The total time loading and running the test in milliseconds.
1314-
* @type {number}
1315-
* @private
1316-
*/
1317-
goog.testing.MultiTestRunner.TestFrame.prototype.totalTime_ = 0;
1313+
/**
1314+
* The total time loading and running the test in milliseconds.
1315+
* @type {number}
1316+
* @private
1317+
*/
1318+
this.totalTime_ = 0;
13181319

13191320

1320-
/**
1321-
* The actual runtime of the test in milliseconds.
1322-
* @type {number}
1323-
* @private
1324-
*/
1325-
goog.testing.MultiTestRunner.TestFrame.prototype.runTime_ = 0;
1321+
/**
1322+
* The actual runtime of the test in milliseconds.
1323+
* @type {number}
1324+
* @private
1325+
*/
1326+
this.runTime_ = 0;
13261327

13271328

1328-
/**
1329-
* The number of files loaded by the test.
1330-
* @type {number}
1331-
* @private
1332-
*/
1333-
goog.testing.MultiTestRunner.TestFrame.prototype.numFilesLoaded_ = 0;
1329+
/**
1330+
* The number of files loaded by the test.
1331+
* @type {number}
1332+
* @private
1333+
*/
1334+
this.numFilesLoaded_ = 0;
13341335

13351336

1336-
/**
1337-
* Whether the test was successful, null if no result has been returned yet.
1338-
* @type {?boolean}
1339-
* @private
1340-
*/
1341-
goog.testing.MultiTestRunner.TestFrame.prototype.isSuccess_ = null;
1337+
/**
1338+
* Whether the test was successful, null if no result has been returned yet.
1339+
* @type {?boolean}
1340+
* @private
1341+
*/
1342+
this.isSuccess_ = null;
13421343

13431344

1344-
/**
1345-
* Timestamp for the when the test was started.
1346-
* @type {number}
1347-
* @private
1348-
*/
1349-
goog.testing.MultiTestRunner.TestFrame.prototype.startTime_ = 0;
1345+
/**
1346+
* Timestamp for the when the test was started.
1347+
* @type {number}
1348+
* @private
1349+
*/
1350+
this.startTime_ = 0;
13501351

13511352

1352-
/**
1353-
* Timestamp for the last state, used to determine timeouts.
1354-
* @type {number}
1355-
* @private
1356-
*/
1357-
goog.testing.MultiTestRunner.TestFrame.prototype.lastStateTime_ = 0;
1353+
/**
1354+
* Timestamp for the last state, used to determine timeouts.
1355+
* @type {number}
1356+
* @private
1357+
*/
1358+
this.lastStateTime_ = 0;
13581359

13591360

1360-
/**
1361-
* The state of the active test.
1362-
* @type {number}
1363-
* @private
1364-
*/
1365-
goog.testing.MultiTestRunner.TestFrame.prototype.currentState_ = 0;
1361+
/**
1362+
* The state of the active test.
1363+
* @type {!goog.testing.MultiTestRunner.State}
1364+
* @private
1365+
*/
1366+
this.currentState_ = goog.testing.MultiTestRunner.State.WAITING;
1367+
};
1368+
goog.inherits(goog.testing.MultiTestRunner.TestFrame, goog.ui.Component);
13661369

13671370

13681371
/** @override */
@@ -1386,7 +1389,7 @@ goog.testing.MultiTestRunner.TestFrame.prototype.runTest = function(testFile) {
13861389
}
13871390

13881391
this.iframeLoaded_ = false;
1389-
this.currentState_ = 0;
1392+
this.currentState_ = goog.testing.MultiTestRunner.State.WAITING;
13901393
this.isSuccess_ = null;
13911394
this.report_ = '';
13921395
this.testResults_ = {};
@@ -1506,49 +1509,53 @@ goog.testing.MultiTestRunner.TestFrame.prototype.onIframeLoaded_ = function(e) {
15061509
*/
15071510
goog.testing.MultiTestRunner.TestFrame.prototype.checkForCompletion_ =
15081511
function() {
1509-
var js = goog.dom.getFrameContentWindow(this.iframeEl_);
1512+
var frameWindow = goog.dom.getFrameContentWindow(this.iframeEl_);
1513+
var /** @type {?goog.testing.TestRunner} */ frameTestRunner =
1514+
frameWindow['G_testRunner'];
1515+
15101516
switch (this.currentState_) {
1511-
case 0:
1512-
if (this.iframeLoaded_ && js['G_testRunner']) {
1517+
case goog.testing.MultiTestRunner.State.WAITING:
1518+
if (this.iframeLoaded_ && frameTestRunner) {
15131519
this.lastStateTime_ = goog.now();
1514-
this.currentState_++;
1520+
this.currentState_ = goog.testing.MultiTestRunner.State.INITIALIZING;
15151521
}
15161522
break;
1517-
case 1:
1518-
if (js['G_testRunner']['isInitialized']()) {
1523+
1524+
case goog.testing.MultiTestRunner.State.INITIALIZING:
1525+
if (frameTestRunner.isInitialized()) {
15191526
this.lastStateTime_ = goog.now();
1520-
this.currentState_++;
1527+
this.currentState_ = goog.testing.MultiTestRunner.State.RUNNING;
15211528
}
15221529
break;
1523-
case 2:
1524-
if (js['G_testRunner']['isFinished']()) {
1525-
var tr = js['G_testRunner'];
1526-
this.isSuccess_ = tr['isSuccess']();
1527-
this.report_ = tr['getReport'](this.verbosePasses_);
1528-
this.testResults_ = tr['getTestResults']();
1529-
// If there is a syntax error, or no tests, it's not possible to get the
1530-
// individual test method results from TestCase. So just create one here
1531-
// based on the test report and filename.
1532-
if (goog.object.isEmpty(this.testResults_)) {
1533-
// Existence of a report is a signal of a test failure by the test
1534-
// runner.
1535-
this.testResults_[this.testFile_] = this.isSuccess_ ? [] : [{
1536-
'message': this.report_,
1537-
'source': this.testFile_,
1538-
'stacktrace': ''
1539-
}];
1540-
}
1541-
this.runTime_ = tr['getRunTime']();
1542-
this.numFilesLoaded_ = tr['getNumFilesLoaded']();
1543-
this.finish_();
1544-
return;
1530+
1531+
case goog.testing.MultiTestRunner.State.RUNNING:
1532+
if (!frameTestRunner.isComplete()) {
1533+
break;
1534+
}
1535+
1536+
this.currentState_ = goog.testing.MultiTestRunner.State.COMPLETE;
1537+
this.isSuccess_ = frameTestRunner.isSuccess();
1538+
this.report_ = frameTestRunner.getReport(this.verbosePasses_);
1539+
this.testResults_ = frameTestRunner.getTestResults() || {};
1540+
// If there is a syntax error, or no tests, it's not possible to get the
1541+
// individual test method results from TestCase. So just create one here
1542+
// based on the test report and filename.
1543+
if (goog.object.isEmpty(this.testResults_)) {
1544+
// Existence of a report is a signal of a test failure by the test
1545+
// runner.
1546+
this.testResults_[this.testFile_] = this.isSuccess_ ? [] : [
1547+
{'message': this.report_, 'source': this.testFile_, 'stacktrace': ''}
1548+
];
15451549
}
1550+
this.runTime_ = frameTestRunner.getRunTime();
1551+
this.numFilesLoaded_ = frameTestRunner.getNumFilesLoaded();
1552+
this.finish_();
1553+
return;
15461554
}
15471555

15481556
// Check to see if the test has timed out.
15491557
if (goog.now() - this.lastStateTime_ > this.timeoutMs_) {
1550-
this.report_ = this.testFile_ + ' timed out ' +
1551-
goog.testing.MultiTestRunner.STATES[this.currentState_];
1558+
this.report_ = this.testFile_ + ' timed out ' + this.currentState_;
15521559
this.testResults_[this.testFile_] =
15531560
[{'message': this.report_, 'source': this.testFile_, 'stacktrace': ''}];
15541561
this.isSuccess_ = false;

0 commit comments

Comments
 (0)