1package s3crypto
2
3import (
4	"bytes"
5	"errors"
6	"fmt"
7	"io/ioutil"
8	"net/http"
9	"strings"
10	"testing"
11
12	"github.com/aws/aws-sdk-go/aws"
13	"github.com/aws/aws-sdk-go/aws/awserr"
14	"github.com/aws/aws-sdk-go/aws/request"
15	"github.com/aws/aws-sdk-go/awstesting"
16	"github.com/aws/aws-sdk-go/awstesting/unit"
17	"github.com/aws/aws-sdk-go/service/kms"
18	"github.com/aws/aws-sdk-go/service/s3"
19)
20
21func TestDefaultConfigValues(t *testing.T) {
22	sess := unit.Session.Copy(&aws.Config{
23		MaxRetries:       aws.Int(0),
24		S3ForcePathStyle: aws.Bool(true),
25		Region:           aws.String("us-west-2"),
26	})
27	svc := kms.New(sess)
28	handler := NewKMSKeyGenerator(svc, "testid")
29
30	c := NewEncryptionClient(sess, AESGCMContentCipherBuilder(handler))
31
32	if c == nil {
33		t.Error("expected non-vil client value")
34	}
35	if c.ContentCipherBuilder == nil {
36		t.Error("expected non-vil content cipher builder value")
37	}
38	if c.SaveStrategy == nil {
39		t.Error("expected non-vil save strategy value")
40	}
41}
42
43func TestPutObject(t *testing.T) {
44	size := 1024 * 1024
45	data := make([]byte, size)
46	expected := bytes.Repeat([]byte{1}, size)
47	generator := mockGenerator{}
48	cb := mockCipherBuilder{generator}
49	sess := unit.Session.Copy(&aws.Config{
50		MaxRetries:       aws.Int(0),
51		S3ForcePathStyle: aws.Bool(true),
52		Region:           aws.String("us-west-2"),
53	})
54	c := NewEncryptionClient(sess, cb)
55	if c == nil {
56		t.Error("expected non-vil client value")
57	}
58	input := &s3.PutObjectInput{
59		Key:    aws.String("test"),
60		Bucket: aws.String("test"),
61		Body:   bytes.NewReader(data),
62	}
63	req, _ := c.PutObjectRequest(input)
64	req.Handlers.Send.Clear()
65	req.Handlers.Send.PushBack(func(r *request.Request) {
66		r.Error = errors.New("stop")
67		r.HTTPResponse = &http.Response{
68			StatusCode: 200,
69		}
70	})
71	err := req.Send()
72	if e, a := "stop", err.Error(); e != a {
73		t.Errorf("expected %s error, but received %s", e, a)
74	}
75	b, err := ioutil.ReadAll(req.HTTPRequest.Body)
76	if err != nil {
77		t.Errorf("expected no error, but received %v", err)
78	}
79	if !bytes.Equal(expected, b) {
80		t.Error("expected bytes to be equivalent, but received otherwise")
81	}
82}
83
84func TestPutObjectWithContext(t *testing.T) {
85	generator := mockGenerator{}
86	cb := mockCipherBuilder{generator}
87
88	c := NewEncryptionClient(unit.Session, cb)
89
90	ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})}
91	ctx.Error = fmt.Errorf("context canceled")
92	close(ctx.DoneCh)
93
94	input := s3.PutObjectInput{
95		Bucket: aws.String("test"),
96		Key:    aws.String("test"),
97		Body:   bytes.NewReader([]byte{}),
98	}
99	_, err := c.PutObjectWithContext(ctx, &input)
100	if err == nil {
101		t.Fatalf("expected error, did not get one")
102	}
103	aerr := err.(awserr.Error)
104	if e, a := request.CanceledErrorCode, aerr.Code(); e != a {
105		t.Errorf("expected error code %q, got %q", e, a)
106	}
107	if e, a := "canceled", aerr.Message(); !strings.Contains(a, e) {
108		t.Errorf("expected error message to contain %q, but did not %q", e, a)
109	}
110}
111
112func TestEncryptionClient_PutObject_InvalidClientConstruction(t *testing.T) {
113	generator := mockGeneratorV2{}
114	cb := mockCipherBuilderV2{generator: generator}
115
116	c := NewEncryptionClient(unit.Session, cb)
117	if c == nil {
118		t.Errorf("expected client not to be nil")
119	}
120
121	input := s3.PutObjectInput{
122		Bucket: aws.String("test"),
123		Key:    aws.String("test"),
124		Body:   bytes.NewReader([]byte{}),
125	}
126	_, err := c.PutObject(&input)
127	if err == nil {
128		t.Fatalf("expected error, did not get one")
129	}
130	if e, a := "invalid client configuration", err.Error(); !strings.Contains(a, e) {
131		t.Errorf("expected %v, got %v", e, a)
132	}
133
134	_, err = c.PutObjectWithContext(aws.BackgroundContext(), &input)
135	if err == nil {
136		t.Fatalf("expected error, did not get one")
137	}
138	if e, a := "invalid client configuration", err.Error(); !strings.Contains(a, e) {
139		t.Errorf("expected %v, got %v", e, a)
140	}
141
142	_, err = c.PutObjectWithContext(aws.BackgroundContext(), &input)
143	if err == nil {
144		t.Fatalf("expected error, did not get one")
145	}
146	if e, a := "invalid client configuration", err.Error(); !strings.Contains(a, e) {
147		t.Errorf("expected %v, got %v", e, a)
148	}
149
150	req, _ := c.PutObjectRequest(&input)
151	err = req.Send()
152	if err == nil {
153		t.Fatalf("expected error, did not get one")
154	}
155	if e, a := "invalid client configuration", err.Error(); !strings.Contains(a, e) {
156		t.Errorf("expected %v, got %v", e, a)
157	}
158}
159