133 lines
3.8 KiB
Go
133 lines
3.8 KiB
Go
package pierre
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter"
|
|
"github.com/google/go-cmp/cmp"
|
|
)
|
|
|
|
// mockChat implements the ChatAdapter interface for testing.
|
|
type mockChat struct{ callCount int }
|
|
|
|
func (m *mockChat) GenerateStructured(ctx context.Context, msgs []chatter.Message, target interface{}) error {
|
|
m.callCount++
|
|
if cSlice, ok := target.(*[]Comment); ok {
|
|
*cSlice = []Comment{{File: "file.go", Line: 1, Message: "test comment"}}
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *mockChat) GetProviderName() string { return "mock" }
|
|
|
|
// mockGit implements the GitAdapter interface for testing.
|
|
type mockGit struct{}
|
|
|
|
func (g *mockGit) GetDiff(ctx context.Context, owner, repo string, prID int) (io.ReadCloser, error) {
|
|
diff := "diff --git a/file1.go b/file1.go\n+line1\n" + "diff --git a/file2.go b/file2.go\n+line2\n"
|
|
return io.NopCloser(bytes.NewReader([]byte(diff))), nil
|
|
}
|
|
|
|
func (g *mockGit) AddComment(ctx context.Context, owner, repo string, prID int, comment Comment) error {
|
|
return nil
|
|
}
|
|
|
|
func TestSplitDiffIntoChunks(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
diff string
|
|
maxSize int
|
|
wantChunks int // 0 means we don't assert exact count
|
|
wantPrefixes []string
|
|
checkRecombine bool
|
|
}{
|
|
{
|
|
name: "small diff",
|
|
diff: "diff --git a/file1.txt b/file1.txt\n+added line\n",
|
|
maxSize: 1000,
|
|
wantChunks: 1,
|
|
wantPrefixes: []string{"diff --git a/file1.txt"},
|
|
checkRecombine: true,
|
|
},
|
|
{
|
|
name: "multiple files",
|
|
diff: "diff --git a/file1.txt b/file1.txt\n+added line 1\n" +
|
|
"diff --git a/file2.txt b/file2.txt\n+added line 2\n",
|
|
maxSize: 50,
|
|
wantChunks: 2,
|
|
wantPrefixes: []string{"diff --git a/file1.txt", "diff --git a/file2.txt"},
|
|
checkRecombine: false,
|
|
},
|
|
{
|
|
name: "large single file",
|
|
diff: func() string {
|
|
line := "+very long added line that will be repeated many times to exceed the chunk size\n"
|
|
return "diff --git a/large.txt b/large.txt\n" + strings.Repeat(line, 200)
|
|
}(),
|
|
maxSize: 500,
|
|
wantChunks: 0,
|
|
wantPrefixes: nil,
|
|
checkRecombine: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
chunks := splitDiffIntoChunks([]byte(tc.diff), tc.maxSize)
|
|
if tc.wantChunks > 0 && len(chunks) != tc.wantChunks {
|
|
t.Fatalf("expected %d chunks, got %d", tc.wantChunks, len(chunks))
|
|
}
|
|
for i, prefix := range tc.wantPrefixes {
|
|
if i >= len(chunks) {
|
|
t.Fatalf("missing chunk %d for prefix check", i)
|
|
}
|
|
trimmed := strings.TrimPrefix(chunks[i], "\n")
|
|
if !strings.HasPrefix(trimmed, prefix) {
|
|
t.Fatalf("chunk %d does not start with expected prefix %q: %s", i, prefix, chunks[i])
|
|
}
|
|
}
|
|
for i, c := range chunks {
|
|
if tc.maxSize > 0 && len(c) > tc.maxSize {
|
|
t.Fatalf("chunk %d exceeds max size %d: %d", i, tc.maxSize, len(c))
|
|
}
|
|
}
|
|
if tc.checkRecombine {
|
|
recombined := strings.Join(chunks, "")
|
|
if diff := cmp.Diff(tc.diff, recombined); diff != "" {
|
|
t.Fatalf("recombined diff differs:\n%s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJudgePR_ChunkAggregationAndDeduplication(t *testing.T) {
|
|
chatMock := &mockChat{}
|
|
svc := &Service{
|
|
maxChunkSize: 50,
|
|
guidelines: nil,
|
|
git: &mockGit{},
|
|
chat: chatMock,
|
|
}
|
|
diffReader, err := svc.git.GetDiff(context.Background(), "", "", 0)
|
|
if err != nil {
|
|
t.Fatalf("failed to get diff: %v", err)
|
|
}
|
|
defer diffReader.Close()
|
|
comments, err := svc.judgePR(context.Background(), diffReader)
|
|
if err != nil {
|
|
t.Fatalf("judgePR error: %v", err)
|
|
}
|
|
if got, want := len(comments), 1; got != want {
|
|
t.Fatalf("expected %d comment after deduplication, got %d", want, got)
|
|
}
|
|
if chatMock.callCount != 2 {
|
|
t.Fatalf("expected mockChat to be called for each chunk (2), got %d", chatMock.callCount)
|
|
}
|
|
}
|