github.com/thiagoyeds/go-cloud@v0.26.0/runtimevar/constantvar/constantvar_test.go (about) 1 // Copyright 2018 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 constantvar 16 17 import ( 18 "context" 19 "errors" 20 "testing" 21 "time" 22 23 "github.com/google/go-cmp/cmp" 24 "gocloud.dev/runtimevar" 25 "gocloud.dev/runtimevar/driver" 26 "gocloud.dev/runtimevar/drivertest" 27 ) 28 29 type harness struct { 30 // vars stores the variable value(s) that have been set using CreateVariable. 31 vars map[string][]byte 32 } 33 34 func newHarness(t *testing.T) (drivertest.Harness, error) { 35 return &harness{vars: map[string][]byte{}}, nil 36 } 37 38 func (h *harness) MakeWatcher(ctx context.Context, name string, decoder *runtimevar.Decoder) (driver.Watcher, error) { 39 rawVal, found := h.vars[name] 40 if !found { 41 // The variable isn't set. Create a Variable that always returns an error. 42 return &watcher{err: errNotExist}, nil 43 } 44 val, err := decoder.Decode(ctx, rawVal) 45 if err != nil { 46 // The variable didn't decode. 47 return &watcher{err: err}, nil 48 } 49 return &watcher{value: val, t: time.Now()}, nil 50 } 51 52 func (h *harness) CreateVariable(ctx context.Context, name string, val []byte) error { 53 h.vars[name] = val 54 return nil 55 } 56 57 func (h *harness) UpdateVariable(ctx context.Context, name string, val []byte) error { 58 return errors.New("not supported") 59 } 60 61 func (h *harness) DeleteVariable(ctx context.Context, name string) error { 62 return errors.New("not supported") 63 } 64 65 func (h *harness) Close() {} 66 67 func (h *harness) Mutable() bool { return false } 68 69 func TestConformance(t *testing.T) { 70 drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{}}) 71 } 72 73 type verifyAs struct{} 74 75 func (verifyAs) Name() string { 76 return "verify As" 77 } 78 79 func (verifyAs) SnapshotCheck(s *runtimevar.Snapshot) error { 80 var ss string 81 if s.As(&ss) { 82 return errors.New("Snapshot.As expected to fail") 83 } 84 return nil 85 } 86 87 func (verifyAs) ErrorCheck(v *runtimevar.Variable, err error) error { 88 var ss string 89 if v.ErrorAs(err, &ss) { 90 return errors.New("runtimevar.ErrorAs expected to fail") 91 } 92 return nil 93 } 94 95 func TestNew(t *testing.T) { 96 ctx := context.Background() 97 98 // Use New with an error value; it should be plumbed through as a Value. 99 errFail := errors.New("fail") 100 v := New(errFail) 101 defer v.Close() 102 val, err := v.Watch(ctx) 103 if err != nil { 104 t.Fatal(err) 105 } 106 if val.Value != errFail { 107 t.Errorf("got %v want %v", val.Value, errFail) 108 } 109 } 110 111 func TestNewBytes(t *testing.T) { 112 ctx := context.Background() 113 content := "hello world" 114 115 // Decode succeeds. 116 v := NewBytes([]byte(content), runtimevar.StringDecoder) 117 defer v.Close() 118 val, err := v.Watch(ctx) 119 if err != nil { 120 t.Fatal(err) 121 } 122 if val.Value != content { 123 t.Errorf("got %v want %v", val.Value, content) 124 } 125 126 // Decode fails. 127 var jsonData []string 128 v = NewBytes([]byte(content), runtimevar.NewDecoder(jsonData, runtimevar.JSONDecode)) 129 defer v.Close() 130 val, err = v.Watch(ctx) 131 if err == nil { 132 t.Errorf("got nil error and %v, want error", val) 133 } 134 } 135 136 func TestNewError(t *testing.T) { 137 ctx := context.Background() 138 139 v := NewError(errors.New("fail")) 140 defer v.Close() 141 _, err := v.Watch(ctx) 142 if err == nil { 143 t.Errorf("got nil err want fail err") 144 } 145 } 146 147 func TestOpenVariable(t *testing.T) { 148 tests := []struct { 149 URL string 150 WantErr bool 151 WantWatchErr bool 152 Want interface{} 153 }{ 154 // Empty URL results in empty byte slice. 155 {"constant://", false, false, []byte("")}, 156 // Invalid query param. 157 {"constant://?param=value", true, false, nil}, 158 // String value. 159 {"constant://?val=hello+world&decoder=string", false, false, "hello world"}, 160 // JSON value; val parameter is {"Foo": "Bar"}, URL-encoded. 161 {"constant://?val=%7B%22Foo%22%3A%22Bar%22%7d&decoder=jsonmap", false, false, &map[string]interface{}{"Foo": "Bar"}}, 162 // Error. 163 {"constant://?err=fail", false, true, nil}, 164 // Invalid decoder. 165 {"constant://?decoder=notadecoder", true, false, nil}, 166 } 167 168 ctx := context.Background() 169 for _, test := range tests { 170 t.Run(test.URL, func(t *testing.T) { 171 v, err := runtimevar.OpenVariable(ctx, test.URL) 172 if (err != nil) != test.WantErr { 173 t.Errorf("%s: got error %v, want error %v", test.URL, err, test.WantErr) 174 } 175 if err != nil { 176 return 177 } 178 defer v.Close() 179 snapshot, err := v.Watch(ctx) 180 if (err != nil) != test.WantWatchErr { 181 t.Errorf("%s: got Watch error %v, want error %v", test.URL, err, test.WantWatchErr) 182 } 183 if err != nil { 184 return 185 } 186 if !cmp.Equal(snapshot.Value, test.Want) { 187 t.Errorf("%s: got snapshot value\n%v\n want\n%v", test.URL, snapshot.Value, test.Want) 188 } 189 }) 190 } 191 } 192 193 func TestDecryptWithNoURLEnv(t *testing.T) { 194 if _, err := runtimevar.OpenVariable(context.Background(), "constant://?decoder=decrypt"); err == nil { 195 t.Error("got nil error, want environment variable not set") 196 } 197 }