File Coverage

blib/lib/STF/Dispatcher/Test.pm
Criterion Covered Total %
statement 111 140 79.2
branch 29 58 50.0
condition n/a
subroutine 9 9 100.0
pod 0 2 0.0
total 149 209 71.2


line stmt bran cond sub pod time code
1             package STF::Dispatcher::Test;
2 1     1   21565 use strict;
  1         3  
  1         33  
3 1     1   4 use base qw(Exporter);
  1         3  
  1         88  
4 1     1   814 use Plack::Test ();
  1         1767  
  1         21  
5 1     1   890 use HTTP::Date ();
  1         4566  
  1         60  
6 1     1   1016 use HTTP::Request::Common qw(PUT HEAD GET DELETE POST);
  1         32912  
  1         185  
7 1     1   13 use Test::More;
  1         2  
  1         18  
8              
9             our @EXPORT = qw( test_stf_impl );
10              
11             sub test_stf_impl {
12 2     2 0 7564 my $impl = shift;
13 2         24 Plack::Test::test_psgi(
14             app => STF::Dispatcher::PSGI->new( impl => $impl )->to_app,
15             client => \&run_tests,
16             );
17             }
18              
19             sub run_tests {
20 2     2 0 11607 my $cb = shift;
21              
22 2         6 my $res;
23             my $randstr = sub {
24 10     10   16 my $len = shift;
25 10         284 my @chars = ('a'..'z', 0..9);
26 10         24 return join '', map { $chars[rand @chars] } 1..$len;
  80         315  
27 2         22 };
28 2         9 my $bucket_name = $randstr->(8);
29 2         10 my $object_name = (join "/", map { $randstr->(8) } 1..4) . '.txt';
  8         17  
30              
31 2         18 $res = $cb->(
32             PUT "http://127.0.0.1/$bucket_name/should_fail"
33             );
34 2 50       1560 if (! ok ! $res->is_success, "bucket creation request with object_name should fail") {
35 0         0 diag $res->as_string;
36             }
37              
38 2         934 $res = $cb->(
39             GET "http://127.0.0.1/$bucket_name/should_fail"
40             );
41 2 50       1304 if (ok ! $res->is_success, "bucket fetch with non-existing bucket should fail") {
42 2         17364 is $res->code, 404, "HTTP status should be 404";
43             } else {
44 0         0 diag $res->as_string;
45             }
46            
47 2         607 $res = $cb->(
48             PUT "http://127.0.0.1/$bucket_name"
49             );
50 2 50       798 if (! ok $res->is_success, "bucket creation request was successful") {
51 0         0 diag $res->as_string;
52             }
53              
54             # Creating a bucket again should respond with a 204
55 2         1045 $res = $cb->(
56             PUT "http://127.0.0.1/$bucket_name"
57             );
58 2 50       904 if (! ok $res->is_success, "bucket creation request (again) was successful") {
59 0         0 diag $res->as_string;
60             }
61 2 50       1032 if (! is $res->code, 204, "status should be 204") {
62 0         0 diag $res->as_string;
63             }
64              
65 2         815 my $content = join ".", $$, time(), {}, rand();
66              
67             # Creating an object with non-existent bucket should fail
68 2         19 $res = $cb->(
69             PUT "http://127.0.0.1/$bucket_name-non-existent/$object_name",
70             "X-Replication-Count" => 3,
71             "Content-Type" => "text/plain",
72             Content => $content,
73             );
74 2 50       2825 if (! ok ! $res->is_success, "object creation request should fail") {
75 0         0 diag $res->as_string;
76             }
77              
78             # Creating an object without giving an object name should fail
79 2         1161 $res = $cb->(
80             PUT "http://127.0.0.1/$bucket_name",
81             "X-Replication-Count" => 3,
82             "Content-Type" => "text/plain",
83             Content => $content,
84             );
85 2 50       801 if (! ok ! $res->is_success, "object creation request should fail") {
86 0         0 diag $res->as_string;
87             }
88              
89             # normal object creation
90 2         867 $res = $cb->(
91             PUT "http://127.0.0.1/$bucket_name/$object_name",
92             "X-Replication-Count" => 3,
93             "Content-Type" => "text/plain",
94             Content => $content,
95             );
96 2 50       1955 if (! ok $res->is_success, "object creation request was successful") {
97 0         0 diag $res->as_string;
98             }
99              
100             # Get an object with a bad object name
101 2         2169 $res = $cb->(
102             GET "http://127.0.0.1/$bucket_name/$object_name-non-existent",
103             );
104 2 50       9030 if (! ok ! $res->is_success, "object fetch request should fail") {
105 0         0 diag $res->as_string;
106             }
107              
108 2         1015 $res = $cb->(
109             GET "http://127.0.0.1/$bucket_name/$object_name",
110             );
111 2         1162 is $res->content, $content, "content matches";
112 2         809 is $res->header('X-Content-Type-Options'), 'nosniff', "nosniff is on";
113              
114 2 50       646 if ( my $last_mod = $res->header('Last-Modified') ) {
115 2         93 my $last_mod_t = HTTP::Date::str2time($last_mod);
116 2         147 $res = $cb->(
117             GET "http://127.0.0.1/$bucket_name/$object_name",
118             "If-Modified-Since" => $last_mod
119             );
120 2 50       1124 if ( ! is $res->code, 200, "code is 200") {
121 0         0 diag $res->as_string;
122             }
123 2         576 is $res->header('X-Content-Type-Options'), 'nosniff', "nosniff is on";
124              
125 2         2551 $res = $cb->(
126             GET "http://127.0.0.1/$bucket_name/$object_name",
127             "If-Modified-Since" => HTTP::Date::time2str($last_mod_t - 30)
128             );
129 2 50       692 if (! is $res->code, 304, "code is 304!") {
130 0         0 diag $res->as_string;
131             }
132             }
133              
134              
135             TODO: {
136             # Content-Type handling should probably be removed from
137             # STF::Dispatcher
138 2         763 todo_skip "This is probably not necessary", 1;
  2         14  
139 0         0 is $res->content_type, "text/plain", "content type matches";
140             }
141              
142 2         271 $res = $cb->(
143             HEAD "http://127.0.0.1/$bucket_name/$object_name",
144             );
145 2         820 ok $res->is_success, "HEAD works";
146 2         546 ok ! $res->content, "Should have no body";
147              
148             # Modify the object
149 2         471 $res = $cb->(
150             POST "http://127.0.0.1/$bucket_name/$object_name",
151             );
152 2         768 ok $res->is_success, "POST works";
153              
154              
155             # Deleting an object with a bad bucket name
156 2         2097 $res = $cb->(
157             DELETE "http://127.0.0.1/$bucket_name-non-existent/$object_name"
158             );
159 2 50       841 if (! ok ! $res->is_success, "object deletion request should fail") {
160 0         0 diag $res->as_string;
161             }
162              
163             # Deleting an object with a bad object name
164 2         716 $res = $cb->(
165             DELETE "http://127.0.0.1/$bucket_name/$object_name-non-existent"
166             );
167 2 50       644 if (! ok ! $res->is_success, "object deletion request should fail") {
168 0         0 diag $res->as_string;
169             }
170              
171             # Normal object deletion
172 2         575 $res = $cb->(
173             DELETE "http://127.0.0.1/$bucket_name/$object_name"
174             );
175 2 50       748 if (! ok $res->is_success, "object deletion request was successful") {
176 0         0 diag $res->as_string;
177             }
178              
179             # now that the object is deleted, this should fail
180 2         657 $res = $cb->(
181             GET "http://127.0.0.1/$bucket_name/$object_name",
182             );
183 2 50       669 if (! is $res->code, 404, "get after delete is 404" ) {
184 0         0 diag $res->as_string;
185             }
186 2         622 is $res->header('X-Content-Type-Options'), 'nosniff', "nosniff is on";
187              
188             # Create another object (use same name, cause we're lazy)
189 2         554 $res = $cb->(
190             PUT "http://127.0.0.1/$bucket_name/$object_name",
191             "X-Replication-Count" => 3,
192             "Content-Type" => "text/plain",
193             Content => $content,
194             );
195 2 50       1007 if (! ok $res->is_success, "object creation request was successful") {
196 0         0 diag $res->as_string;
197             }
198              
199             # XXX Rename object/bucket
200 2         728 note "Testing MOVE object/bucket";
201             {
202 2         118 my $move_req = HTTP::Request->new(MOVE => "http://127.0.0.1/$bucket_name/$object_name");
  2         20  
203 2         271 $move_req->header( "X-STF-Move-Destination" => "/$bucket_name/$object_name.2" );
204 2         541 $res = $cb->( $move_req );
205 2 50       829 if (! is $res->code, 201, "move should result in 201" ) {
206 0         0 diag $res->as_string;
207             }
208            
209 2         2698 $res = $cb->(
210             GET "http://127.0.0.1/$bucket_name/$object_name",
211             );
212 2 50       1423 if (! is $res->code, 404, "get after move is 404" ) {
213 0         0 diag $res->as_string;
214             }
215              
216 2         623 $res = $cb->(
217             GET "http://127.0.0.1/$bucket_name/$object_name.2",
218             );
219 2 50       763 if (! is $res->code, 200, "get new url after move is 200" ) {
220 0         0 diag $res->as_string;
221             }
222              
223             # Move from bucket_name to bucket_name.2
224 2         597 $move_req = HTTP::Request->new(MOVE => "http://127.0.0.1/$bucket_name/$object_name.2" );
225 2         247 $move_req->header( "X-STF-Move-Destination" => "/$bucket_name.2/$object_name" );
226 2         140 $res = $cb->( $move_req );
227 2 50       739 if (! is $res->code, 500, "move to non-existent bucket should fail" ) {
228 0         0 diag $res->as_string;
229             }
230              
231 2         1912 $res = $cb->( PUT "http://127.0.0.1/$bucket_name.2" );
232 2 50       591 if (! is $res->code, 201, "create new bucket should be 201" ) {
233 0         0 diag $res->as_string;
234             }
235              
236 2         2455 $res = $cb->( $move_req );
237 2 50       677 if (! is $res->code, 201, "move to another bucket should be 201" ) {
238 0         0 diag $res->as_string;
239             }
240              
241             # Rename bucket_name.2 to bucket_name. this should fail
242              
243 2         590 $move_req = HTTP::Request->new(MOVE => "http://127.0.0.1/$bucket_name.2");
244 2         249 $move_req->header( "X-STF-Move-Destination" => "/$bucket_name" );
245 2         126 $res = $cb->( $move_req );
246 2 50       723 if (! is $res->code, 500, "renaming bucket to an existing one should fail") {
247 0         0 diag $res->as_string;
248             }
249              
250             # Rename bucket_name.2 to bucket_name.3. This should succeed
251 2         967 $move_req->header( "X-STF-Move-Destination" => "/$bucket_name.3" );
252 2         113 $res = $cb->( $move_req );
253 2 50       796 if (! is $res->code, 201, "renaming bucket to a new name should be 201" ) {
254 0         0 diag $res->as_string;
255             }
256              
257             # Get the object for sanity
258 2         595 $res = $cb->( GET "http://127.0.0.1/$bucket_name.3/$object_name" );
259 2 50       993 if (! is $res->code, 200, "GET on the renamed bucket + object should be 200" ) {
260 0         0 diag $res->as_string;
261             }
262 2         712 is $res->content, $content, "content matches";
263             }
264              
265             # Create another object (use same name, cause we're lazy)
266 2         633 $res = $cb->(
267             PUT "http://127.0.0.1/$bucket_name/$object_name",
268             "X-Replication-Count" => 3,
269             "Content-Type" => "text/plain",
270             Content => $content,
271             );
272 2 50       866 if (! ok $res->is_success, "object creation request was successful") {
273 0         0 diag $res->as_string;
274             }
275              
276             # non-existent bucket deletion should fail
277 2         793 $res = $cb->(
278             DELETE "http://127.0.0.1/$bucket_name-non-existent"
279             );
280 2 50       844 if (! is $res->code, 404, "bucket deletion request was 404") {
281 0         0 diag $res->as_string;
282             }
283              
284             # normal bucket deletion
285 2         705 $res = $cb->(
286             DELETE "http://127.0.0.1/$bucket_name"
287             );
288 2 50       872 if (! is $res->code, 204, "bucket deletion request was 204") {
289 0           diag $res->as_string;
290             }
291             }
292              
293             1;
294              
295             __END__