github.com/thiagoyeds/go-cloud@v0.26.0/secrets/secrets_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 secrets 16 17 import ( 18 "context" 19 "errors" 20 "net/url" 21 "strings" 22 "sync" 23 "testing" 24 25 "github.com/google/go-cmp/cmp" 26 "gocloud.dev/gcerrors" 27 "gocloud.dev/internal/gcerr" 28 "gocloud.dev/internal/testing/octest" 29 "gocloud.dev/secrets/driver" 30 ) 31 32 var errFake = errors.New("fake") 33 34 type erroringKeeper struct { 35 driver.Keeper 36 } 37 38 func (k *erroringKeeper) Decrypt(ctx context.Context, b []byte) ([]byte, error) { 39 return nil, errFake 40 } 41 42 func (k *erroringKeeper) Encrypt(ctx context.Context, b []byte) ([]byte, error) { 43 return nil, errFake 44 } 45 46 func (k *erroringKeeper) Close() error { return errFake } 47 func (k *erroringKeeper) ErrorCode(error) gcerrors.ErrorCode { return gcerrors.Internal } 48 49 func TestErrorsAreWrapped(t *testing.T) { 50 ctx := context.Background() 51 k := NewKeeper(&erroringKeeper{}) 52 53 // verifyWrap ensures that err is wrapped exactly once. 54 verifyWrap := func(description string, err error) { 55 if err == nil { 56 t.Errorf("%s: got nil error, wanted non-nil", description) 57 } else if unwrapped, ok := err.(*gcerr.Error); !ok { 58 t.Errorf("%s: not wrapped: %v", description, err) 59 } else if du, ok := unwrapped.Unwrap().(*gcerr.Error); ok { 60 t.Errorf("%s: double wrapped: %v", description, du) 61 } 62 if s := err.Error(); !strings.HasPrefix(s, "secrets ") { 63 t.Errorf("%s: Error() for wrapped error doesn't start with secrets: prefix: %s", description, s) 64 } 65 } 66 67 _, err := k.Decrypt(ctx, nil) 68 verifyWrap("Decrypt", err) 69 70 _, err = k.Encrypt(ctx, nil) 71 verifyWrap("Encrypt", err) 72 73 err = k.Close() 74 verifyWrap("Close", err) 75 } 76 77 // TestKeeperIsClosed tests that Keeper functions return an error when the 78 // Keeper is closed. 79 func TestKeeperIsClosed(t *testing.T) { 80 ctx := context.Background() 81 k := NewKeeper(&erroringKeeper{}) 82 k.Close() 83 84 if _, err := k.Decrypt(ctx, nil); err != errClosed { 85 t.Error(err) 86 } 87 if _, err := k.Encrypt(ctx, nil); err != errClosed { 88 t.Error(err) 89 } 90 if err := k.Close(); err != errClosed { 91 t.Error(err) 92 } 93 } 94 95 func TestOpenCensus(t *testing.T) { 96 ctx := context.Background() 97 te := octest.NewTestExporter(OpenCensusViews) 98 defer te.Unregister() 99 100 k := NewKeeper(&erroringKeeper{}) 101 defer k.Close() 102 k.Encrypt(ctx, nil) 103 k.Decrypt(ctx, nil) 104 diff := octest.Diff(te.Spans(), te.Counts(), "gocloud.dev/secrets", "gocloud.dev/secrets", []octest.Call{ 105 {Method: "Encrypt", Code: gcerrors.Internal}, 106 {Method: "Decrypt", Code: gcerrors.Internal}, 107 }) 108 if diff != "" { 109 t.Error(diff) 110 } 111 } 112 113 var ( 114 testOpenOnce sync.Once 115 testOpenGot *url.URL 116 ) 117 118 func TestURLMux(t *testing.T) { 119 ctx := context.Background() 120 121 mux := new(URLMux) 122 fake := &fakeOpener{} 123 mux.RegisterKeeper("foo", fake) 124 mux.RegisterKeeper("err", fake) 125 126 if diff := cmp.Diff(mux.KeeperSchemes(), []string{"err", "foo"}); diff != "" { 127 t.Errorf("Schemes: %s", diff) 128 } 129 if !mux.ValidKeeperScheme("foo") || !mux.ValidKeeperScheme("err") { 130 t.Errorf("ValidKeeperScheme didn't return true for valid scheme") 131 } 132 if mux.ValidKeeperScheme("foo2") || mux.ValidKeeperScheme("http") { 133 t.Errorf("ValidKeeperScheme didn't return false for invalid scheme") 134 } 135 136 for _, tc := range []struct { 137 name string 138 url string 139 wantErr bool 140 }{ 141 { 142 name: "empty URL", 143 wantErr: true, 144 }, 145 { 146 name: "invalid URL", 147 url: ":foo", 148 wantErr: true, 149 }, 150 { 151 name: "invalid URL no scheme", 152 url: "foo", 153 wantErr: true, 154 }, 155 { 156 name: "unregistered scheme", 157 url: "bar://mykeeper", 158 wantErr: true, 159 }, 160 { 161 name: "func returns error", 162 url: "err://mykeeper", 163 wantErr: true, 164 }, 165 { 166 name: "no query options", 167 url: "foo://mykeeper", 168 }, 169 { 170 name: "empty query options", 171 url: "foo://mykeeper?", 172 }, 173 { 174 name: "query options", 175 url: "foo://mykeeper?aAa=bBb&cCc=dDd", 176 }, 177 { 178 name: "multiple query options", 179 url: "foo://mykeeper?x=a&x=b&x=c", 180 }, 181 { 182 name: "fancy keeper name", 183 url: "foo:///foo/bar/baz", 184 }, 185 { 186 name: "using api scheme prefix", 187 url: "secrets+foo://mykeeper", 188 }, 189 { 190 name: "using api+type scheme prefix", 191 url: "secrets+keeper+foo://mykeeper", 192 }, 193 } { 194 t.Run(tc.name, func(t *testing.T) { 195 keeper, gotErr := mux.OpenKeeper(ctx, tc.url) 196 if (gotErr != nil) != tc.wantErr { 197 t.Fatalf("got err %v, want error %v", gotErr, tc.wantErr) 198 } 199 if gotErr != nil { 200 return 201 } 202 defer keeper.Close() 203 if got := fake.u.String(); got != tc.url { 204 t.Errorf("got %q want %q", got, tc.url) 205 } 206 // Repeat with OpenKeeperURL. 207 parsed, err := url.Parse(tc.url) 208 if err != nil { 209 t.Fatal(err) 210 } 211 keeper, gotErr = mux.OpenKeeperURL(ctx, parsed) 212 if gotErr != nil { 213 t.Fatalf("got err %v, want nil", gotErr) 214 } 215 defer keeper.Close() 216 if got := fake.u.String(); got != tc.url { 217 t.Errorf("got %q want %q", got, tc.url) 218 } 219 }) 220 } 221 } 222 223 type fakeOpener struct { 224 u *url.URL // last url passed to OpenKeeperURL 225 } 226 227 func (o *fakeOpener) OpenKeeperURL(ctx context.Context, u *url.URL) (*Keeper, error) { 228 if u.Scheme == "err" { 229 return nil, errors.New("fail") 230 } 231 o.u = u 232 return NewKeeper(&erroringKeeper{}), nil 233 }