141 lines · 5.2 KB · Go
RawDownload
package helps import (	"strings"	"testing" 	"github.com/tidwall/gjson") func TestSanitizeCodexInputItemIDsBoundaries(t *testing.T) {	id64 := strings.Repeat("a", 64)	id65 := strings.Repeat("b", 65)	unicode65 := strings.Repeat("界", 65)	body := []byte(`{"input":[{"id":"` + id64 + `"},{"id":"` + id65 + `"},{"id":"` + unicode65 + `"}]}`) 	got := SanitizeCodexInputItemIDs(body) 	if actual := gjson.GetBytes(got, "input.0.id").String(); actual != id64 {		t.Fatalf("64-character ID changed: %q", actual)	}	for _, path := range []string{"input.1.id", "input.2.id"} {		actual := gjson.GetBytes(got, path).String()		if len([]rune(actual)) != 64 {			t.Fatalf("%s length = %d, want 64: %q", path, len([]rune(actual)), actual)		}	}} func TestSanitizeCodexInputItemIDsNormalizesMessageIDs(t *testing.T) {	const invalidID = "item_74ec40c883248ebb4885ec84"	body := []byte(`{"input":[` +		`{"type":"message","id":"` + invalidID + `","role":"user"},` +		`{"type":"message","id":"msg-1","role":"assistant"},` +		`{"type":"function_call","id":"item_call","call_id":"call-1"}` +		`]}`) 	first := SanitizeCodexInputItemIDs(body)	second := SanitizeCodexInputItemIDs(body) 	if got := gjson.GetBytes(first, "input.0.id").String(); got != "msg_"+invalidID {		t.Fatalf("message ID = %q, want msg-prefixed ID", got)	}	if got := gjson.GetBytes(first, "input.1.id").String(); got != "msg-1" {		t.Fatalf("valid message ID changed: %q", got)	}	if got := gjson.GetBytes(first, "input.2.id").String(); got != "item_call" {		t.Fatalf("non-message ID changed: %q", got)	}	if string(first) != string(second) {		t.Fatalf("message ID normalization is not deterministic: first=%s second=%s", first, second)	}} func TestSanitizeCodexInputItemIDsDropsOverlongEncryptedReasoningItem(t *testing.T) {	longReasoningID := "rs_" + strings.Repeat("a", 64)	shortReasoningID := "rs_" + strings.Repeat("b", 48)	longCallID := strings.Repeat("call-item-", 8)	body := []byte(`{"input":[` +		`{"type":"message","id":"msg-1","role":"user","content":"before"},` +		`{"type":"reasoning","id":"` + longReasoningID + `","encrypted_content":"gAAAA-encrypted","summary":[{"type":"summary_text","text":"drop me"}]},` +		`{"type":"reasoning","id":"` + shortReasoningID + `","encrypted_content":"gAAAA-encrypted","summary":[]},` +		`{"type":"function_call","id":"` + longCallID + `","call_id":"call-1","name":"lookup","arguments":"{}"}` +		`]}`) 	got := SanitizeCodexInputItemIDs(body)	input := gjson.GetBytes(got, "input").Array() 	if len(input) != 3 {		t.Fatalf("input length = %d, want 3: %s", len(input), got)	}	if gotID := input[0].Get("id").String(); gotID != "msg-1" {		t.Fatalf("input.0.id = %q, want msg-1", gotID)	}	if gotID := input[1].Get("id").String(); gotID != shortReasoningID {		t.Fatalf("short encrypted reasoning id changed: %q", gotID)	}	if gotID := input[2].Get("id").String(); gotID == longCallID || len([]rune(gotID)) != 64 {		t.Fatalf("ordinary overlong id was not shortened: %q", gotID)	}} func TestSanitizeCodexInputItemIDsShortensOverlongReasoningWithoutEncryptedContent(t *testing.T) {	longReasoningID := "rs_" + strings.Repeat("a", 64)	for _, testCase := range []struct {		name             string		encryptedContent string	}{		{name: "missing"},		{name: "empty", encryptedContent: `,"encrypted_content":""`},		{name: "null", encryptedContent: `,"encrypted_content":null`},	} {		t.Run(testCase.name, func(t *testing.T) {			body := []byte(`{"input":[{"type":"reasoning","id":"` + longReasoningID + `"` + testCase.encryptedContent + `,"summary":[]}]}`) 			got := SanitizeCodexInputItemIDs(body)			input := gjson.GetBytes(got, "input").Array()			if len(input) != 1 {				t.Fatalf("input length = %d, want 1: %s", len(input), got)			}			gotID := input[0].Get("id").String()			if gotID == longReasoningID || len([]rune(gotID)) != 64 {				t.Fatalf("overlong reasoning id was not shortened: %q", gotID)			}		})	}} func TestSanitizeCodexInputItemIDsAvoidsExistingIDCollision(t *testing.T) {	longID := strings.Repeat("grok-item-", 10)	collidingValidID := shortenCodexInputItemID(longID)	body := []byte(`{"input":[{"id":"` + longID + `"},{"id":"` + collidingValidID + `"}]}`) 	first := SanitizeCodexInputItemIDs(body)	second := SanitizeCodexInputItemIDs(body) 	shortened := gjson.GetBytes(first, "input.0.id").String()	if shortened == collidingValidID {		t.Fatalf("shortened ID collided with an existing valid ID: %q", shortened)	}	if len([]rune(shortened)) > 64 {		t.Fatalf("shortened ID length = %d, want at most 64", len([]rune(shortened)))	}	if actual := gjson.GetBytes(first, "input.1.id").String(); actual != collidingValidID {		t.Fatalf("existing valid ID changed: %q", actual)	}	if actual := gjson.GetBytes(second, "input.0.id").String(); actual != shortened {		t.Fatalf("collision resolution is not deterministic: first=%q second=%q", shortened, actual)	}} func TestSanitizeCodexInputItemIDsLeavesUnsupportedPayloadsUnchanged(t *testing.T) {	for _, body := range [][]byte{		[]byte(`not-json`),		[]byte(`{"input":{"id":"item-1"}}`),		[]byte(`{"input":[1,{"id":2},{"id":"item-1"}]}`),	} {		if got := string(SanitizeCodexInputItemIDs(body)); got != string(body) {			t.Fatalf("payload changed: got=%q want=%q", got, body)		}	}}