mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-14 11:17:52 +08:00
110 lines
1.9 KiB
Go
110 lines
1.9 KiB
Go
package edit
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/elves/elvish/sys"
|
|
)
|
|
|
|
// Pretty arbitrary numbers. May not reveal deadlocks on all machines.
|
|
|
|
var (
|
|
DeadlockNWrite = 1024
|
|
DeadlockRun = 64
|
|
DeadlockTimeout = 500 * time.Millisecond
|
|
DeadlockMaxJitter = time.Millisecond
|
|
)
|
|
|
|
func jitter() {
|
|
time.Sleep(time.Duration(float64(DeadlockMaxJitter) * rand.Float64()))
|
|
}
|
|
|
|
func f(done chan struct{}) {
|
|
r, w, err := os.Pipe()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer r.Close()
|
|
defer w.Close()
|
|
|
|
ar := NewAsyncReader(r)
|
|
defer ar.Close()
|
|
fmt.Fprintf(w, "%*s", DeadlockNWrite, "")
|
|
go func() {
|
|
jitter()
|
|
ar.Run()
|
|
}()
|
|
jitter()
|
|
ar.Quit()
|
|
done <- struct{}{}
|
|
}
|
|
|
|
func TestAsyncReaderDeadlock(t *testing.T) {
|
|
done := make(chan struct{})
|
|
isatty := sys.IsATTY(1)
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
|
|
timer := time.NewTimer(DeadlockTimeout)
|
|
for i := 0; i < DeadlockRun; i++ {
|
|
if isatty {
|
|
fmt.Printf("\r%d/%d ", i+1, DeadlockRun)
|
|
}
|
|
|
|
go f(done)
|
|
|
|
select {
|
|
case <-done:
|
|
// no deadlock trigerred
|
|
case <-timer.C:
|
|
// deadlock
|
|
t.Errorf("%s", sys.DumpStack())
|
|
t.Fatalf("AsyncReader deadlock trigerred on run %d/%d, stack trace:\n%s", i, DeadlockRun, sys.DumpStack())
|
|
}
|
|
timer.Reset(DeadlockTimeout)
|
|
}
|
|
if isatty {
|
|
fmt.Print("\r \r")
|
|
}
|
|
}
|
|
|
|
var ReadTimeout = time.Second
|
|
|
|
func TestAsyncReader(t *testing.T) {
|
|
r, w, err := os.Pipe()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer r.Close()
|
|
defer w.Close()
|
|
|
|
ar := NewAsyncReader(r)
|
|
defer ar.Close()
|
|
go ar.Run()
|
|
|
|
go func() {
|
|
var i rune
|
|
for i = 0; i <= 1280; i += 10 {
|
|
w.WriteString(string(i))
|
|
}
|
|
}()
|
|
|
|
var i rune
|
|
timer := time.NewTimer(ReadTimeout)
|
|
for i = 0; i <= 1280; i += 10 {
|
|
select {
|
|
case r := <-ar.Chan():
|
|
if r != i {
|
|
t.Fatalf("expect %q, got %q\n", i, r)
|
|
}
|
|
case <-timer.C:
|
|
t.Fatalf("read timeout (i = %d)", i)
|
|
}
|
|
timer.Reset(ReadTimeout)
|
|
}
|
|
ar.Quit()
|
|
}
|