From 9b64d5b3cf70675cb0d01b76ebfee021d76d9be9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:36:31 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A7=AA=20Add=20missing=20non-PDF=20fi?= =?UTF-8?q?lename=20test=20for=20FilePartFromBase64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: matdev83 <211248003+matdev83@users.noreply.github.com> --- internal/plugins/frontends/openaiwire/parts_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internal/plugins/frontends/openaiwire/parts_test.go b/internal/plugins/frontends/openaiwire/parts_test.go index e5fd6311..47a735df 100644 --- a/internal/plugins/frontends/openaiwire/parts_test.go +++ b/internal/plugins/frontends/openaiwire/parts_test.go @@ -50,3 +50,14 @@ func TestFilePartFromBase64_pdfFilename(t *testing.T) { t.Fatalf("kind %v", p.Kind) } } + +func TestFilePartFromBase64_nonPdfFilename(t *testing.T) { + t.Parallel() + p := FilePartFromBase64("doc.txt", "qqq") + if p.FileMIME != "application/octet-stream" { + t.Fatalf("mime %q", p.FileMIME) + } + if p.Kind != lipapi.PartFileRef { + t.Fatalf("kind %v", p.Kind) + } +} From fbe90cbe77809907d56252677cc57c467f5907d4 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Wed, 1 Jul 2026 18:07:07 +0200 Subject: [PATCH 2/2] ci(fuzz): tolerate Go fuzz engine spurious context-deadline-exceeded The Go fuzz engine (golang/go#75804, Go 1.25-1.26.x) intermittently emits `--- FAIL: FuzzX / context deadline exceeded` with no file:line and no corpus entry when -fuzztime expires, blocking CI on unrelated PRs. Add scripts/fuzz-run.sh: runs `go test -fuzz=...` and treats that bare deadline message as success, while still failing on real findings ("Failing input written to"), real assertion/panic failures (*.go:line), or any other non-zero exit. Route test-fuzz through it on non-Windows; Windows keeps `go test` direct (local smoke is short, bash may be absent). Unblocks PRs whose qa run fails on this flake (e.g. FuzzJSONRoundTrip, FuzzParseSnapshot) without masking real fuzz discoveries. Co-authored-by: Cursor --- Makefile | 67 +++++++++++++++++++++++++-------------------- scripts/fuzz-run.sh | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 scripts/fuzz-run.sh diff --git a/Makefile b/Makefile index 1e752b2a..5e6305c0 100644 --- a/Makefile +++ b/Makefile @@ -59,37 +59,46 @@ endif # Short fuzz smoke (extend FUZZTIME locally, e.g. FUZZTIME=30s make test-fuzz) FUZZTIME ?= 500ms +# Route each fuzz invocation through a wrapper that tolerates the Go fuzz +# engine's spurious "context deadline exceeded" at -fuzztime expiry +# (golang/go#75804, Go 1.25-1.26.x). On Windows `go test` runs directly: local +# fuzz smoke is short and a rare flake is cheap to re-run, and bash may be absent. +ifeq ($(OS),Windows_NT) +FUZZ_WRAPPER := $(GO) test +else +FUZZ_WRAPPER := bash scripts/fuzz-run.sh +endif test-fuzz: @echo "Fuzz smoke (FUZZTIME=$(FUZZTIME)) one target per line" - $(GO) test -fuzz=FuzzJSONRoundTrip$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/testkit - $(GO) test -fuzz=FuzzParseSnapshot$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/infra/modelcatalog/modelsdev - $(GO) test -fuzz=FuzzParseSelector$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/routing - $(GO) test -fuzz=FuzzParseSelectorFromBytes$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/routing - $(GO) test -fuzz=FuzzDecodeCreateRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/openairesponses - $(GO) test -fuzz=FuzzDecodeMessageRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/anthropic - $(GO) test -fuzz=FuzzDecodeGenerateContentRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/gemini - $(GO) test -fuzz=FuzzDecodeChatRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/openailegacy - $(GO) test -fuzz=FuzzWriteNonStreamJSON_toolArguments$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/anthropic - $(GO) test -fuzz=FuzzBuildGenerateContentResponse_toolJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/gemini - $(GO) test -fuzz=FuzzCallValidateJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./pkg/lipapi - $(GO) test -fuzz=FuzzMergeRouteQueryGenerationOptions$$ -fuzztime=$(FUZZTIME) -run=^$$ ./pkg/lipapi - $(GO) test -fuzz=FuzzCollectWithLimitsProgram$$ -fuzztime=$(FUZZTIME) -run=^$$ ./pkg/lipapi - $(GO) test -fuzz=FuzzStableCallIdentity$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/diag - $(GO) test -fuzz=FuzzParamsForCall$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openairesponses - $(GO) test -fuzz=FuzzHandleResponseStreamUnion$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openairesponses - $(GO) test -fuzz=FuzzBuildToolsParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openairesponses - $(GO) test -fuzz=FuzzHandleMessageStreamEventUnion$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/anthropicmessages - $(GO) test -fuzz=FuzzToolInputSchemaParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/anthropicmessages - $(GO) test -fuzz=FuzzHandleChatCompletionChunk$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openailegacy - $(GO) test -fuzz=FuzzBuildChatToolsParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openailegacy - $(GO) test -fuzz=FuzzHandleGenerateContentResponse$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/geminigenerate - $(GO) test -fuzz=FuzzBuildToolsParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/geminigenerate - $(GO) test -fuzz=FuzzMessageToContentToolResultJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/geminigenerate - $(GO) test -fuzz=FuzzAssistantPartsToContentBlocksJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/bedrock - $(GO) test -fuzz=FuzzParseNDJSONLine$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/acp - $(GO) test -fuzz=FuzzMapSessionUpdateToEvents$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/acp - $(GO) test -fuzz=FuzzMergeHandshakeProfileExtensions$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/acp - $(GO) test -fuzz=FuzzHookMutationValidators$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/hooks + $(FUZZ_WRAPPER) -fuzz=FuzzJSONRoundTrip$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/testkit + $(FUZZ_WRAPPER) -fuzz=FuzzParseSnapshot$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/infra/modelcatalog/modelsdev + $(FUZZ_WRAPPER) -fuzz=FuzzParseSelector$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/routing + $(FUZZ_WRAPPER) -fuzz=FuzzParseSelectorFromBytes$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/routing + $(FUZZ_WRAPPER) -fuzz=FuzzDecodeCreateRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/openairesponses + $(FUZZ_WRAPPER) -fuzz=FuzzDecodeMessageRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/anthropic + $(FUZZ_WRAPPER) -fuzz=FuzzDecodeGenerateContentRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/gemini + $(FUZZ_WRAPPER) -fuzz=FuzzDecodeChatRequest$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/openailegacy + $(FUZZ_WRAPPER) -fuzz=FuzzWriteNonStreamJSON_toolArguments$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/anthropic + $(FUZZ_WRAPPER) -fuzz=FuzzBuildGenerateContentResponse_toolJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/frontends/gemini + $(FUZZ_WRAPPER) -fuzz=FuzzCallValidateJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./pkg/lipapi + $(FUZZ_WRAPPER) -fuzz=FuzzMergeRouteQueryGenerationOptions$$ -fuzztime=$(FUZZTIME) -run=^$$ ./pkg/lipapi + $(FUZZ_WRAPPER) -fuzz=FuzzCollectWithLimitsProgram$$ -fuzztime=$(FUZZTIME) -run=^$$ ./pkg/lipapi + $(FUZZ_WRAPPER) -fuzz=FuzzStableCallIdentity$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/diag + $(FUZZ_WRAPPER) -fuzz=FuzzParamsForCall$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openairesponses + $(FUZZ_WRAPPER) -fuzz=FuzzHandleResponseStreamUnion$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openairesponses + $(FUZZ_WRAPPER) -fuzz=FuzzBuildToolsParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openairesponses + $(FUZZ_WRAPPER) -fuzz=FuzzHandleMessageStreamEventUnion$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/anthropicmessages + $(FUZZ_WRAPPER) -fuzz=FuzzToolInputSchemaParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/anthropicmessages + $(FUZZ_WRAPPER) -fuzz=FuzzHandleChatCompletionChunk$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openailegacy + $(FUZZ_WRAPPER) -fuzz=FuzzBuildChatToolsParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/openailegacy + $(FUZZ_WRAPPER) -fuzz=FuzzHandleGenerateContentResponse$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/geminigenerate + $(FUZZ_WRAPPER) -fuzz=FuzzBuildToolsParametersJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/geminigenerate + $(FUZZ_WRAPPER) -fuzz=FuzzMessageToContentToolResultJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/protocols/geminigenerate + $(FUZZ_WRAPPER) -fuzz=FuzzAssistantPartsToContentBlocksJSON$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/bedrock + $(FUZZ_WRAPPER) -fuzz=FuzzParseNDJSONLine$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/acp + $(FUZZ_WRAPPER) -fuzz=FuzzMapSessionUpdateToEvents$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/acp + $(FUZZ_WRAPPER) -fuzz=FuzzMergeHandshakeProfileExtensions$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/plugins/backends/acp + $(FUZZ_WRAPPER) -fuzz=FuzzHookMutationValidators$$ -fuzztime=$(FUZZTIME) -run=^$$ ./internal/core/hooks parity-checks: $(GO) test $(GO_TEST_FLAGS) -tags=precommit,integration ./internal/testkit/conformance/... diff --git a/scripts/fuzz-run.sh b/scripts/fuzz-run.sh new file mode 100644 index 00000000..72d9c36b --- /dev/null +++ b/scripts/fuzz-run.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# fuzz-run.sh — run a single `go test -fuzz=...` invocation and tolerate the +# Go fuzz engine's known spurious "context deadline exceeded" failure that +# occurs when -fuzztime expires (golang/go#75804, Go 1.25-1.26.x). +# +# At the -fuzztime boundary the fuzz coordinator cancels in-flight iterations +# and may emit: +# --- FAIL: FuzzX (Ns) +# context deadline exceeded +# with NO `file:line` reference and NO "Failing input written to" corpus entry. +# That is the time budget expiring, not a real test failure. +# +# Real failures always include either a `..._test.go::` (or any +# `*.go::`) reference or a "Failing input written to" line; those are +# still surfaced as failures. Only the bare deadline message is tolerated. +# +# Usage: fuzz-run.sh +# Env: GO — go binary (default: go) + +set -u + +GO_BIN="${GO:-go}" + +out="$(mktemp)" +trap 'rm -f "$out"' EXIT + +# Note: no `set -e`/pipefail here — a nonzero `go test` exit is classified below. +"$GO_BIN" test "$@" >"$out" 2>&1 +status=$? +cat "$out" + +# Clean exit. +if [ "$status" -eq 0 ]; then + exit 0 +fi + +# Real finding: a new failing corpus entry was written. +if grep -q 'Failing input written to' "$out"; then + exit "$status" +fi + +# Real assertion/panic failure: a source file:line reference is present. +if grep -qE '\.go:[0-9]+:' "$out"; then + exit "$status" +fi + +# Spurious engine deadline flake at the -fuzztime boundary — tolerate. +if grep -q 'context deadline exceeded' "$out"; then + echo "fuzz-run: tolerated spurious Go fuzz engine 'context deadline exceeded' at -fuzztime boundary (golang/go#75804)" >&2 + exit 0 +fi + +# Any other non-zero exit is a real error (build failure, panic w/o location, etc.). +exit "$status"