# Run parallel chatty tests. Assert on CONT lines. This test makes sure that
# multiple parallel outputs have the appropriate CONT lines between them.
! go test -parallel 3 chatty_parallel_test.go -v

stdout -count=1 '^=== CONT  TestChattyParallel/sub-0\n    chatty_parallel_test.go:38: error from sub-0$'
stdout -count=1 '^=== CONT  TestChattyParallel/sub-1\n    chatty_parallel_test.go:38: error from sub-1$'
stdout -count=1 '^=== CONT  TestChattyParallel/sub-2\n    chatty_parallel_test.go:38: error from sub-2$'

# Run parallel chatty tests with -json. Assert on CONT lines as above - make
# sure there are CONT lines before each output line.
! go test -json -parallel 3 chatty_parallel_test.go -v
stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"=== CONT  TestChattyParallel/sub-0\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"    chatty_parallel_test.go:38: error from sub-0\\n"}'
stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"=== CONT  TestChattyParallel/sub-1\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"    chatty_parallel_test.go:38: error from sub-1\\n"}'
stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"=== CONT  TestChattyParallel/sub-2\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"    chatty_parallel_test.go:38: error from sub-2\\n"}'

-- chatty_parallel_test.go --
package chatty_paralell_test

import (
	"testing"
	"fmt"
	"flag"
)

// This test ensures the the order of CONT lines in parallel chatty tests.
func TestChattyParallel(t *testing.T) {
	t.Parallel()

	// The number of concurrent tests running. This is closely tied to the
	// -parallel test flag, so we grab it from the flag rather than setting it
	// to some constant.
	parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int)

	// ready is a synchronization mechanism that causes subtests to execute
	// round robin.
	ready := make([]chan bool, parallel)
	for i := range ready {
		ready[i] = make(chan bool, 1)
	}
	ready[0] <- true

	for i := range ready {
		i := i
		t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
			t.Parallel()

			// Some basic log output to precede the failures.
			<-ready[i]
			t.Logf("this is sub-%d", i)
			ready[(i+1)%len(ready)] <- true

			// The actual failure messages we care about.
			<-ready[i]
			t.Errorf("error from sub-%d", i)
			ready[(i+1)%len(ready)] <- true
		})
	}
}
