Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bundler/bundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2319,8 +2319,8 @@ func TestCopySchemaToComponents_NameCollision(t *testing.T) {
func TestCalculateCollisionNameInline_NumericSuffix(t *testing.T) {
// Test: When filename-based name also collides, use numeric suffix
existingNames := map[string]bool{
"Cat": true,
"Cat__external": true, // Filename-based collision also exists
"Cat": true,
"Cat__external": true, // Filename-based collision also exists
"Cat__external__1": true, // First numeric suffix also taken (format: name__basename__N)
}

Expand Down
2 changes: 1 addition & 1 deletion bundler/origin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ func TestCaptureOrigin_FullCoverage(t *testing.T) {
pr := &processRef{
ref: &index.Reference{
FullDefinition: "test.yaml",
Node: &yaml.Node{Line: 5, Column: 2},
Node: &yaml.Node{Line: 5, Column: 2},
},
idx: &index.SpecIndex{},
originalName: "Test",
Expand Down
10 changes: 5 additions & 5 deletions datamodel/high/base/dynamic_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import (
//
// The N value indicates which value is set (0 = A, 1 == B), preventing the need to check both values.
type DynamicValue[A any, B any] struct {
N int // 0 == A, 1 == B
A A
B B
inline bool
renderCtx any // Context for inline rendering (typed as any to avoid import cycles)
N int // 0 == A, 1 == B
A A
B B
inline bool
renderCtx any // Context for inline rendering (typed as any to avoid import cycles)
}

// IsA will return true if the 'A' or left value is set.
Expand Down
10 changes: 5 additions & 5 deletions datamodel/high/overlay/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import (
// Action represents a high-level Overlay Action Object.
// https://spec.openapis.org/overlay/v1.1.0#action-object
type Action struct {
Target string `json:"target,omitempty" yaml:"target,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Update *yaml.Node `json:"update,omitempty" yaml:"update,omitempty"`
Remove bool `json:"remove,omitempty" yaml:"remove,omitempty"`
Copy string `json:"copy,omitempty" yaml:"copy,omitempty"`
Target string `json:"target,omitempty" yaml:"target,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Update *yaml.Node `json:"update,omitempty" yaml:"update,omitempty"`
Remove bool `json:"remove,omitempty" yaml:"remove,omitempty"`
Copy string `json:"copy,omitempty" yaml:"copy,omitempty"`
Extensions *orderedmap.Map[string, *yaml.Node] `json:"-" yaml:"-"`
low *low.Action
}
Expand Down
6 changes: 3 additions & 3 deletions datamodel/high/overlay/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
// Info represents a high-level Overlay Info Object.
// https://spec.openapis.org/overlay/v1.1.0#info-object
type Info struct {
Title string `json:"title,omitempty" yaml:"title,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Title string `json:"title,omitempty" yaml:"title,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Extensions *orderedmap.Map[string, *yaml.Node] `json:"-" yaml:"-"`
low *low.Info
}
Expand Down
8 changes: 4 additions & 4 deletions datamodel/high/overlay/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import (
// Overlay represents a high-level OpenAPI Overlay document.
// https://spec.openapis.org/overlay/v1.0.0
type Overlay struct {
Overlay string `json:"overlay,omitempty" yaml:"overlay,omitempty"`
Info *Info `json:"info,omitempty" yaml:"info,omitempty"`
Extends string `json:"extends,omitempty" yaml:"extends,omitempty"`
Actions []*Action `json:"actions,omitempty" yaml:"actions,omitempty"`
Overlay string `json:"overlay,omitempty" yaml:"overlay,omitempty"`
Info *Info `json:"info,omitempty" yaml:"info,omitempty"`
Extends string `json:"extends,omitempty" yaml:"extends,omitempty"`
Actions []*Action `json:"actions,omitempty" yaml:"actions,omitempty"`
Extensions *orderedmap.Map[string, *yaml.Node] `json:"-" yaml:"-"`
low *low.Overlay
}
Expand Down
1 change: 0 additions & 1 deletion datamodel/high/v3/request_body_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,3 @@ paths: {}`
assert.NoError(t, err)
assert.NotNil(t, result)
}

1 change: 0 additions & 1 deletion datamodel/high/v3/security_scheme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ func TestSecurityScheme_MarshalYAMLInlineWithContext_Reference(t *testing.T) {
assert.Equal(t, "$ref", yamlNode.Content[0].Value)
}


func TestBuildLowSecurityScheme_Success(t *testing.T) {
yml := `type: apiKey
name: X-API-Key
Expand Down
2 changes: 1 addition & 1 deletion datamodel/high/v3/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
// Server represents a high-level OpenAPI 3+ Server object, that is backed by a low level one.
// - https://spec.openapis.org/oas/v3.1.0#server-object
type Server struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"` // OpenAPI 3.2+ name field for documentation
Name string `json:"name,omitempty" yaml:"name,omitempty"` // OpenAPI 3.2+ name field for documentation
URL string `json:"url,omitempty" yaml:"url,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Variables *orderedmap.Map[string, *ServerVariable] `json:"variables,omitempty" yaml:"variables,omitempty"`
Expand Down
28 changes: 14 additions & 14 deletions datamodel/low/v3/security_scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ import (
// Recommended for most use case is Authorization Code Grant flow with PKCE.
// - https://spec.openapis.org/oas/v3.1.0#security-scheme-object
type SecurityScheme struct {
Type low.NodeReference[string]
Description low.NodeReference[string]
Name low.NodeReference[string]
In low.NodeReference[string]
Scheme low.NodeReference[string]
BearerFormat low.NodeReference[string]
Flows low.NodeReference[*OAuthFlows]
OpenIdConnectUrl low.NodeReference[string]
Type low.NodeReference[string]
Description low.NodeReference[string]
Name low.NodeReference[string]
In low.NodeReference[string]
Scheme low.NodeReference[string]
BearerFormat low.NodeReference[string]
Flows low.NodeReference[*OAuthFlows]
OpenIdConnectUrl low.NodeReference[string]
OAuth2MetadataUrl low.NodeReference[string] // OpenAPI 3.2+ OAuth2 metadata URL
Deprecated low.NodeReference[bool] // OpenAPI 3.2+ deprecated flag
Extensions *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
KeyNode *yaml.Node
RootNode *yaml.Node
index *index.SpecIndex
context context.Context
Deprecated low.NodeReference[bool] // OpenAPI 3.2+ deprecated flag
Extensions *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
KeyNode *yaml.Node
RootNode *yaml.Node
index *index.SpecIndex
context context.Context
*low.Reference
low.NodeMap
}
Expand Down
2 changes: 1 addition & 1 deletion datamodel/spec_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type SpecInfo struct {
APISchema string `json:"-"` // API Schema for supplied spec type (2 or 3)
Generated time.Time `json:"-"`
OriginalIndentation int `json:"-"` // the original whitespace
Self string `json:"-"` // the $self field for OpenAPI 3.2+ documents (base URI)
Self string `json:"-"` // the $self field for OpenAPI 3.2+ documents (base URI)
}

func ExtractSpecInfoWithConfig(spec []byte, config *DocumentConfiguration) (*SpecInfo, error) {
Expand Down
24 changes: 13 additions & 11 deletions datamodel/translate_coverage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import (
// TestTranslateMapParallel_ContextCancellation specifically targets lines 158-159
// in translate.go which handle context cancellation during job dispatch.
// This test ensures 100% coverage even on single-CPU systems like GitHub runners.
//
//
// The flaky coverage issue occurs because the select statement at lines 156-160:
// select {
// case jobChan <- j:
// case <-ctx.Done():
// return
// }
//
// select {
// case jobChan <- j:
// case <-ctx.Done():
// return
// }
//
// The ctx.Done() branch (lines 158-159) is only hit when the context is cancelled
// while the goroutine is blocked trying to send to jobChan. This is a race condition
// that doesn't always occur, especially on single-CPU systems.
Expand Down Expand Up @@ -57,7 +59,7 @@ func TestTranslateMapParallel_ContextCancellation(t *testing.T) {
time.Sleep(10 * time.Millisecond)
return "", errors.New("trigger cancellation")
}

// Other jobs: count how many get started
jobsBlocked.Add(1)
time.Sleep(100 * time.Millisecond)
Expand All @@ -72,13 +74,13 @@ func TestTranslateMapParallel_ContextCancellation(t *testing.T) {
err := datamodel.TranslateMapParallel[string, int, string](m, translateFunc, resultFunc)
require.Error(t, err)
assert.Contains(t, err.Error(), "trigger cancellation")

// Wait for goroutines to clean up
time.Sleep(20 * time.Millisecond)

// Verify context cancellation prevented all jobs from running
// If lines 158-159 are hit, some jobs will be skipped
assert.Less(t, int(jobsBlocked.Load()), itemCount-1,
assert.Less(t, int(jobsBlocked.Load()), itemCount-1,
"Iteration %d: Context cancellation should prevent some jobs", iteration)
}
}
}
2 changes: 1 addition & 1 deletion index/enhanced_coverage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,4 @@ other: test`,
}
}
})
}
}
26 changes: 13 additions & 13 deletions index/issue361_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,28 @@ properties:
// Create a Rolodex and add the standard fs.FS
config := CreateOpenAPIIndexConfig()
rolo := NewRolodex(config)

// Add the fs.FS with a base directory
// The fix ensures that when opening files, relative paths are used
// with the fs.FS interface, not absolute paths
// Use a temporary directory to ensure cross-platform compatibility
tempDir, err := os.MkdirTemp("", "rolodex-test")
require.NoError(t, err, "Should be able to create temp dir")
defer os.RemoveAll(tempDir)

baseDir := filepath.Join(tempDir, "api", "v1")
rolo.AddLocalFS(baseDir, testFS)

// Test 1: Open a file at the root of the FS
f1, err := rolo.Open("openapi.yaml")
require.NoError(t, err, "Should open file using relative path with fs.FS")
assert.Contains(t, f1.GetContent(), "Test API")

// Test 2: Open a nested file
f2, err := rolo.Open("schemas/pet.yaml")
require.NoError(t, err, "Should open nested file using relative path with fs.FS")
assert.Contains(t, f2.GetContent(), "type: object")

// Test 3: Verify absolute paths are converted correctly
// Even if we pass an absolute path matching the base + relative path,
// it should work by converting to relative
Expand All @@ -87,33 +87,33 @@ func TestIssue361_MultipleFileSystems(t *testing.T) {
apiFS := fstest.MapFS{
"api.yaml": {Data: []byte("api content"), ModTime: time.Now()},
}

schemaFS := fstest.MapFS{
"schema.json": {Data: []byte("schema content"), ModTime: time.Now()},
}

// Create Rolodex with multiple file systems
config := CreateOpenAPIIndexConfig()
rolo := NewRolodex(config)

// Use temporary directories for cross-platform compatibility
tempDir, err := os.MkdirTemp("", "rolodex-multi-test")
require.NoError(t, err, "Should be able to create temp dir")
defer os.RemoveAll(tempDir)

rolo.AddLocalFS(filepath.Join(tempDir, "apis"), apiFS)
rolo.AddLocalFS(filepath.Join(tempDir, "schemas"), schemaFS)

// Files should be found in their respective file systems
f1, err := rolo.Open("api.yaml")
require.NoError(t, err, "Should find api.yaml in first FS")
assert.Equal(t, "api content", f1.GetContent())

f2, err := rolo.Open("schema.json")
require.NoError(t, err, "Should find schema.json in second FS")
assert.Equal(t, "schema content", f2.GetContent())

// Non-existent file should return error
_, err = rolo.Open("nonexistent.yaml")
assert.Error(t, err, "Should return error for non-existent file")
}
}
6 changes: 6 additions & 0 deletions index/rolodex.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@ func (r *Rolodex) IndexTheRolodex(ctx context.Context) error {
if strings.HasPrefix(normalizedSpecPath, normalizedOrigBasePath+string(os.PathSeparator)) {
// SpecFilePath includes the original basePath, make it absolute directly
r.indexConfig.SpecAbsolutePath, _ = filepath.Abs(normalizedSpecPath)
} else if strings.HasPrefix(normalizedSpecPath, "..") {
// SpecFilePath starts with ".." (parent directory), resolve it from cwd
// Using filepath.Join with basePath would incorrectly double paths
// e.g., basePath="/Users/foo/bar" + "../bar/file.yaml" would give
// "/Users/foo/bar/bar/file.yaml" instead of "/Users/foo/bar/file.yaml"
r.indexConfig.SpecAbsolutePath, _ = filepath.Abs(normalizedSpecPath)
} else {
// SpecFilePath is relative to basePath, join them
r.indexConfig.SpecAbsolutePath = filepath.Join(basePath, normalizedSpecPath)
Expand Down
32 changes: 16 additions & 16 deletions index/rolodex_fscompat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ func (s strictFS) Open(name string) (fs.File, error) {

func TestRolodex_FSCompatibility_RelativePath(t *testing.T) {
t.Parallel()

// Create a test filesystem that strictly enforces fs.FS interface
testFS := strictFS{
FS: fstest.MapFS{
"spec.yaml": {Data: []byte("test content"), ModTime: time.Now()},
"refs/common.yaml": {Data: []byte("common ref"), ModTime: time.Now()},
"schemas/pet.yaml": {Data: []byte("pet schema"), ModTime: time.Now()},
"spec.yaml": {Data: []byte("test content"), ModTime: time.Now()},
"refs/common.yaml": {Data: []byte("common ref"), ModTime: time.Now()},
"schemas/pet.yaml": {Data: []byte("pet schema"), ModTime: time.Now()},
},
}

baseDir := "/project/api"

rolo := NewRolodex(CreateOpenAPIIndexConfig())
rolo.AddLocalFS(baseDir, testFS)

Expand All @@ -67,17 +67,17 @@ func TestRolodex_FSCompatibility_RelativePath(t *testing.T) {

func TestRolodex_FSCompatibility_AbsolutePath(t *testing.T) {
t.Parallel()

// Create a test filesystem that strictly enforces fs.FS interface
testFS := strictFS{
FS: fstest.MapFS{
"api/spec.yaml": {Data: []byte("api spec"), ModTime: time.Now()},
"common/base.yaml": {Data: []byte("base spec"), ModTime: time.Now()},
"api/spec.yaml": {Data: []byte("api spec"), ModTime: time.Now()},
"common/base.yaml": {Data: []byte("base spec"), ModTime: time.Now()},
},
}

baseDir, _ := filepath.Abs("/tmp/test")

rolo := NewRolodex(CreateOpenAPIIndexConfig())
rolo.AddLocalFS(baseDir, testFS)

Expand All @@ -90,17 +90,17 @@ func TestRolodex_FSCompatibility_AbsolutePath(t *testing.T) {

func TestRolodex_FSCompatibility_MultipleFS(t *testing.T) {
t.Parallel()

// For this test, we don't need strict enforcement since we're testing
// the ability to find files across multiple file systems
// The strict enforcement is tested in other test cases
apiFS := fstest.MapFS{
"openapi.yaml": {Data: []byte("api spec"), ModTime: time.Now()},
}

schemasFS := fstest.MapFS{
"pet.json": {Data: []byte("pet schema"), ModTime: time.Now()},
"store.json": {Data: []byte("store schema"), ModTime: time.Now()},
"pet.json": {Data: []byte("pet schema"), ModTime: time.Now()},
"store.json": {Data: []byte("store schema"), ModTime: time.Now()},
}

rolo := NewRolodex(CreateOpenAPIIndexConfig())
Expand All @@ -120,7 +120,7 @@ func TestRolodex_FSCompatibility_MultipleFS(t *testing.T) {

func TestRolodex_FSCompatibility_StandardFS(t *testing.T) {
t.Parallel()

// Test with various standard fs.FS implementations
testCases := []struct {
name string
Expand All @@ -139,10 +139,10 @@ func TestRolodex_FSCompatibility_StandardFS(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
rolo := NewRolodex(CreateOpenAPIIndexConfig())
rolo.AddLocalFS("/base", tc.fs)

f, err := rolo.Open("test.yaml")
require.NoError(t, err, "Should work with %s", tc.name)
assert.Equal(t, "test data", f.GetContent())
})
}
}
}
Loading