github.com/kubri/kubri@v0.5.1-0.20240317001612-bda2aaef967e/internal/test/target.go (about) 1 package test 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 "io/fs" 8 "testing" 9 "time" 10 11 "github.com/google/go-cmp/cmp" 12 13 "github.com/kubri/kubri/target" 14 ) 15 16 type targetOptions struct { 17 delay time.Duration 18 ignoreRemoveNotFound bool 19 } 20 21 type TargetOption func(*targetOptions) 22 23 // WithDelay adds a delay between writing, updating & reading, to allow for 24 // services where the changes aren't available instantly. 25 func WithDelay(d time.Duration) TargetOption { 26 return func(opts *targetOptions) { 27 opts.delay = d 28 } 29 } 30 31 // WithIgnoreRemoveNotFound disables testing if removing a non-existent file 32 // returns an error. 33 func WithIgnoreRemoveNotFound() TargetOption { 34 return func(opts *targetOptions) { 35 opts.ignoreRemoveNotFound = true 36 } 37 } 38 39 //nolint:funlen,gocognit 40 func Target(t *testing.T, tgt target.Target, makeURL func(string) string, opt ...TargetOption) { 41 t.Helper() 42 43 opts := &targetOptions{} 44 for _, o := range opt { 45 o(opts) 46 } 47 48 ctx := context.Background() 49 data := []byte("test") 50 51 t.Run("NewWriter_Create", func(t *testing.T) { 52 t.Helper() 53 54 w, err := tgt.NewWriter(ctx, "path/to/file") 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 if _, err = w.Write([]byte("foo")); err != nil { 60 t.Fatal(err) 61 } 62 63 if err = w.Close(); err != nil { 64 t.Fatal(err) 65 } 66 }) 67 68 time.Sleep(opts.delay) 69 70 t.Run("NewWriter_Update", func(t *testing.T) { 71 t.Helper() 72 73 w, err := tgt.NewWriter(ctx, "path/to/file") 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 if _, err = w.Write(data); err != nil { 79 t.Fatal(err) 80 } 81 82 if err = w.Close(); err != nil { 83 t.Fatal(err) 84 } 85 }) 86 87 time.Sleep(opts.delay) 88 89 t.Run("NewReader", func(t *testing.T) { 90 t.Helper() 91 92 r, err := tgt.NewReader(ctx, "path/to/file") 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 got, err := io.ReadAll(r) 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 if err = r.Close(); err != nil { 103 t.Fatal(err) 104 } 105 106 if diff := cmp.Diff(data, got); diff != "" { 107 t.Fatal(diff) 108 } 109 110 _, err = tgt.NewReader(ctx, "does/not/exist") 111 if !errors.Is(err, fs.ErrNotExist) { 112 t.Fatalf("Should return %q - got %q", fs.ErrNotExist, err) 113 } 114 }) 115 116 t.Run("Sub", func(t *testing.T) { 117 t.Helper() 118 119 sub := tgt.Sub("path/to") 120 121 r, err := sub.NewReader(ctx, "file") 122 if err != nil { 123 t.Fatal(err) 124 } else { 125 r.Close() 126 } 127 }) 128 129 t.Run("URL", func(t *testing.T) { 130 t.Helper() 131 132 url, err := tgt.URL(ctx, "path/to/file") 133 if err != nil { 134 t.Fatal(err) 135 } 136 137 if diff := cmp.Diff(makeURL("path/to/file"), url); diff != "" { 138 t.Fatal(diff) 139 } 140 }) 141 142 t.Run("Remove", func(t *testing.T) { 143 t.Helper() 144 145 err := tgt.Remove(ctx, "path/to/file") 146 if err != nil { 147 t.Fatal(err) 148 } 149 150 time.Sleep(opts.delay) 151 152 r, err := tgt.NewReader(ctx, "path/to/file") 153 if err == nil { 154 r.Close() 155 } 156 if !errors.Is(err, fs.ErrNotExist) { 157 t.Fatalf("Read should return %q - got %q", fs.ErrNotExist, err) 158 } 159 160 if !opts.ignoreRemoveNotFound { 161 err = tgt.Remove(ctx, "does/not/exist") 162 if !errors.Is(err, fs.ErrNotExist) { 163 t.Fatalf("Remove should return %q - got %q", fs.ErrNotExist, err) 164 } 165 } 166 }) 167 }