)]}'
{
  "commit": "212b76d63d55e0107353f3200ed10518de8612a6",
  "tree": "c4b27b09f23935cb9e3ed795050464f5c71d335d",
  "parents": [
    "8c95bcf1078cdf45b2942db1c24cdd331b0d71dc"
  ],
  "author": {
    "name": "Zhongpeng Lin",
    "email": "zplin@uber.com",
    "time": "Fri Feb 07 16:07:47 2025 -0800"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Sat Feb 08 00:07:47 2025 +0000"
  },
  "message": "Reporting subtests as they finish (#4250)\n\n**What type of PR is this?**\r\nFeature\r\n\r\n**What does this PR do? Why is it needed?**\r\nThis PR makes rules_go report all finished subtests in the XML file,\r\neven when the test target times out. It does this by adding\r\n`-test.v\u003dtest2json` when verbose mode is requested. According to [Go\u0027s\r\ncomment](https://github.com/golang/go/blob/go1.23.2/src/testing/testing.go#L836):\r\n\r\n\u003e If test2json is used, we never flush to parent tests, so that the json\r\nstream shows subtests as they finish.\r\n\r\nIt also sync test2json.go from upstream golang/go.\r\n\r\nWith a test file like this:\r\n\r\n```go\r\npackage test_report\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"testing\"\r\n\t\"time\"\r\n)\r\n\r\nfunc TestReport(t *testing.T) {\r\n\tfor i :\u003d 0; i \u003c 10; i++ {\r\n\t\tt.Run(fmt.Sprintf(\"test %d\", i), func(t *testing.T) {\r\n\t\t\ttime.Sleep(2 * time.Second)\r\n\t\t})\r\n\t}\r\n}\r\n```\r\n\r\nRunning with `--test_timeout\u003d10 --test_env\u003dGO_TEST_WRAP_TESTV\u003d1`, the\r\nXML before the PR:\r\n\r\n```xml\r\n\u003ctestsuites\u003e\r\n\t\u003ctestsuite errors\u003d\"6\" failures\u003d\"0\" skipped\u003d\"0\" tests\u003d\"6\" time\u003d\"\" name\u003d\"example.com/test_report/go_default_test\"\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_0\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport/test_0\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_1\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport/test_1\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_2\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport/test_2\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_3\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport/test_3\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_4\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport/test_4\u0026#xA;panic: test timed out after 10s\u0026#xA;\u0026#x9;running tests:\u0026#xA;\u0026#x9;\u0026#x9;TestReport (10s)\u0026#xA;\u0026#x9;\u0026#x9;TestReport/test_4 (2s)\u0026#xA;\u0026#xA;goroutine 22 [running]:\u0026#xA;testing.(*M).startAlarm.func1()\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2373 +0x385\u0026#xA;created by time.goFunc\u0026#xA;\u0026#x9;GOROOT/src/time/sleep.go:215 +0x2d\u0026#xA;\u0026#xA;goroutine 1 [chan receive]:\u0026#xA;testing.(*T).Run(0xc0001aa000, {0x5b8d09?, 0x0?}, 0x5db1c0)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1751 +0x3ab\u0026#xA;testing.runTests.func1(0xc0001aa000)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2168 +0x37\u0026#xA;testing.tRunner(0xc0001aa000, 0xc00015cb18)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1690 +0xf4\u0026#xA;testing.runTests(0xc0001a2000, {0x712a50, 0x1, 0x1}, {0xc00015cb48?, 0x16?, 0x721b00?})\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2166 +0x43d\u0026#xA;testing.(*M).Run(0xc0001521e0)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2034 +0x64a\u0026#xA;go.uber.org/goleak.VerifyTestMain({0x60dc20?, 0xc0001521e0?}, {0x0, 0x0, 0x0})\u0026#xA;\u0026#x9;external/org_uber_go_goleak/testmain.go:53 +0x5a\u0026#xA;main.main()\u0026#xA;\u0026#x9;bazel-out/k8-fastbuild/bin/src/code.uber.internal/devexp/test_report/go_default_test_/testmain.go:130 +0x355\u0026#xA;\u0026#xA;goroutine 17 [syscall]:\u0026#xA;os/signal.signal_recv()\u0026#xA;\u0026#x9;GOROOT/src/runtime/sigqueue.go:152 +0x29\u0026#xA;os/signal.loop()\u0026#xA;\u0026#x9;GOROOT/src/os/signal/signal_unix.go:23 +0x13\u0026#xA;created by os/signal.Notify.func1.1 in goroutine 1\u0026#xA;\u0026#x9;GOROOT/src/os/signal/signal.go:151 +0x1f\u0026#xA;\u0026#xA;goroutine 18 [chan receive]:\u0026#xA;testing.(*T).Run(0xc0001aa1a0, {0xc000282060?, 0xc00015cf50?}, 0x5db310)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1751 +0x3ab\u0026#xA;src/code.uber.internal/devexp/test_report/go_default_test.TestReport(0xc0001aa1a0)\u0026#xA;\u0026#x9;src/code.uber.internal/devexp/test_report/a_test.go:11 +0x74\u0026#xA;testing.tRunner(0xc0001aa1a0, 0x5db1c0)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1690 +0xf4\u0026#xA;created by testing.(*T).Run in goroutine 1\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1743 +0x390\u0026#xA;\u0026#xA;goroutine 34 [sleep]:\u0026#xA;time.Sleep(0x77359400)\u0026#xA;\u0026#x9;GOROOT/src/runtime/time.go:315 +0xf2\u0026#xA;src/code.uber.internal/devexp/test_report/go_default_test.TestReport.func1(0xc0002961a0?)\u0026#xA;\u0026#x9;src/code.uber.internal/devexp/test_report/a_test.go:12 +0x18\u0026#xA;testing.tRunner(0xc0002961a0, 0x5db310)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1690 +0xf4\u0026#xA;created by testing.(*T).Run in goroutine 18\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1743 +0x390\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\u003c/testsuite\u003e\r\n\u003c/testsuites\u003e\r\n```\r\n\r\nThe XML after the PR:\r\n\r\n```xml\r\n\u003ctestsuites\u003e\r\n\t\u003ctestsuite errors\u003d\"2\" failures\u003d\"0\" skipped\u003d\"0\" tests\u003d\"6\" time\u003d\"\" name\u003d\"example.com/test_report/go_default_test\"\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_0\" time\u003d\"2.000\"\u003e\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_1\" time\u003d\"2.000\"\u003e\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_2\" time\u003d\"2.000\"\u003e\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_3\" time\u003d\"2.000\"\u003e\u003c/testcase\u003e\r\n\t\t\u003ctestcase classname\u003d\"go_default_test\" name\u003d\"TestReport/test_4\" time\u003d\"\"\u003e\r\n\t\t\t\u003cerror message\u003d\"No pass/skip/fail event found for test\" type\u003d\"\"\u003e\u003d\u003d\u003d RUN   TestReport/test_4\u0026#xA;panic: test timed out after 10s\u0026#xA;\u0026#x9;running tests:\u0026#xA;\u0026#x9;\u0026#x9;TestReport (10s)\u0026#xA;\u0026#x9;\u0026#x9;TestReport/test_4 (2s)\u0026#xA;\u0026#xA;goroutine 21 [running]:\u0026#xA;testing.(*M).startAlarm.func1()\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2373 +0x385\u0026#xA;created by time.goFunc\u0026#xA;\u0026#x9;GOROOT/src/time/sleep.go:215 +0x2d\u0026#xA;\u0026#xA;goroutine 1 [chan receive]:\u0026#xA;testing.(*T).Run(0xc0001aa000, {0x5b8d07?, 0x0?}, 0x5db1d0)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1751 +0x3ab\u0026#xA;testing.runTests.func1(0xc0001aa000)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2168 +0x37\u0026#xA;testing.tRunner(0xc0001aa000, 0xc00015cb18)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1690 +0xf4\u0026#xA;testing.runTests(0xc0001a2000, {0x712a50, 0x1, 0x1}, {0xc00015cb48?, 0x16?, 0x721b00?})\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2166 +0x43d\u0026#xA;testing.(*M).Run(0xc0001521e0)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:2034 +0x64a\u0026#xA;go.uber.org/goleak.VerifyTestMain({0x60dc40?, 0xc0001521e0?}, {0x0, 0x0, 0x0})\u0026#xA;\u0026#x9;external/org_uber_go_goleak/testmain.go:53 +0x5a\u0026#xA;main.main()\u0026#xA;\u0026#x9;bazel-out/k8-fastbuild/bin/src/code.uber.internal/devexp/test_report/go_default_test_/testmain.go:130 +0x355\u0026#xA;\u0026#xA;goroutine 17 [syscall]:\u0026#xA;os/signal.signal_recv()\u0026#xA;\u0026#x9;GOROOT/src/runtime/sigqueue.go:152 +0x29\u0026#xA;os/signal.loop()\u0026#xA;\u0026#x9;GOROOT/src/os/signal/signal_unix.go:23 +0x13\u0026#xA;created by os/signal.Notify.func1.1 in goroutine 1\u0026#xA;\u0026#x9;GOROOT/src/os/signal/signal.go:151 +0x1f\u0026#xA;\u0026#xA;goroutine 18 [chan receive]:\u0026#xA;testing.(*T).Run(0xc0001aa1a0, {0xc000282086?, 0xc00015cf50?}, 0x5db320)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1751 +0x3ab\u0026#xA;src/code.uber.internal/devexp/test_report/go_default_test.TestReport(0xc0001aa1a0)\u0026#xA;\u0026#x9;src/code.uber.internal/devexp/test_report/a_test.go:11 +0x74\u0026#xA;testing.tRunner(0xc0001aa1a0, 0x5db1d0)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1690 +0xf4\u0026#xA;created by testing.(*T).Run in goroutine 1\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1743 +0x390\u0026#xA;\u0026#xA;goroutine 35 [sleep]:\u0026#xA;time.Sleep(0x77359400)\u0026#xA;\u0026#x9;GOROOT/src/runtime/time.go:315 +0xf2\u0026#xA;src/code.uber.internal/devexp/test_report/go_default_test.TestReport.func1(0xc000294340?)\u0026#xA;\u0026#x9;src/code.uber.internal/devexp/test_report/a_test.go:12 +0x18\u0026#xA;testing.tRunner(0xc000294340, 0x5db320)\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1690 +0xf4\u0026#xA;created by testing.(*T).Run in goroutine 18\u0026#xA;\u0026#x9;GOROOT/src/testing/testing.go:1743 +0x390\u0026#xA;\u003c/error\u003e\r\n\t\t\u003c/testcase\u003e\r\n\t\u003c/testsuite\u003e\r\n\u003c/testsuites\u003e\r\n```\r\n\r\n---------\r\n\r\nCo-authored-by: Jay Conrod \u003cjayconrod@gmail.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "b4229e2235f538a8e42adb51c2b61cfdcdcbcd2d",
      "old_mode": 33188,
      "old_path": "go/tools/bzltestutil/wrap.go",
      "new_id": "3e9a083ff1b7211aa71fe7cef7f83ee085908995",
      "new_mode": 33188,
      "new_path": "go/tools/bzltestutil/wrap.go"
    }
  ]
}
