1 | // vtest flaky: true |
2 | // vtest retry: 15 |
3 | |
4 | // This test case runs concurrent 3 instances of `do_select` that |
5 | // communicate with 6 other threads doing send and receive operations. |
6 | // There are buffered and unbuffered channels - handled by one or two |
7 | // concurrend threads on the other side |
8 | |
9 | fn do_select(ch1 chan int, ch2 chan int, chf1 chan f64, chf2 chan f64, sumch1 chan i64, sumch2 chan i64) { |
10 | mut sum1 := i64(0) |
11 | mut sum2 := i64(0) |
12 | f1 := 17.0 |
13 | f2 := 7.0 |
14 | for _ in 0 .. 20000 + chf1.cap / 3 { |
15 | select { |
16 | chf1 <- f1 {} |
17 | i := <-ch1 { |
18 | sum1 += i |
19 | } |
20 | j := <-ch2 { |
21 | sum2 += j |
22 | } |
23 | chf2 <- f2 {} |
24 | } |
25 | } |
26 | sumch1 <- sum1 |
27 | sumch2 <- sum2 |
28 | } |
29 | |
30 | fn do_send_int(ch chan int, factor int) { |
31 | for i in 0 .. 10000 { |
32 | ch <- (i * factor) |
33 | } |
34 | } |
35 | |
36 | fn do_rec_f64(ch chan f64, sumch chan f64) { |
37 | mut sum := 0.0 |
38 | for _ in 0 .. 10000 { |
39 | sum += <-ch |
40 | } |
41 | sumch <- sum |
42 | } |
43 | |
44 | fn test_select() { |
45 | ch1 := chan int{cap: 3} |
46 | ch2 := chan int{} |
47 | // buffer length of chf1 mus be mutiple of 3 (# select threads) |
48 | chf1 := chan f64{cap: 30} |
49 | chf2 := chan f64{} |
50 | chsum1 := chan i64{} |
51 | chsum2 := chan i64{} |
52 | chsumf1 := chan f64{} |
53 | chsumf2 := chan f64{} |
54 | spawn do_send_int(ch1, 3) |
55 | spawn do_select(ch1, ch2, chf1, chf2, chsum1, chsum2) |
56 | spawn do_rec_f64(chf1, chsumf1) |
57 | spawn do_rec_f64(chf2, chsumf2) |
58 | spawn do_rec_f64(chf2, chsumf2) |
59 | spawn do_select(ch1, ch2, chf1, chf2, chsum1, chsum2) |
60 | spawn do_send_int(ch2, 7) |
61 | spawn do_send_int(ch2, 17) |
62 | spawn do_select(ch1, ch2, chf1, chf2, chsum1, chsum2) |
63 | |
64 | sum1 := <-chsum1 + <-chsum1 + <-chsum1 |
65 | sum2 := <-chsum2 + <-chsum2 + <-chsum2 |
66 | mut sumf1 := <-chsumf1 |
67 | // empty channel buffer |
68 | for _ in 0 .. chf1.cap { |
69 | sumf1 += <-chf1 |
70 | } |
71 | sumf2 := <-chsumf2 + <-chsumf2 |
72 | // Use Gauß' formula |
73 | expected_sum := i64(10000) * (10000 - 1) / 2 |
74 | assert sum1 == 3 * expected_sum |
75 | assert sum2 == (7 + 17) * expected_sum |
76 | assert sumf1 == 17.0 * f64(10000 + chf1.cap) |
77 | assert sumf2 == 7.0 * 20000 |
78 | } |