diff --git a/src/unit/parser/ArcanistGoTestResultParser.php b/src/unit/parser/ArcanistGoTestResultParser.php --- a/src/unit/parser/ArcanistGoTestResultParser.php +++ b/src/unit/parser/ArcanistGoTestResultParser.php @@ -25,7 +25,39 @@ // Temp store for test case results (in case we run multiple test cases) $test_case_results = array(); - foreach ($test_results as $i => $line) { + for ($i = 0; $i < count($test_results); $i++) { + $line = $test_results[$i]; + + if (strlen($line) >= 18 + && strncmp($line, '==================', 18) === 0 + && strncmp($test_results[$i + 1], 'WARNING: DATA RACE', 18) === 0) { + // We have a race condition + $i++; // Advance to WARNING: DATA RACE + $reason = ''; + $test_name = ''; + + // loop to collect all data and move to the === line + while (strncmp($test_results[$i], '==================', 18) !== 0) { + if (strncmp($test_results[$i], 'Goroutine', 9) === 0) { + $meta = array(); + preg_match( + '/^.*\.(?P[^\.]+)$/', + $test_results[$i + 1], + $meta); + $test_name = $meta['test_name'].' Race Detected'; + } + $reason .= $test_results[$i++]."\n"; + } + + $result = new ArcanistUnitTestResult(); + $result->setName($test_name); + $result->setResult(ArcanistUnitTestResult::RESULT_FAIL); + $result->setUserData($reason); + + $test_case_results[] = $result; + + continue; + } if (strncmp($line, '--- PASS', 8) === 0) { // We have a passing test diff --git a/src/unit/parser/__tests__/ArcanistGoTestResultParserTestCase.php b/src/unit/parser/__tests__/ArcanistGoTestResultParserTestCase.php --- a/src/unit/parser/__tests__/ArcanistGoTestResultParserTestCase.php +++ b/src/unit/parser/__tests__/ArcanistGoTestResultParserTestCase.php @@ -39,6 +39,47 @@ $parsed_results[1]->getResult()); } + public function testRaceWarningTestCaseSuccess() { + $stubbed_results = Filesystem::readFile( + dirname(__FILE__).'/testresults/go.race-warning-test-case-success-go1.4'); + + $parsed_results = id(new ArcanistGoTestResultParser()) + ->parseTestResults('racepackage_test.go', $stubbed_results); + + $this->assertEqual(3, count($parsed_results)); + $this->assertEqual( + ArcanistUnitTestResult::RESULT_FAIL, + $parsed_results[0]->getResult()); + $this->assertEqual( + 'WARNING: DATA RACE', + idx(explode("\n", $parsed_results[0]->getUserData()), 0)); + $this->assertEqual( + ArcanistUnitTestResult::RESULT_PASS, + $parsed_results[1]->getResult()); + } + + public function testRaceWarningTestCaseFailure() { + $stubbed_results = Filesystem::readFile( + dirname(__FILE__).'/testresults/go.race-warning-test-case-failure-go1.4'); + + $parsed_results = id(new ArcanistGoTestResultParser()) + ->parseTestResults('racepackage_test.go', $stubbed_results); + + $this->assertEqual(3, count($parsed_results)); + $this->assertEqual( + ArcanistUnitTestResult::RESULT_FAIL, + $parsed_results[0]->getResult()); + $this->assertEqual( + 'WARNING: DATA RACE', + idx(explode("\n", $parsed_results[0]->getUserData()), 0)); + $this->assertEqual( + ArcanistUnitTestResult::RESULT_PASS, + $parsed_results[1]->getResult()); + $this->assertEqual( + "racepackage_test.go:30: got: 2, want: 1\n", + $parsed_results[2]->getUserData()); + } + public function testMultipleTestCasesSuccessful() { $stubbed_results = Filesystem::readFile( dirname(__FILE__).'/testresults/go.multiple-test-cases-successful'); diff --git a/src/unit/parser/__tests__/testresults/go.race-warning-test-case-failure-go1.4 b/src/unit/parser/__tests__/testresults/go.race-warning-test-case-failure-go1.4 new file mode 100644 --- /dev/null +++ b/src/unit/parser/__tests__/testresults/go.race-warning-test-case-failure-go1.4 @@ -0,0 +1,29 @@ +================== +WARNING: DATA RACE +Write by goroutine 8: + racepackage.func~002() + /tmp/racepackage_test.go:21 +0x5d + +Previous write by goroutine 7: + racepackage.func~001() + /tmp/racepackage_test.go:17 +0x5d + +Goroutine 8 (running) created at: + racepackage.TestBar() + /tmp/racepackage_test.go:22 +0x1e8 + testing.tRunner() + /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:447 +0x133 + +Goroutine 7 (finished) created at: + racepackage.TestBar() + /tmp/racepackage_test.go:18 +0x13e + testing.tRunner() + /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:447 +0x133 +================== +=== RUN TestFoo +--- PASS: TestFoo (0.03s) +=== RUN TestBar +--- FAIL: TestBar (0.02s) + racepackage_test.go:30: got: 2, want: 1 +PASS +ok package/racepackage 0.042s diff --git a/src/unit/parser/__tests__/testresults/go.race-warning-test-case-success-go1.4 b/src/unit/parser/__tests__/testresults/go.race-warning-test-case-success-go1.4 new file mode 100644 --- /dev/null +++ b/src/unit/parser/__tests__/testresults/go.race-warning-test-case-success-go1.4 @@ -0,0 +1,28 @@ +================== +WARNING: DATA RACE +Write by goroutine 8: + racepackage.func~002() + /tmp/racepackage_test.go:21 +0x5d + +Previous write by goroutine 7: + racepackage.func~001() + /tmp/racepackage_test.go:17 +0x5d + +Goroutine 8 (running) created at: + racepackage.TestBar() + /tmp/racepackage_test.go:22 +0x1e8 + testing.tRunner() + /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:447 +0x133 + +Goroutine 7 (finished) created at: + racepackage.TestBar() + /tmp/racepackage_test.go:18 +0x13e + testing.tRunner() + /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:447 +0x133 +================== +=== RUN TestFoo +--- PASS: TestFoo (0.03s) +=== RUN TestBar +--- PASS: TestBar (0.01s) +PASS +ok package/racepackage 0.042s