App-FuguWeb

 view release on metacpan or  search on metacpan

t/fuguweb/rotate.t  view on Meta::CPAN

	Fugu::File->write( "$root/.fuguwebrc", <<'RC' );
site = Example

nav "index.html" {
	label = Home
}

page "index.html" {
	title = Home
	body  = index.body.html
}
RC

	return $root;
}

# _rotate($root):
#	A rotation over the description of the project, with the
#	bootstrap words that a first mint needs.
sub _rotate ($root)
{
	my $reason;
	my $config = App::FuguWeb::Config->load( root => $root,
		error => \$reason )
	    or die "load $root: $reason\n";

	return App::FuguWeb::Rotate->new(
		config => $config,
		org    => $ORG,
		url    => $URL,
	);
}

# _mint($root, %args), _promote($root, %args):
#	One step over a fresh rotation, so each step reads the
#	description that the step before it wrote.
sub _mint ( $root, %args )
{
	my $rotate = _rotate($root);
	my $facts  = $rotate->mint( purpose => 'release', %args );

	return ( $facts, $rotate->error );
}

sub _promote ( $root, %args )
{
	my $rotate = _rotate($root);
	my $facts  = $rotate->promote( purpose => 'release', %args );

	return ( $facts, $rotate->error );
}

# _run(@argv):
#	Drive the real command in process, and answer the exit code
#	with what it wrote.
sub _run (@argv)
{
	my ( $out, $err ) = ( '', '' );

	open my $saved_out, '>&', \*STDOUT or die "Cannot save stdout: $!";
	open my $saved_err, '>&', \*STDERR or die "Cannot save stderr: $!";
	close STDOUT;
	close STDERR;
	open STDOUT, '>', \$out or die 'Cannot capture stdout';
	open STDERR, '>', \$err or die 'Cannot capture stderr';

	my $exit = eval { App::FuguWeb::CLI->run(@argv) };
	my $died = $@;

	close STDOUT;
	close STDERR;
	open STDOUT, '>&', $saved_out or die "Cannot restore stdout: $!";
	open STDERR, '>&', $saved_err or die "Cannot restore stderr: $!";

	die $died if $died;

	return ( $exit, $out, $err );
}

# _verifies($root, $stem):
#	True when the published key of the stem verifies the manifest
#	pair of the key directory.
sub _verifies ( $root, $stem )
{
	my $dir     = "$root/web/keys";
	my $signify = Fugu::Signify->new( keys => ["$dir/$stem.pub"] );

	return $signify->verify( "$dir/SHA256", "$dir/SHA256.sig" ) ? 1 : 0;
}

# _problems($root):
#	What App::FuguWeb::Keys reports about the directory.
sub _problems ($root)
{
	my $reason;
	my $config = App::FuguWeb::Config->load( root => $root,
		error => \$reason )
	    or return ("load: $reason");

	return App::FuguWeb::Keys->new( config => $config )->problems;
}

subtest 'the first mint bootstraps and signs its own manifest' => sub {
	my $root = _site();
	my ( $facts, $error ) =
	    _mint( $root, secret => "$root/k1.sec" );

	ok( $facts, 'the mint succeeds' ) or diag($error);
	return unless $facts;

	is( $facts->{name},   'fugubsd-1-release.pub', 'the name of the key' );
	is( $facts->{serial}, 1,                       'the serial starts at 1' );

	# WEB-ROTATE-3. The purpose held no current key.
	is( $facts->{status}, 'current', 'the first key is current at once' );

	# WEB-ROTATE-15. The keys block and the first key block
	# arrive together, and the block carries the published prefix.
	my $rc = Fugu::File->read("$root/.fuguwebrc");
	like( $rc, qr/^keys "keys" \{$/m, 'the description takes a keys block' );
	like( $rc, qr/^\torg = \Q$ORG\E$/m, 'with the organization word' );
	like( $rc, qr/^\turl = \Q$URL\E$/m, 'and the published prefix' );
	like(
		$rc,
		qr/^key "fugubsd-1-release" \{\n\tstatus = current$/m,
		'and the block of the first key'
	);

	# WEB-ROTATE-6. The one exception: this key signs for itself.
	ok( _verifies( $root, 'fugubsd-1-release' ),
		'the published key verifies the manifest' );

	# WEB-ROTATE-2. The private half takes no group mode and no



( run in 1.553 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )