App-karr

 view release on metacpan or  search on metacpan

t/191-foundation-questions.t  view on Meta::CPAN

    my $id = $box->ask(
        question => 'Which registry do we publish to?',
        context  => 'The release gate is waiting on this.',
        options  => [ 'cpan', 'darkpan' ],
        default  => 'cpan',
        policy   => 'use_default',
        deadline => stamp(3600),
        step     => 12,
    );
    is( $id, 1, 'the first question is #1' );

    is_deeply(
        [ refs_under( $repo, 'refs/karr-foundation/' ) ],
        ['refs/karr-foundation/questions/1/ask'],
        'asking writes one ref and nothing else'
    );

    my $q = $box->question(1);
    is( $q->{question}, 'Which registry do we publish to?', 'the question survives' );
    is( $q->{context},  'The release gate is waiting on this.', 'the context survives' );
    is_deeply( $q->{options}, [ 'cpan', 'darkpan' ], 'the options survive' );
    is( $q->{default}, 'cpan',        'the default survives' );
    is( $q->{policy},  'use_default', 'the policy survives' );
    is( $q->{step},    12,            'the step the chain is waiting on survives' );
    like( $q->{asked}, qr/\A[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8}Z\z/, 'and when' );

    my $before = oid_of( $repo, 'refs/karr-foundation/questions/1/ask' );
    $box->settle( 1, 'darkpan', note => 'the release is a private one' );

    is_deeply(
        [ refs_under( $repo, 'refs/karr-foundation/' ) ],
        [   'refs/karr-foundation/questions/1/answer',
            'refs/karr-foundation/questions/1/ask',
        ],
        'the answer is its own ref beside the question'
    );
    is( oid_of( $repo, 'refs/karr-foundation/questions/1/ask' ), $before,
        'answering does not rewrite the question ref -- which is the whole '
      . 'reason the answer is not a field in it (#190)' );

    my $a = $box->answer(1);
    is( $a->{answer}, 'darkpan', 'the answer is there' );
    is( $a->{note}, 'the release is a private one', 'with its note' );
    is( $a->{question}, 'Which registry do we publish to?',
        'and it names the question it answers' );
};

subtest 'an answer that names another question does not settle this one' => sub {
    my $repo = init_repo();
    my $box  = mk_mailbox($repo);

    my $id = $box->ask( question => 'Ship it?' );
    $box->settle( $id, 'yes' );
    is( $box->resolve($id)->{state}, 'answered', 'the matching answer counts' );

    # What two clones minting the same id between syncs leaves behind: an
    # answer ref that survived and an ask ref that is now somebody else's
    # question. Simulated by writing the ask ref to a different question.
    App::karr::Git->new( dir => "$repo" )->write_ref(
        'refs/karr-foundation/questions/1/ask',
        "id: 1\nquestion: Delete the backups?\nasked: " . stamp(-60) . "\npolicy: block\n" );

    my $warned = '';
    my $r = do {
        local $SIG{__WARN__} = sub { $warned .= $_[0] };
        $box->resolve($id);
    };
    is( $r->{state}, 'open',
        'an answer to a different question does not settle this one' );
    like( $warned, qr/different question/, 'and it says so out loud' );

    # ... and re-answering it needs no force: there is nothing to protect.
    $box->settle( $id, 'no' );
    is( $box->resolve($id)->{state}, 'answered', 'the new answer settles it' );
    is( $box->answer($id)->{answer}, 'no',       'with the new value' );
};

subtest 'a mint that loses the race bumps instead of clobbering the winner' => sub {
    my $repo = init_repo();
    my $box  = mk_mailbox($repo);
    my $git  = App::karr::Git->new( dir => "$repo" );

    # Another writer takes the id between this one's read and its write. No
    # fork needed to pin the decision: what matters is that the create-only
    # write refuses and the caller moves on to the next id.
    my $raced = 0;
    no warnings 'redefine';
    my $orig = \&App::karr::Git::write_ref_cas;
    local *App::karr::Git::write_ref_cas = sub {
        my ( $self, $ref, $content, $old ) = @_;
        if ( !$raced++ && $ref eq 'refs/karr-foundation/questions/1/ask' ) {
            $git->write_ref( $ref,
                "id: 1\nquestion: Somebody else got here first\n"
              . "asked: " . stamp(-5) . "\npolicy: block\n" );
        }
        return $orig->( $self, $ref, $content, $old );
    };

    my $id = $box->ask( question => 'Mine' );
    is( $id, 2, 'the loser takes the next id' );
    is( $box->question(1)->{question}, 'Somebody else got here first',
        'and the winner is untouched' );
    is( $box->question(2)->{question}, 'Mine', 'while the loser is stored whole' );
};

subtest 'two answers at once is one answer and one refusal' => sub {
    my $repo = init_repo();
    my $box  = mk_mailbox($repo);
    my $id   = $box->ask( question => 'Ship it?' );

    $box->settle( $id, 'yes' );
    my $err = err_of( sub { $box->settle( $id, 'no' ) } );
    like( $err, qr/already answered/, 'the second answer is refused' );
    unlike( $err, qr/ at \S+ line \d+/, 'without a source location' );
    is( $box->answer($id)->{answer}, 'yes', 'and the first one stands' );

    $box->settle( $id, 'no', force => 1 );
    is( $box->answer($id)->{answer}, 'no', 'force is the way to change it' );
};

subtest 'the policy for nobody-answers is checked where it is written' => sub {



( run in 0.470 second using v1.01-cache-2.11-cpan-4ef0a570458 )