github.com/thiagoyeds/go-cloud@v0.26.0/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  	}
   147  
   148  	ctx := context.Background()
   149  	for _, test := range tests {
   150  		t.Run(test.BucketURL, func(t *testing.T) {
   151  			os.Setenv("BLOBVAR_BUCKET_URL", test.BucketURL)
   152  
   153  			opener := &defaultOpener{}
   154  			defer func() {
   155  				if opener.opener != nil && opener.opener.Bucket != nil {
   156  					opener.opener.Bucket.Close()
   157  				}
   158  			}()
   159  			u, err := url.Parse(test.URL)
   160  			if err != nil {
   161  				t.Error(err)
   162  			}
   163  			v, err := opener.OpenVariableURL(ctx, u)
   164  			if v != nil {
   165  				defer v.Close()
   166  			}
   167  			if (err != nil) != test.WantErr {
   168  				t.Errorf("BucketURL %s URL %s: got error %v, want error %v", test.BucketURL, test.URL, err, test.WantErr)
   169  			}
   170  			if err != nil {
   171  				return
   172  			}
   173  			defer v.Close()
   174  			snapshot, err := v.Watch(ctx)
   175  			if (err != nil) != test.WantWatchErr {
   176  				t.Errorf("BucketURL %s URL %s: got Watch error %v, want error %v", test.BucketURL, test.URL, err, test.WantWatchErr)
   177  			}
   178  			if err != nil {
   179  				return
   180  			}
   181  			if !cmp.Equal(snapshot.Value, test.Want) {
   182  				t.Errorf("BucketURL %s URL %s: got snapshot value\n%v\n  want\n%v", test.BucketURL, test.URL, snapshot.Value, test.Want)
   183  			}
   184  		})
   185  	}
   186  }