github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/pkg/googlestorage/googlestorage_test.go (about)

     1  /*
     2  Copyright 2011 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // FYI These tests are integration tests that need to run against google
    18  // storage. See the README for more details on necessary setup
    19  
    20  package googlestorage
    21  
    22  import (
    23  	"bytes"
    24  	"fmt"
    25  	"os"
    26  	"path/filepath"
    27  	"testing"
    28  	"time"
    29  
    30  	"camlistore.org/pkg/jsonconfig"
    31  	"camlistore.org/pkg/osutil"
    32  	"camlistore.org/pkg/test"
    33  )
    34  
    35  const testObjectContent = "Google Storage Test\n"
    36  
    37  type BufferCloser struct {
    38  	*bytes.Buffer
    39  }
    40  
    41  func (b *BufferCloser) Close() error {
    42  	b.Reset()
    43  	return nil
    44  }
    45  
    46  // Reads google storage config and creates a Client.  Exits on error.
    47  func doConfig(t *testing.T) (gsa *Client, bucket string) {
    48  	gsConfigPath := filepath.Join(osutil.CamliConfigDir(), "gstestconfig.json")
    49  
    50  	if _, err := os.Stat(gsConfigPath); os.IsNotExist(err) {
    51  		test.DependencyErrorOrSkip(t)
    52  		t.Fatalf("Missing config file: %v", err)
    53  	}
    54  	cf, err := jsonconfig.ReadFile(gsConfigPath)
    55  	if err != nil {
    56  		t.Fatalf("Failed to read config: %v", err)
    57  	}
    58  
    59  	var config jsonconfig.Obj
    60  	config = cf.RequiredObject("gsconf")
    61  	if err := cf.Validate(); err != nil {
    62  		t.Fatalf("Invalid config: %v", err)
    63  	}
    64  
    65  	auth := config.RequiredObject("auth")
    66  	bucket = config.RequiredString("bucket")
    67  	if err := config.Validate(); err != nil {
    68  		t.Fatalf("Invalid config: %v", err)
    69  	}
    70  
    71  	gsa = NewClient(MakeOauthTransport(auth.RequiredString("client_id"),
    72  		auth.RequiredString("client_secret"),
    73  		auth.RequiredString("refresh_token")))
    74  
    75  	if err := auth.Validate(); err != nil {
    76  		t.Fatalf("Invalid config: %v", err)
    77  	}
    78  	return
    79  }
    80  
    81  func TestGetObject(t *testing.T) {
    82  	gs, bucket := doConfig(t)
    83  
    84  	body, size, err := gs.GetObject(&Object{bucket, "test-get"})
    85  	if err != nil {
    86  		t.Fatalf("Fetch failed: %v\n", err)
    87  	}
    88  
    89  	content := make([]byte, size)
    90  	if _, err = body.Read(content); err != nil {
    91  		t.Fatalf("Failed to read response body: %v:\n", err)
    92  	}
    93  
    94  	if string(content) != testObjectContent {
    95  		t.Fatalf("Object has incorrect content.\nExpected: '%v'\nFound: '%v'\n", testObjectContent, string(content))
    96  	}
    97  }
    98  
    99  func TestStatObject(t *testing.T) {
   100  	gs, bucket := doConfig(t)
   101  
   102  	// Stat a nonexistant file
   103  	size, exists, err := gs.StatObject(&Object{bucket, "test-shouldntexist"})
   104  	if err != nil {
   105  		t.Fatalf("Stat failed: %v\n", err)
   106  	} else {
   107  		if exists {
   108  			t.Errorf("Test object exists!")
   109  		}
   110  		if size != 0 {
   111  			t.Errorf("Expected size to be 0, found %v\n", size)
   112  		}
   113  	}
   114  
   115  	// Try statting an object which does exist
   116  	size, exists, err = gs.StatObject(&Object{bucket, "test-stat"})
   117  	if err != nil {
   118  		t.Fatalf("Stat failed: %v\n", err)
   119  	} else {
   120  		if !exists {
   121  			t.Errorf("Test object doesn't exist!")
   122  		}
   123  		if size != int64(len(testObjectContent)) {
   124  			t.Errorf("Test object size is wrong: \nexpected: %v\nfound: %v\n",
   125  				len(testObjectContent), size)
   126  		}
   127  	}
   128  }
   129  
   130  func TestPutObject(t *testing.T) {
   131  	gs, bucket := doConfig(t)
   132  
   133  	now := time.Now()
   134  	testKey := fmt.Sprintf("test-put-%v.%v.%v-%v.%v.%v",
   135  		now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
   136  
   137  	shouldRetry, err := gs.PutObject(&Object{bucket, testKey},
   138  		&BufferCloser{bytes.NewBufferString(testObjectContent)})
   139  	if shouldRetry {
   140  		shouldRetry, err = gs.PutObject(&Object{bucket, testKey},
   141  			&BufferCloser{bytes.NewBufferString(testObjectContent)})
   142  	}
   143  	if err != nil {
   144  		t.Fatalf("Failed to put object: %v", err)
   145  	}
   146  
   147  	// Just stat to check that it actually uploaded, don't bother reading back
   148  	size, exists, err := gs.StatObject(&Object{bucket, testKey})
   149  	if !exists {
   150  		t.Errorf("Test object doesn't exist!")
   151  	}
   152  	if size != int64(len(testObjectContent)) {
   153  		t.Errorf("Test object size is wrong: \nexpected: %v\nfound: %v\n",
   154  			len(testObjectContent), size)
   155  	}
   156  }
   157  
   158  func TestDeleteObject(t *testing.T) {
   159  	gs, bucket := doConfig(t)
   160  
   161  	// Try deleting a nonexitent file
   162  	err := gs.DeleteObject(&Object{bucket, "test-shouldntexist"})
   163  	if err == nil {
   164  		t.Errorf("Tried to delete nonexistent object, succeeded.")
   165  	}
   166  
   167  	// Create a file, try to delete it
   168  	now := time.Now()
   169  	testKey := fmt.Sprintf("test-delete-%v.%v.%v-%v.%v.%v",
   170  		now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
   171  	_, err = gs.PutObject(&Object{bucket, testKey},
   172  		&BufferCloser{bytes.NewBufferString("Delete Me")})
   173  	if err != nil {
   174  		t.Fatalf("Failed to put file to delete.")
   175  	}
   176  	err = gs.DeleteObject(&Object{bucket, testKey})
   177  	if err != nil {
   178  		t.Errorf("Failed to delete object: %v", err)
   179  	}
   180  }
   181  
   182  func TestEnumerateBucket(t *testing.T) {
   183  	gs, bucket := doConfig(t)
   184  
   185  	// Enumerate ALL the things!
   186  	objs, err := gs.EnumerateObjects(bucket, "", 0)
   187  	if err != nil {
   188  		t.Errorf("Enumeration failed: %v\n", err)
   189  	} else if len(objs) < 7 {
   190  		// Minimum number of blobs, equal to the number of files in testdata
   191  		t.Errorf("Expected at least 7 files, found %v", len(objs))
   192  	}
   193  
   194  	// Test a limited enum
   195  	objs, err = gs.EnumerateObjects(bucket, "", 5)
   196  	if err != nil {
   197  		t.Errorf("Enumeration failed: %v\n", err)
   198  	} else if len(objs) != 5 {
   199  		t.Errorf(
   200  			"Limited enum returned wrong number of blobs.\nExpected: %v\nFound: %v",
   201  			5, len(objs))
   202  	}
   203  
   204  	// Test fetching a limited set from a known start point
   205  	objs, err = gs.EnumerateObjects(bucket, "test-enum", 4)
   206  	if err != nil {
   207  		t.Errorf("Enumeration failed: %v\n", err)
   208  	} else {
   209  		for i := 0; i < 4; i += 1 {
   210  			if objs[i].Key != fmt.Sprintf("test-enum-%v", i+1) {
   211  				t.Errorf(
   212  					"Enum from start point returned wrong key:\nExpected: test-enum-%v\nFound: %v",
   213  					i+1, objs[i].Key)
   214  			}
   215  		}
   216  	}
   217  }