1use strict;
2use warnings;
3use Test2::Tools::Tiny;
4
5use Test2::Event();
6use Test2::EventFacet::Trace();
7use Test2::Event::Generic;
8
9use Test2::API qw/context/;
10use Scalar::Util qw/reftype/;
11
12tests old_api => sub {
13    {
14        package My::MockEvent;
15
16        use base 'Test2::Event';
17        use Test2::Util::HashBase qw/foo bar baz/;
18    }
19
20    ok(My::MockEvent->can($_), "Added $_ accessor") for qw/foo bar baz/;
21
22    my $one = My::MockEvent->new(trace => 'fake');
23
24    ok(!$one->causes_fail, "Events do not cause failures by default");
25
26    ok(!$one->$_, "$_ is false by default") for qw/increments_count terminate global/;
27
28    ok(!$one->get_meta('xxx'), "no meta-data associated for key 'xxx'");
29
30    $one->set_meta('xxx', '123');
31
32    is($one->meta('xxx'), '123', "got meta-data");
33
34    is($one->meta('xxx', '321'), '123', "did not use default");
35
36    is($one->meta('yyy', '1221'), '1221', "got the default");
37
38    is($one->meta('yyy'), '1221', "last call set the value to the default for future use");
39
40    is($one->summary, 'My::MockEvent', "Default summary is event package");
41
42    is($one->diagnostics, 0, "Not diagnostics by default");
43};
44
45tests deprecated => sub {
46    my $e = Test2::Event->new(trace => Test2::EventFacet::Trace->new(frame => ['foo', 'foo.pl', 42], nested => 2, hid => 'maybe'));
47
48    my $warnings = warnings {
49        local $ENV{AUTHOR_TESTING} = 1;
50        is($e->nested, 2, "Got nested from the trace");
51        is($e->in_subtest, 'maybe', "got hid from trace");
52
53        $e->trace->{nested} = 0;
54
55        local $ENV{AUTHOR_TESTING} = 0;
56        is($e->nested, 0, "Not nested");
57        is($e->in_subtest, undef, "Did not get hid");
58    };
59
60    is(@$warnings, 2, "got warnings once each");
61    like($warnings->[0], qr/Use of Test2::Event->nested\(\) is deprecated/, "Warned about deprecation");
62    like($warnings->[1], qr/Use of Test2::Event->in_subtest\(\) is deprecated/, "Warned about deprecation");
63};
64
65tests facet_data => sub {
66    my $e = Test2::Event::Generic->new(
67        causes_fail      => 0,
68        increments_count => 0,
69        diagnostics      => 0,
70        no_display       => 0,
71        callback         => undef,
72        terminate        => undef,
73        global           => undef,
74        sets_plan        => undef,
75        summary          => undef,
76        facet_data       => undef,
77    );
78
79    is_deeply(
80        $e->facet_data,
81        {
82            about => {
83                package    => 'Test2::Event::Generic',
84                details    => 'Test2::Event::Generic',
85                eid        => $e->eid,
86                no_display => undef,
87            },
88            control => {
89                has_callback => 0,
90                terminate    => undef,
91                global       => 0
92            },
93        },
94        "Facet data has control with only false values, and an about"
95    );
96
97    $e->set_trace(Test2::EventFacet::Trace->new(frame => ['foo', 'foo.t', 42]));
98    is_deeply(
99        $e->facet_data,
100        {
101            about => {
102                package    => 'Test2::Event::Generic',
103                details    => 'Test2::Event::Generic',
104                eid        => $e->eid,
105                no_display => undef,
106            },
107            control => {
108                has_callback => 0,
109                terminate    => undef,
110                global       => 0
111            },
112            trace => {
113                frame => ['foo', 'foo.t', 42],
114                pid => $$,
115                tid => 0,
116            },
117        },
118        "Got a trace now"
119    );
120
121    $e->set_causes_fail(1);
122    is_deeply(
123        $e->facet_data,
124        {
125            about => {
126                package    => 'Test2::Event::Generic',
127                details    => 'Test2::Event::Generic',
128                eid        => $e->eid,
129                no_display => undef
130            },
131            control => {
132                has_callback => 0,
133                terminate    => undef,
134                global       => 0
135            },
136            trace => {
137                frame => ['foo', 'foo.t', 42],
138                pid   => $$,
139                tid   => 0,
140            },
141            errors => [
142                {
143                    tag     => 'FAIL',
144                    details => 'Test2::Event::Generic',
145                    fail    => 1,
146                }
147            ],
148        },
149        "Got an error"
150    );
151
152    $e->set_increments_count(1);
153    is_deeply(
154        $e->facet_data,
155        {
156            about => {
157                package    => 'Test2::Event::Generic',
158                details    => 'Test2::Event::Generic',
159                eid        => $e->eid,
160                no_display => undef
161            },
162            control => {
163                has_callback => 0,
164                terminate    => undef,
165                global       => 0
166            },
167            trace => {
168                frame => ['foo', 'foo.t', 42],
169                pid   => $$,
170                tid   => 0,
171            },
172            assert => {
173                no_debug => 1,
174                pass => 0,
175                details => 'Test2::Event::Generic',
176            },
177        },
178        "Got an assert now"
179    );
180
181    $e->set_causes_fail(0);
182    is_deeply(
183        $e->facet_data,
184        {
185            about => {
186                package    => 'Test2::Event::Generic',
187                details    => 'Test2::Event::Generic',
188                eid        => $e->eid,
189                no_display => undef
190            },
191            control => {
192                has_callback => 0,
193                terminate    => undef,
194                global       => 0
195            },
196            trace => {
197                frame => ['foo', 'foo.t', 42],
198                pid   => $$,
199                tid   => 0,
200            },
201            assert => {
202                no_debug => 1,
203                pass => 1,
204                details => 'Test2::Event::Generic',
205            },
206        },
207        "Got a passing assert now"
208    );
209
210    $e->set_global(1);
211    $e->set_terminate(255);
212    $e->set_callback(sub {1});
213    is_deeply(
214        $e->facet_data,
215        {
216            about => {
217                package    => 'Test2::Event::Generic',
218                details    => 'Test2::Event::Generic',
219                eid        => $e->eid,
220                no_display => undef
221            },
222            control => {
223                has_callback => 1,
224                terminate    => 255,
225                global       => 1,
226            },
227            trace => {
228                frame => ['foo', 'foo.t', 42],
229                pid   => $$,
230                tid   => 0,
231            },
232            assert => {
233                no_debug => 1,
234                pass => 1,
235                details => 'Test2::Event::Generic',
236            },
237        },
238        "control fields were altered"
239    );
240
241    my $data;
242    {
243        no warnings 'once';
244        local *Test2::Event::Generic::subtest_id = sub { 123 };
245        $data = $e->facet_data;
246    }
247    is_deeply(
248        $data,
249        {
250            about => {
251                package    => 'Test2::Event::Generic',
252                details    => 'Test2::Event::Generic',
253                eid        => $e->eid,
254                no_display => undef
255            },
256            control => {
257                has_callback => 1,
258                terminate    => 255,
259                global       => 1,
260            },
261            trace => {
262                frame => ['foo', 'foo.t', 42],
263                pid   => $$,
264                tid   => 0,
265            },
266            assert => {
267                no_debug => 1,
268                pass     => 1,
269                details  => 'Test2::Event::Generic',
270            },
271            parent => {hid => 123},
272        },
273        "Added parent"
274    );
275
276    $e->set_meta('foo', {a => 1});
277    is_deeply(
278        $e->facet_data,
279        {
280            about => {
281                package    => 'Test2::Event::Generic',
282                details    => 'Test2::Event::Generic',
283                eid        => $e->eid,
284                no_display => undef
285            },
286            control => {
287                has_callback => 1,
288                terminate    => 255,
289                global       => 1,
290            },
291            trace => {
292                frame => ['foo', 'foo.t', 42],
293                pid   => $$,
294                tid   => 0,
295            },
296            assert => {
297                no_debug => 1,
298                pass     => 1,
299                details  => 'Test2::Event::Generic',
300            },
301            meta => {foo => {a => 1}},
302        },
303        "Grabbed meta"
304    );
305
306
307    $e->set_sets_plan([5]);
308    is_deeply(
309        $e->facet_data,
310        {
311            about => {
312                package    => 'Test2::Event::Generic',
313                details    => 'Test2::Event::Generic',
314                eid        => $e->eid,
315                no_display => undef
316            },
317            control => {
318                has_callback => 1,
319                terminate    => 255,
320                global       => 1,
321            },
322            trace => {
323                frame => ['foo', 'foo.t', 42],
324                pid   => $$,
325                tid   => 0,
326            },
327            assert => {
328                no_debug => 1,
329                pass     => 1,
330                details  => 'Test2::Event::Generic',
331            },
332            meta => {foo => {a => 1}},
333            plan => { count => 5 },
334        },
335        "Plan facet added"
336    );
337
338    $e->set_terminate(undef);
339    $e->set_sets_plan([0, SKIP => 'because']);
340    is_deeply(
341        $e->facet_data,
342        {
343            about => {
344                package    => 'Test2::Event::Generic',
345                details    => 'Test2::Event::Generic',
346                eid        => $e->eid,
347                no_display => undef
348            },
349            control => {
350                has_callback => 1,
351                terminate    => 0,
352                global       => 1,
353            },
354            trace => {
355                frame => ['foo', 'foo.t', 42],
356                pid   => $$,
357                tid   => 0,
358            },
359            assert => {
360                no_debug => 1,
361                pass     => 1,
362                details  => 'Test2::Event::Generic',
363            },
364            meta => {foo => {a => 1}},
365            plan => { count => 0, skip => 1, details => 'because' },
366        },
367        "Plan set terminate, skip, and details"
368    );
369
370    $e->set_sets_plan([0, 'NO PLAN' => 'because']);
371    is_deeply(
372        $e->facet_data,
373        {
374            about => {
375                package    => 'Test2::Event::Generic',
376                details    => 'Test2::Event::Generic',
377                eid        => $e->eid,
378                no_display => undef
379            },
380            control => {
381                has_callback => 1,
382                terminate    => undef,
383                global       => 1,
384            },
385            trace => {
386                frame => ['foo', 'foo.t', 42],
387                pid   => $$,
388                tid   => 0,
389            },
390            assert => {
391                no_debug => 1,
392                pass     => 1,
393                details  => 'Test2::Event::Generic',
394            },
395            meta => {foo => {a => 1}},
396            plan => { count => 0, none => 1, details => 'because' },
397        },
398        "Plan does not set terminate, but sets 'none' and 'details'"
399    );
400
401    $e->add_amnesty({tag => 'foo', details => 'bar'});
402    $e->add_amnesty({tag => 'baz', details => 'bat'});
403    is_deeply(
404        $e->facet_data,
405        {
406            about => {
407                package    => 'Test2::Event::Generic',
408                details    => 'Test2::Event::Generic',
409                eid        => $e->eid,
410                no_display => undef
411            },
412            control => {
413                has_callback => 1,
414                terminate    => undef,
415                global       => 1,
416            },
417            trace => {
418                frame => ['foo', 'foo.t', 42],
419                pid   => $$,
420                tid   => 0,
421            },
422            assert => {
423                no_debug => 1,
424                pass     => 1,
425                details  => 'Test2::Event::Generic',
426            },
427            meta => {foo => {a => 1}},
428            plan => { count => 0, none => 1, details => 'because' },
429            amnesty => [
430                { tag => 'foo', details => 'bar' },
431                { tag => 'baz', details => 'bat' },
432            ],
433        },
434        "Amnesty added"
435    );
436
437    $e = Test2::Event::Generic->new();
438    $e->set_diagnostics(1);
439    $e->set_no_display(1);
440    is_deeply(
441        $e->facet_data,
442        {
443            about => {
444                package    => 'Test2::Event::Generic',
445                details    => 'Test2::Event::Generic',
446                eid        => $e->eid,
447                no_display => 1,
448            },
449            control => {
450                has_callback => 0,
451                terminate    => undef,
452                global       => 0,
453            },
454        },
455        "No Info"
456    );
457
458    $e->set_no_display(0);
459    is_deeply(
460        $e->facet_data,
461        {
462            about => {
463                package    => 'Test2::Event::Generic',
464                details    => 'Test2::Event::Generic',
465                eid        => $e->eid,
466                no_display => undef,
467            },
468            control => {
469                has_callback => 0,
470                terminate    => undef,
471                global       => 0,
472            },
473            info => [{
474                details => 'Test2::Event::Generic',
475                tag => 'DIAG',
476                debug => 1,
477            }],
478        },
479        "Got debug Info"
480    );
481
482    $e->set_summary("foo bar baz");
483    is_deeply(
484        $e->facet_data,
485        {
486            about => {
487                package    => 'Test2::Event::Generic',
488                details    => 'foo bar baz',
489                eid        => $e->eid,
490                no_display => undef,
491            },
492            control => {
493                has_callback => 0,
494                terminate    => undef,
495                global       => 0,
496            },
497            info => [{
498                details => 'foo bar baz',
499                tag => 'DIAG',
500                debug => 1,
501            }],
502        },
503        "Got debug Info with summary change"
504    );
505};
506
507tests facets => sub {
508    my $data = {
509        about => {
510            package    => 'Test2::Event::Generic',
511            details    => 'Test2::Event::Generic',
512            no_display => undef
513        },
514        control => {
515            has_callback => 1,
516            terminate    => undef,
517            global       => 1,
518        },
519        trace => {
520            frame => ['foo', 'foo.t', 42],
521            pid   => $$,
522            tid   => 0,
523        },
524        assert => {
525            no_debug => 1,
526            pass     => 1,
527            details  => 'Test2::Event::Generic',
528        },
529        meta => {foo => {a => 1}},
530        plan    => {count => 0,   none     => 1, details => 'because'},
531        parent  => {hid   => 123, children => []},
532        amnesty => [
533            {tag => 'foo', details => 'bar'},
534            {tag => 'baz', details => 'bat'},
535        ],
536        info => [
537            {
538                details => 'foo bar baz',
539                tag     => 'DIAG',
540                debug   => 1,
541            }
542        ],
543        errors => [{
544            tag     => 'FAIL',
545            details => 'Test2::Event::Generic',
546            fail    => 1,
547        }],
548    };
549
550    my $e = Test2::Event::Generic->new(facet_data => $data);
551    is_deeply(
552        $e->facet_data,
553        $e->facets,
554        "Facets and facet_data have the same structure"
555    );
556
557    my $facets = $e->facets;
558
559    for my $key (sort keys %$facets) {
560        my $type = "Test2::EventFacet::" . ucfirst($key);
561        $type =~ s/s$//;
562        my $val  = $facets->{$key};
563        if ($type->is_list) {
564            for my $f (@$val) {
565                ok($f->isa('Test2::EventFacet'), "'$key' has a blessed facet");
566                ok($f->isa("$type"), "'$key' is a '$type'") or diag("$f");
567            }
568        }
569        else {
570            ok($val->isa('Test2::EventFacet'), "'$key' has a blessed facet");
571            ok($val->isa($type), "'$key' is a '$type'");
572        }
573    }
574};
575
576tests common_facet_data => sub {
577    my $e = Test2::Event::Generic->new(
578        causes_fail      => 0,
579        increments_count => 0,
580        diagnostics      => 0,
581        no_display       => 0,
582        callback         => undef,
583        terminate        => undef,
584        global           => undef,
585        sets_plan        => undef,
586        summary          => undef,
587        facet_data       => undef,
588    );
589
590    is_deeply(
591        $e->common_facet_data,
592        {
593            about => {
594                package => 'Test2::Event::Generic',
595                eid     => $e->eid,
596            },
597        },
598        "Facet data has an about"
599    );
600
601    $e->set_trace(Test2::EventFacet::Trace->new(frame => ['foo', 'foo.t', 42]));
602    is_deeply(
603        $e->common_facet_data,
604        {
605            about => {
606                package => 'Test2::Event::Generic',
607                eid     => $e->eid,
608            },
609            trace => {
610                frame => ['foo', 'foo.t', 42],
611                pid   => $$,
612                tid   => 0,
613            },
614        },
615        "Got a trace now"
616    );
617
618    $e->set_meta('foo', {a => 1});
619    is_deeply(
620        $e->common_facet_data,
621        {
622            about => {
623                package => 'Test2::Event::Generic',
624                eid     => $e->eid,
625            },
626            trace => {
627                frame => ['foo', 'foo.t', 42],
628                pid   => $$,
629                tid   => 0,
630            },
631            meta => {foo => {a => 1}},
632        },
633        "Grabbed meta"
634    );
635
636    $e->add_amnesty({tag => 'foo', details => 'bar'});
637    $e->add_amnesty({tag => 'baz', details => 'bat'});
638    is_deeply(
639        $e->common_facet_data,
640        {
641            about => {
642                package => 'Test2::Event::Generic',
643                eid     => $e->eid,
644            },
645            trace => {
646                frame => ['foo', 'foo.t', 42],
647                pid   => $$,
648                tid   => 0,
649            },
650            meta    => {foo => {a => 1}},
651            amnesty => [
652                {tag => 'foo', details => 'bar'},
653                {tag => 'baz', details => 'bat'},
654            ],
655        },
656        "Amnesty added"
657    );
658};
659
660tests related => sub {
661    my $ctx = context();
662    my $ev_a = $ctx->build_ev2(about => {});
663    my $ev_b = $ctx->build_ev2(about => {});
664    $ctx->release;
665
666    $ctx = context();
667    my $ev_c = $ctx->build_ev2(about => {});
668    $ctx->release;
669
670    delete $ev_a->{trace}->{uuid};
671    delete $ev_b->{trace}->{uuid};
672    delete $ev_c->{trace}->{uuid};
673
674    ok($ev_a->related($ev_b), "Related as they were created with the same context (no uuid)");
675    ok(!$ev_a->related($ev_c), "Not related as they were created with a different context (no uuid)");
676
677    $ev_a->{trace}->{uuid} = 'xxx'; # Yes I know it is not valid.
678    $ev_b->{trace}->{uuid} = 'yyy'; # Yes I know it is not valid.
679    $ev_c->{trace}->{uuid} = 'xxx'; # Yes I know it is not valid.
680
681    ok(!$ev_a->related($ev_b), "Not related, traces have different UUID's");
682    ok($ev_a->related($ev_c), "Related, traces have the same UUID's");
683};
684
685tests verify_facet_data => sub {
686    my $ev1 = Test2::Event::V2->new(
687        assert => { pass => 1 },
688        info => [{tag => 'NOTE', details => 'oops' }],
689        'a custom one' => {},
690    );
691
692    is_deeply(
693        [$ev1->validate_facet_data],
694        [],
695        "No errors"
696    );
697
698    my $ev2 = Test2::Event::V2->new(
699        assert => [{ pass => 1 }],
700        info => {tag => 'NOTE', details => 'oops' },
701        'a custom one' => {},
702    );
703
704    my @errors = $ev2->validate_facet_data;
705    is(@errors, 2, "Got 2 errors");
706    like($errors[0], qr/^Facet 'assert' should not be a list, but got a a list/, "Got a list for a non-list type");
707    like($errors[1], qr/^Facet 'info' should be a list, but got a single item/, "Got a single item when a list is needed");
708
709    @errors = $ev2->validate_facet_data(require_facet_class => 1);
710    is(@errors, 3, "Got 3 errors");
711    is($errors[0], "Could not find a facet class for facet 'a custom one'", "Classes required");
712    like($errors[1], qr/^Facet 'assert' should not be a list, but got a a list/, "Got a list for a non-list type");
713    like($errors[2], qr/^Facet 'info' should be a list, but got a single item/, "Got a single item when a list is needed");
714
715    is_deeply(
716        [Test2::Event->validate_facet_data($ev1->facet_data)],
717        [],
718        "No errors"
719    );
720
721    @errors = Test2::Event->validate_facet_data($ev2->facet_data);
722    is(@errors, 2, "Got 2 errors");
723    like($errors[0], qr/^Facet 'assert' should not be a list, but got a a list/, "Got a list for a non-list type");
724    like($errors[1], qr/^Facet 'info' should be a list, but got a single item/, "Got a single item when a list is needed");
725
726    @errors = Test2::Event->validate_facet_data($ev2->facet_data, require_facet_class => 1);
727    is(@errors, 3, "Got 3 errors");
728    is($errors[0], "Could not find a facet class for facet 'a custom one'", "Classes required");
729    like($errors[1], qr/^Facet 'assert' should not be a list, but got a a list/, "Got a list for a non-list type");
730    like($errors[2], qr/^Facet 'info' should be a list, but got a single item/, "Got a single item when a list is needed");
731};
732
733done_testing;
734