Skip to content

Commit 48eede6

Browse files
authored
Merge pull request #236 from tzvatot/fix-generator
Fix generators to check empty field set slice
2 parents eb17109 + 6400581 commit 48eede6

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

pkg/generators/golang/builders_generator.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,26 +240,35 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
240240
// {{ $builderCtor }} creates a new builder of '{{ .Type.Name }}' objects.
241241
func {{ $builderCtor }}() *{{ $builderName }} {
242242
return &{{ $builderName }}{
243-
fieldSet_: make([]bool, {{ fieldSetSize .Type }}),
243+
fieldSet_: make([]bool, {{ fieldSetSize $.Type }}),
244244
}
245245
}
246246
247247
{{ if .Type.IsClass }}
248248
// Link sets the flag that indicates if this is a link.
249249
func (b *{{ $builderName }}) Link(value bool) *{{ $builderName }} {
250+
if len(b.fieldSet_) == 0 {
251+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
252+
}
250253
b.fieldSet_[0] = true
251254
return b
252255
}
253256
254257
// ID sets the identifier of the object.
255258
func (b *{{ $builderName }}) ID(value string) *{{ $builderName }} {
259+
if len(b.fieldSet_) == 0 {
260+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
261+
}
256262
b.id = value
257263
b.fieldSet_[1] = true
258264
return b
259265
}
260266
261267
// HREF sets the link to the object.
262268
func (b *{{ $builderName }}) HREF(value string) *{{ $builderName }} {
269+
if len(b.fieldSet_) == 0 {
270+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
271+
}
263272
b.href = value
264273
b.fieldSet_[2] = true
265274
return b
@@ -302,6 +311,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
302311
{{ lineComment .Type.Doc }}
303312
{{ if .Link }}
304313
func (b *{{ $builderName }}) {{ $setterName }}(value {{ $setterType }}) *{{ $builderName }} {
314+
if len(b.fieldSet_) == 0 {
315+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
316+
}
305317
b.{{ $fieldName }} = value
306318
b.fieldSet_[{{ $fieldIndex }}] = true
307319
return b
@@ -310,6 +322,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
310322
{{ $elementType := valueType .Type.Element }}
311323
{{ if .Type.Element.IsScalar }}
312324
func (b *{{ $builderName }}) {{ $setterName }}(values ...{{ $elementType }}) *{{ $builderName }} {
325+
if len(b.fieldSet_) == 0 {
326+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
327+
}
313328
b.{{ $fieldName }} = make([]{{ $elementType }}, len(values))
314329
copy(b.{{ $fieldName }}, values)
315330
b.fieldSet_[{{ $fieldIndex }}] = true
@@ -318,6 +333,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
318333
{{ else }}
319334
{{ $elementBuilderName := builderName .Type.Element }}
320335
func (b *{{ $builderName }}) {{ $setterName }}(values ...*{{ selectorType . }}{{ $elementBuilderName }}) *{{ $builderName }} {
336+
if len(b.fieldSet_) == 0 {
337+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
338+
}
321339
b.{{ $fieldName }} = make([]*{{ selectorType . }}{{ $elementBuilderName }}, len(values))
322340
copy(b.{{ $fieldName }}, values)
323341
b.fieldSet_[{{ $fieldIndex }}] = true
@@ -330,6 +348,9 @@ func (g *BuildersGenerator) generateStructBuilderSource(typ *concepts.Type) {
330348
//
331349
{{ lineComment .Type.Doc }}
332350
func (b *{{ $builderName }}) {{ $setterName }}(value {{ $setterType }}) *{{ $builderName }} {
351+
if len(b.fieldSet_) == 0 {
352+
b.fieldSet_ = make([]bool, {{ fieldSetSize $.Type }})
353+
}
333354
b.{{ $fieldName }} = value
334355
{{ if .Type.IsScalar }}
335356
b.fieldSet_[{{ $fieldIndex }}] = true

tests/go/builders_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,4 +468,52 @@ var _ = Describe("Builder", func() {
468468
Expect(builder.Empty()).To(BeTrue())
469469
})
470470
})
471+
472+
Describe("Defensive initialization", func() {
473+
It("Should not panic when using setter on uninitialized builder struct", func() {
474+
// Create builder struct directly without using constructor
475+
// This simulates the bug condition where fieldSet_ is uninitialized
476+
builder := &amv1.RegistryAuthBuilder{}
477+
478+
// This should not panic - the setter should defensively initialize fieldSet_
479+
Expect(func() {
480+
builder.Username("test-user")
481+
}).ToNot(Panic())
482+
483+
// Verify the builder can still build successfully
484+
auth, err := builder.Build()
485+
Expect(err).ToNot(HaveOccurred())
486+
Expect(auth).ToNot(BeNil())
487+
Expect(auth.Username()).To(Equal("test-user"))
488+
})
489+
490+
It("Should handle class setters on uninitialized builder", func() {
491+
// Test class-specific setters (ID, HREF, Link)
492+
builder := &cmv1.ClusterBuilder{}
493+
494+
Expect(func() {
495+
builder.ID("test-id").HREF("test-href")
496+
}).ToNot(Panic())
497+
498+
cluster, err := builder.Build()
499+
Expect(err).ToNot(HaveOccurred())
500+
Expect(cluster).ToNot(BeNil())
501+
Expect(cluster.ID()).To(Equal("test-id"))
502+
Expect(cluster.HREF()).To(Equal("test-href"))
503+
})
504+
505+
It("Should handle list setters on uninitialized builder", func() {
506+
// Test list attribute setters with GithubIdentityProvider.Teams
507+
builder := &cmv1.GithubIdentityProviderBuilder{}
508+
509+
Expect(func() {
510+
builder.Teams("team1", "team2")
511+
}).ToNot(Panic())
512+
513+
provider, err := builder.Build()
514+
Expect(err).ToNot(HaveOccurred())
515+
Expect(provider).ToNot(BeNil())
516+
Expect(provider.Teams()).To(Equal([]string{"team1", "team2"}))
517+
})
518+
})
471519
})

0 commit comments

Comments
 (0)