1package getter 2 3import ( 4 "bytes" 5 "context" 6 "io" 7 "testing" 8 "time" 9) 10 11// OneDoneContext is a context that is 12// cancelled after a first done is called. 13type OneDoneContext bool 14 15func (*OneDoneContext) Deadline() (deadline time.Time, ok bool) { return } 16func (*OneDoneContext) Value(key interface{}) interface{} { return nil } 17 18func (o *OneDoneContext) Err() error { 19 if *o == false { 20 return nil 21 } 22 return context.Canceled 23} 24 25func (o *OneDoneContext) Done() <-chan struct{} { 26 if *o == false { 27 *o = true 28 return nil 29 } 30 c := make(chan struct{}) 31 close(c) 32 return c 33} 34 35func (o *OneDoneContext) String() string { 36 if *o { 37 return "done OneDoneContext" 38 } 39 return "OneDoneContext" 40} 41 42func TestCopy(t *testing.T) { 43 const text3lines = `line1 44 line2 45 line3 46 ` 47 48 cancelledContext, cancel := context.WithCancel(context.Background()) 49 _ = cancelledContext 50 cancel() 51 type args struct { 52 ctx context.Context 53 src io.Reader 54 } 55 tests := []struct { 56 name string 57 args args 58 want int64 59 wantDst string 60 wantErr error 61 }{ 62 {"read all", args{context.Background(), bytes.NewBufferString(text3lines)}, int64(len(text3lines)), text3lines, nil}, 63 {"read none", args{cancelledContext, bytes.NewBufferString(text3lines)}, 0, "", context.Canceled}, 64 {"cancel after read", args{new(OneDoneContext), bytes.NewBufferString(text3lines)}, int64(len(text3lines)), text3lines, context.Canceled}, 65 } 66 for _, tt := range tests { 67 t.Run(tt.name, func(t *testing.T) { 68 dst := &bytes.Buffer{} 69 got, err := Copy(tt.args.ctx, dst, tt.args.src) 70 if err != tt.wantErr { 71 t.Errorf("Copy() error = %v, wantErr %v", err, tt.wantErr) 72 return 73 } 74 if got != tt.want { 75 t.Errorf("Copy() = %v, want %v", got, tt.want) 76 } 77 if gotDst := dst.String(); gotDst != tt.wantDst { 78 t.Errorf("Copy() = %v, want %v", gotDst, tt.wantDst) 79 } 80 }) 81 } 82} 83