Download
70 lines 2 KiBGoModified 2026-10-26 raw
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
package tools

import (
	"path/filepath"
	"strings"
	"testing"
)

// git's output is parsed as framed: whatever it prints, the blobs are
// what their headers say, or it is an error, never a panic.
func FuzzParseBatch(f *testing.F) {
	f.Add("0000 missing\nabc blob 3\nhi\n\n", 2)
	f.Add("abc blob 9999999999999999999\nx\n", 1)
	f.Add("abc blob -1\n\n", 1)
	f.Fuzz(func(t *testing.T, out string, n int) {
		n = n % 8
		if n < 0 {
			n = -n
		}
		blobs, err := parseBatch(out, n)
		if err == nil && len(blobs) != n {
			t.Fatalf("parseBatch gave %d blobs, want %d", len(blobs), n)
		}
		total := 0
		for _, b := range blobs {
			total += len(b)
		}
		if total > len(out) {
			t.Fatalf("blobs hold %d bytes of a %d-byte output", total, len(out))
		}
	})
}

// Every path git lists is inside the repository, or the listing is an
// error.
func FuzzParseRaw(f *testing.F) {
	f.Add(":100644 100644 aaa bbb M\x00src/a.go\x00")
	f.Add(":000000 100644 0 b A\x00../escape\x00")
	f.Add(":100644 100644 a b M\x00/abs\x00:1 2 3 4 D\x00x\x00")
	f.Fuzz(func(t *testing.T, raw string) {
		changes, err := parseRaw(raw)
		if err != nil {
			return
		}
		for _, c := range changes {
			if !filepath.IsLocal(c.path) {
				t.Fatalf("parseRaw(%q) gave %q", raw, c.path)
			}
		}
	})
}

// The trailer is added once: adding it again changes nothing.
func FuzzWithTrailer(f *testing.F) {
	f.Add("Fix it", "gpt")
	f.Add("Fix it\n\nSigned-off-by: A <a@b>", "m")
	f.Add("Fix: it\n\nKey: value\nmore", "")
	f.Fuzz(func(t *testing.T, msg, model string) {
		tr := coauthor(model)
		// The model's name may come from the server: it must not add
		// lines of its own to the commit message.
		if strings.ContainsFunc(tr, func(r rune) bool { return r < 0x20 || r == 0x7f || r == 0x85 }) { // git splits lines at \n only
			t.Fatalf("coauthor(%q) = %q", model, tr)
		}
		once := withTrailer(msg, tr)
		if !strings.Contains(once, tr) || withTrailer(once, tr) != once {
			t.Fatalf("withTrailer(%q) = %q, then %q", msg, once, withTrailer(once, tr))
		}
	})
}