diff --git a/t/evaluator/evaluate-constituents-gc.t b/t/evaluator/evaluate-constituents-gc.t index a9b23e6c..2a5337b2 100644 --- a/t/evaluator/evaluate-constituents-gc.t +++ b/t/evaluator/evaluate-constituents-gc.t @@ -5,13 +5,58 @@ use Test2::V0; my $ctx = test_context(); -my $builds = $ctx->makeAndEvaluateJobset( - expression => 'constituents.nix', +my $expression = 'constituents.nix'; +my $jobsetCtx = $ctx->makeJobset( + expression => $expression, +); +my $builds = $ctx->evaluateJobset( + jobset => $jobsetCtx->{"jobset"}, + expression => $expression, + build => 0, ); my $constituentA = $builds->{"constituentA"}; my $directAggregate = $builds->{"direct_aggregate"}; my $indirectAggregate = $builds->{"indirect_aggregate"}; +my $mixedAggregate = $builds->{"mixed_aggregate"}; + +# Ensure that we get exactly the aggregates we expect +my %expected_constituents = ( + 'direct_aggregate' => { + 'constituentA' => 1, + }, + 'indirect_aggregate' => { + 'constituentA' => 1, + }, + 'mixed_aggregate' => { + # Note that `constituentA_alias` becomes `constituentA`, because + # the shorter name is preferred + 'constituentA' => 1, + 'constituentB' => 1, + }, +); + +my $rs = $ctx->db->resultset('AggregateConstituents')->search( + {}, + { + join => [ 'aggregate', 'constituent' ], # Use correct relationship names + columns => [], + '+select' => [ 'aggregate.job', 'constituent.job' ], + '+as' => [ 'aggregate_job', 'constituent_job' ], + } +); + +my %actual_constituents; +while (my $row = $rs->next) { + my $aggregate_job = $row->get_column('aggregate_job'); + my $constituent_job = $row->get_column('constituent_job'); + $actual_constituents{$aggregate_job} //= {}; + $actual_constituents{$aggregate_job}{$constituent_job} = 1; +} + +is(\%actual_constituents, \%expected_constituents, "Exact aggregate constituents as expected"); + +# Check that deletion also doesn't work accordingly is(system('nix-store', '--delete', $constituentA->drvpath), 256, "Deleting a constituent derivation fails"); is(system('nix-store', '--delete', $directAggregate->drvpath), 256, "Deleting the direct aggregate derivation fails"); diff --git a/t/jobs/constituents.nix b/t/jobs/constituents.nix index 5b7106b9..b8b88702 100644 --- a/t/jobs/constituents.nix +++ b/t/jobs/constituents.nix @@ -5,6 +5,8 @@ rec { builder = ./empty-dir-builder.sh; }; + constituentA_alias = constituentA; + constituentB = mkDerivation { name = "empty-dir-B"; builder = ./empty-dir-builder.sh; @@ -32,7 +34,7 @@ rec { name = "mixed_aggregate"; _hydraAggregate = true; constituents = [ - "constituentA" + "constituentA_alias" constituentB ]; builder = ./empty-dir-builder.sh; diff --git a/t/lib/HydraTestContext.pm b/t/lib/HydraTestContext.pm index 34d41eb2..27b0be0a 100644 --- a/t/lib/HydraTestContext.pm +++ b/t/lib/HydraTestContext.pm @@ -172,7 +172,6 @@ sub makeAndEvaluateJobset { } my $jobsdir = $opts{'jobsdir'} // $self->jobsdir; - my $should_build = $opts{'build'} // 0; my %args = ( jobsdir => $jobsdir, @@ -184,12 +183,28 @@ sub makeAndEvaluateJobset { $args{flake} = $flake; } my $jobsetCtx = $self->makeJobset(%args); - my $jobset = $jobsetCtx->{"jobset"}; + + return $self->evaluateJobset( + jobset => $jobsetCtx->{"jobset"}, + expression => $expression, + flake => $flake, + build => $opts{"build"} // 0, + ) +} + +sub evaluateJobset { + my ($self, %opts) = @_; + + my $jobset = $opts{'jobset'}; + + my $expression = $opts{'expression'} // $opts{'flake'}; evalSucceeds($jobset) or die "Evaluating jobs/$expression should exit with return code 0.\n"; my $builds = {}; + my $should_build = $opts{'build'}; + for my $build ($jobset->builds) { if ($should_build) { runBuild($build) or die "Build '".$build->job."' from jobs/$expression should exit with return code 0.\n";