File Coverage

blib/lib/Devel/hdb/Client.pm
Criterion Covered Total %
statement 297 318 93.4
branch 35 44 79.5
condition 9 12 75.0
subroutine 65 69 94.2
pod 22 27 81.4
total 428 470 91.0


line stmt bran cond sub pod time code
1             package Devel::hdb::Client;
2              
3 37     37   1358279 use strict;
  37         395  
  37         933  
4 37     37   175 use warnings;
  37         57  
  37         1131  
5              
6 37     37   19214 use LWP::UserAgent;
  37         1386338  
  37         1213  
7 37     37   19245 use JSON;
  37         297124  
  37         224  
8 37     37   4816 use Carp;
  37         76  
  37         2049  
9 37     37   16682 use Data::Dumper;
  37         188469  
  37         2244  
10 37     37   257 use URI::Escape qw();
  37         69  
  37         740  
11 37     37   13750 use Data::Transform::ExplicitMetadata '0.02';
  37         164780  
  37         4881  
12 37     37   289 use Scalar::Util qw(reftype);
  37         80  
  37         1545  
13              
14 37     37   14601 use Devel::hdb::Utils;
  37         87  
  37         2177  
15              
16             our $VERSION = '0.24';
17              
18             use Exception::Class (
19 37         419 'Devel::hdb::Client::Exception',
20             'Devel::hdb::Client::RequiredParameterMissing' => {
21             isa => 'Devel::hdb::Client::Exception',
22             description => 'Required parameter missing',
23             fields => ['params'],
24             },
25             'Devel::hdb::Client::Exception::HTTP' => {
26             isa => 'Devel::hdb::Client::Exception',
27             fields => [qw( http_code http_message http_content )],
28             },
29             'Devel::hdb::Client::Exception::Eval' => {
30             isa => 'Devel::hdb::Client::Exception',
31             },
32             'Devel::hdb::Client::Exception::Error' => {
33             isa => 'Devel::hdb::Client::Exception',
34             },
35 37     37   14592 );
  37         262590  
36              
37             my $JSON ||= JSON->new->utf8->allow_nonref();
38              
39             sub new {
40 38     38 1 786463 my $class = shift;
41 38         896 my %params = @_;
42              
43 38         425 my %self;
44 38         666 $self{base_url} = delete $params{url};
45 38 50       659 unless ($self{base_url}) {
46 0         0 Devel::hdb::Client::RequiredParameterMissing->throw(params => ['url']);
47             }
48              
49 38         444 $self{debug} = delete $params{debug};
50 38         913 $self{base_url} =~ s{/$}{};
51              
52 38         1644 $self{http_client} = LWP::UserAgent->new();
53 38         132449 $self{http_client}->agent("Devel::hdb::Client/$VERSION");
54              
55 38         3020 return bless \%self, $class;
56             }
57              
58             sub stack {
59 41     41 1 21145 my($self, %params) = @_;
60              
61 41         187 my $url = 'stack';
62 41 100       230 if ($params{exclude_sub_params}) {
63 1         62 $url .= '?exclude_sub_params=1';
64             }
65              
66 41         396 my $response = $self->_GET($url);
67 41         214 _assert_success($response, q(Can't get stack position));
68 41         764 my $stack = $JSON->decode($response->content);
69 41         2583 foreach my $frame ( @$stack ) {
70 62         495 $frame->{args} = _decode_stack_frame_args($frame->{args});
71             }
72 41         583 return $stack;
73             }
74              
75             sub stack_depth {
76 1     1 0 2381 my $self = shift;
77              
78 1         14 my $response = $self->_HEAD('stack');
79 1         4 _assert_success($response, q(Can't get stack depth));
80 1         12 return $response->header('X-Stack-Depth');
81             }
82              
83              
84             sub stack_frame {
85 12     12 1 68064 my($self, $level, %params) = @_;
86              
87 12         51 my $url = join('/', 'stack', $level);
88 12 100       53 if ($params{exclude_sub_params}) {
89 6         14 $url .= '?exclude_sub_params=1';
90             }
91              
92 12         54 my $response = $self->_GET($url);
93 12         57 _assert_success($response, q(Can't get stack frame));
94 12         197 my $frame = $JSON->decode($response->content);
95 12         492 $frame->{args} = _decode_stack_frame_args($frame->{args});
96              
97 12         172 return $frame;
98             }
99              
100             sub _decode_stack_frame_args {
101 74     74   206 my $args = shift;
102 74 100       347 return unless $args;
103 62         126 [ map { Data::Transform::ExplicitMetadata::decode($_) } @{$args} ];
  13         112  
  62         238  
104             }
105              
106             sub stack_frame_signature {
107 12     12 1 58905 my($self, $level) = @_;
108              
109 12         100 my $response = $self->_HEAD(join('/', 'stack', $level));
110 12         54 _assert_success($response, q(Can't get stack frame));
111              
112 12         174 return ( $response->header('X-Stack-Serial'),
113             $response->header('X-Stack-Line') );
114             }
115              
116              
117 3     3   42194 sub _gui_url { 'debugger-gui' }
118              
119             sub gui {
120 1     1 1 2822 my $self = shift;
121              
122 1         11 my $response = $self->_GET( _gui_url );
123 1         7 _assert_success($response, q(Can't get debugger gui'));
124 1         24 return $response->content;
125             }
126              
127             sub _deserialize_status {
128 71     71   2382 my $status = shift;
129 71 100 100     461 if ($status->{events}
130             and
131 16         141 my @watchpoint_events = grep { $_->{type} eq 'watchpoint' } @{$status->{events}}
  16         73  
132             ) {
133 4         11 foreach my $event ( @watchpoint_events ) {
134 4         36 $event->{$_} = Data::Transform::ExplicitMetadata::decode($event->{$_}) foreach (qw(old new));
135             }
136             }
137 71         1595 return $status;
138             }
139              
140             sub _encode_url {
141 72     72   521 my $base = shift;
142 72         170 my @params;
143 72         375 for(my $i = 0; $i < @_; $i += 2) {
144 8 50       34 if (defined $_[$i + 1]) {
145 8         55 push @params, join('=', @_[$i, $i+1])
146             } else {
147 0         0 push @params, $_[$i];
148             }
149             }
150 72         420 return join('', $base, '?', join('&', @params));
151             }
152              
153             sub _validate_params {
154 72     72   181 my $params = shift;
155 72         226 my %allowed = map { $_ => 1 } @_;
  184         842  
156 72         440 for (my $i = 0; $i < @$params; $i += 2) {
157 8 50       46 unless (exists $allowed{ $params->[$i] }) {
158 0         0 Carp::croak('Unrecognized param ' . $params->[$i]);
159             }
160             }
161 72         259 return 1;
162             }
163              
164             sub stepin {
165 11     11 1 12617 my $self = shift;
166              
167 11         64 _validate_params(\@_, qw(next_statement next_fragment));
168 11         71 my $url = _encode_url('stepin', @_);
169 11         55 my $response = $self->_POST($url);
170 11         53 _assert_success($response, q(Can't stepin));
171 11         162 return _deserialize_status $JSON->decode($response->content);
172             }
173              
174             sub stepover {
175 14     14 1 15762 my $self = shift;
176              
177 14         77 _validate_params(\@_, qw(next_statement next_fragment));
178 14         109 my $url = _encode_url('stepover', @_);
179 14         61 my $response = $self->_POST($url);
180 14         55 _assert_success($response, q(Can't stepover));
181 14         173 return _deserialize_status $JSON->decode($response->content);
182             }
183              
184             sub stepout {
185 4     4 1 3193 my $self = shift;
186              
187 4         27 _validate_params(\@_, qw(next_statement next_fragment));
188 4         11 my $url = _encode_url('stepout', @_);
189 4         13 my $response = $self->_POST($url);
190 4         14 _assert_success($response, q(Can't stepover));
191 4         42 return _deserialize_status $JSON->decode($response->content);
192             }
193              
194             sub continue {
195 40     40 1 34039 my $self = shift;
196              
197 40         320 _validate_params(\@_, qw(nostop next_statement next_fragment));
198 40         191 my %params = @_;
199 40         267 my $url = _encode_url('continue', %params);
200              
201 40         301 my $response = $self->_POST($url);
202 40         267 _assert_success($response, q(Can't continue'));
203             return $params{nostop}
204 40 100       884 ? 1
205             : _deserialize_status $JSON->decode($response->content);
206             }
207              
208             sub status {
209 3     3 1 1173 my $self = shift;
210              
211 3         48 _validate_params(\@_, qw(next_statement next_fragment));
212 3         15 my $url = _encode_url('status', @_);
213 3         33 my $response = $self->_GET($url);
214 3         14 _assert_success($response, q(Can't get status));
215 3         71 return _deserialize_status $JSON->decode($response->content);
216             }
217              
218             sub overview {
219 1     1 0 20 my $self = shift;
220              
221 1         16 my $response = $self->_GET('');
222 1         5 _assert_success($response, q(Can't get status));
223 1         25 return $JSON->decode($response->content);
224             }
225              
226             sub _create_breakpoint_action_sub {
227 74     74   174 my($type, $required_params, $default_params) = @_;
228              
229             # create_breakpoint() and create_action()
230             return sub {
231 19     19   23306 my $self = shift;
232 19         151 my %params = @_;
233              
234 19         132 _verify_required_params_exist(\%params, $required_params);
235 19         145 _fill_in_default_params(\%params, $default_params);
236              
237 19         106 my $response = $self->_POST("${type}s", \%params);
238 19         156 _assert_success($response, "Can't create $type");
239              
240 15         327 my $bp = $JSON->decode($response->content);
241 15         741 return $bp->{href};
242 74         435 };
243             }
244              
245             my $create_breakpoint = "create_breakpoint";
246             my $create_action = "create_action";
247             {
248 37     37   96506 no strict 'refs';
  37         102  
  37         15400  
249             *$create_breakpoint = _create_breakpoint_action_sub(
250             'breakpoint',
251             [qw( filename line )],
252             { code => 1, inactive => 0 } );
253             *$create_action = _create_breakpoint_action_sub(
254             'action',
255             [qw( filename line code )],
256             { inactive => 0 } );
257             }
258              
259             foreach my $type ( qw(breakpoint action) ) {
260             # change_breakpoint() and change_action()
261             my $change_subname = "change_$type";
262             my $change = sub {
263 8     8   10879 my($self, $bp, %params) = @_;
264              
265 8         38 my $response = $self->_POST($bp, \%params);
266 8         60 _assert_success($response, "Can't $change_subname");
267 6         94 return $JSON->decode($response->content);
268             };
269              
270             # delete_breakpoint() and delete_action()
271             my $delete_subname = "delete_$type";
272             my $delete = sub {
273 4     4   8245 my($self, $href) = @_;
274              
275 4         18 my $response = $self->_DELETE($href);
276 4         25 _assert_success($response, "Can't $delete_subname");
277 3         49 return 1;
278             };
279              
280             # get_breakpoint() and get_action()
281             my $get_one_subname = "get_$type";
282             my $get_one = sub {
283 2     2   6147 my($self, $href) = @_;
284              
285 2         11 my $response = $self->_GET($href);
286 2         11 _assert_success($response, "Can't $get_one_subname");
287              
288 1         11 my $bp = $JSON->decode($response->content);
289 1         23 return $bp;
290             };
291              
292             my $get_multiple_subname = "get_${type}s";
293             my $get_multiple = do {
294             my @recognized_params = qw(filename line code inactive);
295              
296             # get_breakpoints() and get_actions()
297             sub {
298 9     9   9408 my $self = shift;
299 9         34 my %filters = @_;
300              
301 9         65 _verify_recognized_params(\%filters, \@recognized_params);
302              
303 9         34 my $url = "${type}s";
304 9         54 my $query_string = _encode_query_string_for_hash(%filters);
305 9 100       37 $url .= '?' . $query_string if length($query_string);
306 9         64 my $response = $self->_GET($url);
307 9         50 _assert_success($response, "Can't $get_multiple_subname");
308              
309 9         151 return $JSON->decode($response->content);
310             };
311             };
312              
313 37     37   269 no strict 'refs';
  37         80  
  37         14146  
314             *$change_subname = $change;
315             *$delete_subname = $delete;
316             *$get_one_subname = $get_one;
317             *$get_multiple_subname = $get_multiple;
318             }
319              
320             sub loaded_files {
321 4     4 1 4832 my $self = shift;
322              
323 4         21 my $response = $self->_GET('source');
324 4         24 _assert_success($response, q(Can't get loaded files));
325              
326 4         65 return $JSON->decode($response->content);
327             }
328              
329             sub file_source_and_breakable {
330 4     4 1 3581 my($self, $filename) = @_;
331              
332 4         16 my $escaped_filename = URI::Escape::uri_escape($filename);
333 4         157 my $response = $self->_GET(join('/', 'source', $escaped_filename));
334 4         20 _assert_success($response, "Can't get source for $filename");
335              
336 2         24 return $JSON->decode($response->content);
337             }
338              
339             sub eval {
340 22     22 1 22045 my($self, $eval_string) = @_;
341              
342 22         235 my $string_was_fixed_up = $eval_string ne Devel::hdb::Utils::_fixup_expr_for_eval($eval_string);
343              
344 22         158 my %params = ( 'wantarray' => wantarray, code => $eval_string );
345 22         140 my $response = $self->_POST('eval', \%params);
346              
347 22         134 my $result = Data::Transform::ExplicitMetadata::decode($JSON->decode($response->content));
348              
349 22 100       2304 if ($response->code == 409) {
350 1         56 Devel::hdb::Client::Exception::Eval->throw(
351             error => $result
352             );
353             }
354 21         402 _assert_success($response, q(eval failed));
355              
356 21         290 return _return_eval_data($result, $string_was_fixed_up);
357             }
358              
359             sub _return_eval_data {
360 21     21   72 my($result, $string_was_fixed_up) = @_;
361              
362 21         86 my $reftype = reftype($result);
363              
364 21 50 66     117 if (wantarray and $reftype and $reftype ne 'ARRAY') {
      66        
365 0         0 Devel::hdb::Exception::Error->throw(
366             error => "Expected ARRAY ref but got $reftype"
367             );
368             }
369              
370 21         86 return _return_unfixed_value_from_eval($string_was_fixed_up, $result);
371             }
372              
373             sub _return_unfixed_value_from_eval {
374 21     21   48 my $was_fixed_up = shift;
375 21         46 my $val = shift;
376              
377 37     37   274 no warnings 'uninitialized';
  37         70  
  37         58182  
378              
379 21 100       71 if ($was_fixed_up) {
380 2 100 66     21 if (wantarray and reftype($val->[0]) eq 'HASH') {
    50          
381 1         3 return %{ $val->[0] };
  1         18  
382             } elsif (reftype($val) eq 'GLOB') {
383 1         17 return *$val;
384             }
385             }
386              
387 19 100       60 if (wantarray) {
388 3         37 return @$val;
389             } else {
390 16         226 return $val;
391             }
392             }
393              
394             sub list_vars_at_level {
395 0     0 0 0 my($self, $level) = @_;
396              
397             }
398              
399             sub get_var_at_level {
400 32     32 1 26428 my($self, $varname, $level) = @_;
401              
402 32         134 my $string_was_fixed_up = $varname ne Devel::hdb::Utils::_fixup_expr_for_eval($varname);
403              
404 32         105 my $escaped_varname = URI::Escape::uri_escape($varname);
405 32         811 my $response = $self->_GET(join('/', 'getvar', $level, $escaped_varname));
406 32         152 _assert_success($response, "Can't get $varname at level $level");
407              
408 32         386 return Data::Transform::ExplicitMetadata::decode($JSON->decode($response->content));
409             }
410              
411             sub load_config {
412 1     1 1 3866 my($self, $filename) = @_;
413              
414 1         7 my $escaped_filename = URI::Escape::uri_escape($filename);
415 1         67 my $response = $self->_POST(join('/', 'loadconfig', $escaped_filename));
416 1         10 _assert_success($response, "Loading config from $filename failed: " . $response->content);
417              
418 1         26 return 1;
419             }
420              
421             sub save_config {
422 1     1 1 1266 my($self, $filename) = @_;
423              
424 1         5 my $escaped_filename = URI::Escape::uri_escape($filename);
425 1         59 my $response = $self->_POST(join('/', 'saveconfig', $escaped_filename));
426 1         7 _assert_success($response, "Save config to $filename failed: " . $response->content);
427              
428 1         19 return 1;
429             }
430              
431             sub exit {
432 1     1 1 610 my $self = shift;
433              
434 1         6 my $response = $self->_POST('exit');
435 1         8 _assert_success($response, q(Can't exit));
436              
437 1         30 return 1;
438             }
439              
440             sub package_info {
441 8     8 1 12668 my($self, $package) = @_;
442              
443 8         41 my $escaped_pkg = URI::Escape::uri_escape($package);
444 8         236 my $response = $self->_GET(join('/', 'packageinfo', $escaped_pkg));
445 8         44 _assert_success($response, "Cannot get info for package $package");
446              
447 7         100 return $JSON->decode($response->content);
448             }
449              
450             sub sub_info {
451 10     10 1 26491 my($self, $subname) = @_;
452              
453 10         43 my $escaped_subname = URI::Escape::uri_escape($subname);
454 10         334 my $response = $self->_GET(join('/', 'subinfo', $escaped_subname));
455 10         47 _assert_success($response, "Cannot get info for subroutine $subname");
456              
457 9         118 return $JSON->decode($response->content);
458             }
459              
460             sub add_watchpoint {
461 1     1 1 1741 my($self, $expr) = @_;
462              
463 1         12 my $escaped_expr = URI::Escape::uri_escape($expr);
464 1         74 my $response = $self->_PUT(join('/', 'watchpoints', $escaped_expr));
465 1         8 _assert_success($response, "Cannot add watchpoint for $expr");
466              
467 1         27 return 1;
468             }
469              
470             sub delete_watchpoint {
471 0     0 1 0 my($self, $expr) = @_;
472              
473 0         0 my $escaped_expr = URI::Escape::uri_escape($expr);
474 0         0 my $response = $self->_DELETE(join('/', 'watchpoints', $escaped_expr));
475 0         0 _assert_success($response, "Cannot delete watchpoint for $expr");
476              
477 0         0 return 1;
478             }
479              
480             sub get_watchpoints {
481 0     0 1 0 my $self = shift;
482              
483 0         0 my $response = $self->_GET('watchpoints');
484 0         0 _assert_success($response, 'Cannot get watchpoints');
485              
486 0         0 return $JSON->decode($response->content);
487             }
488              
489             sub print_optree {
490 0     0 0 0 my $self = shift;
491 0         0 my $response = $self->_GET('print_optree');
492 0         0 _assert_success($response, 'Cannot print_optree');
493             }
494              
495             sub _encode_query_string_for_hash {
496 9     9   20 my @params;
497 9         39 for(my $i = 0; $i < @_; $i += 2) {
498             push @params,
499 8         108 join('=', map { URI::Escape::uri_escape($_) } @_[$i, $i+1]);
  16         183  
500             }
501 9         146 return join('&', @params);
502             }
503              
504             sub _verify_required_params_exist {
505 19     19   62 my($param_hash, $required_list) = @_;
506 19         82 foreach my $required ( @$required_list ) {
507 45 50       147 unless (exists $param_hash->{$required}) {
508 0         0 my $sub_name = (caller())[3];
509 0         0 Carp::croak("$required is a required param of $sub_name");
510             }
511             }
512 19         51 return 1;
513             }
514              
515             sub _verify_recognized_params {
516 9     9   28 my($param_hash, $recognized_list) = @_;
517              
518 9         36 my %recognized = map { $_ => 1 } @$recognized_list;
  36         137  
519              
520 9         60 foreach my $key ( keys %$param_hash ) {
521 8 50       28 Carp::croak("Unrecognized param $key") unless exists $recognized{$key};
522             }
523             }
524              
525             sub _fill_in_default_params {
526 19     19   54 my($params_hash, $defaults) = @_;
527              
528 19         100 foreach my $param_name (keys %$defaults) {
529             $params_hash->{$param_name} = $defaults->{$param_name}
530 31 100       113 unless (exists $params_hash->{$param_name});
531             }
532             }
533              
534 270     270   1381 sub _base_url { shift->{base_url} }
535 268     268   1659 sub _http_client { shift->{http_client} }
536              
537             sub _combined_url {
538 270     270   580 my $self = shift;
539 270         1058 return join('/', $self->_base_url, @_);
540             }
541              
542             sub _http_request {
543 268     268   690 my $self = shift;
544 268         722 my $method = shift;
545 268         599 my $url_ext = shift;
546 268         530 my $body = shift;
547              
548 268         944 my $url = $self->_combined_url($url_ext);
549 268         1729 $self->_dmsg("\nSending $method => $url");
550              
551 268         2270 my $request = HTTP::Request->new($method => $url);
552              
553 268 100       302672 if (defined $body) {
554 49         278 $request->content_type('application/json');
555 49         1796 $request->content($JSON->encode($body));
556             } else {
557 219         1619 $request->content_type('text/html');
558             }
559              
560 268         9614 $self->_dmsg("Request: ",Data::Dumper::Dumper($request));
561 268         1150 my $response = $self->_http_client->request($request);
562 268         11713938 $self->_dmsg('Response ', Data::Dumper::Dumper($response));
563 268         1603 return $response;
564             }
565              
566             sub _dmsg {
567 804     804   74550 my $self = shift;
568 804 50       2463 return unless $self->debug;
569 0         0 print STDERR @_,"\n";
570             }
571              
572             sub _GET {
573 129     129   354 my $self = shift;
574 129         569 $self->_http_request('GET', @_);
575             }
576              
577             sub _POST {
578 121     121   298 my $self = shift;
579 121         544 $self->_http_request('POST', @_);
580             }
581              
582             sub _PUT {
583 1     1   4 my $self = shift;
584 1         6 $self->_http_request('PUT', @_);
585             }
586              
587             sub _HEAD {
588 13     13   42 my $self = shift;
589 13         59 $self->_http_request('HEAD', @_);
590             }
591              
592             sub _DELETE {
593 4     4   11 my $self = shift;
594 4         14 $self->_http_request('DELETE', @_);
595             }
596              
597             sub _assert_success {
598 265     265   596 my $response = shift;
599 265         660 my $error = shift;
600 265 100       1175 unless ($response->is_success) {
601 12         175 Devel::hdb::Client::Exception::HTTP->throw(
602             error => $error . ': ' . $response->message,
603             http_code => $response->code,
604             http_message => $response->message,
605             http_content => $response->content,
606             );
607             }
608             }
609              
610             sub debug {
611 804     804 0 1386 my $self = shift;
612 804 50       2310 if (@_) {
613 0         0 $self->{debug} = shift;
614             }
615 804         2598 return $self->{debug};
616             }
617              
618             1;
619              
620             =pod
621              
622             =head1 NAME
623              
624             Devel::hdb::Client - Perl bindings for Devel::hdb's REST interface
625              
626             =head1 DESCRIPTION
627              
628             Talks to the REST interface of Devel::hdb to control the debugged program.
629             It uses the same interface the HTML/GUI debugger uses, and has all the same
630             capabilities.
631              
632             =head1 SYNOPSIS
633              
634             my $client = Devel::hdb::Client->new(url => 'http://localhost:8080');
635             my $status = $client->status();
636             printf("Stopped in %s at %s:%d\n", @status{'subroutine','filename','line});
637              
638             $status = $client->step();
639              
640             $client->exit();
641              
642             =head1 CONSTRUCTOR
643              
644             my $client = Devel::hdb::Client->new(url => $url);
645              
646             Create a new client instance. C<$url> is the base url the debugger is
647             listening on. In particular, it does _not_ include '/debugger-gui'.
648             new() also accepts the parameter C 1> to turn on the debugging
649             flag; when on, it prints messages to STDERR.
650              
651             =head1 METHODS
652              
653             All methods will throw an exception if the response from the debugger is not
654             a successful response. See L below for more info.
655              
656             =over 4
657              
658             =item $client->stack();
659              
660             Perform GET /stack
661              
662             Return an arrayref of hashrefs. Each hashref is a caller frame. It returns
663             all the same data as L. Their keys are the same as
664             is returned by the caller() built-in:
665              
666             =over 2
667              
668             =item filename
669              
670             =item line
671              
672             =item package
673              
674             =item subroutine
675              
676             =item wantarray
677              
678             =item hasargs
679              
680             =item evaltext
681              
682             =item is_require
683              
684             =item hints
685              
686             =item bitmask
687              
688             =back
689              
690             and a few derived items
691              
692             =over 2
693              
694             =item args
695              
696             An arrayref of arguments to the function. See L below.
697              
698             =item autoload
699              
700             If this frame is a call to &AUTOLOAD, then this will be the
701             name this function was called as.
702              
703             =item evalfile
704              
705             If this frame is a string eval, this is the file the string eval appears.
706              
707             =item evalline
708              
709             If this frame is a string eval, this is the line the string eval appears.
710              
711             =item subname
712              
713             The subroutine name without the package name.
714              
715             =item level
716              
717             A number indicating how deep this caller frame actually is.
718              
719             =item serial
720              
721             A unique identifier for this caller frame. It will stay the same as long
722             as this frame is still active.
723              
724             =back
725              
726             =item $client->stack_frame($level);
727              
728             Perform GET /stack/$level
729              
730             Get a single caller frame. Returns a hashref representing the requested
731             frame. Frames are numbered starting with 0. Frame 0 is the point the debugged
732             program is stopped at. If using this method to scan for frames by repetedly
733             calling stack_frame() with larger numbers, remember that it will throw an
734             exception when retrieving a frame that does not exist (eg. getting frame 10
735             when the stack is only 9 deep).
736              
737             =item $client->stack_frame_signature($level)
738              
739             Perform HEAD /stack/$level
740              
741             Return a 2-element list for the given frame: serial and line. If a particular
742             frame's serial number changes, it is a new function call. If the serial is
743             the same, but the line changes, then the same function call has moved on to
744             a different line.
745              
746             =item $client->gui()
747              
748             Perform GET /debugger-gui and return a string.
749              
750             =item $client->status()
751              
752             Perform GET /status
753              
754             Return a hashref with short information about the debugged program. It has
755             these keys:
756              
757             =over 2
758              
759             =item running - Boolean, true if the program has not yet terminated
760              
761             =item subroutine - Subroutine name the program is stopped in
762              
763             =item filename - File the program is stopped in
764              
765             =item line - Line the program is stopped in
766              
767             =back
768              
769             Additionally, if there were any asynchronous events since the last status-like
770             call, there's a key 'events' containing a listref of hashrefs, one for each
771             event. See the section L below.
772              
773             =item $client->stepin()
774              
775             Perform POST /stepin
776              
777             Tell the debugger to step into the next statement, including function calls.
778             Returns the same hashref as status().
779              
780             =item $client->stepover()
781              
782             Perform POST /stepover
783              
784             Tell the debugger to step over one statement. If the next statment is a
785             function call, it stops immediately after that subroutine returns. Returns
786             the same hashref as status().
787              
788             =item $client->stepout()
789              
790             Perform POST /stepout
791              
792             Tell the debugger to continue until the current function returns. The
793             debugger stops before the next statment after the function call. Returns
794             the same hashref as status().
795              
796             =item $client->continue()
797              
798             Perform POST /continue
799              
800             Tell the debugger to continue running the program. The next time the debugger
801             stops, the call returns the same hashref as status().
802              
803             =item $client->exit()
804              
805             Perform POST /exit
806              
807             Tell the debugger to exit. Returns true.
808              
809             =item $client->create_breakpoint(filename => $file, line => $line, code => $expr, inactive => $bool)
810              
811             =item $client->create_action(filename => $file, line => $line, code => $expr, inactive => $bool)
812              
813             Perform POST /breakpoints or POST /actions
814              
815             Create a breakpoint or action on the given file and line, which are required
816             arguments.
817              
818             'code' is a Perl expression to execute before the actual program line. For
819             breakpoints, if this expression evaluates to true, the debugger will stop
820             before executing that line. It defaults to '1' to create an unconditional
821             breakpoint. For actions, the result is ignored, but 'code' is a required
822             argument.
823              
824             If 'inactive' is true, the breakpoint/action will be saved, but not actually
825             evaluated. Defaults to false.
826              
827             Returns a scalar value representing the breakpoint/action.
828              
829             =item $client->get_breakpoint($bp)
830              
831             =item $client->get_action($bp)
832              
833             Perform GET /breakpoints/ or GET /actions/
834              
835             Return a hashref containing information about the requested breakpoint/action.
836             The arg, $bp, is the scalar returned by create_breakpoint() or create_action().
837             The returned hashref has these keys:
838              
839             =over 2
840              
841             =item filename
842              
843             =item line
844              
845             =item code
846              
847             =item inactive
848              
849             =item href
850              
851             =back
852              
853             =item $client->delete_breakpoint($bp)
854              
855             =item $client->delete_action($bp)
856              
857             Perform DELETE /breakpoints/ or DELETE /actions/
858              
859             Removes the given breakpoint or action. Returns true. Throws an exception if
860             the given breakpoint/action does not exist.
861              
862             =item $client->change_breakpoint($bp, %changes)
863              
864             =item $client->change_breakpoint($bp, %changes)
865              
866             Perform POST /breakpoints/ or POST /actions/
867              
868             Changes parameters for the given breakpoint or action. The only 'code' and
869             'inactive' may be changed.
870              
871             =item $client->get_breakpoints(%filter)
872              
873             =item $client->get_actions(%filter)
874              
875             Perform GET /breakpoints or GET /actions with parameters
876              
877             Find breakpoints or actions matching the given parameters. The %filter
878             is a list of key/value pairs describing what you're looking for. For example:
879              
880             $client->get_breakpoints(filename => 'main.pl')
881              
882             Will return all the breakpoints in the file main.pl.
883              
884             $client->get_breakpoints(inactive => 0)
885              
886             Will return all active breakpoints in the program.
887              
888             You can filter on filename, line, code or inactive. If no filters are used,
889             then it returns all breakpoints or actions.
890              
891             The return value is a listref of hashrefs.
892              
893             =item $client->add_watchpoint($expression)
894              
895             Add a watchpoint expression. These expressions are evaluated before each
896             statement in the program. If their value ever changes, the program will
897             stop and the status will include a 'watchpoint' event indicating which line
898             caused the change.
899              
900             =item $client->delete_watchpoint($expression)
901              
902             Remove a watchpoint expression. It must have been previously added with
903             C or an exception will be thrown.
904              
905             =item $client->get_watchpoints($expression)
906              
907             Return a listref of hashrefs with all the currently set watchpoints. Each
908             hashref has these keys
909              
910             =over 2
911              
912             =item expr
913              
914             The watchpoint expression
915              
916             =item href
917              
918             A URL uniquely identifying this watchpoint
919              
920             =back
921              
922             =item $client->loaded_files()
923              
924             Perform GET /source
925              
926             Return a listref of hashrefs, one for each file currently loaded in the
927             program. Each hashref has a key 'filename' with the name of the file.
928              
929             =item $client->file_source_and_breakable()
930              
931             Perform GET /source/
932              
933             Return a listref of 2-element listrefs. For each 2-elt list, the first
934             element is a string containing the perl source code for that line. The
935             second element is true if that line may contain a breakpoint.
936              
937             =item $client->eval($expr)
938              
939             Perform POST /eval
940              
941             Evaluate an expression in the most recent caller frame of the debugged
942             program. The expression is evaluated in the same context as the call to
943             this method: void, scalar or list.
944              
945             Returns whatever the expression evaluated to. See L below.
946              
947             =item $client->get_var_at_level($varname, $level)
948              
949             Perform GET /getvar//
950              
951             Get the value of the given variable at the given caller frame depth. The
952             variable must contain the sigil. If the frame does not exist, or the variable
953             does not exist at that depth, it will throw an exception.
954              
955             Returns the value of the variable. See L below.
956              
957             =item $client->load_config($filename)
958              
959             Load configuration information from the given filename.
960              
961             =item $client->save_config($filename)
962              
963             Save configuration such as breakpoints, to the given filename.
964              
965             =item $client->package_info($package)
966              
967             Perform GET /packageinfo/$package
968              
969             Get information about the given package. Returns a hashref with these keys
970              
971             =over 2
972              
973             =item name
974              
975             Name of the pckage
976              
977             =item packages
978              
979             Listref of hashrefs, one for each package inside this one. Each hashref has
980             a 'name' key with the name of the package.
981              
982             =item subroutines
983              
984             Listref of hashrefs, one for each subroutine inside this package. Each hashref has
985             a 'name' key with the name of the sub.
986              
987             =back
988              
989             =item $client->sub_info($sub_name)
990              
991             Perform GET /subinfo/$sub_name
992              
993             Return a hashref with information about the named sub. $sub_name should
994             include the package, or 'main::' is assummed.
995              
996             =over 2
997              
998             =item suboroutine
999              
1000             Subroutine name, not including the package
1001              
1002             =item package
1003              
1004             Package name
1005              
1006             =item filename
1007              
1008             File the sub is in
1009              
1010             =item line
1011              
1012             Line the subroutine is defined
1013              
1014             =item end
1015              
1016             Last line where the sub is defined
1017              
1018             =item source
1019              
1020             If the sub was created in a string eval, this is the file the eval happened in
1021              
1022             =item source_line
1023              
1024             Line the string eval happened at
1025              
1026             =back
1027              
1028             =back
1029              
1030             =head1 EVENTS
1031              
1032             The control methods (stepin, stepout, stepover, continue) and status() all
1033             return a data structure that may contain a listref for the key 'events'.
1034             Events are asynchronous events that happened since the last status report.
1035             They all have a 'type' key. Other keys are type specific.
1036              
1037             =head2 fork event
1038              
1039             When the debugged program fork()s, this event is generated in the parent
1040             process.
1041              
1042             =over 2
1043              
1044             =item pid
1045              
1046             The processID of the child process
1047              
1048             =item href
1049              
1050             URL for the debugger in the child process. You may use this URL to construct
1051             another Devel::hdb::Client.
1052              
1053             =item gui_href
1054              
1055             URL to bring up the graphical debugger in a browser.
1056              
1057             =item href_continue
1058              
1059             URL to POST to tell the child to run without stopping.
1060              
1061             =back
1062              
1063             =head2 watchpoint event
1064              
1065             When a watchpoint expression's value changes.
1066              
1067             =over 2
1068              
1069             =item expr
1070              
1071             The perl expression whose value changed
1072              
1073             =item old
1074              
1075             The old value of the expression. Watchpoint expressions are evaluated in
1076             list context, so old will always be a listref.
1077              
1078             =item new
1079              
1080             The new value of the expression. Also a listref.
1081              
1082             =item filename
1083              
1084             =item line
1085              
1086             =item package
1087              
1088             =item subroutine
1089              
1090             The location where the change likely happened. This is whichever line was
1091             executing immediately before the change was detected.
1092              
1093             =back
1094              
1095             =head2 exception event
1096              
1097             When the program throws an uncaught exception.
1098              
1099             =over 2
1100              
1101             =item value
1102              
1103             The "value" of the exception. Either the string passed to C, or perhaps
1104             an exception object
1105              
1106             =item package
1107              
1108             =item filename
1109              
1110             =item line
1111              
1112             =item subroutine
1113              
1114             Location information about where the exception was thrown
1115              
1116             =back
1117              
1118             =head2 exit event
1119              
1120             When the debugged program has finished. The debugger is still running.
1121              
1122             =over 2
1123              
1124             =item value
1125              
1126             The process exit code
1127              
1128             =back
1129              
1130             =head2 hangup event
1131              
1132             When the debugger has exited and is no longer listening for requests.
1133              
1134             =head2 trace_diff event
1135              
1136             When execution has differed from the previous run, when run in follow mode.
1137              
1138             =over 2
1139              
1140             =item filename
1141              
1142             =item line
1143              
1144             =item package
1145              
1146             =item subroutine
1147              
1148             =item sub_offset
1149              
1150             Where the program is currently stopped. sub_offset is the line number within
1151             the subroutine.
1152              
1153             =item expected_filename
1154              
1155             =item expected_line
1156              
1157             =item expected_package
1158              
1159             =item expected_subroutine
1160              
1161             =item expected_sub_offset
1162              
1163             Where the debugger expected the program to be.
1164              
1165             =back
1166              
1167             =head1 PERL VALUES
1168              
1169             For methods that return Perl values such as eval(), get_var_at_level(), or the
1170             argument lists in a stack frame, the data is deserialized with
1171             Data::Transform::ExplicitMetadata::decode(). If the variable has special Perl
1172             attributes (such as blessed, tied, filehandle), decode() will try to re-create
1173             that specialness.
1174              
1175             =head1 EXCEPTIONS
1176              
1177             This class uses Exception classes. They stringify to something reasonable.
1178              
1179             Devel::hdb::Client::RequiredParameterMissing is thrown when a method requires
1180             a parameter that was missing. The exception's attribute 'params' is a listref
1181             of parameter names that were missing.
1182              
1183             Devel::hdb::Client::Exception::Eval is thrown by eval() when the evaluated
1184             code throws an exception.
1185              
1186             Devel::hdb::Client::Exception::Error is thrown when data returned from the
1187             debugger is not formatted as expected.
1188              
1189             Devel::hdb::Client::Exception::HTTP is thrown when a response is an
1190             unsuccessful response code (4XX, 5XX). The exception's attributes
1191             http_code, http_message and http_content store the code, message
1192             and content from the response.
1193              
1194             =head1 SEE ALSO
1195              
1196             L, L
1197              
1198             =head1 AUTHOR
1199              
1200             Anthony Brummett
1201              
1202             =head1 COPYRIGHT
1203              
1204             Copyright 2018, Anthony Brummett. This module is free software. It may
1205             be used, redistributed and/or modified under the same terms as Perl itself.