File Coverage

blib/lib/Couchbase/Test/Views.pm
Criterion Covered Total %
statement 51 169 30.1
branch 0 8 0.0
condition n/a
subroutine 17 26 65.3
pod 1 9 11.1
total 69 212 32.5


line stmt bran cond sub pod time code
1             package Couchbase::Test::Views;
2 2     2   760 use strict;
  2         4  
  2         62  
3 2     2   6 use warnings;
  2         2  
  2         42  
4 2     2   6 use base qw(Couchbase::Test::Common);
  2         2  
  2         110  
5 2     2   8 use Test::More;
  2         2  
  2         10  
6 2     2   356 use Couchbase::Client;
  2         4  
  2         34  
7 2     2   6 use Couchbase::Client::Errors;
  2         2  
  2         178  
8 2     2   8 use Data::Dumper;
  2         2  
  2         82  
9             use Class::XSAccessor {
10 2         12 accessors => [ qw(cbo) ]
11 2     2   8 };
  2         2  
12              
13             use constant {
14 2         250 DESIGN_NAME => "blog"
15 2     2   258 };
  2         2  
16              
17             my $DESIGN_JSON = {
18             _id => "_design/blog",
19             language => "javascript",
20             views => {
21             recent_posts => {
22             map => 'function(doc) ' .
23             '{ if (doc.date && doc.title) ' .
24             '{ emit(doc.date, doc.title); } }'
25             }
26             }
27             };
28              
29             sub SKIP_CLASS {
30              
31 0 0   0 1   if (!$Couchbase::Test::Common::RealServer) {
32 0           return 1;
33             }
34              
35 0           return 0;
36             }
37              
38             sub setup_client :Test(startup) {
39 0     0 0 0 my $self = shift;
40 0         0 $self->cbo( $self->make_cbo );
41 2     2   8 }
  2         2  
  2         8  
42              
43             sub TV01_create_ddoc :Test(no_plan) {
44              
45 0     0 0 0 my $self = shift;
46 0         0 my $o = $self->cbo;
47 0         0 my $ret = $o->couch_design_put($DESIGN_JSON);
48 0         0 ok($ret->is_ok, "Design doc put did not return errors");
49              
50 0         0 my $design = $o->couch_design_get(DESIGN_NAME);
51              
52 0         0 isa_ok($design, 'Couchbase::Couch::Design');
53 0         0 is($design->path, '_design/blog', "Have path");
54 0         0 is($design->http_code, 200, "Have HTTP 200");
55 0         0 ok($design->is_ok, "Overall object OK");
56 0         0 is_deeply($design->value, $DESIGN_JSON, "Got back view");
57 2     2   566 }
  2         4  
  2         4  
58              
59             sub TV02_create_invalid_ddoc :Test(no_plan) {
60 0     0 0 0 my $self = shift;
61 0         0 my $o = $self->cbo;
62              
63 0         0 eval {
64 0         0 $o->couch_design_put("blah");
65 0         0 }; like($@, '/path cannot be empty/');
66              
67 0         0 my $ret = $o->couch_design_put({
68             _id => "_design/meh",
69             views => {
70             foo => "blehblehbleh"
71             }
72             });
73              
74 0         0 is($ret->http_code, 400, "Got error for invalid view");
75 0         0 is($ret->errinfo->{error}, "invalid_design_document");
76 2     2   490 }
  2         4  
  2         6  
77              
78             sub TV03_view_query :Test(no_plan) {
79 0     0 0 0 my $self = shift;
80 0         0 my $o = $self->cbo;
81              
82             # First, load up the keys
83 0         0 my @posts = (
84             [ "bought-a-cat" => {
85             title => "bought-a-cat",
86             body => "I went to the pet store earlier and brought home a little kitty",
87             date => "2009/01/30 18:04:11"
88             }],
89             [ "biking" => {
90             title => "Biking",
91             body => "My biggest hobby is mountainbiking. The other day..",
92             date => "2009/01/30 18:04:11"
93             }],
94             [ "hello-world" => {
95             title => "Hello World",
96             body => "Well hello and welcome to my new blog...",
97             date => "2009/01/15 15:52:20"
98             }]
99             );
100              
101 0         0 my %dkeys = map { $_->[0], 1 } @posts;
  0         0  
102              
103             # See if we can slurp the view
104 0         0 my $res = $o->couch_view_slurp(["blog", "recent_posts"], stale => "false");
105              
106 0         0 my @rm_errors = ();
107 0         0 foreach my $id (map $_->{id}, @{ $res->value }) {
  0         0  
108 0         0 my $rv = $o->remove($id);
109 0 0       0 if (!$rv->is_ok) {
110 0         0 push @rm_errors, $rv;
111             }
112             }
113              
114 0         0 ok(!@rm_errors);
115              
116 0         0 my $results = $o->couch_set_multi(@posts);
117 0         0 my @errkeys = grep { !$results->{$_}->is_ok } keys %$results;
  0         0  
118 0         0 ok(!@errkeys, "No store errors");
119 0         0 $res = $o->couch_view_slurp(["blog", "recent_posts"],
120             stale => "false");
121 0         0 isa_ok($res, 'Couchbase::Couch::HandleInfo');
122              
123 0         0 my %rkeys = map { $_->{id}, 1 } @{ $res->value };
  0         0  
  0         0  
124 0         0 is_deeply(\%rkeys, \%dkeys, "Got back the same rows");
125              
126 0         0 %rkeys = ();
127             # Try with the view iterator
128 0         0 my $iter = $o->couch_view_iterator(["blog", "recent_posts"]);
129 0         0 my $rescount = 0;
130 0         0 while (my $row = $iter->next) {
131 0         0 $rescount++;
132 0         0 $rkeys{$row->id} = 1;
133             }
134              
135 0         0 is_deeply(\%rkeys, \%dkeys, "View Iterator");
136 2     2   832 }
  2         4  
  2         6  
137              
138             sub TV04_vq_errors :Test(no_plan) {
139 0     0 0 0 my $self = shift;
140 0         0 my $o = $self->cbo;
141              
142 0         0 my $res = $o->couch_view_slurp(["nonexist", "nonexist"]);
143 0         0 isa_ok($res, 'Couchbase::Couch::HandleInfo');
144 0         0 ok(!$res->is_ok);
145 0         0 is($res->http_code, 404);
146              
147 0         0 my $path_re = '/path/i';
148              
149 0         0 eval {
150 0         0 $res = $o->couch_view_slurp();
151 0         0 }; like($@, $path_re);
152              
153 0         0 eval {
154 0         0 $res = $o->couch_view_slurp([]);
155 0         0 }; like($@, $path_re);
156              
157 0         0 eval {
158 0         0 $res = $o->couch_view_slurp([undef, undef]);
159 0         0 }; like($@, $path_re);
160              
161             # Test with invalid view parameters
162 0         0 $res = $o->couch_view_slurp(["blog", "recent_posts"],
163             'include_docs' => 'bad ^VALUE^');
164 0         0 is($res->http_code, 400);
165 2     2   686 }
  2         4  
  2         6  
166              
167             sub TV05_empty_rows :Test(no_plan) {
168 0     0 0 0 my $self = shift;
169 0         0 my $o = $self->cbo;
170 0         0 my $res = $o->couch_view_slurp(['blog', 'recent_posts'],
171             limit => 0);
172 0         0 is_deeply($res->value, [], "No rows");
173              
174              
175 0         0 $res = $o->couch_view_iterator(['blog', 'recent_posts'],
176             limit => 0);
177              
178 0         0 ok(!$res->next);
179 0         0 is($res->info->http_code, 200);
180 2     2   450 }
  2         4  
  2         6  
181              
182             sub TV06_iterator :Test(no_plan) {
183 0     0 0 0 my $self = shift;
184              
185 0         0 my $iter;
186             {
187 0         0 my $o = $self->make_cbo();
  0         0  
188 0         0 $iter = $o->couch_view_iterator(['blog', 'recent_posts']);
189             }
190 0         0 ok($iter->next, "Iterator keeps object in scope");
191              
192 0         0 $iter->stop();
193 0         0 ok($iter->count, "Can get count");
194              
195              
196             # Create a rather long view/design document, so that
197             # we can guarantee to get a split buffer.
198              
199 0         0 my $mapfn = <
200             function (doc) {
201             if (doc.tv06_iterator) {
202             emit(doc.tv06_iterator);
203             }
204             }
205             EOF
206              
207 0         0 my $d_json = {
208             _id => '_design/tv06',
209             language => 'javascript',
210             views => {
211             tv06 => {
212             map => $mapfn
213             }
214             }
215             };
216              
217 0         0 my $o = $self->cbo;
218 0         0 my $rv = $o->couch_design_put($d_json);
219 0         0 ok($rv->is_ok);
220              
221 0         0 my @objs = ();
222 0         0 foreach my $i (0..2000) {
223 0         0 my $kv = ['key-tv06-'.$i, {'tv06_iterator' => $i}];
224 0         0 push @objs, $kv;
225             }
226 0         0 my $rvs = $o->couch_set_multi(@objs);
227              
228             # Make sure there are no store errors
229 0         0 my @errs = grep { !$rvs->{$_}->is_ok } keys %$rvs;
  0         0  
230 0         0 ok(!@errs, "No store errors");
231              
232             # Now, query the view
233 0         0 $iter = $o->couch_view_iterator(['tv06', 'tv06'],
234             stale => 'false', limit => '100');
235             # Do we have a count?
236              
237 0         0 my %rkeys;
238 0         0 my @kv_errors = ();
239 0         0 my @rows;
240 0         0 do {
241 0         0 @rows = $iter->next;
242 0         0 my $krv = $o->set("foo", "bar");
243 0 0       0 if (!$krv->is_ok) {
244 0         0 push @kv_errors, $krv;
245             }
246             } while (@rows);
247              
248 0         0 ok(!@kv_errors, "No errors during async handle usage");
249 2     2   814 }
  2         2  
  2         8  
250              
251             sub TV07_synopsis :Test(no_plan) {
252 0     0 0   my $self = shift;
253 0           my $client = $self->cbo;
254              
255 0           my $ddoc = {
256             '_id' => '_design/blog',
257             language => 'javascript',
258             views => {
259             'recent-posts' => {
260             map => 'function(d) { if(d.date) { emit(d.date, d.title); }}'
261             }
262             }
263             };
264              
265 0           my $rv = $client->couch_design_put($ddoc);
266 0 0         if (!$rv->is_ok) {
267             # check for possible errors here..
268             }
269              
270             # Now, let's load up some documents
271              
272 0           my @posts = (
273             ["i-like-perl" => {
274             title => "Perl is cool",
275             date => "4/26/2013"
276             }],
277             ["couchbase-and-perl" => {
278             title => "Couchbase::Client is super fast",
279             date => "4/26/2013"
280             }]
281             );
282              
283             # This is a convenience around set_multi. It encodes values into JSON
284 0           my $rvs = $client->couch_set_multi(@posts);
285              
286             # Now, query the view. We use stale = 'false' to ensure consistency
287              
288 0           $rv = $client->couch_view_slurp(['blog', 'recent-posts'], stale => 'false');
289              
290             # Now dump the rows to the screen
291             # OK, this is test code. We can't dump to screen, but we can ensure that
292             # this works "in general"
293 0           ok($rv->value->[0]->{id});
294 2     2   516 }
  2         4  
  2         6  
295              
296             1;