1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package runtime_test
6
7import (
8	"runtime"
9	"sync"
10	"testing"
11)
12
13type response struct {
14}
15
16type myError struct {
17}
18
19func (myError) Error() string { return "" }
20
21func doRequest(useSelect bool) (*response, error) {
22	type async struct {
23		resp *response
24		err  error
25	}
26	ch := make(chan *async, 0)
27	done := make(chan struct{}, 0)
28
29	if useSelect {
30		go func() {
31			select {
32			case ch <- &async{resp: nil, err: myError{}}:
33			case <-done:
34			}
35		}()
36	} else {
37		go func() {
38			ch <- &async{resp: nil, err: myError{}}
39		}()
40	}
41
42	r := <-ch
43	runtime.Gosched()
44	return r.resp, r.err
45}
46
47func TestChanSendSelectBarrier(t *testing.T) {
48	t.Parallel()
49	testChanSendBarrier(true)
50}
51
52func TestChanSendBarrier(t *testing.T) {
53	t.Parallel()
54	testChanSendBarrier(false)
55}
56
57func testChanSendBarrier(useSelect bool) {
58	var wg sync.WaitGroup
59	outer := 100
60	inner := 100000
61	if testing.Short() || runtime.GOARCH == "wasm" {
62		outer = 10
63		inner = 1000
64	}
65	for i := 0; i < outer; i++ {
66		wg.Add(1)
67		go func() {
68			defer wg.Done()
69			var garbage []byte
70			for j := 0; j < inner; j++ {
71				_, err := doRequest(useSelect)
72				_, ok := err.(myError)
73				if !ok {
74					panic(1)
75				}
76				garbage = makeByte()
77			}
78			_ = garbage
79		}()
80	}
81	wg.Wait()
82}
83
84//go:noinline
85func makeByte() []byte {
86	return make([]byte, 1<<10)
87}
88