mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 14:48:40 +00:00
9fd1b7b1a8
Since we switched to OS threads for goroutines, the testdata/goroutines.go test has been flaky. Not surprising, if threads need to be scheduled within 1ms on a busy CI system. This PR makes the test a bit less flaky (hopefully) by increasing the time to 100ms.
226 lines
4.0 KiB
Go
226 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
func init() {
|
|
println("init")
|
|
go println("goroutine in init")
|
|
time.Sleep(1 * time.Millisecond)
|
|
}
|
|
|
|
func main() {
|
|
println("main 1")
|
|
go sub()
|
|
time.Sleep(100 * time.Millisecond)
|
|
println("main 2")
|
|
time.Sleep(200 * time.Millisecond)
|
|
println("main 3")
|
|
|
|
// Await a blocking call.
|
|
println("wait:")
|
|
wait()
|
|
println("end waiting")
|
|
|
|
value := delayedValue()
|
|
println("value produced after some time:", value)
|
|
|
|
// Run a non-blocking call in a goroutine. This should be turned into a
|
|
// regular call, so should be equivalent to calling nowait() without 'go'
|
|
// prefix.
|
|
go nowait()
|
|
time.Sleep(time.Millisecond)
|
|
println("done with non-blocking goroutine")
|
|
|
|
var printer Printer
|
|
printer = &myPrinter{}
|
|
printer.Print()
|
|
|
|
sleepFuncValue(func(x int) {
|
|
time.Sleep(1 * time.Millisecond)
|
|
println("slept inside func pointer", x)
|
|
})
|
|
time.Sleep(1 * time.Millisecond)
|
|
n := 20
|
|
sleepFuncValue(func(x int) {
|
|
time.Sleep(1 * time.Millisecond)
|
|
println("slept inside closure, with value:", n, x)
|
|
})
|
|
|
|
time.Sleep(2 * time.Millisecond)
|
|
|
|
var x int
|
|
go func() {
|
|
time.Sleep(2 * time.Millisecond)
|
|
x = 1
|
|
}()
|
|
time.Sleep(time.Second / 2)
|
|
println("closure go call result:", x)
|
|
|
|
time.Sleep(2 * time.Millisecond)
|
|
|
|
var m sync.Mutex
|
|
var wg sync.WaitGroup
|
|
m.Lock()
|
|
println("pre-acquired mutex")
|
|
wg.Add(1)
|
|
go acquire(&m, &wg)
|
|
time.Sleep(2 * time.Millisecond)
|
|
println("releasing mutex")
|
|
m.Unlock()
|
|
wg.Wait()
|
|
time.Sleep(2 * time.Millisecond)
|
|
m.Lock()
|
|
println("re-acquired mutex")
|
|
m.Unlock()
|
|
println("done")
|
|
|
|
startSimpleFunc(emptyFunc)
|
|
|
|
time.Sleep(2 * time.Millisecond)
|
|
|
|
testGoOnBuiltins()
|
|
|
|
testGoOnInterface(Foo(0))
|
|
|
|
testIssue1790()
|
|
|
|
done := make(chan int)
|
|
go testPaddedParameters(paddedStruct{x: 5, y: 7}, done)
|
|
<-done
|
|
}
|
|
|
|
func acquire(m *sync.Mutex, wg *sync.WaitGroup) {
|
|
m.Lock()
|
|
wg.Done()
|
|
println("acquired mutex from goroutine")
|
|
time.Sleep(2 * time.Millisecond)
|
|
println("releasing mutex from goroutine")
|
|
m.Unlock()
|
|
}
|
|
|
|
func sub() {
|
|
println("sub 1")
|
|
time.Sleep(200 * time.Millisecond)
|
|
println("sub 2")
|
|
}
|
|
|
|
func wait() {
|
|
println(" wait start")
|
|
time.Sleep(time.Millisecond)
|
|
println(" wait end")
|
|
}
|
|
|
|
func delayedValue() int {
|
|
time.Sleep(time.Millisecond)
|
|
return 42
|
|
}
|
|
|
|
func sleepFuncValue(fn func(int)) {
|
|
go fn(8)
|
|
}
|
|
|
|
func startSimpleFunc(fn simpleFunc) {
|
|
// Test that named function types don't crash the compiler.
|
|
go fn()
|
|
}
|
|
|
|
func nowait() {
|
|
println("non-blocking goroutine")
|
|
}
|
|
|
|
type Printer interface {
|
|
Print()
|
|
}
|
|
|
|
type myPrinter struct {
|
|
}
|
|
|
|
func (i *myPrinter) Print() {
|
|
time.Sleep(time.Millisecond)
|
|
println("async interface method call")
|
|
}
|
|
|
|
type simpleFunc func()
|
|
|
|
func emptyFunc() {
|
|
}
|
|
|
|
func testGoOnBuiltins() {
|
|
// Test copy builtin (there is no non-racy practical use of this).
|
|
go copy(make([]int, 8), []int{2, 5, 8, 4})
|
|
|
|
// Test recover builtin (no-op).
|
|
go recover()
|
|
|
|
// Test close builtin.
|
|
ch := make(chan int)
|
|
go close(ch)
|
|
n, ok := <-ch
|
|
if n != 0 || ok != false {
|
|
println("error: expected closed channel to return 0, false")
|
|
}
|
|
|
|
// Test delete builtin.
|
|
m := map[string]int{"foo": 3}
|
|
go delete(m, "foo")
|
|
time.Sleep(time.Millisecond)
|
|
v, ok := m["foo"]
|
|
if v != 0 || ok != false {
|
|
println("error: expected deleted map entry to be 0, false")
|
|
}
|
|
}
|
|
|
|
var once sync.Once
|
|
|
|
var waitChan = make(chan struct{})
|
|
|
|
func testGoOnInterface(f Itf) {
|
|
go f.Nowait()
|
|
time.Sleep(time.Millisecond)
|
|
go f.Wait()
|
|
<-waitChan
|
|
time.Sleep(time.Millisecond * 2)
|
|
println("done with 'go on interface'")
|
|
}
|
|
|
|
// This tests a fix for issue 1790:
|
|
// https://github.com/tinygo-org/tinygo/issues/1790
|
|
func testIssue1790() *int {
|
|
once.Do(func() {})
|
|
i := 0
|
|
return &i
|
|
}
|
|
|
|
type Itf interface {
|
|
Nowait()
|
|
Wait()
|
|
}
|
|
|
|
type Foo string
|
|
|
|
func (f Foo) Nowait() {
|
|
println("called: Foo.Nowait")
|
|
}
|
|
|
|
func (f Foo) Wait() {
|
|
println("called: Foo.Wait")
|
|
close(waitChan)
|
|
time.Sleep(time.Microsecond)
|
|
println(" ...waited")
|
|
}
|
|
|
|
type paddedStruct struct {
|
|
x uint8
|
|
_ [0]int64
|
|
y uint8
|
|
}
|
|
|
|
// Structs with interesting padding used to crash.
|
|
func testPaddedParameters(s paddedStruct, done chan int) {
|
|
println("paddedStruct:", s.x, s.y)
|
|
close(done)
|
|
}
|