Skip to content

fix: resolve corpus testing bugs in generator and converter#317

Merged
erraggy merged 2 commits intomainfrom
fix/corpus-bug-fixes
Feb 15, 2026
Merged

fix: resolve corpus testing bugs in generator and converter#317
erraggy merged 2 commits intomainfrom
fix/corpus-bug-fixes

Conversation

@erraggy
Copy link
Owner

@erraggy erraggy commented Feb 15, 2026

Summary

  • Generator collision fix: Schema names ending in "Request" (e.g., CreatePetRequest) collided with generated server wrapper structs. Added resolveWrapperName with suffix cascade (Request → Input → Req → numeric fallback) to disambiguate.
  • Converter formData fix (2.0→3.x): in: "formData" parameters were passed through unconverted. Added convertOAS2FormDataToRequestBody that builds a proper requestBody with object schema, handles file uploads, transfers validation properties, and respects operation-level consumes.
  • Converter downconversion fix (3.0→2.0): Parameters with composite schemas (allOf/oneOf/anyOf) lost their type field, and #/components/headers/* refs were left unresolved. Added type inference from composite schemas and header ref inlining with deep copy.

All three bugs were discovered during MCP plugin corpus testing (discord-openapi.json, petstore 2.0, nws 3.0).

Test plan

  • TestServerWrapperTypeCollision — OAS3 spec with colliding schema name
  • TestResolveWrapperName — 6 table-driven subtests (no collision, nil map, cascade, numeric)
  • TestConvertOAS2FormDataToRequestBody — 4 subtests (url-encoded, multipart, mixed, consumes override)
  • TestConvertOAS3ParameterToOAS2_TypeFallback — 3 subtests (allOf, oneOf, default to string)
  • TestConvertOAS3ToOAS2_InlineHeaderRefs — end-to-end with component header resolution
  • make check passes (8078 tests)

🤖 Generated with Claude Code

Fix three bugs discovered during MCP plugin corpus testing:

**Generator: server wrapper type collision**
- Schema names ending in "Request" (e.g., CreatePetRequest) collided with
  generated server wrapper structs, causing Go compilation failures
- Added resolveWrapperName with suffix cascade: Request → Input → Req → numeric
- Added defensive iteration limit (1000) on numeric fallback

**Converter: formData parameters not converted (2.0→3.x)**
- formData parameters were passed through unconverted during OAS 2.0→3.x
- Added convertOAS2FormDataToRequestBody: builds requestBody with object schema
- Handles file uploads (multipart/form-data), url-encoded, and mixed params
- Transfers validation properties (enum, min/max, pattern, etc.) to schema
- Converts array-type Items to Schema via convertOAS2ItemsToSchema
- Sets Required on RequestBody when any formData param is required
- Respects operation-level consumes override

**Converter: incomplete 3.0→2.0 downconversion**
- Parameters with composite schemas (allOf/oneOf/anyOf) lost their type field
- Added inferTypeFromSchema to walk composite schemas for concrete types
- Header $refs (#/components/headers/*) were left unresolved in OAS 2.0 output
- Added resolveHeaderRef to inline component headers during downconversion
- Uses DeepCopy for all header assignments to prevent source document mutation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 15, 2026

📝 Walkthrough

Walkthrough

This pull request adds converter fixes (OAS2 formData→requestBody conversion, OAS3→OAS2 parameter type inference fallback, and inlining component header refs) and generator changes to avoid wrapper name collisions in generated server request types.

Changes

Cohort / File(s) Summary
Converter state
converter/converter.go
Adds private sourceHeaders map[string]*parser.Header field to hold OAS 3.x component headers during 3.0→2.0 conversion.
Converter: parameter & header helpers
converter/helpers.go
Adds type-inference fallback for non-body params (infers from allOf/oneOf/anyOf or defaults to "string"), inferTypeFromSchema, resolveHeaderRef for inlining #/components/headers/*, and safer deep-copying/inlining of response headers.
Converter: OAS3→OAS2 flow
converter/oas3_to_oas2.go, converter/oas3_to_oas2_test.go
Threads sourceHeaders into components conversion (set before, cleared after). Tests added for parameter type fallback and inlining header refs.
Converter: OAS2→OAS3 formData conversion
converter/oas2_to_oas3.go, converter/oas2_to_oas3_test.go
Converts OAS2 formData parameters to an OAS3 RequestBody with content-type selection (multipart vs x-www-form-urlencoded), builds schema properties from formData params, propagates validations, removes formData params from parameters list; tests for multiple scenarios (duplicate test block present).
Generator: wrapper-name collision avoidance
generator/security_gen_shared.go, generator/oas2_generator.go, generator/oas3_generator.go, generator/server_test.go
Adds resolveWrapperName and wrapperSuffixes to pick non-colliding request wrapper names, threads generatedTypes/schemaTypes through server generation contexts, and updates request type naming and signatures. Tests verify collision and numeric-suffix fallbacks.
Docs / Plans
docs/plans/2026-02-14-corpus-bug-fixes-design.md, docs/plans/2026-02-14-corpus-bug-fixes.md
Design and implementation plans documenting the three converter fixes and the generator wrapper-name change, with tasks, tests, and verification steps.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: resolve corpus testing bugs in generator and converter' accurately and concisely summarizes the main changes across multiple files addressing three related bugs.
Description check ✅ Passed The description comprehensively covers all three bug fixes (generator collision, converter formData, converter downconversion), includes test plan details, and relates directly to the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 82.35% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/corpus-bug-fixes

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Feb 15, 2026

Codecov Report

❌ Patch coverage is 70.85427% with 58 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.42%. Comparing base (697ff0a) to head (ac54799).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
converter/oas2_to_oas3.go 60.00% 36 Missing and 6 partials ⚠️
converter/helpers.go 72.72% 11 Missing and 4 partials ⚠️
generator/security_gen_shared.go 94.73% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #317      +/-   ##
==========================================
- Coverage   84.50%   84.42%   -0.09%     
==========================================
  Files         182      182              
  Lines       26226    26410     +184     
==========================================
+ Hits        22163    22296     +133     
- Misses       2755     2797      +42     
- Partials     1308     1317       +9     
Files with missing lines Coverage Δ
converter/converter.go 85.90% <ø> (ø)
converter/oas3_to_oas2.go 87.98% <100.00%> (+0.11%) ⬆️
generator/oas2_generator.go 79.14% <100.00%> (+0.16%) ⬆️
generator/oas3_generator.go 82.31% <100.00%> (+0.12%) ⬆️
generator/security_gen_shared.go 82.63% <94.73%> (+0.22%) ⬆️
converter/helpers.go 78.28% <72.72%> (-2.71%) ⬇️
converter/oas2_to_oas3.go 79.41% <60.00%> (-12.21%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@converter/helpers.go`:
- Around line 159-178: In resolveHeaderRef, add a defensive nil check for
c.sourceHeaders at the top (e.g., if c.sourceHeaders == nil) and handle it the
same way unresolved names are handled: call c.addIssueWithContext(result, path,
fmt.Sprintf("Unresolved header ref: %s", ref), "Header not found in
components.headers") and return nil; this prevents a nil-map panic if the method
is called without the upstream guard while keeping existing behavior around
addIssueWithContext, inlined := header.DeepCopy(), and clearing inlined.Ref
intact.

In `@converter/oas2_to_oas3.go`:
- Around line 278-316: The code sets propSchema.Format only in the default
switch branch, dropping param.Format for array and file cases; update the logic
in the parameter-to-schema conversion (in the block building propSchema for each
param in convertOAS2ItemsToSchema usage) to copy param.Format into propSchema
unconditionally (e.g., set propSchema.Format = param.Format after the switch) or
at minimum add propSchema.Format = param.Format into the "array" branch so
schema.Properties[param.Name] preserves any provided format; keep existing
special-case settings for "file" (Format = "binary") intact by overriding after
the unconditional copy if needed.
- Around line 256-341: The convertOAS2FormDataToRequestBody function currently
returns a RequestBody without Description and only treats "multipart/form-data"
as an override; update it to set RequestBody.Description (e.g., "Form data
parameters") and change the consumes fallback logic to detect any multipart
media type (e.g., use a prefix check like strings.HasPrefix(ct, "multipart/"))
when iterating the slice returned by c.getConsumes(src, doc), so multipart/mixed
and other multipart types are honored; keep existing behavior for
application/x-www-form-urlencoded when no multipart is found.

In `@converter/oas3_to_oas2_test.go`:
- Around line 711-768: Add a test case to
TestConvertOAS3ParameterToOAS2_TypeFallback exercising the AnyOf branch used by
inferTypeFromSchema: create a parameter whose Schema has AnyOf with at least one
concrete Type (e.g., "string" and "integer"), call convertOAS3ParameterToOAS2,
assert the converted.Type matches the expected concrete type (consistent with
the OneOf test), and assert result.Issues is non-empty to maintain existing
expectations.

In `@generator/security_gen_shared.go`:
- Around line 60-80: The final fallback in resolveWrapperName can return a name
that was already detected as colliding; update resolveWrapperName to handle
exhaustion explicitly by emitting a clear failure instead of silently returning
methodName+"Request": after exhausting wrapperSuffixes and numeric attempts
(maxAttempts), either panic or return an error/log with context (including
methodName and the attempted suffixes/maxAttempts) so generation fails loudly;
modify the function around resolveWrapperName, wrapperSuffixes, schemaTypes and
maxAttempts to replace the silent return with an explicit panic or
processLogger/error return that includes methodName and that no unique wrapper
name could be found.

- Add defensive nil check for sourceHeaders in resolveHeaderRef
- Transfer Format field in array-type formData parameter conversion
- Detect any multipart/* content type in consumes (not just multipart/form-data)
- Add anyOf test case for type inference branch coverage
- Return novel numeric suffix on exhaustion instead of known-colliding name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@erraggy erraggy merged commit e979130 into main Feb 15, 2026
28 checks passed
@erraggy erraggy deleted the fix/corpus-bug-fixes branch February 15, 2026 03:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant