1package testing
2
3import (
4	"crypto/md5"
5	"fmt"
6	"io"
7	"net/http"
8	"testing"
9	"time"
10
11	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
12	th "github.com/gophercloud/gophercloud/testhelper"
13	fake "github.com/gophercloud/gophercloud/testhelper/client"
14)
15
16// HandleDownloadObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
17// responds with a `Download` response.
18func HandleDownloadObjectSuccessfully(t *testing.T) {
19	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
20		th.TestMethod(t, r, "GET")
21		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
22		th.TestHeader(t, r, "Accept", "application/json")
23		w.Header().Set("Date", "Wed, 10 Nov 2009 23:00:00 GMT")
24		w.Header().Set("X-Static-Large-Object", "True")
25		w.WriteHeader(http.StatusOK)
26		fmt.Fprintf(w, "Successful download with Gophercloud")
27	})
28}
29
30// ExpectedListInfo is the result expected from a call to `List` when full
31// info is requested.
32var ExpectedListInfo = []objects.Object{
33	{
34		Hash:         "451e372e48e0f6b1114fa0724aa79fa1",
35		LastModified: time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC), //"2016-08-17T22:11:58.602650"
36		Bytes:        14,
37		Name:         "goodbye",
38		ContentType:  "application/octet-stream",
39	},
40	{
41		Hash:         "451e372e48e0f6b1114fa0724aa79fa1",
42		LastModified: time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC),
43		Bytes:        14,
44		Name:         "hello",
45		ContentType:  "application/octet-stream",
46	},
47}
48
49// ExpectedListSubdir is the result expected from a call to `List` when full
50// info is requested.
51var ExpectedListSubdir = []objects.Object{
52	{
53		Subdir: "directory/",
54	},
55}
56
57// ExpectedListNames is the result expected from a call to `List` when just
58// object names are requested.
59var ExpectedListNames = []string{"hello", "goodbye"}
60
61// HandleListObjectsInfoSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
62// responds with a `List` response when full info is requested.
63func HandleListObjectsInfoSuccessfully(t *testing.T) {
64	th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
65		th.TestMethod(t, r, "GET")
66		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
67		th.TestHeader(t, r, "Accept", "application/json")
68
69		w.Header().Set("Content-Type", "application/json")
70		r.ParseForm()
71		marker := r.Form.Get("marker")
72		switch marker {
73		case "":
74			fmt.Fprintf(w, `[
75      {
76        "hash": "451e372e48e0f6b1114fa0724aa79fa1",
77        "last_modified": "2016-08-17T22:11:58.602650",
78        "bytes": 14,
79        "name": "goodbye",
80        "content_type": "application/octet-stream"
81      },
82      {
83        "hash": "451e372e48e0f6b1114fa0724aa79fa1",
84        "last_modified": "2016-08-17T22:11:58.602650",
85        "bytes": 14,
86        "name": "hello",
87        "content_type": "application/octet-stream"
88      }
89    ]`)
90		case "hello":
91			fmt.Fprintf(w, `[]`)
92		default:
93			t.Fatalf("Unexpected marker: [%s]", marker)
94		}
95	})
96}
97
98// HandleListSubdirSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
99// responds with a `List` response when full info is requested.
100func HandleListSubdirSuccessfully(t *testing.T) {
101	th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
102		th.TestMethod(t, r, "GET")
103		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
104		th.TestHeader(t, r, "Accept", "application/json")
105
106		w.Header().Set("Content-Type", "application/json")
107		r.ParseForm()
108		marker := r.Form.Get("marker")
109		switch marker {
110		case "":
111			fmt.Fprintf(w, `[
112      {
113        "subdir": "directory/"
114      }
115    ]`)
116		case "directory/":
117			fmt.Fprintf(w, `[]`)
118		default:
119			t.Fatalf("Unexpected marker: [%s]", marker)
120		}
121	})
122}
123
124// HandleListObjectNamesSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
125// responds with a `List` response when only object names are requested.
126func HandleListObjectNamesSuccessfully(t *testing.T) {
127	th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
128		th.TestMethod(t, r, "GET")
129		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
130		th.TestHeader(t, r, "Accept", "text/plain")
131
132		w.Header().Set("Content-Type", "text/plain")
133		r.ParseForm()
134		marker := r.Form.Get("marker")
135		switch marker {
136		case "":
137			fmt.Fprintf(w, "hello\ngoodbye\n")
138		case "goodbye":
139			fmt.Fprintf(w, "")
140		default:
141			t.Fatalf("Unexpected marker: [%s]", marker)
142		}
143	})
144}
145
146// HandleCreateTextObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux
147// that responds with a `Create` response. A Content-Type of "text/plain" is expected.
148func HandleCreateTextObjectSuccessfully(t *testing.T, content string) {
149	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
150		th.TestMethod(t, r, "PUT")
151		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
152		th.TestHeader(t, r, "Content-Type", "text/plain")
153		th.TestHeader(t, r, "Accept", "application/json")
154
155		hash := md5.New()
156		io.WriteString(hash, content)
157		localChecksum := hash.Sum(nil)
158
159		w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
160		w.WriteHeader(http.StatusCreated)
161	})
162}
163
164// HandleCreateTextWithCacheControlSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler
165// mux that responds with a `Create` response. A Cache-Control of `max-age="3600", public` is expected.
166func HandleCreateTextWithCacheControlSuccessfully(t *testing.T, content string) {
167	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
168		th.TestMethod(t, r, "PUT")
169		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
170		th.TestHeader(t, r, "Cache-Control", `max-age="3600", public`)
171		th.TestHeader(t, r, "Accept", "application/json")
172
173		hash := md5.New()
174		io.WriteString(hash, content)
175		localChecksum := hash.Sum(nil)
176
177		w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
178		w.WriteHeader(http.StatusCreated)
179	})
180}
181
182// HandleCreateTypelessObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler
183// mux that responds with a `Create` response. No Content-Type header may be present in the request, so that server-
184// side content-type detection will be triggered properly.
185func HandleCreateTypelessObjectSuccessfully(t *testing.T, content string) {
186	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
187		th.TestMethod(t, r, "PUT")
188		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
189		th.TestHeader(t, r, "Accept", "application/json")
190
191		if contentType, present := r.Header["Content-Type"]; present {
192			t.Errorf("Expected Content-Type header to be omitted, but was %#v", contentType)
193		}
194
195		hash := md5.New()
196		io.WriteString(hash, content)
197		localChecksum := hash.Sum(nil)
198
199		w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
200		w.WriteHeader(http.StatusCreated)
201	})
202}
203
204// HandleCopyObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
205// responds with a `Copy` response.
206func HandleCopyObjectSuccessfully(t *testing.T) {
207	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
208		th.TestMethod(t, r, "COPY")
209		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
210		th.TestHeader(t, r, "Accept", "application/json")
211		th.TestHeader(t, r, "Destination", "/newTestContainer/newTestObject")
212		w.WriteHeader(http.StatusCreated)
213	})
214}
215
216// HandleDeleteObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
217// responds with a `Delete` response.
218func HandleDeleteObjectSuccessfully(t *testing.T) {
219	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
220		th.TestMethod(t, r, "DELETE")
221		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
222		th.TestHeader(t, r, "Accept", "application/json")
223		w.WriteHeader(http.StatusNoContent)
224	})
225}
226
227// HandleUpdateObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
228// responds with a `Update` response.
229func HandleUpdateObjectSuccessfully(t *testing.T) {
230	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
231		th.TestMethod(t, r, "POST")
232		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
233		th.TestHeader(t, r, "Accept", "application/json")
234		th.TestHeader(t, r, "X-Object-Meta-Gophercloud-Test", "objects")
235		w.WriteHeader(http.StatusAccepted)
236	})
237}
238
239// HandleGetObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
240// responds with a `Get` response.
241func HandleGetObjectSuccessfully(t *testing.T) {
242	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
243		th.TestMethod(t, r, "HEAD")
244		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
245		th.TestHeader(t, r, "Accept", "application/json")
246		w.Header().Add("X-Object-Meta-Gophercloud-Test", "objects")
247		w.Header().Add("X-Static-Large-Object", "true")
248		w.WriteHeader(http.StatusNoContent)
249	})
250}
251