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