49d6ca77a3
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 17s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 32s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m2s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 2m21s
- Extract doGetWithReader to share retry/backoff logic between doGet and doGetLimited, eliminating ~60 lines of duplicated code (addresses MINOR finding from all reviewers). - redactURL now strips userinfo credentials (user:pass@host) in addition to query parameters (addresses security-review-bot finding). - GetPullRequestDiff treats MaxDiffSize == math.MaxInt64 as disabled, preventing the silent enforcement bypass where the overflow clamp makes the size check unreachable (addresses security-review-bot finding). - Improved error message wording: 'response exceeds N bytes' (NIT fix).
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package gitea
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"math"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestGetPullRequestDiff_SizeLimits(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
diff string
|
|
maxDiffSize int64
|
|
wantErr error
|
|
wantDiff string
|
|
}{
|
|
{
|
|
name: "exceeds max size",
|
|
diff: strings.Repeat("+ added line\n", 1000), // ~13 KB
|
|
maxDiffSize: 100,
|
|
wantErr: ErrDiffTooLarge,
|
|
},
|
|
{
|
|
name: "within max size",
|
|
diff: "diff --git a/f.go b/f.go\n--- a/f.go\n+++ b/f.go\n@@ -1 +1 @@\n-old\n+new\n",
|
|
maxDiffSize: 1024,
|
|
wantDiff: "diff --git a/f.go b/f.go\n--- a/f.go\n+++ b/f.go\n@@ -1 +1 @@\n-old\n+new\n",
|
|
},
|
|
{
|
|
name: "exactly at limit",
|
|
diff: strings.Repeat("x", 50),
|
|
maxDiffSize: 50,
|
|
wantDiff: strings.Repeat("x", 50),
|
|
},
|
|
{
|
|
name: "one byte over limit",
|
|
diff: strings.Repeat("x", 51),
|
|
maxDiffSize: 50,
|
|
wantErr: ErrDiffTooLarge,
|
|
},
|
|
{
|
|
name: "disabled limit",
|
|
diff: strings.Repeat("x", 10000),
|
|
maxDiffSize: -1,
|
|
wantDiff: strings.Repeat("x", 10000),
|
|
},
|
|
{
|
|
name: "math.MaxInt64 treated as disabled",
|
|
diff: strings.Repeat("x", 10000),
|
|
maxDiffSize: math.MaxInt64,
|
|
wantDiff: strings.Repeat("x", 10000),
|
|
},
|
|
{
|
|
name: "default limit",
|
|
diff: "diff content",
|
|
maxDiffSize: 0, // zero means use DefaultMaxDiffSize
|
|
wantDiff: "diff content",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Write([]byte(tt.diff)) //nolint:errcheck // test handler
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(server.URL, "test-token")
|
|
client.MaxDiffSize = tt.maxDiffSize
|
|
client.RetryBackoff = []time.Duration{}
|
|
|
|
got, err := client.GetPullRequestDiff(context.Background(), "owner", "repo", 1)
|
|
|
|
if tt.wantErr != nil {
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
if !errors.Is(err, tt.wantErr) {
|
|
t.Errorf("expected %v, got: %v", tt.wantErr, err)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got != tt.wantDiff {
|
|
t.Errorf("diff mismatch: got length %d, want length %d", len(got), len(tt.wantDiff))
|
|
}
|
|
})
|
|
}
|
|
}
|