Initial commit: Go 1.23 release state

This commit is contained in:
Vorapol Rinsatitnon
2024-09-21 23:49:08 +10:00
commit 17cd57a668
13231 changed files with 3114330 additions and 0 deletions

87
test/chan/doubleselect.go Normal file
View File

@@ -0,0 +1,87 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test the situation in which two cases of a select can
// both end up running. See http://codereview.appspot.com/180068.
package main
import (
"flag"
"runtime"
)
var iterations *int = flag.Int("n", 100000, "number of iterations")
// sender sends a counter to one of four different channels. If two
// cases both end up running in the same iteration, the same value will be sent
// to two different channels.
func sender(n int, c1, c2, c3, c4 chan<- int) {
defer close(c1)
defer close(c2)
defer close(c3)
defer close(c4)
for i := 0; i < n; i++ {
select {
case c1 <- i:
case c2 <- i:
case c3 <- i:
case c4 <- i:
}
}
}
// mux receives the values from sender and forwards them onto another channel.
// It would be simpler to just have sender's four cases all be the same
// channel, but this doesn't actually trigger the bug.
func mux(out chan<- int, in <-chan int, done chan<- bool) {
for v := range in {
out <- v
}
done <- true
}
// recver gets a steam of values from the four mux's and checks for duplicates.
func recver(in <-chan int) {
seen := make(map[int]bool)
for v := range in {
if _, ok := seen[v]; ok {
println("got duplicate value: ", v)
panic("fail")
}
seen[v] = true
}
}
func main() {
runtime.GOMAXPROCS(2)
flag.Parse()
c1 := make(chan int)
c2 := make(chan int)
c3 := make(chan int)
c4 := make(chan int)
done := make(chan bool)
cmux := make(chan int)
go sender(*iterations, c1, c2, c3, c4)
go mux(cmux, c1, done)
go mux(cmux, c2, done)
go mux(cmux, c3, done)
go mux(cmux, c4, done)
go func() {
<-done
<-done
<-done
<-done
close(cmux)
}()
// We keep the recver because it might catch more bugs in the future.
// However, the result of the bug linked to at the top is that we'll
// end up panicking with: "throw: bad g->status in ready".
recver(cmux)
}

56
test/chan/fifo.go Normal file
View File

@@ -0,0 +1,56 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that unbuffered channels act as pure fifos.
package main
import "os"
const N = 10
func AsynchFifo() {
ch := make(chan int, N)
for i := 0; i < N; i++ {
ch <- i
}
for i := 0; i < N; i++ {
if <-ch != i {
print("bad receive\n")
os.Exit(1)
}
}
}
func Chain(ch <-chan int, val int, in <-chan int, out chan<- int) {
<-in
if <-ch != val {
panic(val)
}
out <- 1
}
// thread together a daisy chain to read the elements in sequence
func SynchFifo() {
ch := make(chan int)
in := make(chan int)
start := in
for i := 0; i < N; i++ {
out := make(chan int)
go Chain(ch, i, in, out)
in = out
}
start <- 0
for i := 0; i < N; i++ {
ch <- i
}
<-in
}
func main() {
AsynchFifo()
SynchFifo()
}

41
test/chan/goroutines.go Normal file
View File

@@ -0,0 +1,41 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Torture test for goroutines.
// Make a lot of goroutines, threaded together, and tear them down cleanly.
package main
import (
"os"
"strconv"
)
func f(left, right chan int) {
left <- <-right
}
func main() {
var n = 10000
if len(os.Args) > 1 {
var err error
n, err = strconv.Atoi(os.Args[1])
if err != nil {
print("bad arg\n")
os.Exit(1)
}
}
leftmost := make(chan int)
right := leftmost
left := leftmost
for i := 0; i < n; i++ {
right = make(chan int)
go f(left, right)
left = right
}
go func(c chan int) { c <- 1 }(right)
<-leftmost
}

282
test/chan/nonblock.go Normal file
View File

@@ -0,0 +1,282 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test channel operations that test for blocking.
// Use several sizes and types of operands.
package main
import "runtime"
import "time"
func i32receiver(c chan int32, strobe chan bool) {
if <-c != 123 {
panic("i32 value")
}
strobe <- true
}
func i32sender(c chan int32, strobe chan bool) {
c <- 234
strobe <- true
}
func i64receiver(c chan int64, strobe chan bool) {
if <-c != 123456 {
panic("i64 value")
}
strobe <- true
}
func i64sender(c chan int64, strobe chan bool) {
c <- 234567
strobe <- true
}
func breceiver(c chan bool, strobe chan bool) {
if !<-c {
panic("b value")
}
strobe <- true
}
func bsender(c chan bool, strobe chan bool) {
c <- true
strobe <- true
}
func sreceiver(c chan string, strobe chan bool) {
if <-c != "hello" {
panic("s value")
}
strobe <- true
}
func ssender(c chan string, strobe chan bool) {
c <- "hello again"
strobe <- true
}
var ticker = time.Tick(10 * 1000) // 10 us
func sleep() {
<-ticker
<-ticker
runtime.Gosched()
runtime.Gosched()
runtime.Gosched()
}
const maxTries = 10000 // Up to 100ms per test.
func main() {
var i32 int32
var i64 int64
var b bool
var s string
var sync = make(chan bool)
for buffer := 0; buffer < 2; buffer++ {
c32 := make(chan int32, buffer)
c64 := make(chan int64, buffer)
cb := make(chan bool, buffer)
cs := make(chan string, buffer)
select {
case i32 = <-c32:
panic("blocked i32sender")
default:
}
select {
case i64 = <-c64:
panic("blocked i64sender")
default:
}
select {
case b = <-cb:
panic("blocked bsender")
default:
}
select {
case s = <-cs:
panic("blocked ssender")
default:
}
go i32receiver(c32, sync)
try := 0
Send32:
for {
select {
case c32 <- 123:
break Send32
default:
try++
if try > maxTries {
println("i32receiver buffer=", buffer)
panic("fail")
}
sleep()
}
}
<-sync
go i32sender(c32, sync)
if buffer > 0 {
<-sync
}
try = 0
Recv32:
for {
select {
case i32 = <-c32:
break Recv32
default:
try++
if try > maxTries {
println("i32sender buffer=", buffer)
panic("fail")
}
sleep()
}
}
if i32 != 234 {
panic("i32sender value")
}
if buffer == 0 {
<-sync
}
go i64receiver(c64, sync)
try = 0
Send64:
for {
select {
case c64 <- 123456:
break Send64
default:
try++
if try > maxTries {
panic("i64receiver")
}
sleep()
}
}
<-sync
go i64sender(c64, sync)
if buffer > 0 {
<-sync
}
try = 0
Recv64:
for {
select {
case i64 = <-c64:
break Recv64
default:
try++
if try > maxTries {
panic("i64sender")
}
sleep()
}
}
if i64 != 234567 {
panic("i64sender value")
}
if buffer == 0 {
<-sync
}
go breceiver(cb, sync)
try = 0
SendBool:
for {
select {
case cb <- true:
break SendBool
default:
try++
if try > maxTries {
panic("breceiver")
}
sleep()
}
}
<-sync
go bsender(cb, sync)
if buffer > 0 {
<-sync
}
try = 0
RecvBool:
for {
select {
case b = <-cb:
break RecvBool
default:
try++
if try > maxTries {
panic("bsender")
}
sleep()
}
}
if !b {
panic("bsender value")
}
if buffer == 0 {
<-sync
}
go sreceiver(cs, sync)
try = 0
SendString:
for {
select {
case cs <- "hello":
break SendString
default:
try++
if try > maxTries {
panic("sreceiver")
}
sleep()
}
}
<-sync
go ssender(cs, sync)
if buffer > 0 {
<-sync
}
try = 0
RecvString:
for {
select {
case s = <-cs:
break RecvString
default:
try++
if try > maxTries {
panic("ssender")
}
sleep()
}
}
if s != "hello again" {
panic("ssender value")
}
if buffer == 0 {
<-sync
}
}
}

70
test/chan/perm.go Normal file
View File

@@ -0,0 +1,70 @@
// errorcheck
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test various correct and incorrect permutations of send-only,
// receive-only, and bidirectional channels.
// Does not compile.
package main
var (
cr <-chan int
cs chan<- int
c chan int
)
func main() {
cr = c // ok
cs = c // ok
c = cr // ERROR "illegal types|incompatible|cannot"
c = cs // ERROR "illegal types|incompatible|cannot"
cr = cs // ERROR "illegal types|incompatible|cannot"
cs = cr // ERROR "illegal types|incompatible|cannot"
var n int
<-n // ERROR "receive from non-chan|expected channel"
n <- 2 // ERROR "send to non-chan|must be channel"
c <- 0 // ok
<-c // ok
x, ok := <-c // ok
_, _ = x, ok
cr <- 0 // ERROR "send"
<-cr // ok
x, ok = <-cr // ok
_, _ = x, ok
cs <- 0 // ok
<-cs // ERROR "receive"
x, ok = <-cs // ERROR "receive"
_, _ = x, ok
select {
case c <- 0: // ok
case x := <-c: // ok
_ = x
case cr <- 0: // ERROR "send"
case x := <-cr: // ok
_ = x
case cs <- 0: // ok
case x := <-cs: // ERROR "receive"
_ = x
}
for _ = range cs { // ERROR "receive"
}
for range cs { // ERROR "receive"
}
close(c)
close(cs)
close(cr) // ERROR "receive"
close(n) // ERROR "invalid operation.*non-chan type|must be channel|non-channel"
}

741
test/chan/powser1.go Normal file
View File

@@ -0,0 +1,741 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test concurrency primitives: power series.
// Power series package
// A power series is a channel, along which flow rational
// coefficients. A denominator of zero signifies the end.
// Original code in Newsqueak by Doug McIlroy.
// See Squinting at Power Series by Doug McIlroy,
// https://swtch.com/~rsc/thread/squint.pdf
package main
import "os"
type rat struct {
num, den int64 // numerator, denominator
}
func (u rat) pr() {
if u.den == 1 {
print(u.num)
} else {
print(u.num, "/", u.den)
}
print(" ")
}
func (u rat) eq(c rat) bool {
return u.num == c.num && u.den == c.den
}
type dch struct {
req chan int
dat chan rat
nam int
}
type dch2 [2]*dch
var chnames string
var chnameserial int
var seqno int
func mkdch() *dch {
c := chnameserial % len(chnames)
chnameserial++
d := new(dch)
d.req = make(chan int)
d.dat = make(chan rat)
d.nam = c
return d
}
func mkdch2() *dch2 {
d2 := new(dch2)
d2[0] = mkdch()
d2[1] = mkdch()
return d2
}
// split reads a single demand channel and replicates its
// output onto two, which may be read at different rates.
// A process is created at first demand for a rat and dies
// after the rat has been sent to both outputs.
// When multiple generations of split exist, the newest
// will service requests on one channel, which is
// always renamed to be out[0]; the oldest will service
// requests on the other channel, out[1]. All generations but the
// newest hold queued data that has already been sent to
// out[0]. When data has finally been sent to out[1],
// a signal on the release-wait channel tells the next newer
// generation to begin servicing out[1].
func dosplit(in *dch, out *dch2, wait chan int) {
both := false // do not service both channels
select {
case <-out[0].req:
case <-wait:
both = true
select {
case <-out[0].req:
case <-out[1].req:
out[0], out[1] = out[1], out[0]
}
}
seqno++
in.req <- seqno
release := make(chan int)
go dosplit(in, out, release)
dat := <-in.dat
out[0].dat <- dat
if !both {
<-wait
}
<-out[1].req
out[1].dat <- dat
release <- 0
}
func split(in *dch, out *dch2) {
release := make(chan int)
go dosplit(in, out, release)
release <- 0
}
func put(dat rat, out *dch) {
<-out.req
out.dat <- dat
}
func get(in *dch) rat {
seqno++
in.req <- seqno
return <-in.dat
}
// Get one rat from each of n demand channels
func getn(in []*dch) []rat {
n := len(in)
if n != 2 {
panic("bad n in getn")
}
req := new([2]chan int)
dat := new([2]chan rat)
out := make([]rat, 2)
var i int
var it rat
for i = 0; i < n; i++ {
req[i] = in[i].req
dat[i] = nil
}
for n = 2 * n; n > 0; n-- {
seqno++
select {
case req[0] <- seqno:
dat[0] = in[0].dat
req[0] = nil
case req[1] <- seqno:
dat[1] = in[1].dat
req[1] = nil
case it = <-dat[0]:
out[0] = it
dat[0] = nil
case it = <-dat[1]:
out[1] = it
dat[1] = nil
}
}
return out
}
// Get one rat from each of 2 demand channels
func get2(in0 *dch, in1 *dch) []rat {
return getn([]*dch{in0, in1})
}
func copy(in *dch, out *dch) {
for {
<-out.req
out.dat <- get(in)
}
}
func repeat(dat rat, out *dch) {
for {
put(dat, out)
}
}
type PS *dch // power series
type PS2 *[2]PS // pair of power series
var Ones PS
var Twos PS
func mkPS() *dch {
return mkdch()
}
func mkPS2() *dch2 {
return mkdch2()
}
// Conventions
// Upper-case for power series.
// Lower-case for rationals.
// Input variables: U,V,...
// Output variables: ...,Y,Z
// Integer gcd; needed for rational arithmetic
func gcd(u, v int64) int64 {
if u < 0 {
return gcd(-u, v)
}
if u == 0 {
return v
}
return gcd(v%u, u)
}
// Make a rational from two ints and from one int
func i2tor(u, v int64) rat {
g := gcd(u, v)
var r rat
if v > 0 {
r.num = u / g
r.den = v / g
} else {
r.num = -u / g
r.den = -v / g
}
return r
}
func itor(u int64) rat {
return i2tor(u, 1)
}
var zero rat
var one rat
// End mark and end test
var finis rat
func end(u rat) int64 {
if u.den == 0 {
return 1
}
return 0
}
// Operations on rationals
func add(u, v rat) rat {
g := gcd(u.den, v.den)
return i2tor(u.num*(v.den/g)+v.num*(u.den/g), u.den*(v.den/g))
}
func mul(u, v rat) rat {
g1 := gcd(u.num, v.den)
g2 := gcd(u.den, v.num)
var r rat
r.num = (u.num / g1) * (v.num / g2)
r.den = (u.den / g2) * (v.den / g1)
return r
}
func neg(u rat) rat {
return i2tor(-u.num, u.den)
}
func sub(u, v rat) rat {
return add(u, neg(v))
}
func inv(u rat) rat { // invert a rat
if u.num == 0 {
panic("zero divide in inv")
}
return i2tor(u.den, u.num)
}
// print eval in floating point of PS at x=c to n terms
func evaln(c rat, U PS, n int) {
xn := float64(1)
x := float64(c.num) / float64(c.den)
val := float64(0)
for i := 0; i < n; i++ {
u := get(U)
if end(u) != 0 {
break
}
val = val + x*float64(u.num)/float64(u.den)
xn = xn * x
}
print(val, "\n")
}
// Print n terms of a power series
func printn(U PS, n int) {
done := false
for ; !done && n > 0; n-- {
u := get(U)
if end(u) != 0 {
done = true
} else {
u.pr()
}
}
print(("\n"))
}
// Evaluate n terms of power series U at x=c
func eval(c rat, U PS, n int) rat {
if n == 0 {
return zero
}
y := get(U)
if end(y) != 0 {
return zero
}
return add(y, mul(c, eval(c, U, n-1)))
}
// Power-series constructors return channels on which power
// series flow. They start an encapsulated generator that
// puts the terms of the series on the channel.
// Make a pair of power series identical to a given power series
func Split(U PS) *dch2 {
UU := mkdch2()
go split(U, UU)
return UU
}
// Add two power series
func Add(U, V PS) PS {
Z := mkPS()
go func() {
var uv []rat
for {
<-Z.req
uv = get2(U, V)
switch end(uv[0]) + 2*end(uv[1]) {
case 0:
Z.dat <- add(uv[0], uv[1])
case 1:
Z.dat <- uv[1]
copy(V, Z)
case 2:
Z.dat <- uv[0]
copy(U, Z)
case 3:
Z.dat <- finis
}
}
}()
return Z
}
// Multiply a power series by a constant
func Cmul(c rat, U PS) PS {
Z := mkPS()
go func() {
done := false
for !done {
<-Z.req
u := get(U)
if end(u) != 0 {
done = true
} else {
Z.dat <- mul(c, u)
}
}
Z.dat <- finis
}()
return Z
}
// Subtract
func Sub(U, V PS) PS {
return Add(U, Cmul(neg(one), V))
}
// Multiply a power series by the monomial x^n
func Monmul(U PS, n int) PS {
Z := mkPS()
go func() {
for ; n > 0; n-- {
put(zero, Z)
}
copy(U, Z)
}()
return Z
}
// Multiply by x
func Xmul(U PS) PS {
return Monmul(U, 1)
}
func Rep(c rat) PS {
Z := mkPS()
go repeat(c, Z)
return Z
}
// Monomial c*x^n
func Mon(c rat, n int) PS {
Z := mkPS()
go func() {
if c.num != 0 {
for ; n > 0; n = n - 1 {
put(zero, Z)
}
put(c, Z)
}
put(finis, Z)
}()
return Z
}
func Shift(c rat, U PS) PS {
Z := mkPS()
go func() {
put(c, Z)
copy(U, Z)
}()
return Z
}
// simple pole at 1: 1/(1-x) = 1 1 1 1 1 ...
// Convert array of coefficients, constant term first
// to a (finite) power series
/*
func Poly(a []rat) PS {
Z:=mkPS()
begin func(a []rat, Z PS) {
j:=0
done:=0
for j=len(a); !done&&j>0; j=j-1)
if(a[j-1].num!=0) done=1
i:=0
for(; i<j; i=i+1) put(a[i],Z)
put(finis,Z)
}()
return Z
}
*/
// Multiply. The algorithm is
// let U = u + x*UU
// let V = v + x*VV
// then UV = u*v + x*(u*VV+v*UU) + x*x*UU*VV
func Mul(U, V PS) PS {
Z := mkPS()
go func() {
<-Z.req
uv := get2(U, V)
if end(uv[0]) != 0 || end(uv[1]) != 0 {
Z.dat <- finis
} else {
Z.dat <- mul(uv[0], uv[1])
UU := Split(U)
VV := Split(V)
W := Add(Cmul(uv[0], VV[0]), Cmul(uv[1], UU[0]))
<-Z.req
Z.dat <- get(W)
copy(Add(W, Mul(UU[1], VV[1])), Z)
}
}()
return Z
}
// Differentiate
func Diff(U PS) PS {
Z := mkPS()
go func() {
<-Z.req
u := get(U)
if end(u) == 0 {
done := false
for i := 1; !done; i++ {
u = get(U)
if end(u) != 0 {
done = true
} else {
Z.dat <- mul(itor(int64(i)), u)
<-Z.req
}
}
}
Z.dat <- finis
}()
return Z
}
// Integrate, with const of integration
func Integ(c rat, U PS) PS {
Z := mkPS()
go func() {
put(c, Z)
done := false
for i := 1; !done; i++ {
<-Z.req
u := get(U)
if end(u) != 0 {
done = true
}
Z.dat <- mul(i2tor(1, int64(i)), u)
}
Z.dat <- finis
}()
return Z
}
// Binomial theorem (1+x)^c
func Binom(c rat) PS {
Z := mkPS()
go func() {
n := 1
t := itor(1)
for c.num != 0 {
put(t, Z)
t = mul(mul(t, c), i2tor(1, int64(n)))
c = sub(c, one)
n++
}
put(finis, Z)
}()
return Z
}
// Reciprocal of a power series
// let U = u + x*UU
// let Z = z + x*ZZ
// (u+x*UU)*(z+x*ZZ) = 1
// z = 1/u
// u*ZZ + z*UU +x*UU*ZZ = 0
// ZZ = -UU*(z+x*ZZ)/u
func Recip(U PS) PS {
Z := mkPS()
go func() {
ZZ := mkPS2()
<-Z.req
z := inv(get(U))
Z.dat <- z
split(Mul(Cmul(neg(z), U), Shift(z, ZZ[0])), ZZ)
copy(ZZ[1], Z)
}()
return Z
}
// Exponential of a power series with constant term 0
// (nonzero constant term would make nonrational coefficients)
// bug: the constant term is simply ignored
// Z = exp(U)
// DZ = Z*DU
// integrate to get Z
func Exp(U PS) PS {
ZZ := mkPS2()
split(Integ(one, Mul(ZZ[0], Diff(U))), ZZ)
return ZZ[1]
}
// Substitute V for x in U, where the leading term of V is zero
// let U = u + x*UU
// let V = v + x*VV
// then S(U,V) = u + VV*S(V,UU)
// bug: a nonzero constant term is ignored
func Subst(U, V PS) PS {
Z := mkPS()
go func() {
VV := Split(V)
<-Z.req
u := get(U)
Z.dat <- u
if end(u) == 0 {
if end(get(VV[0])) != 0 {
put(finis, Z)
} else {
copy(Mul(VV[0], Subst(U, VV[1])), Z)
}
}
}()
return Z
}
// Monomial Substitution: U(c x^n)
// Each Ui is multiplied by c^i and followed by n-1 zeros
func MonSubst(U PS, c0 rat, n int) PS {
Z := mkPS()
go func() {
c := one
for {
<-Z.req
u := get(U)
Z.dat <- mul(u, c)
c = mul(c, c0)
if end(u) != 0 {
Z.dat <- finis
break
}
for i := 1; i < n; i++ {
<-Z.req
Z.dat <- zero
}
}
}()
return Z
}
func Init() {
chnameserial = -1
seqno = 0
chnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
zero = itor(0)
one = itor(1)
finis = i2tor(1, 0)
Ones = Rep(one)
Twos = Rep(itor(2))
}
func check(U PS, c rat, count int, str string) {
for i := 0; i < count; i++ {
r := get(U)
if !r.eq(c) {
print("got: ")
r.pr()
print("should get ")
c.pr()
print("\n")
panic(str)
}
}
}
const N = 10
func checka(U PS, a []rat, str string) {
for i := 0; i < N; i++ {
check(U, a[i], 1, str)
}
}
func main() {
Init()
if len(os.Args) > 1 { // print
print("Ones: ")
printn(Ones, 10)
print("Twos: ")
printn(Twos, 10)
print("Add: ")
printn(Add(Ones, Twos), 10)
print("Diff: ")
printn(Diff(Ones), 10)
print("Integ: ")
printn(Integ(zero, Ones), 10)
print("CMul: ")
printn(Cmul(neg(one), Ones), 10)
print("Sub: ")
printn(Sub(Ones, Twos), 10)
print("Mul: ")
printn(Mul(Ones, Ones), 10)
print("Exp: ")
printn(Exp(Ones), 15)
print("MonSubst: ")
printn(MonSubst(Ones, neg(one), 2), 10)
print("ATan: ")
printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
} else { // test
check(Ones, one, 5, "Ones")
check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
check(Add(Ones, Twos), itor(3), 0, "Add Ones Twos") // 3 3 3 3 3
a := make([]rat, N)
d := Diff(Ones)
for i := 0; i < N; i++ {
a[i] = itor(int64(i + 1))
}
checka(d, a, "Diff") // 1 2 3 4 5
in := Integ(zero, Ones)
a[0] = zero // integration constant
for i := 1; i < N; i++ {
a[i] = i2tor(1, int64(i))
}
checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
m := Mul(Ones, Ones)
for i := 0; i < N; i++ {
a[i] = itor(int64(i + 1))
}
checka(m, a, "Mul") // 1 2 3 4 5
e := Exp(Ones)
a[0] = itor(1)
a[1] = itor(1)
a[2] = i2tor(3, 2)
a[3] = i2tor(13, 6)
a[4] = i2tor(73, 24)
a[5] = i2tor(167, 40)
a[6] = i2tor(4051, 720)
a[7] = i2tor(37633, 5040)
a[8] = i2tor(43817, 4480)
a[9] = i2tor(4596553, 362880)
checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
at := Integ(zero, MonSubst(Ones, neg(one), 2))
for c, i := 1, 0; i < N; i++ {
if i%2 == 0 {
a[i] = zero
} else {
a[i] = i2tor(int64(c), int64(i))
c *= -1
}
}
checka(at, a, "ATan") // 0 -1 0 -1/3 0 -1/5
/*
t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
a[0] = zero
a[1] = itor(1)
a[2] = zero
a[3] = i2tor(1,3)
a[4] = zero
a[5] = i2tor(2,15)
a[6] = zero
a[7] = i2tor(17,315)
a[8] = zero
a[9] = i2tor(62,2835)
checka(t, a, "Tan") // 0 1 0 1/3 0 2/15
*/
}
}

755
test/chan/powser2.go Normal file
View File

@@ -0,0 +1,755 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test concurrency primitives: power series.
// Like powser1.go but uses channels of interfaces.
// Has not been cleaned up as much as powser1.go, to keep
// it distinct and therefore a different test.
// Power series package
// A power series is a channel, along which flow rational
// coefficients. A denominator of zero signifies the end.
// Original code in Newsqueak by Doug McIlroy.
// See Squinting at Power Series by Doug McIlroy,
// https://swtch.com/~rsc/thread/squint.pdf
package main
import "os"
type rat struct {
num, den int64 // numerator, denominator
}
type item interface {
pr()
eq(c item) bool
}
func (u *rat) pr() {
if u.den == 1 {
print(u.num)
} else {
print(u.num, "/", u.den)
}
print(" ")
}
func (u *rat) eq(c item) bool {
c1 := c.(*rat)
return u.num == c1.num && u.den == c1.den
}
type dch struct {
req chan int
dat chan item
nam int
}
type dch2 [2]*dch
var chnames string
var chnameserial int
var seqno int
func mkdch() *dch {
c := chnameserial % len(chnames)
chnameserial++
d := new(dch)
d.req = make(chan int)
d.dat = make(chan item)
d.nam = c
return d
}
func mkdch2() *dch2 {
d2 := new(dch2)
d2[0] = mkdch()
d2[1] = mkdch()
return d2
}
// split reads a single demand channel and replicates its
// output onto two, which may be read at different rates.
// A process is created at first demand for an item and dies
// after the item has been sent to both outputs.
// When multiple generations of split exist, the newest
// will service requests on one channel, which is
// always renamed to be out[0]; the oldest will service
// requests on the other channel, out[1]. All generations but the
// newest hold queued data that has already been sent to
// out[0]. When data has finally been sent to out[1],
// a signal on the release-wait channel tells the next newer
// generation to begin servicing out[1].
func dosplit(in *dch, out *dch2, wait chan int) {
both := false // do not service both channels
select {
case <-out[0].req:
case <-wait:
both = true
select {
case <-out[0].req:
case <-out[1].req:
out[0], out[1] = out[1], out[0]
}
}
seqno++
in.req <- seqno
release := make(chan int)
go dosplit(in, out, release)
dat := <-in.dat
out[0].dat <- dat
if !both {
<-wait
}
<-out[1].req
out[1].dat <- dat
release <- 0
}
func split(in *dch, out *dch2) {
release := make(chan int)
go dosplit(in, out, release)
release <- 0
}
func put(dat item, out *dch) {
<-out.req
out.dat <- dat
}
func get(in *dch) *rat {
seqno++
in.req <- seqno
return (<-in.dat).(*rat)
}
// Get one item from each of n demand channels
func getn(in []*dch) []item {
n := len(in)
if n != 2 {
panic("bad n in getn")
}
req := make([]chan int, 2)
dat := make([]chan item, 2)
out := make([]item, 2)
var i int
var it item
for i = 0; i < n; i++ {
req[i] = in[i].req
dat[i] = nil
}
for n = 2 * n; n > 0; n-- {
seqno++
select {
case req[0] <- seqno:
dat[0] = in[0].dat
req[0] = nil
case req[1] <- seqno:
dat[1] = in[1].dat
req[1] = nil
case it = <-dat[0]:
out[0] = it
dat[0] = nil
case it = <-dat[1]:
out[1] = it
dat[1] = nil
}
}
return out
}
// Get one item from each of 2 demand channels
func get2(in0 *dch, in1 *dch) []item {
return getn([]*dch{in0, in1})
}
func copy(in *dch, out *dch) {
for {
<-out.req
out.dat <- get(in)
}
}
func repeat(dat item, out *dch) {
for {
put(dat, out)
}
}
type PS *dch // power series
type PS2 *[2]PS // pair of power series
var Ones PS
var Twos PS
func mkPS() *dch {
return mkdch()
}
func mkPS2() *dch2 {
return mkdch2()
}
// Conventions
// Upper-case for power series.
// Lower-case for rationals.
// Input variables: U,V,...
// Output variables: ...,Y,Z
// Integer gcd; needed for rational arithmetic
func gcd(u, v int64) int64 {
if u < 0 {
return gcd(-u, v)
}
if u == 0 {
return v
}
return gcd(v%u, u)
}
// Make a rational from two ints and from one int
func i2tor(u, v int64) *rat {
g := gcd(u, v)
r := new(rat)
if v > 0 {
r.num = u / g
r.den = v / g
} else {
r.num = -u / g
r.den = -v / g
}
return r
}
func itor(u int64) *rat {
return i2tor(u, 1)
}
var zero *rat
var one *rat
// End mark and end test
var finis *rat
func end(u *rat) int64 {
if u.den == 0 {
return 1
}
return 0
}
// Operations on rationals
func add(u, v *rat) *rat {
g := gcd(u.den, v.den)
return i2tor(u.num*(v.den/g)+v.num*(u.den/g), u.den*(v.den/g))
}
func mul(u, v *rat) *rat {
g1 := gcd(u.num, v.den)
g2 := gcd(u.den, v.num)
r := new(rat)
r.num = (u.num / g1) * (v.num / g2)
r.den = (u.den / g2) * (v.den / g1)
return r
}
func neg(u *rat) *rat {
return i2tor(-u.num, u.den)
}
func sub(u, v *rat) *rat {
return add(u, neg(v))
}
func inv(u *rat) *rat { // invert a rat
if u.num == 0 {
panic("zero divide in inv")
}
return i2tor(u.den, u.num)
}
// print eval in floating point of PS at x=c to n terms
func Evaln(c *rat, U PS, n int) {
xn := float64(1)
x := float64(c.num) / float64(c.den)
val := float64(0)
for i := 0; i < n; i++ {
u := get(U)
if end(u) != 0 {
break
}
val = val + x*float64(u.num)/float64(u.den)
xn = xn * x
}
print(val, "\n")
}
// Print n terms of a power series
func Printn(U PS, n int) {
done := false
for ; !done && n > 0; n-- {
u := get(U)
if end(u) != 0 {
done = true
} else {
u.pr()
}
}
print(("\n"))
}
func Print(U PS) {
Printn(U, 1000000000)
}
// Evaluate n terms of power series U at x=c
func eval(c *rat, U PS, n int) *rat {
if n == 0 {
return zero
}
y := get(U)
if end(y) != 0 {
return zero
}
return add(y, mul(c, eval(c, U, n-1)))
}
// Power-series constructors return channels on which power
// series flow. They start an encapsulated generator that
// puts the terms of the series on the channel.
// Make a pair of power series identical to a given power series
func Split(U PS) *dch2 {
UU := mkdch2()
go split(U, UU)
return UU
}
// Add two power series
func Add(U, V PS) PS {
Z := mkPS()
go func(U, V, Z PS) {
var uv []item
for {
<-Z.req
uv = get2(U, V)
switch end(uv[0].(*rat)) + 2*end(uv[1].(*rat)) {
case 0:
Z.dat <- add(uv[0].(*rat), uv[1].(*rat))
case 1:
Z.dat <- uv[1]
copy(V, Z)
case 2:
Z.dat <- uv[0]
copy(U, Z)
case 3:
Z.dat <- finis
}
}
}(U, V, Z)
return Z
}
// Multiply a power series by a constant
func Cmul(c *rat, U PS) PS {
Z := mkPS()
go func(c *rat, U, Z PS) {
done := false
for !done {
<-Z.req
u := get(U)
if end(u) != 0 {
done = true
} else {
Z.dat <- mul(c, u)
}
}
Z.dat <- finis
}(c, U, Z)
return Z
}
// Subtract
func Sub(U, V PS) PS {
return Add(U, Cmul(neg(one), V))
}
// Multiply a power series by the monomial x^n
func Monmul(U PS, n int) PS {
Z := mkPS()
go func(n int, U PS, Z PS) {
for ; n > 0; n-- {
put(zero, Z)
}
copy(U, Z)
}(n, U, Z)
return Z
}
// Multiply by x
func Xmul(U PS) PS {
return Monmul(U, 1)
}
func Rep(c *rat) PS {
Z := mkPS()
go repeat(c, Z)
return Z
}
// Monomial c*x^n
func Mon(c *rat, n int) PS {
Z := mkPS()
go func(c *rat, n int, Z PS) {
if c.num != 0 {
for ; n > 0; n = n - 1 {
put(zero, Z)
}
put(c, Z)
}
put(finis, Z)
}(c, n, Z)
return Z
}
func Shift(c *rat, U PS) PS {
Z := mkPS()
go func(c *rat, U, Z PS) {
put(c, Z)
copy(U, Z)
}(c, U, Z)
return Z
}
// simple pole at 1: 1/(1-x) = 1 1 1 1 1 ...
// Convert array of coefficients, constant term first
// to a (finite) power series
/*
func Poly(a [] *rat) PS{
Z:=mkPS()
begin func(a [] *rat, Z PS){
j:=0
done:=0
for j=len(a); !done&&j>0; j=j-1)
if(a[j-1].num!=0) done=1
i:=0
for(; i<j; i=i+1) put(a[i],Z)
put(finis,Z)
}()
return Z
}
*/
// Multiply. The algorithm is
// let U = u + x*UU
// let V = v + x*VV
// then UV = u*v + x*(u*VV+v*UU) + x*x*UU*VV
func Mul(U, V PS) PS {
Z := mkPS()
go func(U, V, Z PS) {
<-Z.req
uv := get2(U, V)
if end(uv[0].(*rat)) != 0 || end(uv[1].(*rat)) != 0 {
Z.dat <- finis
} else {
Z.dat <- mul(uv[0].(*rat), uv[1].(*rat))
UU := Split(U)
VV := Split(V)
W := Add(Cmul(uv[0].(*rat), VV[0]), Cmul(uv[1].(*rat), UU[0]))
<-Z.req
Z.dat <- get(W)
copy(Add(W, Mul(UU[1], VV[1])), Z)
}
}(U, V, Z)
return Z
}
// Differentiate
func Diff(U PS) PS {
Z := mkPS()
go func(U, Z PS) {
<-Z.req
u := get(U)
if end(u) == 0 {
done := false
for i := 1; !done; i++ {
u = get(U)
if end(u) != 0 {
done = true
} else {
Z.dat <- mul(itor(int64(i)), u)
<-Z.req
}
}
}
Z.dat <- finis
}(U, Z)
return Z
}
// Integrate, with const of integration
func Integ(c *rat, U PS) PS {
Z := mkPS()
go func(c *rat, U, Z PS) {
put(c, Z)
done := false
for i := 1; !done; i++ {
<-Z.req
u := get(U)
if end(u) != 0 {
done = true
}
Z.dat <- mul(i2tor(1, int64(i)), u)
}
Z.dat <- finis
}(c, U, Z)
return Z
}
// Binomial theorem (1+x)^c
func Binom(c *rat) PS {
Z := mkPS()
go func(c *rat, Z PS) {
n := 1
t := itor(1)
for c.num != 0 {
put(t, Z)
t = mul(mul(t, c), i2tor(1, int64(n)))
c = sub(c, one)
n++
}
put(finis, Z)
}(c, Z)
return Z
}
// Reciprocal of a power series
// let U = u + x*UU
// let Z = z + x*ZZ
// (u+x*UU)*(z+x*ZZ) = 1
// z = 1/u
// u*ZZ + z*UU +x*UU*ZZ = 0
// ZZ = -UU*(z+x*ZZ)/u
func Recip(U PS) PS {
Z := mkPS()
go func(U, Z PS) {
ZZ := mkPS2()
<-Z.req
z := inv(get(U))
Z.dat <- z
split(Mul(Cmul(neg(z), U), Shift(z, ZZ[0])), ZZ)
copy(ZZ[1], Z)
}(U, Z)
return Z
}
// Exponential of a power series with constant term 0
// (nonzero constant term would make nonrational coefficients)
// bug: the constant term is simply ignored
// Z = exp(U)
// DZ = Z*DU
// integrate to get Z
func Exp(U PS) PS {
ZZ := mkPS2()
split(Integ(one, Mul(ZZ[0], Diff(U))), ZZ)
return ZZ[1]
}
// Substitute V for x in U, where the leading term of V is zero
// let U = u + x*UU
// let V = v + x*VV
// then S(U,V) = u + VV*S(V,UU)
// bug: a nonzero constant term is ignored
func Subst(U, V PS) PS {
Z := mkPS()
go func(U, V, Z PS) {
VV := Split(V)
<-Z.req
u := get(U)
Z.dat <- u
if end(u) == 0 {
if end(get(VV[0])) != 0 {
put(finis, Z)
} else {
copy(Mul(VV[0], Subst(U, VV[1])), Z)
}
}
}(U, V, Z)
return Z
}
// Monomial Substitution: U(c x^n)
// Each Ui is multiplied by c^i and followed by n-1 zeros
func MonSubst(U PS, c0 *rat, n int) PS {
Z := mkPS()
go func(U, Z PS, c0 *rat, n int) {
c := one
for {
<-Z.req
u := get(U)
Z.dat <- mul(u, c)
c = mul(c, c0)
if end(u) != 0 {
Z.dat <- finis
break
}
for i := 1; i < n; i++ {
<-Z.req
Z.dat <- zero
}
}
}(U, Z, c0, n)
return Z
}
func Init() {
chnameserial = -1
seqno = 0
chnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
zero = itor(0)
one = itor(1)
finis = i2tor(1, 0)
Ones = Rep(one)
Twos = Rep(itor(2))
}
func check(U PS, c *rat, count int, str string) {
for i := 0; i < count; i++ {
r := get(U)
if !r.eq(c) {
print("got: ")
r.pr()
print("should get ")
c.pr()
print("\n")
panic(str)
}
}
}
const N = 10
func checka(U PS, a []*rat, str string) {
for i := 0; i < N; i++ {
check(U, a[i], 1, str)
}
}
func main() {
Init()
if len(os.Args) > 1 { // print
print("Ones: ")
Printn(Ones, 10)
print("Twos: ")
Printn(Twos, 10)
print("Add: ")
Printn(Add(Ones, Twos), 10)
print("Diff: ")
Printn(Diff(Ones), 10)
print("Integ: ")
Printn(Integ(zero, Ones), 10)
print("CMul: ")
Printn(Cmul(neg(one), Ones), 10)
print("Sub: ")
Printn(Sub(Ones, Twos), 10)
print("Mul: ")
Printn(Mul(Ones, Ones), 10)
print("Exp: ")
Printn(Exp(Ones), 15)
print("MonSubst: ")
Printn(MonSubst(Ones, neg(one), 2), 10)
print("ATan: ")
Printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
} else { // test
check(Ones, one, 5, "Ones")
check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
check(Add(Ones, Twos), itor(3), 0, "Add Ones Twos") // 3 3 3 3 3
a := make([]*rat, N)
d := Diff(Ones)
for i := 0; i < N; i++ {
a[i] = itor(int64(i + 1))
}
checka(d, a, "Diff") // 1 2 3 4 5
in := Integ(zero, Ones)
a[0] = zero // integration constant
for i := 1; i < N; i++ {
a[i] = i2tor(1, int64(i))
}
checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
m := Mul(Ones, Ones)
for i := 0; i < N; i++ {
a[i] = itor(int64(i + 1))
}
checka(m, a, "Mul") // 1 2 3 4 5
e := Exp(Ones)
a[0] = itor(1)
a[1] = itor(1)
a[2] = i2tor(3, 2)
a[3] = i2tor(13, 6)
a[4] = i2tor(73, 24)
a[5] = i2tor(167, 40)
a[6] = i2tor(4051, 720)
a[7] = i2tor(37633, 5040)
a[8] = i2tor(43817, 4480)
a[9] = i2tor(4596553, 362880)
checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
at := Integ(zero, MonSubst(Ones, neg(one), 2))
for c, i := 1, 0; i < N; i++ {
if i%2 == 0 {
a[i] = zero
} else {
a[i] = i2tor(int64(c), int64(i))
c *= -1
}
}
checka(at, a, "ATan") // 0 -1 0 -1/3 0 -1/5
/*
t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
a[0] = zero
a[1] = itor(1)
a[2] = zero
a[3] = i2tor(1,3)
a[4] = zero
a[5] = i2tor(2,15)
a[6] = zero
a[7] = i2tor(17,315)
a[8] = zero
a[9] = i2tor(62,2835)
checka(t, a, "Tan") // 0 1 0 1/3 0 2/15
*/
}
}

58
test/chan/select.go Normal file
View File

@@ -0,0 +1,58 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test simple select.
package main
var counter uint
var shift uint
func GetValue() uint {
counter++
return 1 << shift
}
func Send(a, b chan uint) int {
var i int
LOOP:
for {
select {
case a <- GetValue():
i++
a = nil
case b <- GetValue():
i++
b = nil
default:
break LOOP
}
shift++
}
return i
}
func main() {
a := make(chan uint, 1)
b := make(chan uint, 1)
if v := Send(a, b); v != 2 {
println("Send returned", v, "!= 2")
panic("fail")
}
if av, bv := <-a, <-b; av|bv != 3 {
println("bad values", av, bv)
panic("fail")
}
if v := Send(a, nil); v != 1 {
println("Send returned", v, "!= 1")
panic("fail")
}
if counter != 10 {
println("counter is", counter, "!= 10")
panic("fail")
}
}

54
test/chan/select2.go Normal file
View File

@@ -0,0 +1,54 @@
// run
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that selects do not consume undue memory.
package main
import "runtime"
func sender(c chan int, n int) {
for i := 0; i < n; i++ {
c <- 1
}
}
func receiver(c, dummy chan int, n int) {
for i := 0; i < n; i++ {
select {
case <-c:
// nothing
case <-dummy:
panic("dummy")
}
}
}
func main() {
runtime.MemProfileRate = 0
c := make(chan int)
dummy := make(chan int)
// warm up
go sender(c, 100000)
receiver(c, dummy, 100000)
runtime.GC()
memstats := new(runtime.MemStats)
runtime.ReadMemStats(memstats)
alloc := memstats.Alloc
// second time shouldn't increase footprint by much
go sender(c, 100000)
receiver(c, dummy, 100000)
runtime.GC()
runtime.ReadMemStats(memstats)
// Be careful to avoid wraparound.
if memstats.Alloc > alloc && memstats.Alloc-alloc > 1.1e5 {
println("BUG: too much memory for 100,000 selects:", memstats.Alloc-alloc)
}
}

226
test/chan/select3.go Normal file
View File

@@ -0,0 +1,226 @@
// run
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test the semantics of the select statement
// for basic empty/non-empty cases.
package main
import "time"
const always = "function did not"
const never = "function did"
func unreachable() {
panic("control flow shouldn't reach here")
}
// Calls f and verifies that f always/never panics depending on signal.
func testPanic(signal string, f func()) {
defer func() {
s := never
if recover() != nil {
s = always // f panicked
}
if s != signal {
panic(signal + " panic")
}
}()
f()
}
// Calls f and empirically verifies that f always/never blocks depending on signal.
func testBlock(signal string, f func()) {
c := make(chan string)
go func() {
f()
c <- never // f didn't block
}()
go func() {
if signal == never {
// Wait a long time to make sure that we don't miss our window by accident on a slow machine.
time.Sleep(10 * time.Second)
} else {
// Wait as short a time as we can without false negatives.
// 10ms should be long enough to catch most failures.
time.Sleep(10 * time.Millisecond)
}
c <- always // f blocked always
}()
if <-c != signal {
panic(signal + " block")
}
}
func main() {
const async = 1 // asynchronous channels
var nilch chan int
closedch := make(chan int)
close(closedch)
// sending/receiving from a nil channel blocks
testBlock(always, func() {
nilch <- 7
})
testBlock(always, func() {
<-nilch
})
// sending/receiving from a nil channel inside a select is never selected
testPanic(never, func() {
select {
case nilch <- 7:
unreachable()
default:
}
})
testPanic(never, func() {
select {
case <-nilch:
unreachable()
default:
}
})
// sending to an async channel with free buffer space never blocks
testBlock(never, func() {
ch := make(chan int, async)
ch <- 7
})
// receiving from a closed channel never blocks
testBlock(never, func() {
for i := 0; i < 10; i++ {
if <-closedch != 0 {
panic("expected zero value when reading from closed channel")
}
if x, ok := <-closedch; x != 0 || ok {
println("closedch:", x, ok)
panic("expected 0, false from closed channel")
}
}
})
// sending to a closed channel panics.
testPanic(always, func() {
closedch <- 7
})
// receiving from a non-ready channel always blocks
testBlock(always, func() {
ch := make(chan int)
<-ch
})
// empty selects always block
testBlock(always, func() {
select {}
})
// selects with only nil channels always block
testBlock(always, func() {
select {
case <-nilch:
unreachable()
}
})
testBlock(always, func() {
select {
case nilch <- 7:
unreachable()
}
})
testBlock(always, func() {
select {
case <-nilch:
unreachable()
case nilch <- 7:
unreachable()
}
})
// selects with non-ready non-nil channels always block
testBlock(always, func() {
ch := make(chan int)
select {
case <-ch:
unreachable()
}
})
// selects with default cases don't block
testBlock(never, func() {
select {
default:
}
})
testBlock(never, func() {
select {
case <-nilch:
unreachable()
default:
}
})
testBlock(never, func() {
select {
case nilch <- 7:
unreachable()
default:
}
})
// selects with ready channels don't block
testBlock(never, func() {
ch := make(chan int, async)
select {
case ch <- 7:
default:
unreachable()
}
})
testBlock(never, func() {
ch := make(chan int, async)
ch <- 7
select {
case <-ch:
default:
unreachable()
}
})
// selects with closed channels behave like ordinary operations
testBlock(never, func() {
select {
case <-closedch:
}
})
testBlock(never, func() {
select {
case x := (<-closedch):
_ = x
}
})
testBlock(never, func() {
select {
case x, ok := (<-closedch):
_, _ = x, ok
}
})
testPanic(always, func() {
select {
case closedch <- 7:
}
})
// select should not get confused if it sees itself
testBlock(always, func() {
c := make(chan int)
select {
case c <- 1:
case <-c:
}
})
}

31
test/chan/select4.go Normal file
View File

@@ -0,0 +1,31 @@
// run
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
// Test that a select statement proceeds when a value is ready.
package main
func f() *int {
println("BUG: called f")
return new(int)
}
func main() {
var x struct {
a int
}
c := make(chan int, 1)
c1 := make(chan int)
c <- 42
select {
case *f() = <-c1:
// nothing
case x.a = <-c:
if x.a != 42 {
println("BUG:", x.a)
}
}
}

481
test/chan/select5.go Normal file
View File

@@ -0,0 +1,481 @@
// runoutput
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Generate test of channel operations and simple selects.
// The output of this program is compiled and run to do the
// actual test.
// Each test does only one real send or receive at a time, but phrased
// in various ways that the compiler may or may not rewrite
// into simpler expressions.
package main
import (
"bufio"
"fmt"
"io"
"os"
"text/template"
)
func main() {
out := bufio.NewWriter(os.Stdout)
fmt.Fprintln(out, header)
a := new(arg)
// Generate each test as a separate function to avoid
// hitting the gc optimizer with one enormous function.
// If we name all the functions init we don't have to
// maintain a list of which ones to run.
do := func(t *template.Template) {
for ; next(); a.reset() {
fmt.Fprintln(out, `func init() {`)
run(t, a, out)
fmt.Fprintln(out, `}`)
}
}
do(recv)
do(send)
do(recvOrder)
do(sendOrder)
do(nonblock)
fmt.Fprintln(out, "//", a.nreset, "cases")
out.Flush()
}
func run(t *template.Template, a interface{}, out io.Writer) {
if err := t.Execute(out, a); err != nil {
panic(err)
}
}
type arg struct {
def bool
nreset int
}
func (a *arg) Maybe() bool {
return maybe()
}
func (a *arg) MaybeDefault() bool {
if a.def {
return false
}
a.def = maybe()
return a.def
}
func (a *arg) MustDefault() bool {
return !a.def
}
func (a *arg) reset() {
a.def = false
a.nreset++
}
const header = `// GENERATED BY select5.go; DO NOT EDIT
package main
// channel is buffered so test is single-goroutine.
// we are not interested in the concurrency aspects
// of select, just testing that the right calls happen.
var c = make(chan int, 1)
var nilch chan int
var n = 1
var x int
var i interface{}
var dummy = make(chan int)
var m = make(map[int]int)
var order = 0
func f(p *int) *int {
return p
}
// check order of operations by ensuring that
// successive calls to checkorder have increasing o values.
func checkorder(o int) {
if o <= order {
println("invalid order", o, "after", order)
panic("order")
}
order = o
}
func fc(c chan int, o int) chan int {
checkorder(o)
return c
}
func fp(p *int, o int) *int {
checkorder(o)
return p
}
func fn(n, o int) int {
checkorder(o)
return n
}
func die(x int) {
println("have", x, "want", n)
panic("chan")
}
func main() {
// everything happens in init funcs
}
`
func parse(name, s string) *template.Template {
t, err := template.New(name).Parse(s)
if err != nil {
panic(fmt.Sprintf("%q: %s", name, err))
}
return t
}
var recv = parse("recv", `
{{/* Send n, receive it one way or another into x, check that they match. */}}
c <- n
{{if .Maybe}}
x = <-c
{{else}}
select {
{{/* Blocking or non-blocking, before the receive. */}}
{{/* The compiler implements two-case select where one is default with custom code, */}}
{{/* so test the default branch both before and after the send. */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Receive from c. Different cases are direct, indirect, :=, interface, and map assignment. */}}
{{if .Maybe}}
case x = <-c:
{{else}}{{if .Maybe}}
case *f(&x) = <-c:
{{else}}{{if .Maybe}}
case y := <-c:
x = y
{{else}}{{if .Maybe}}
case i = <-c:
x = i.(int)
{{else}}
case m[13] = <-c:
x = m[13]
{{end}}{{end}}{{end}}{{end}}
{{/* Blocking or non-blocking again, after the receive. */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Dummy send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case dummy <- 1:
panic("dummy send")
{{end}}
{{if .Maybe}}
case <-dummy:
panic("dummy receive")
{{end}}
{{/* Nil channel send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case nilch <- 1:
panic("nilch send")
{{end}}
{{if .Maybe}}
case <-nilch:
panic("nilch recv")
{{end}}
}
{{end}}
if x != n {
die(x)
}
n++
`)
var recvOrder = parse("recvOrder", `
{{/* Send n, receive it one way or another into x, check that they match. */}}
{{/* Check order of operations along the way by calling functions that check */}}
{{/* that the argument sequence is strictly increasing. */}}
order = 0
c <- n
{{if .Maybe}}
{{/* Outside of select, left-to-right rule applies. */}}
{{/* (Inside select, assignment waits until case is chosen, */}}
{{/* so right hand side happens before anything on left hand side. */}}
*fp(&x, 1) = <-fc(c, 2)
{{else}}{{if .Maybe}}
m[fn(13, 1)] = <-fc(c, 2)
x = m[13]
{{else}}
select {
{{/* Blocking or non-blocking, before the receive. */}}
{{/* The compiler implements two-case select where one is default with custom code, */}}
{{/* so test the default branch both before and after the send. */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Receive from c. Different cases are direct, indirect, :=, interface, and map assignment. */}}
{{if .Maybe}}
case *fp(&x, 100) = <-fc(c, 1):
{{else}}{{if .Maybe}}
case y := <-fc(c, 1):
x = y
{{else}}{{if .Maybe}}
case i = <-fc(c, 1):
x = i.(int)
{{else}}
case m[fn(13, 100)] = <-fc(c, 1):
x = m[13]
{{end}}{{end}}{{end}}
{{/* Blocking or non-blocking again, after the receive. */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Dummy send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case fc(dummy, 2) <- fn(1, 3):
panic("dummy send")
{{end}}
{{if .Maybe}}
case <-fc(dummy, 4):
panic("dummy receive")
{{end}}
{{/* Nil channel send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case fc(nilch, 5) <- fn(1, 6):
panic("nilch send")
{{end}}
{{if .Maybe}}
case <-fc(nilch, 7):
panic("nilch recv")
{{end}}
}
{{end}}{{end}}
if x != n {
die(x)
}
n++
`)
var send = parse("send", `
{{/* Send n one way or another, receive it into x, check that they match. */}}
{{if .Maybe}}
c <- n
{{else}}
select {
{{/* Blocking or non-blocking, before the receive (same reason as in recv). */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Send c <- n. No real special cases here, because no values come back */}}
{{/* from the send operation. */}}
case c <- n:
{{/* Blocking or non-blocking. */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Dummy send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case dummy <- 1:
panic("dummy send")
{{end}}
{{if .Maybe}}
case <-dummy:
panic("dummy receive")
{{end}}
{{/* Nil channel send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case nilch <- 1:
panic("nilch send")
{{end}}
{{if .Maybe}}
case <-nilch:
panic("nilch recv")
{{end}}
}
{{end}}
x = <-c
if x != n {
die(x)
}
n++
`)
var sendOrder = parse("sendOrder", `
{{/* Send n one way or another, receive it into x, check that they match. */}}
{{/* Check order of operations along the way by calling functions that check */}}
{{/* that the argument sequence is strictly increasing. */}}
order = 0
{{if .Maybe}}
fc(c, 1) <- fn(n, 2)
{{else}}
select {
{{/* Blocking or non-blocking, before the receive (same reason as in recv). */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Send c <- n. No real special cases here, because no values come back */}}
{{/* from the send operation. */}}
case fc(c, 1) <- fn(n, 2):
{{/* Blocking or non-blocking. */}}
{{if .MaybeDefault}}
default:
panic("nonblock")
{{end}}
{{/* Dummy send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case fc(dummy, 3) <- fn(1, 4):
panic("dummy send")
{{end}}
{{if .Maybe}}
case <-fc(dummy, 5):
panic("dummy receive")
{{end}}
{{/* Nil channel send, receive to keep compiler from optimizing select. */}}
{{if .Maybe}}
case fc(nilch, 6) <- fn(1, 7):
panic("nilch send")
{{end}}
{{if .Maybe}}
case <-fc(nilch, 8):
panic("nilch recv")
{{end}}
}
{{end}}
x = <-c
if x != n {
die(x)
}
n++
`)
var nonblock = parse("nonblock", `
x = n
{{/* Test various combinations of non-blocking operations. */}}
{{/* Receive assignments must not edit or even attempt to compute the address of the lhs. */}}
select {
{{if .MaybeDefault}}
default:
{{end}}
{{if .Maybe}}
case dummy <- 1:
panic("dummy <- 1")
{{end}}
{{if .Maybe}}
case nilch <- 1:
panic("nilch <- 1")
{{end}}
{{if .Maybe}}
case <-dummy:
panic("<-dummy")
{{end}}
{{if .Maybe}}
case x = <-dummy:
panic("<-dummy x")
{{end}}
{{if .Maybe}}
case **(**int)(nil) = <-dummy:
panic("<-dummy (and didn't crash saving result!)")
{{end}}
{{if .Maybe}}
case <-nilch:
panic("<-nilch")
{{end}}
{{if .Maybe}}
case x = <-nilch:
panic("<-nilch x")
{{end}}
{{if .Maybe}}
case **(**int)(nil) = <-nilch:
panic("<-nilch (and didn't crash saving result!)")
{{end}}
{{if .MustDefault}}
default:
{{end}}
}
if x != n {
die(x)
}
n++
`)
// Code for enumerating all possible paths through
// some logic. The logic should call choose(n) when
// it wants to choose between n possibilities.
// On successive runs through the logic, choose(n)
// will return 0, 1, ..., n-1. The helper maybe() is
// similar but returns true and then false.
//
// Given a function gen that generates an output
// using choose and maybe, code can generate all
// possible outputs using
//
// for next() {
// gen()
// }
type choice struct {
i, n int
}
var choices []choice
var cp int = -1
func maybe() bool {
return choose(2) == 0
}
func choose(n int) int {
if cp >= len(choices) {
// never asked this before: start with 0.
choices = append(choices, choice{0, n})
cp = len(choices)
return 0
}
// otherwise give recorded answer
if n != choices[cp].n {
panic("inconsistent choices")
}
i := choices[cp].i
cp++
return i
}
func next() bool {
if cp < 0 {
// start a new round
cp = 0
return true
}
// increment last choice sequence
cp = len(choices) - 1
for cp >= 0 && choices[cp].i == choices[cp].n-1 {
cp--
}
if cp < 0 {
choices = choices[:0]
return false
}
choices[cp].i++
choices = choices[:cp+1]
cp = 0
return true
}

34
test/chan/select6.go Normal file
View File

@@ -0,0 +1,34 @@
// run
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test for select: Issue 2075
// A bug in select corrupts channel queues of failed cases
// if there are multiple waiters on those channels and the
// select is the last in the queue. If further waits are made
// on the channel without draining it first then those waiters
// will never wake up. In the code below c1 is such a channel.
package main
func main() {
c1 := make(chan bool)
c2 := make(chan bool)
c3 := make(chan bool)
go func() { <-c1 }()
go func() {
select {
case <-c1:
panic("dummy")
case <-c2:
c3 <- true
}
<-c1
}()
go func() { c2 <- true }()
<-c3
c1 <- true
c1 <- true
}

68
test/chan/select7.go Normal file
View File

@@ -0,0 +1,68 @@
// run
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test select when discarding a value.
package main
import "runtime"
func recv1(c <-chan int) {
<-c
}
func recv2(c <-chan int) {
select {
case <-c:
}
}
func recv3(c <-chan int) {
c2 := make(chan int)
select {
case <-c:
case <-c2:
}
}
func send1(recv func(<-chan int)) {
c := make(chan int)
go recv(c)
runtime.Gosched()
c <- 1
}
func send2(recv func(<-chan int)) {
c := make(chan int)
go recv(c)
runtime.Gosched()
select {
case c <- 1:
}
}
func send3(recv func(<-chan int)) {
c := make(chan int)
go recv(c)
runtime.Gosched()
c2 := make(chan int)
select {
case c <- 1:
case c2 <- 1:
}
}
func main() {
send1(recv1)
send2(recv1)
send3(recv1)
send1(recv2)
send2(recv2)
send3(recv2)
send1(recv3)
send2(recv3)
send3(recv3)
}

55
test/chan/select8.go Normal file
View File

@@ -0,0 +1,55 @@
// run
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test break statements in a select.
// Gccgo had a bug in handling this.
// Test 1,2,3-case selects, so it covers both the general
// code path and the specialized optimizations for one-
// and two-case selects.
package main
var ch = make(chan int)
func main() {
go func() {
for {
ch <- 5
}
}()
select {
case <-ch:
break
panic("unreachable")
}
select {
default:
break
panic("unreachable")
}
select {
case <-ch:
break
panic("unreachable")
default:
break
panic("unreachable")
}
select {
case <-ch:
break
panic("unreachable")
case ch <- 10:
panic("unreachable")
default:
break
panic("unreachable")
}
}

37
test/chan/sendstmt.go Normal file
View File

@@ -0,0 +1,37 @@
// run
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test various parsing cases that are a little
// different now that send is a statement, not an expression.
package main
func main() {
chanchan()
sendprec()
}
func chanchan() {
cc := make(chan chan int, 1)
c := make(chan int, 1)
cc <- c
select {
case <-cc <- 2:
default:
panic("nonblock")
}
if <-c != 2 {
panic("bad receive")
}
}
func sendprec() {
c := make(chan bool, 1)
c <- false || true // not a syntax error: same as c <- (false || true)
if !<-c {
panic("sent false")
}
}

56
test/chan/sieve1.go Normal file
View File

@@ -0,0 +1,56 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test concurrency primitives: classical inefficient concurrent prime sieve.
// Generate primes up to 100 using channels, checking the results.
// This sieve consists of a linear chain of divisibility filters,
// equivalent to trial-dividing each n by all primes p ≤ n.
package main
// Send the sequence 2, 3, 4, ... to channel 'ch'.
func Generate(ch chan<- int) {
for i := 2; ; i++ {
ch <- i // Send 'i' to channel 'ch'.
}
}
// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in <-chan int, out chan<- int, prime int) {
for i := range in { // Loop over values received from 'in'.
if i%prime != 0 {
out <- i // Send 'i' to channel 'out'.
}
}
}
// The prime sieve: Daisy-chain Filter processes together.
func Sieve(primes chan<- int) {
ch := make(chan int) // Create a new channel.
go Generate(ch) // Start Generate() as a subprocess.
for {
// Note that ch is different on each iteration.
prime := <-ch
primes <- prime
ch1 := make(chan int)
go Filter(ch, ch1, prime)
ch = ch1
}
}
func main() {
primes := make(chan int)
go Sieve(primes)
a := []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}
for i := 0; i < len(a); i++ {
if x := <-primes; x != a[i] {
println(x, " != ", a[i])
panic("fail")
}
}
}

188
test/chan/sieve2.go Normal file
View File

@@ -0,0 +1,188 @@
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test concurrency primitives: prime sieve of Eratosthenes.
// Generate primes up to 100 using channels, checking the results.
// This sieve is Eratosthenesque and only considers odd candidates.
// See discussion at <http://blog.onideas.ws/eratosthenes.go>.
package main
import (
"container/heap"
"container/ring"
)
// Return a chan of odd numbers, starting from 5.
func odds() chan int {
out := make(chan int, 50)
go func() {
n := 5
for {
out <- n
n += 2
}
}()
return out
}
// Return a chan of odd multiples of the prime number p, starting from p*p.
func multiples(p int) chan int {
out := make(chan int, 10)
go func() {
n := p * p
for {
out <- n
n += 2 * p
}
}()
return out
}
type PeekCh struct {
head int
ch chan int
}
// Heap of PeekCh, sorting by head values, satisfies Heap interface.
type PeekChHeap []*PeekCh
func (h *PeekChHeap) Less(i, j int) bool {
return (*h)[i].head < (*h)[j].head
}
func (h *PeekChHeap) Swap(i, j int) {
(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
}
func (h *PeekChHeap) Len() int {
return len(*h)
}
func (h *PeekChHeap) Pop() (v interface{}) {
*h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1]
return
}
func (h *PeekChHeap) Push(v interface{}) {
*h = append(*h, v.(*PeekCh))
}
// Return a channel to serve as a sending proxy to 'out'.
// Use a goroutine to receive values from 'out' and store them
// in an expanding buffer, so that sending to 'out' never blocks.
func sendproxy(out chan<- int) chan<- int {
proxy := make(chan int, 10)
go func() {
n := 16 // the allocated size of the circular queue
first := ring.New(n)
last := first
var c chan<- int
var e int
for {
c = out
if first == last {
// buffer empty: disable output
c = nil
} else {
e = first.Value.(int)
}
select {
case e = <-proxy:
last.Value = e
if last.Next() == first {
// buffer full: expand it
last.Link(ring.New(n))
n *= 2
}
last = last.Next()
case c <- e:
first = first.Next()
}
}
}()
return proxy
}
// Return a chan int of primes.
func Sieve() chan int {
// The output values.
out := make(chan int, 10)
out <- 2
out <- 3
// The channel of all composites to be eliminated in increasing order.
composites := make(chan int, 50)
// The feedback loop.
primes := make(chan int, 10)
primes <- 3
// Merge channels of multiples of 'primes' into 'composites'.
go func() {
var h PeekChHeap
min := 15
for {
m := multiples(<-primes)
head := <-m
for min < head {
composites <- min
minchan := heap.Pop(&h).(*PeekCh)
min = minchan.head
minchan.head = <-minchan.ch
heap.Push(&h, minchan)
}
for min == head {
minchan := heap.Pop(&h).(*PeekCh)
min = minchan.head
minchan.head = <-minchan.ch
heap.Push(&h, minchan)
}
composites <- head
heap.Push(&h, &PeekCh{<-m, m})
}
}()
// Sieve out 'composites' from 'candidates'.
go func() {
// In order to generate the nth prime we only need multiples of
// primes ≤ sqrt(nth prime). Thus, the merging goroutine will
// receive from 'primes' much slower than this goroutine
// will send to it, making the buffer accumulate and block this
// goroutine from sending, causing a deadlock. The solution is to
// use a proxy goroutine to do automatic buffering.
primes := sendproxy(primes)
candidates := odds()
p := <-candidates
for {
c := <-composites
for p < c {
primes <- p
out <- p
p = <-candidates
}
if p == c {
p = <-candidates
}
}
}()
return out
}
func main() {
primes := Sieve()
a := []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}
for i := 0; i < len(a); i++ {
if x := <-primes; x != a[i] {
println(x, " != ", a[i])
panic("fail")
}
}
}

16
test/chan/zerosize.go Normal file
View File

@@ -0,0 +1,16 @@
// run
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test making channels of a zero-sized type.
package main
func main() {
_ = make(chan [0]byte)
_ = make(chan [0]byte, 1)
_ = make(chan struct{})
_ = make(chan struct{}, 1)
}