All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 25s
				
			Test / Hakurei (push) Successful in 44s
				
			Test / Sandbox (push) Successful in 41s
				
			Test / Hakurei (race detector) (push) Successful in 44s
				
			Test / Sandbox (race detector) (push) Successful in 41s
				
			Test / Hpkg (push) Successful in 41s
				
			Test / Flake checks (push) Successful in 1m24s
				
			Most tests already had no global state, however parallel was never enabled. This change enables it for all applicable tests. Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			175 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package message_test
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"errors"
 | |
| 	"reflect"
 | |
| 	"strconv"
 | |
| 	"syscall"
 | |
| 	"testing"
 | |
| 
 | |
| 	"hakurei.app/container/stub"
 | |
| 	"hakurei.app/message"
 | |
| )
 | |
| 
 | |
| func TestSuspendable(t *testing.T) {
 | |
| 	// copied from output.go
 | |
| 	const suspendBufMax = 1 << 24
 | |
| 	t.Parallel()
 | |
| 
 | |
| 	const (
 | |
| 		// equivalent to len(want.pt)
 | |
| 		nSpecialPtEquiv = -iota - 1
 | |
| 		// equivalent to len(want.w)
 | |
| 		nSpecialWEquiv
 | |
| 		// suspends writer before executing test case, implies nSpecialWEquiv
 | |
| 		nSpecialSuspend
 | |
| 		// offset: resume writer and measure against dump instead, implies nSpecialPtEquiv
 | |
| 		nSpecialDump
 | |
| 	)
 | |
| 
 | |
| 	// shares the same writer
 | |
| 	steps := []struct {
 | |
| 		name    string
 | |
| 		w, pt   []byte
 | |
| 		err     error
 | |
| 		wantErr error
 | |
| 		n       int
 | |
| 	}{
 | |
| 		{"simple", []byte{0xde, 0xad, 0xbe, 0xef}, []byte{0xde, 0xad, 0xbe, 0xef},
 | |
| 			nil, nil, nSpecialPtEquiv},
 | |
| 
 | |
| 		{"error", []byte{0xb, 0xad}, []byte{0xb, 0xad},
 | |
| 			stub.UniqueError(0), stub.UniqueError(0), nSpecialPtEquiv},
 | |
| 
 | |
| 		{"suspend short", []byte{0}, nil,
 | |
| 			nil, nil, nSpecialSuspend},
 | |
| 		{"sw short 0", []byte{0xca, 0xfe, 0xba, 0xbe}, nil,
 | |
| 			nil, nil, nSpecialWEquiv},
 | |
| 		{"sw short 1", []byte{0xff}, nil,
 | |
| 			nil, nil, nSpecialWEquiv},
 | |
| 		{"resume short", nil, []byte{0, 0xca, 0xfe, 0xba, 0xbe, 0xff}, nil, nil,
 | |
| 			nSpecialDump},
 | |
| 
 | |
| 		{"long pt", bytes.Repeat([]byte{0xff}, suspendBufMax+1), bytes.Repeat([]byte{0xff}, suspendBufMax+1),
 | |
| 			nil, nil, nSpecialPtEquiv},
 | |
| 
 | |
| 		{"suspend fill", bytes.Repeat([]byte{0xfe}, suspendBufMax), nil,
 | |
| 			nil, nil, nSpecialSuspend},
 | |
| 		{"drop", []byte{0}, nil,
 | |
| 			nil, syscall.ENOMEM, 0},
 | |
| 		{"drop error", []byte{0}, nil,
 | |
| 			stub.UniqueError(1), syscall.ENOMEM, 0},
 | |
| 		{"resume fill", nil, bytes.Repeat([]byte{0xfe}, suspendBufMax),
 | |
| 			nil, nil, nSpecialDump - 2},
 | |
| 
 | |
| 		{"suspend fill partial", bytes.Repeat([]byte{0xfd}, suspendBufMax-0xf), nil,
 | |
| 			nil, nil, nSpecialSuspend},
 | |
| 		{"partial write", bytes.Repeat([]byte{0xad}, 0x1f), nil,
 | |
| 			nil, syscall.ENOMEM, 0xf},
 | |
| 		{"full drop", []byte{0}, nil,
 | |
| 			nil, syscall.ENOMEM, 0},
 | |
| 		{"resume fill partial", nil, append(bytes.Repeat([]byte{0xfd}, suspendBufMax-0xf), bytes.Repeat([]byte{0xad}, 0xf)...),
 | |
| 			nil, nil, nSpecialDump - 0x10 - 1},
 | |
| 	}
 | |
| 
 | |
| 	var dw expectWriter
 | |
| 
 | |
| 	w := message.Suspendable{Downstream: &dw}
 | |
| 	for _, step := range steps {
 | |
| 		// these share the same writer, so cannot be subtests
 | |
| 		t.Logf("writing step %q", step.name)
 | |
| 		dw.expect, dw.err = step.pt, step.err
 | |
| 
 | |
| 		var (
 | |
| 			gotN   int
 | |
| 			gotErr error
 | |
| 		)
 | |
| 
 | |
| 		wantN := step.n
 | |
| 		switch wantN {
 | |
| 		case nSpecialPtEquiv:
 | |
| 			wantN = len(step.pt)
 | |
| 			gotN, gotErr = w.Write(step.w)
 | |
| 
 | |
| 		case nSpecialWEquiv:
 | |
| 			wantN = len(step.w)
 | |
| 			gotN, gotErr = w.Write(step.w)
 | |
| 
 | |
| 		case nSpecialSuspend:
 | |
| 			s := w.IsSuspended()
 | |
| 			if ok := w.Suspend(); s && ok {
 | |
| 				t.Fatal("Suspend: unexpected success")
 | |
| 			}
 | |
| 
 | |
| 			wantN = len(step.w)
 | |
| 			gotN, gotErr = w.Write(step.w)
 | |
| 
 | |
| 		default:
 | |
| 			if wantN <= nSpecialDump {
 | |
| 				if !w.IsSuspended() {
 | |
| 					t.Fatal("IsSuspended unexpected false")
 | |
| 				}
 | |
| 
 | |
| 				resumed, dropped, n, err := w.Resume()
 | |
| 				if !resumed {
 | |
| 					t.Fatal("Resume: resumed = false")
 | |
| 				}
 | |
| 				if wantDropped := nSpecialDump - wantN; int(dropped) != wantDropped {
 | |
| 					t.Errorf("Resume: dropped = %d, want %d", dropped, wantDropped)
 | |
| 				}
 | |
| 
 | |
| 				wantN = len(step.pt)
 | |
| 				gotN, gotErr = int(n), err
 | |
| 			} else {
 | |
| 				gotN, gotErr = w.Write(step.w)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if gotN != wantN {
 | |
| 			t.Errorf("Write: n = %d, want %d", gotN, wantN)
 | |
| 		}
 | |
| 
 | |
| 		if !reflect.DeepEqual(gotErr, step.wantErr) {
 | |
| 			t.Errorf("Write: %v", gotErr)
 | |
| 		}
 | |
| 
 | |
| 		if dw.expect != nil {
 | |
| 			t.Errorf("expect: %q", string(dw.expect))
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // expectWriter compares Write calls to expect.
 | |
| type expectWriter struct {
 | |
| 	expect []byte
 | |
| 	err    error
 | |
| 
 | |
| 	// optional consecutive write
 | |
| 	next []byte
 | |
| 
 | |
| 	// optional, calls Error on failure if not nil
 | |
| 	t *testing.T
 | |
| }
 | |
| 
 | |
| func (w *expectWriter) Write(p []byte) (n int, err error) {
 | |
| 	defer func() { w.expect = w.next; w.next = nil }()
 | |
| 
 | |
| 	n, err = len(p), w.err
 | |
| 	if w.expect == nil {
 | |
| 		n, err = 0, errors.New("unexpected call to Write: "+strconv.Quote(string(p)))
 | |
| 		if w.t != nil {
 | |
| 			w.t.Error(err.Error())
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 	if string(p) != string(w.expect) {
 | |
| 		n, err = 0, errors.New("p = "+strconv.Quote(string(p))+", want "+strconv.Quote(string(w.expect)))
 | |
| 		if w.t != nil {
 | |
| 			w.t.Error(err.Error())
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 	return
 | |
| }
 |