Add 'build/' from commit '555b039609a3c8700c27767c255fdfe00eb42063'
[arvados.git] / services / keepstore / s3_volume_test.go
1 package main
2
3 import (
4         "bytes"
5         "fmt"
6         "log"
7         "strings"
8         "time"
9
10         "github.com/AdRoll/goamz/aws"
11         "github.com/AdRoll/goamz/s3"
12         "github.com/AdRoll/goamz/s3/s3test"
13         check "gopkg.in/check.v1"
14 )
15
16 type TestableS3Volume struct {
17         *S3Volume
18         server      *s3test.Server
19         c           *check.C
20         serverClock *fakeClock
21 }
22
23 const (
24         TestBucketName = "testbucket"
25 )
26
27 type fakeClock struct {
28         now *time.Time
29 }
30
31 func (c *fakeClock) Now() time.Time {
32         if c.now == nil {
33                 return time.Now()
34         }
35         return *c.now
36 }
37
38 func init() {
39         // Deleting isn't safe from races, but if it's turned on
40         // anyway we do expect it to pass the generic volume tests.
41         s3UnsafeDelete = true
42 }
43
44 func NewTestableS3Volume(c *check.C, readonly bool, replication int) *TestableS3Volume {
45         clock := &fakeClock{}
46         srv, err := s3test.NewServer(&s3test.Config{Clock: clock})
47         c.Assert(err, check.IsNil)
48         auth := aws.Auth{}
49         region := aws.Region{
50                 Name:                 "test-region-1",
51                 S3Endpoint:           srv.URL(),
52                 S3LocationConstraint: true,
53         }
54         bucket := &s3.Bucket{
55                 S3:   s3.New(auth, region),
56                 Name: TestBucketName,
57         }
58         err = bucket.PutBucket(s3.ACL("private"))
59         c.Assert(err, check.IsNil)
60
61         return &TestableS3Volume{
62                 S3Volume:    NewS3Volume(auth, region, TestBucketName, readonly, replication),
63                 server:      srv,
64                 serverClock: clock,
65         }
66 }
67
68 var _ = check.Suite(&StubbedS3Suite{})
69
70 type StubbedS3Suite struct {
71         volumes []*TestableS3Volume
72 }
73
74 func (s *StubbedS3Suite) TestGeneric(c *check.C) {
75         DoGenericVolumeTests(c, func(t TB) TestableVolume {
76                 return NewTestableS3Volume(c, false, 2)
77         })
78 }
79
80 func (s *StubbedS3Suite) TestGenericReadOnly(c *check.C) {
81         DoGenericVolumeTests(c, func(t TB) TestableVolume {
82                 return NewTestableS3Volume(c, true, 2)
83         })
84 }
85
86 func (s *StubbedS3Suite) TestIndex(c *check.C) {
87         v := NewTestableS3Volume(c, false, 2)
88         v.indexPageSize = 3
89         for i := 0; i < 256; i++ {
90                 v.PutRaw(fmt.Sprintf("%02x%030x", i, i), []byte{102, 111, 111})
91         }
92         for _, spec := range []struct {
93                 prefix      string
94                 expectMatch int
95         }{
96                 {"", 256},
97                 {"c", 16},
98                 {"bc", 1},
99                 {"abc", 0},
100         } {
101                 buf := new(bytes.Buffer)
102                 err := v.IndexTo(spec.prefix, buf)
103                 c.Check(err, check.IsNil)
104
105                 idx := bytes.SplitAfter(buf.Bytes(), []byte{10})
106                 c.Check(len(idx), check.Equals, spec.expectMatch+1)
107                 c.Check(len(idx[len(idx)-1]), check.Equals, 0)
108         }
109 }
110
111 // PutRaw skips the ContentMD5 test
112 func (v *TestableS3Volume) PutRaw(loc string, block []byte) {
113         err := v.Bucket.Put(loc, block, "application/octet-stream", s3ACL, s3.Options{})
114         if err != nil {
115                 log.Printf("PutRaw: %+v", err)
116         }
117 }
118
119 // TouchWithDate turns back the clock while doing a Touch(). We assume
120 // there are no other operations happening on the same s3test server
121 // while we do this.
122 func (v *TestableS3Volume) TouchWithDate(locator string, lastPut time.Time) {
123         v.serverClock.now = &lastPut
124         err := v.Touch(locator)
125         if err != nil && !strings.Contains(err.Error(), "PutCopy returned old LastModified") {
126                 log.Printf("Touch: %+v", err)
127         }
128         v.serverClock.now = nil
129 }
130
131 func (v *TestableS3Volume) Teardown() {
132         v.server.Quit()
133 }