github.com/SaurabhDubey-Groww/go-cloud@v0.0.0-20221124105541-b26c29285fd8/runtimevar/blobvar/blobvar_test.go (about) 1 // Copyright 2019 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package blobvar 16 17 import ( 18 "context" 19 "errors" 20 "io/ioutil" 21 "net/url" 22 "os" 23 "path" 24 "path/filepath" 25 "strings" 26 "testing" 27 28 "github.com/google/go-cmp/cmp" 29 "gocloud.dev/blob" 30 "gocloud.dev/blob/fileblob" 31 "gocloud.dev/runtimevar" 32 "gocloud.dev/runtimevar/driver" 33 "gocloud.dev/runtimevar/drivertest" 34 ) 35 36 type harness struct { 37 dir string 38 bucket *blob.Bucket 39 } 40 41 func newHarness(t *testing.T) (drivertest.Harness, error) { 42 dir := path.Join(os.TempDir(), "go-cloud-blobvar") 43 if err := os.MkdirAll(dir, os.ModePerm); err != nil { 44 return nil, err 45 } 46 b, err := fileblob.OpenBucket(dir, nil) 47 if err != nil { 48 return nil, err 49 } 50 return &harness{dir: dir, bucket: b}, nil 51 } 52 53 func (h *harness) MakeWatcher(ctx context.Context, name string, decoder *runtimevar.Decoder) (driver.Watcher, error) { 54 return newWatcher(h.bucket, name, decoder, nil, nil), nil 55 } 56 57 func (h *harness) CreateVariable(ctx context.Context, name string, val []byte) error { 58 return h.bucket.WriteAll(ctx, name, val, nil) 59 } 60 61 func (h *harness) UpdateVariable(ctx context.Context, name string, val []byte) error { 62 return h.bucket.WriteAll(ctx, name, val, nil) 63 } 64 65 func (h *harness) DeleteVariable(ctx context.Context, name string) error { 66 return h.bucket.Delete(ctx, name) 67 } 68 69 func (h *harness) Close() { 70 h.bucket.Close() 71 _ = os.RemoveAll(h.dir) 72 } 73 74 func (h *harness) Mutable() bool { return true } 75 76 func TestConformance(t *testing.T) { 77 drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{}}) 78 } 79 80 type verifyAs struct{} 81 82 func (verifyAs) Name() string { 83 return "verify As" 84 } 85 86 func (verifyAs) SnapshotCheck(s *runtimevar.Snapshot) error { 87 return nil 88 } 89 90 func (verifyAs) ErrorCheck(v *runtimevar.Variable, err error) error { 91 var perr *os.PathError 92 if !v.ErrorAs(err, &perr) { 93 return errors.New("runtimevar.ErrorAs failed with *os.PathError") 94 } 95 return nil 96 } 97 98 func TestOpenVariable(t *testing.T) { 99 dir, err := ioutil.TempDir("", "gcdk-blob-var-example") 100 if err != nil { 101 t.Fatal(err) 102 } 103 if err := ioutil.WriteFile(filepath.Join(dir, "myvar.json"), []byte(`{"Foo": "Bar"}`), 0666); err != nil { 104 t.Fatal(err) 105 } 106 if err := ioutil.WriteFile(filepath.Join(dir, "myvar.txt"), []byte("hello world!"), 0666); err != nil { 107 t.Fatal(err) 108 } 109 defer os.RemoveAll(dir) 110 111 // Convert dir to a URL path, adding a leading "/" if needed on Windows 112 // (on Unix, dirpath already has a leading "/"). 113 dirpath := filepath.ToSlash(dir) 114 if os.PathSeparator != '/' && !strings.HasPrefix(dirpath, "/") { 115 dirpath = "/" + dirpath 116 } 117 bucketURL := "file://" + dirpath 118 119 tests := []struct { 120 BucketURL string 121 URL string 122 WantErr bool 123 WantWatchErr bool 124 Want interface{} 125 }{ 126 // myvar does not exist. 127 {"mem://", "blob://myvar", false, true, nil}, 128 // badscheme does not exist. 129 {"badscheme://", "blob://myvar", true, false, nil}, 130 // directory dirnotfound does not exist, so Bucket creation fails. 131 {"file:///dirnotfound", "blob://myvar.txt", true, false, nil}, 132 // filenotfound does not exist so Watch returns an error. 133 {bucketURL, "blob://filenotfound", false, true, nil}, 134 // Missing bucket env variable. 135 {"", "blob://myvar.txt", true, false, nil}, 136 // Invalid decoder. 137 {bucketURL, "blob://myvar.txt?decoder=notadecoder", true, false, nil}, 138 // Invalid arg. 139 {bucketURL, "blob://myvar.txt?param=value", true, false, nil}, 140 // Working example with default decoder. 141 {bucketURL, "blob://myvar.txt", false, false, []byte("hello world!")}, 142 // Working example with string decoder. 143 {bucketURL, "blob://myvar.txt?decoder=string", false, false, "hello world!"}, 144 // Working example with JSON decoder. 145 {bucketURL, "blob://myvar.json?decoder=jsonmap", false, false, &map[string]interface{}{"Foo": "Bar"}}, 146 // Setting wait. 147 {bucketURL, "blob://myvar.txt?wait=2m", false, false, []byte("hello world!")}, 148 // Invalid wait. 149 {bucketURL, "blob://myvar.txt?wait=x", true, false, nil}, 150 } 151 152 ctx := context.Background() 153 for _, test := range tests { 154 t.Run(test.BucketURL, func(t *testing.T) { 155 os.Setenv("BLOBVAR_BUCKET_URL", test.BucketURL) 156 157 opener := &defaultOpener{} 158 defer func() { 159 if opener.opener != nil && opener.opener.Bucket != nil { 160 opener.opener.Bucket.Close() 161 } 162 }() 163 u, err := url.Parse(test.URL) 164 if err != nil { 165 t.Error(err) 166 } 167 v, err := opener.OpenVariableURL(ctx, u) 168 if v != nil { 169 defer v.Close() 170 } 171 if (err != nil) != test.WantErr { 172 t.Errorf("BucketURL %s URL %s: got error %v, want error %v", test.BucketURL, test.URL, err, test.WantErr) 173 } 174 if err != nil { 175 return 176 } 177 defer v.Close() 178 snapshot, err := v.Watch(ctx) 179 if (err != nil) != test.WantWatchErr { 180 t.Errorf("BucketURL %s URL %s: got Watch error %v, want error %v", test.BucketURL, test.URL, err, test.WantWatchErr) 181 } 182 if err != nil { 183 return 184 } 185 if !cmp.Equal(snapshot.Value, test.Want) { 186 t.Errorf("BucketURL %s URL %s: got snapshot value\n%v\n want\n%v", test.BucketURL, test.URL, snapshot.Value, test.Want) 187 } 188 }) 189 } 190 }