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
23 changes: 22 additions & 1 deletion pkg/generators/golang/builders_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,26 +240,35 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
// {{ $builderCtor }} creates a new builder of '{{ .Type.Name }}' objects.
func {{ $builderCtor }}() *{{ $builderName }} {
return &{{ $builderName }}{
fieldSet_: make([]bool, {{ fieldSetSize .Type }}),
fieldSet_: make([]bool, {{ fieldSetSize $.Type }}),
}
}

{{ if .Type.IsClass }}
// Link sets the flag that indicates if this is a link.
func (b *{{ $builderName }}) Link(value bool) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.fieldSet_[0] = true
return b
}

// ID sets the identifier of the object.
func (b *{{ $builderName }}) ID(value string) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.id = value
b.fieldSet_[1] = true
return b
}

// HREF sets the link to the object.
func (b *{{ $builderName }}) HREF(value string) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.href = value
b.fieldSet_[2] = true
return b
Expand Down Expand Up @@ -302,6 +311,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
{{ lineComment .Type.Doc }}
{{ if .Link }}
func (b *{{ $builderName }}) {{ $setterName }}(value {{ $setterType }}) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.{{ $fieldName }} = value
b.fieldSet_[{{ $fieldIndex }}] = true
return b
Expand All @@ -310,6 +322,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
{{ $elementType := valueType .Type.Element }}
{{ if .Type.Element.IsScalar }}
func (b *{{ $builderName }}) {{ $setterName }}(values ...{{ $elementType }}) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.{{ $fieldName }} = make([]{{ $elementType }}, len(values))
copy(b.{{ $fieldName }}, values)
b.fieldSet_[{{ $fieldIndex }}] = true
Expand All @@ -318,6 +333,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
{{ else }}
{{ $elementBuilderName := builderName .Type.Element }}
func (b *{{ $builderName }}) {{ $setterName }}(values ...*{{ selectorType . }}{{ $elementBuilderName }}) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.{{ $fieldName }} = make([]*{{ selectorType . }}{{ $elementBuilderName }}, len(values))
copy(b.{{ $fieldName }}, values)
b.fieldSet_[{{ $fieldIndex }}] = true
Expand All @@ -330,6 +348,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
//
{{ lineComment .Type.Doc }}
func (b *{{ $builderName }}) {{ $setterName }}(value {{ $setterType }}) *{{ $builderName }} {
if len(b.fieldSet_) == 0 {
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
}
b.{{ $fieldName }} = value
{{ if .Type.IsScalar }}
b.fieldSet_[{{ $fieldIndex }}] = true
Expand Down
48 changes: 48 additions & 0 deletions tests/go/builders_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,4 +468,52 @@ var _ = Describe("Builder", func() {
Expect(builder.Empty()).To(BeTrue())
})
})

Describe("Defensive initialization", func() {
It("Should not panic when using setter on uninitialized builder struct", func() {
// Create builder struct directly without using constructor
// This simulates the bug condition where fieldSet_ is uninitialized
builder := &amv1.RegistryAuthBuilder{}

// This should not panic - the setter should defensively initialize fieldSet_
Expect(func() {
builder.Username("test-user")
}).ToNot(Panic())

// Verify the builder can still build successfully
auth, err := builder.Build()
Expect(err).ToNot(HaveOccurred())
Expect(auth).ToNot(BeNil())
Expect(auth.Username()).To(Equal("test-user"))
})

It("Should handle class setters on uninitialized builder", func() {
// Test class-specific setters (ID, HREF, Link)
builder := &cmv1.ClusterBuilder{}

Expect(func() {
builder.ID("test-id").HREF("test-href")
}).ToNot(Panic())

cluster, err := builder.Build()
Expect(err).ToNot(HaveOccurred())
Expect(cluster).ToNot(BeNil())
Expect(cluster.ID()).To(Equal("test-id"))
Expect(cluster.HREF()).To(Equal("test-href"))
})

It("Should handle list setters on uninitialized builder", func() {
// Test list attribute setters with GithubIdentityProvider.Teams
builder := &cmv1.GithubIdentityProviderBuilder{}

Expect(func() {
builder.Teams("team1", "team2")
}).ToNot(Panic())

provider, err := builder.Build()
Expect(err).ToNot(HaveOccurred())
Expect(provider).ToNot(BeNil())
Expect(provider.Teams()).To(Equal([]string{"team1", "team2"}))
})
})
})