<commit_before>use v6;
use Test;

plan 69;

# L<S02/Mutable types/KeyHash of UInt>

# A KeyBag is a KeyHash of UInt, i.e. the values are positive Int

sub showkv($x) {
    $x.keys.sort.map({ $^k ~ ':' ~ $x{$^k} }).join(' ')
}

# L<S02/Immutable types/'the bag listop'>

{
    my $b = KeyBag.new("a", "foo", "a", "a", "a", "a", "b", "foo");
    isa_ok $b, KeyBag, 'we got a KeyBag';
    is showkv($b), 'a:5 b:1 foo:2', '...with the right elements';

    is $b<a>, 5, 'Single-key subscript (existing element)';
    is $b<santa>, 0, 'Single-key subscript (nonexistent element)';
    ok $b.exists('a'), '.exists with existing element';
    nok $b.exists('santa'), '.exists with nonexistent element';

    dies_ok { $b.keys = <c d> }, "Can't assign to .keys";
    dies_ok { $b.values = 3, 4 }, "Can't assign to .values";

    #?niecza 2 todo
    is ([+] $b<a b>), 6, 'Multiple-element access';
    is ([+] $b<a santa b easterbunny>), 6, 'Multiple-element access (with nonexistent elements)';

    is $b.elems, 8, '.elems gives sum of values';
    is +$b, 8, '+$bag gives sum of values';

    lives_ok { $b<a> = 42 }, "Can assign to an existing element";
    is $b<a>, 42, "... and assignment takes effect";
    lives_ok { $b<brady> = 12 }, "Can assign to a new element";
    is $b<brady>, 12, "... and assignment takes effect";
    
    lives_ok { $b<a>++ }, "Can ++ an existing element";
    is $b<a>, 43, "... and the increment happens";
    lives_ok { $b<carter>++ }, "Can ++ a new element";
    is $b<carter>, 1, "... and the element is created";
    lives_ok { $b<a>-- }, "Can -- an existing element";
    is $b<a>, 42, "... and the decrement happens";
    lives_ok { $b<carter>-- }, "Can -- an element with value 1";
    nok $b.exists("carter"), "... and it goes away";
    lives_ok { $b<farve>-- }, "Can -- an element that doesn't exist";
    nok $b.exists("farve"), "... and everything is still okay";
}

{
    my $b = KeyBag.new('a', False, 2, 'a', False, False);
    my @ks = $b.keys;
    #?niecza 2 todo
    is @ks.grep(Int)[0], 2, 'Int keys are left as Ints';
    is @ks.grep(* eqv False).elems, 1, 'Bool keys are left as Bools';
    is @ks.grep(Str)[0], 'a', 'And Str keys are permitted in the same set';
    #?niecza todo
    is $b{2, 'a', False}.sort.join(' '), '1 2 3', 'All keys have the right values';
}

#?niecza skip "Unmatched key in Hash.LISTSTORE"
{
    my %h = bag <a b o p a p o o>;
    ok %h ~~ Hash, 'A hash to which a Bag has been assigned remains a hash';
    is showkv(%h), 'a:2 b:1 o:3 p:2', '...with the right elements';
}

{
    my $b = bag set <foo bar foo bar baz foo>;
    isa_ok $b, Bag, '&bag given a Set produces a Bag';
    is showkv($b), 'bar:1 baz:1 foo:1', '... with the right elements';
}

# L<S02/Names and Variables/'C<%x> may be bound to'>

{
    my %b := bag <a b c b>;
    isa_ok %b, Bag, 'A Bag bound to a %var is a Bag';
    is showkv(%b), 'a:1 b:2 c:1', '...with the right elements';

    is %b<b>, 2, 'Single-key subscript (existing element)';
    is %b<santa>, 0, 'Single-key subscript (nonexistent element)';

    dies_ok { %b<a> = 1 }, "Can't assign to an element (Bags are immutable)";
    dies_ok { %b = bag <a b> }, "Can't assign to a %var implemented by Bag";
}

# L<S32::Containers/Bag/pick>

{
    my $b = bag <a b b>;

    my @a = $b.pick: *;
    is +@a, 3, '.pick(*) returns the right number of items';
    is @a.grep(* eq 'a').elems, 1, '.pick(*) (1)';
    is @a.grep(* eq 'b').elems, 2, '.pick(*) (2)';
}

# L<S32::Containers/Bag/roll>

{
    my $b = bag <a b b>;

    my @a = $b.roll: 100;
    is +@a, 100, '.roll(100) returns 100 items';
    ok 2 < @a.grep(* eq 'a') < 75, '.roll(100) (1)';
    ok @a.grep(* eq 'a') + 2 < @a.grep(* eq 'b'), '.roll(100) (2)';
}

#?niecza skip "Trait name not available on variables"
{
    my %h is KeyBag = a => 1, b => 0, c => 2;
    nok %h.exists( 'b' ), '"b", initialized to zero, does not exist';
    is +%h.keys, 2, 'Inititalization worked';
    is %h.elems, 3, '.elems works';
    isa_ok %h<nonexisting>, Int, '%h<nonexisting> is an Int';
    is %h<nonexisting>, 0, '%h<nonexisting> is 0';
}

#?niecza skip "Trait name not available on variables"
{
    my %h is KeyBag = a => 1, b => 0, c => 2;

    lives_ok { %h<c> = 0 }, 'can set an item to 0';
    nok %h.exists( 'c' ), '"c", set to zero, does not exist';
    is %h.elems, 1, 'one item left';
    is %h.keys, ('a'), '... and the right one is gone';
<commit_msg>Add 21 new tests.  Still needs more.<commit_after>use v6;
use Test;

plan 90;

# L<S02/Mutable types/KeyHash of UInt>

# A KeyBag is a KeyHash of UInt, i.e. the values are positive Int

sub showkv($x) {
    $x.keys.sort.map({ $^k ~ ':' ~ $x{$^k} }).join(' ')
}

# L<S02/Immutable types/'the bag listop'>

{
    my $b = KeyBag.new("a", "foo", "a", "a", "a", "a", "b", "foo");
    isa_ok $b, KeyBag, 'we got a KeyBag';
    is showkv($b), 'a:5 b:1 foo:2', '...with the right elements';

    is $b<a>, 5, 'Single-key subscript (existing element)';
    isa_ok $b<a>, Int, 'Single-key subscript yields an Int';
    is $b<santa>, 0, 'Single-key subscript (nonexistent element)';
    isa_ok $b<santa>, Int, 'Single-key subscript yields an Int (nonexistent element)';
    ok $b.exists('a'), '.exists with existing element';
    nok $b.exists('santa'), '.exists with nonexistent element';

    is $b.values.elems, 3, "Values returns the correct number of values";
    is ([+] $b.values), 8, "Values returns the correct sum";
    ok ?$b, "Bool returns True if there is something in the KeyBag";
    nok ?KeyBag.new(), "Bool returns False if there is nothing in the KeyBag";
    
    my $hash;
    lives_ok { $hash = $b.hash }, ".hash doesn't die";
    isa_ok $hash, Hash, "...and it returned a Hash";
    is showkv($hash), 'a:5 b:1 foo:2', '...with the right elements';

    dies_ok { $b.keys = <c d> }, "Can't assign to .keys";
    dies_ok { $b.values = 3, 4 }, "Can't assign to .values";

    #?niecza 2 todo
    is ([+] $b<a b>), 6, 'Multiple-element access';
    is ([+] $b<a santa b easterbunny>), 6, 'Multiple-element access (with nonexistent elements)';

    is $b.elems, 8, '.elems gives sum of values';
    is +$b, 8, '+$bag gives sum of values';

    lives_ok { $b<a> = 42 }, "Can assign to an existing element";
    is $b<a>, 42, "... and assignment takes effect";
    lives_ok { $b<brady> = 12 }, "Can assign to a new element";
    is $b<brady>, 12, "... and assignment takes effect";
    lives_ok { $b<spiderman> = 0 }, "Can assign zero to a nonexistent element";
    nok $b.exists("spiderman"), "... and that didn't create the element";
    lives_ok { $b<brady> = 0 }, "Can assign zero to a existing element";
    nok $b.exists("brady"), "... and it goes away";
    
    lives_ok { $b<a>++ }, "Can ++ an existing element";
    is $b<a>, 43, "... and the increment happens";
    lives_ok { $b<carter>++ }, "Can ++ a new element";
    is $b<carter>, 1, "... and the element is created";
    lives_ok { $b<a>-- }, "Can -- an existing element";
    is $b<a>, 42, "... and the decrement happens";
    lives_ok { $b<carter>-- }, "Can -- an element with value 1";
    nok $b.exists("carter"), "... and it goes away";
    lives_ok { $b<farve>-- }, "Can -- an element that doesn't exist";
    nok $b.exists("farve"), "... and everything is still okay";
}

{
    my $b = KeyBag.new('a', False, 2, 'a', False, False);
    my @ks = $b.keys;
    #?niecza 2 todo
    is @ks.grep(Int)[0], 2, 'Int keys are left as Ints';
    is @ks.grep(* eqv False).elems, 1, 'Bool keys are left as Bools';
    is @ks.grep(Str)[0], 'a', 'And Str keys are permitted in the same set';
    #?niecza todo
    is $b{2, 'a', False}.sort.join(' '), '1 2 3', 'All keys have the right values';
}

#?niecza skip "Unmatched key in Hash.LISTSTORE"
{
    my %h = bag <a b o p a p o o>;
    ok %h ~~ Hash, 'A hash to which a Bag has been assigned remains a hash';
    is showkv(%h), 'a:2 b:1 o:3 p:2', '...with the right elements';
}

{
    my $b = KeyBag.new(set <foo bar foo bar baz foo>);
    isa_ok $b, KeyBag, '&KeyBag.new given a Set produces a KeyBag';
    is showkv($b), 'bar:1 baz:1 foo:1', '... with the right elements';
}

{
    my $b = KeyBag.new(KeySet.new(set <foo bar foo bar baz foo>));
    isa_ok $b, KeyBag, '&KeyBag.new given a KeySet produces a KeyBag';
    is showkv($b), 'bar:1 baz:1 foo:1', '... with the right elements';
}

{
    my $b = KeyBag.new(bag set <foo bar foo bar baz foo>);
    isa_ok $b, KeyBag, '&KeyBag.new given a Bag produces a KeyBag';
    is showkv($b), 'bar:1 baz:1 foo:1', '... with the right elements';
}

{
    my $b = KeyBag.new(set <foo bar foo bar baz foo>);
    $b<bar> += 2;
    my $c = KeyBag.new($b);
    isa_ok $c, KeyBag, '&KeyBag.new given a KeyBag produces a KeyBag';
    is showkv($c), 'bar:3 baz:1 foo:1', '... with the right elements';
    $c<manning> = 10;
    is showkv($c), 'bar:3 baz:1 foo:1 manning:10', 'Creating a new element works';
    is showkv($b), 'bar:3 baz:1 foo:1', '... and does not affect the original KeyBag';
}

# L<S02/Names and Variables/'C<%x> may be bound to'>

{
    my %b := KeyBag.new("a", "b", "c", "b");
    isa_ok %b, KeyBag, 'A KeyBag bound to a %var is a KeyBag';
    is showkv(%b), 'a:1 b:2 c:1', '...with the right elements';

    is %b<b>, 2, 'Single-key subscript (existing element)';
    is %b<santa>, 0, 'Single-key subscript (nonexistent element)';

    lives_ok { %b<a> = 4 }, "Assign to an element";
    is %b<a>, 4, "... and gets the correct value";
}

# L<S32::Containers/KeyBag/pick>

{
    my $b = KeyBag.new("a", "b", "b");

    my @a = $b.pick: *;
    is +@a, 3, '.pick(*) returns the right number of items';
    is @a.grep(* eq 'a').elems, 1, '.pick(*) (1)';
    is @a.grep(* eq 'b').elems, 2, '.pick(*) (2)';
}

# L<S32::Containers/KeyBag/roll>

{
    my $b = KeyBag.new("a", "b", "b");

    my @a = $b.roll: 100;
    is +@a, 100, '.roll(100) returns 100 items';
    ok 2 < @a.grep(* eq 'a') < 75, '.roll(100) (1)';
    ok @a.grep(* eq 'a') + 2 < @a.grep(* eq 'b'), '.roll(100) (2)';
}

#?niecza skip "Trait name not available on variables"
{
    my %h is KeyBag = a => 1, b => 0, c => 2;
    nok %h.exists( 'b' ), '"b", initialized to zero, does not exist';
    is +%h.keys, 2, 'Inititalization worked';
    is %h.elems, 3, '.elems works';
    isa_ok %h<nonexisting>, Int, '%h<nonexisting> is an Int';
    is %h<nonexisting>, 0, '%h<nonexisting> is 0';
}

#?niecza skip "Trait name not available on variables"
{
    my %h is KeyBag = a => 1, b => 0, c => 2;

    lives_ok { %h<c> = 0 }, 'can set an item to 0';
    nok %h.exists( 'c' ), '"c", set to zero, does not exist';
    is %h.elems, 1, 'one item left';
    is %h.keys, ('a'), '... and the right one is gone';

{'fraction_non_alphanumeric': 0.19915492957746478, 'fraction_numerical': 0.022347417840375586, 'mean_word_length': 2.9071900220102713, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4074054', 'n_tokens_mistral': 4363, 'n_tokens_neox': 4141, 'n_words': 1459}