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	testChanSendBarrier(true)
49}
50
51func TestChanSendBarrier(t *testing.T) {
52	testChanSendBarrier(false)
53}
54
55func testChanSendBarrier(useSelect bool) {
56	var wg sync.WaitGroup
57	var globalMu sync.Mutex
58	outer := 100
59	inner := 100000
60	if testing.Short() || runtime.GOARCH == "wasm" {
61		outer = 10
62		inner = 1000
63	}
64	for i := 0; i < outer; i++ {
65		wg.Add(1)
66		go func() {
67			defer wg.Done()
68			var garbage []byte
69			for j := 0; j < inner; j++ {
70				_, err := doRequest(useSelect)
71				_, ok := err.(myError)
72				if !ok {
73					panic(1)
74				}
75				garbage = make([]byte, 1<<10)
76			}
77			globalMu.Lock()
78			global = garbage
79			globalMu.Unlock()
80		}()
81	}
82	wg.Wait()
83}
84