|
Line 0
Link Here
|
| 0 |
- |
1 |
#!/usr/bin/perl |
|
|
2 |
|
| 3 |
use Modern::Perl; |
| 4 |
use Test::More; |
| 5 |
use FindBin; |
| 6 |
use lib "$FindBin::Bin/../lib"; |
| 7 |
|
| 8 |
=head1 NAME |
| 9 |
|
| 10 |
t/attach_order.t - Test that attachments are uploaded in correct chronological order |
| 11 |
|
| 12 |
=head1 DESCRIPTION |
| 13 |
|
| 14 |
Tests that when attaching multiple commits, they are uploaded in chronological |
| 15 |
order (oldest first) so they can be applied correctly later. |
| 16 |
|
| 17 |
=cut |
| 18 |
|
| 19 |
# Simple mock for testing without external dependencies |
| 20 |
{ |
| 21 |
package MockBug; |
| 22 |
sub new { |
| 23 |
my ($class, %args) = @_; |
| 24 |
bless { %args, _attachments => [] }, $class; |
| 25 |
} |
| 26 |
sub id { $_[0]->{id} } |
| 27 |
sub summary { $_[0]->{summary} } |
| 28 |
sub status { $_[0]->{status} } |
| 29 |
sub attachments { $_[0]->{_attachments} } |
| 30 |
sub add_attachment { |
| 31 |
my ($self, $patch, $filename, $description, %opts) = @_; |
| 32 |
push @{$self->{_attachment_order}}, $description; |
| 33 |
return 1; |
| 34 |
} |
| 35 |
} |
| 36 |
|
| 37 |
{ |
| 38 |
package MockCommands; |
| 39 |
sub new { |
| 40 |
my ($class, %args) = @_; |
| 41 |
bless \%args, $class; |
| 42 |
} |
| 43 |
} |
| 44 |
|
| 45 |
subtest 'current behavior - attachments uploaded in reverse chronological order' => sub { |
| 46 |
plan tests => 4; |
| 47 |
|
| 48 |
# Track attachment order |
| 49 |
my @attachment_order; |
| 50 |
|
| 51 |
# Create mock bug that captures attachment order |
| 52 |
my $bug = MockBug->new( |
| 53 |
id => 12345, |
| 54 |
summary => 'Test bug', |
| 55 |
status => 'NEW', |
| 56 |
_attachment_order => \@attachment_order |
| 57 |
); |
| 58 |
|
| 59 |
# Simulate current GitBz::Git->get_commits behavior (reverse chronological) |
| 60 |
my @commits = ( |
| 61 |
{ id => 'abc123', subject => 'Third commit (newest)' }, |
| 62 |
{ id => 'def456', subject => 'Second commit (middle)' }, |
| 63 |
{ id => 'ghi789', subject => 'First commit (oldest)' }, |
| 64 |
); |
| 65 |
|
| 66 |
# Simulate current attach_patches behavior |
| 67 |
for my $commit (@commits) { |
| 68 |
$bug->add_attachment( |
| 69 |
"patch content", |
| 70 |
$commit->{id} . ".patch", |
| 71 |
$commit->{subject} |
| 72 |
); |
| 73 |
} |
| 74 |
|
| 75 |
# Verify current (wrong) behavior |
| 76 |
is(scalar @attachment_order, 3, 'Three attachments were created'); |
| 77 |
is($attachment_order[0], 'Third commit (newest)', 'First attachment is newest commit (WRONG)'); |
| 78 |
is($attachment_order[1], 'Second commit (middle)', 'Second attachment is middle commit'); |
| 79 |
is($attachment_order[2], 'First commit (oldest)', 'Third attachment is oldest commit (WRONG)'); |
| 80 |
|
| 81 |
note("CURRENT BEHAVIOR (BROKEN): " . join(' -> ', @attachment_order)); |
| 82 |
note("This is backwards! Patches should be applied oldest-first for correct git apply sequence."); |
| 83 |
}; |
| 84 |
|
| 85 |
subtest 'expected correct behavior - chronological order' => sub { |
| 86 |
plan tests => 4; |
| 87 |
|
| 88 |
my @attachment_order; |
| 89 |
my $bug = MockBug->new( |
| 90 |
id => 12345, |
| 91 |
summary => 'Test bug', |
| 92 |
status => 'NEW', |
| 93 |
_attachment_order => \@attachment_order |
| 94 |
); |
| 95 |
|
| 96 |
# What the corrected behavior should return (chronological order) |
| 97 |
my @commits = ( |
| 98 |
{ id => 'ghi789', subject => 'First commit (oldest)' }, |
| 99 |
{ id => 'def456', subject => 'Second commit (middle)' }, |
| 100 |
{ id => 'abc123', subject => 'Third commit (newest)' }, |
| 101 |
); |
| 102 |
|
| 103 |
# Simulate corrected attach_patches behavior |
| 104 |
for my $commit (@commits) { |
| 105 |
$bug->add_attachment( |
| 106 |
"patch content", |
| 107 |
$commit->{id} . ".patch", |
| 108 |
$commit->{subject} |
| 109 |
); |
| 110 |
} |
| 111 |
|
| 112 |
# Verify correct behavior |
| 113 |
is(scalar @attachment_order, 3, 'Three attachments were created'); |
| 114 |
is($attachment_order[0], 'First commit (oldest)', 'First attachment is oldest commit (CORRECT)'); |
| 115 |
is($attachment_order[1], 'Second commit (middle)', 'Second attachment is middle commit'); |
| 116 |
is($attachment_order[2], 'Third commit (newest)', 'Third attachment is newest commit (CORRECT)'); |
| 117 |
|
| 118 |
note("EXPECTED BEHAVIOR (CORRECT): " . join(' -> ', @attachment_order)); |
| 119 |
note("This is the correct order for sequential git apply."); |
| 120 |
}; |
| 121 |
|
| 122 |
subtest 'git rev-list default behavior analysis' => sub { |
| 123 |
plan tests => 1; |
| 124 |
|
| 125 |
# Document the root cause: git rev-list returns newest-first by default |
| 126 |
my $explanation = <<'EOF'; |
| 127 |
ROOT CAUSE ANALYSIS: |
| 128 |
- git rev-list returns commits in reverse chronological order (newest first) |
| 129 |
- GitBz::Git->get_commits() uses git rev-list without --reverse flag |
| 130 |
- attach_patches() processes commits in the order returned by get_commits() |
| 131 |
- Result: attachments are uploaded newest-first (backwards for applying) |
| 132 |
|
| 133 |
SOLUTION: |
| 134 |
- Add --reverse flag to git rev-list in GitBz::Git->rev_list() |
| 135 |
- This will return commits in chronological order (oldest first) |
| 136 |
- Attachments will then be uploaded in correct sequence for git apply |
| 137 |
EOF |
| 138 |
|
| 139 |
pass("Analysis documented"); |
| 140 |
note($explanation); |
| 141 |
}; |
| 142 |
|
| 143 |
done_testing(); |