github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/edit/async_reader_test.go (about)

     1  package edit
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"os"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/elves/elvish/sys"
    11  )
    12  
    13  // Pretty arbitrary numbers. May not reveal deadlocks on all machines.
    14  
    15  var (
    16  	DeadlockNWrite    = 1024
    17  	DeadlockRun       = 64
    18  	DeadlockTimeout   = 500 * time.Millisecond
    19  	DeadlockMaxJitter = time.Millisecond
    20  )
    21  
    22  func jitter() {
    23  	time.Sleep(time.Duration(float64(DeadlockMaxJitter) * rand.Float64()))
    24  }
    25  
    26  func f(done chan struct{}) {
    27  	r, w, err := os.Pipe()
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  	defer r.Close()
    32  	defer w.Close()
    33  
    34  	ar := NewAsyncReader(r)
    35  	defer ar.Close()
    36  	fmt.Fprintf(w, "%*s", DeadlockNWrite, "")
    37  	go func() {
    38  		jitter()
    39  		ar.Run()
    40  	}()
    41  	jitter()
    42  	ar.Quit()
    43  	done <- struct{}{}
    44  }
    45  
    46  func TestAsyncReaderDeadlock(t *testing.T) {
    47  	done := make(chan struct{})
    48  	isatty := sys.IsATTY(1)
    49  	rand.Seed(time.Now().UTC().UnixNano())
    50  
    51  	timer := time.NewTimer(DeadlockTimeout)
    52  	for i := 0; i < DeadlockRun; i++ {
    53  		if isatty {
    54  			fmt.Printf("\r%d/%d ", i+1, DeadlockRun)
    55  		}
    56  
    57  		go f(done)
    58  
    59  		select {
    60  		case <-done:
    61  			// no deadlock trigerred
    62  		case <-timer.C:
    63  			// deadlock
    64  			t.Errorf("%s", sys.DumpStack())
    65  			t.Fatalf("AsyncReader deadlock trigerred on run %d/%d, stack trace:\n%s", i, DeadlockRun, sys.DumpStack())
    66  		}
    67  		timer.Reset(DeadlockTimeout)
    68  	}
    69  	if isatty {
    70  		fmt.Print("\r       \r")
    71  	}
    72  }
    73  
    74  var ReadTimeout = time.Second
    75  
    76  func TestAsyncReader(t *testing.T) {
    77  	r, w, err := os.Pipe()
    78  	if err != nil {
    79  		panic(err)
    80  	}
    81  	defer r.Close()
    82  	defer w.Close()
    83  
    84  	ar := NewAsyncReader(r)
    85  	defer ar.Close()
    86  	go ar.Run()
    87  
    88  	go func() {
    89  		var i rune
    90  		for i = 0; i <= 1280; i += 10 {
    91  			w.WriteString(string(i))
    92  		}
    93  	}()
    94  
    95  	var i rune
    96  	timer := time.NewTimer(ReadTimeout)
    97  	for i = 0; i <= 1280; i += 10 {
    98  		select {
    99  		case r := <-ar.Chan():
   100  			if r != i {
   101  				t.Fatalf("expect %q, got %q\n", i, r)
   102  			}
   103  		case <-timer.C:
   104  			t.Fatalf("read timeout (i = %d)", i)
   105  		}
   106  		timer.Reset(ReadTimeout)
   107  	}
   108  	ar.Quit()
   109  }