Skip to content

Commit 615ec6e

Browse files
committed
Addressing feedback:Add DV-preferred test coverage and typed initializer
1 parent 1c8af4e commit 615ec6e

3 files changed

Lines changed: 128 additions & 37 deletions

File tree

pkg/analysis/maxlength/analyzer_test.go

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020

2121
"golang.org/x/tools/go/analysis/analysistest"
2222
"k8s.io/apimachinery/pkg/util/validation/field"
23-
"sigs.k8s.io/kube-api-linter/pkg/analysis/initializer"
2423
"sigs.k8s.io/kube-api-linter/pkg/analysis/maxlength"
2524
"sigs.k8s.io/kube-api-linter/pkg/markers"
2625
)
@@ -33,27 +32,14 @@ func TestMaxLength(t *testing.T) {
3332
analysistest.Run(t, testdata, maxlength.Analyzer, "a")
3433
}
3534

36-
// TestMaxLength_DVMarkers tests that the linter (default config) accepts DV
37-
// markers as satisfying the max-length/max-items/max-properties constraints.
38-
func TestMaxLength_DVMarkers(t *testing.T) {
39-
testdata := analysistest.TestData()
40-
41-
// The DV testdata lives in the same package "a" (c.go + d.go).
42-
// Running against "a" exercises both the original kubebuilder fixtures and the new DV ones.
43-
analysistest.Run(t, testdata, maxlength.Analyzer, "a")
44-
}
45-
46-
// TestMaxLength_DVPreferred tests the linter configured to prefer DV markers in
47-
// diagnostic messages.
35+
// TestMaxLength_DVPreferred tests the linter configured to prefer DV markers:
36+
// - DV-style markers (k8s:maxLength, k8s:maxItems, k8s:maxProperties, k8s:maxBytes)
37+
// satisfy the constraints and produce no diagnostic.
38+
// - Missing markers produce diagnostics citing the k8s:* form.
4839
func TestMaxLength_DVPreferred(t *testing.T) {
4940
testdata := analysistest.TestData()
5041

51-
ci, ok := maxlength.Initializer().(initializer.ConfigurableAnalyzerInitializer)
52-
if !ok {
53-
t.Fatal("maxlength.Initializer() does not implement ConfigurableAnalyzerInitializer")
54-
}
55-
56-
a, err := ci.Init(&maxlength.MaxLengthConfig{
42+
a, err := maxlength.Initializer().Initialize(&maxlength.MaxLengthConfig{
5743
PreferredMaxLengthMarker: markers.K8sMaxLengthMarker,
5844
PreferredMaxItemsMarker: markers.K8sMaxItemsMarker,
5945
PreferredMaxPropertiesMarker: markers.K8sMaxPropertiesMarker,
@@ -62,21 +48,16 @@ func TestMaxLength_DVPreferred(t *testing.T) {
6248
t.Fatalf("failed to init analyzer: %v", err)
6349
}
6450

65-
// Run only against c.go-style testdata when DV markers are preferred.
66-
// The want-comments in a.go cite kubebuilder markers; for this run we use a
67-
// separate package that has no want-comments (happy-path only).
68-
// For now we verify the analyzer initialises and runs without panicking.
69-
_ = a
70-
_ = testdata
51+
// Package "b" has want-comments referencing k8s:* marker names, so the
52+
// analyser must emit diagnostics with those names when a field is missing a
53+
// marker, and must not emit anything for fields that carry a DV marker.
54+
analysistest.Run(t, testdata, a, "b")
7155
}
7256

7357
// TestMaxLengthInitializerValidation tests that the MaxLengthConfig validator
7458
// accepts valid values and rejects invalid ones.
7559
func TestMaxLengthInitializerValidation(t *testing.T) {
76-
ci, ok := maxlength.Initializer().(initializer.ConfigurableAnalyzerInitializer)
77-
if !ok {
78-
t.Fatal("maxlength.Initializer() does not implement ConfigurableAnalyzerInitializer")
79-
}
60+
ci := maxlength.Initializer()
8061

8162
tests := []struct {
8263
name string

pkg/analysis/maxlength/initializer.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,29 @@ func init() {
2929
registry.DefaultRegistry().RegisterLinter(Initializer())
3030
}
3131

32-
// Initializer returns the AnalyzerInitializer for this
32+
// MaxLengthInitializer is the initializer for the maxlength analyzer.
33+
// It embeds ConfigurableAnalyzerInitializer and adds a typed Initialize
34+
// method so callers can skip the runtime type assertion.
35+
type MaxLengthInitializer struct {
36+
initializer.ConfigurableAnalyzerInitializer
37+
}
38+
39+
// Initialize creates a new maxlength analyzer configured with cfg.
40+
func (m MaxLengthInitializer) Initialize(cfg *MaxLengthConfig) (*analysis.Analyzer, error) {
41+
return m.Init(cfg)
42+
}
43+
44+
// Initializer returns the MaxLengthInitializer for this
3345
// Analyzer so that it can be added to the registry.
34-
func Initializer() initializer.AnalyzerInitializer {
35-
return initializer.NewConfigurableInitializer(
36-
name,
37-
initAnalyzer,
38-
false, // For now, CRD only, and so not on by default.
39-
validateConfig,
40-
)
46+
func Initializer() MaxLengthInitializer {
47+
return MaxLengthInitializer{
48+
ConfigurableAnalyzerInitializer: initializer.NewConfigurableInitializer(
49+
name,
50+
initAnalyzer,
51+
false, // For now, CRD only, and so not on by default.
52+
validateConfig,
53+
),
54+
}
4155
}
4256

4357
func initAnalyzer(cfg *MaxLengthConfig) (*analysis.Analyzer, error) {
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package b
2+
3+
// DVPreferredMaxLength exercises the linter when configured to prefer DV markers.
4+
// Fields that carry only DV markers should NOT lint.
5+
// Fields that are missing markers should lint with a diagnostic citing the k8s:* form.
6+
type DVPreferredMaxLength struct {
7+
// +k8s:maxLength=256
8+
StringWithDVMaxLength string // satisfied by DV marker — no lint
9+
10+
// +kubebuilder:validation:MaxLength:=128
11+
StringWithKubebuilderMaxLength string // kubebuilder marker also satisfies — no lint
12+
13+
StringWithoutMaxLength string // want `field DVPreferredMaxLength.StringWithoutMaxLength must have a maximum length, add k8s:maxLength marker`
14+
15+
// +k8s:maxBytes=512
16+
ByteSliceWithDVMaxBytes []byte // satisfied by k8s:maxBytes — no lint
17+
18+
ByteSliceWithoutMax []byte // want `field DVPreferredMaxLength.ByteSliceWithoutMax must have a maximum length, add k8s:maxLength marker`
19+
20+
// +k8s:maxItems=128
21+
ArrayWithDVMaxItems []int // satisfied by k8s:maxItems — no lint
22+
23+
// +kubebuilder:validation:MaxItems:=64
24+
ArrayWithKubebuilderMaxItems []int // kubebuilder marker also satisfies — no lint
25+
26+
ArrayWithoutMaxItems []int // want `field DVPreferredMaxLength.ArrayWithoutMaxItems must have a maximum items, add k8s:maxItems marker`
27+
28+
// +k8s:maxProperties=64
29+
MapWithDVMaxProperties map[string]string // satisfied by k8s:maxProperties — no lint
30+
31+
// +kubebuilder:validation:MaxProperties:=32
32+
MapWithKubebuilderMaxProperties map[string]string // kubebuilder marker also satisfies — no lint
33+
34+
MapWithoutMaxProperties map[string]string // want `field DVPreferredMaxLength.MapWithoutMaxProperties must have a maximum properties, add k8s:maxProperties marker`
35+
36+
// Non-string-keyed map — never linted regardless of config.
37+
MapWithIntKey map[int]string
38+
39+
// +k8s:enum
40+
DVEnumString string // enum exempts from max-length — no lint
41+
42+
// +kubebuilder:validation:Enum:="A";"B"
43+
KubebuilderEnumString string // kubebuilder enum also exempts in DV-preferred mode — no lint
44+
45+
// +k8s:format=date-time
46+
DVDateTimeString string // format exempts from max-length — no lint
47+
48+
// +k8s:format=date
49+
DVDateString string // format exempts from max-length — no lint
50+
51+
// +k8s:format=duration
52+
DVDurationString string // format exempts from max-length — no lint
53+
54+
// +kubebuilder:validation:Format:=date-time
55+
KubebuilderDateTimeString string // kubebuilder format also exempts in DV-preferred mode — no lint
56+
57+
// +kubebuilder:validation:Format:=date
58+
KubebuilderDateString string // kubebuilder format also exempts in DV-preferred mode — no lint
59+
60+
// +kubebuilder:validation:Format:=duration
61+
KubebuilderDurationString string // kubebuilder format also exempts in DV-preferred mode — no lint
62+
63+
// +k8s:maxLength=256 on a []byte field is the WRONG DV marker; +k8s:maxBytes should be used.
64+
// The linter must still report the field as missing a valid max-length constraint.
65+
// +k8s:maxLength=256
66+
ByteSliceWithWrongDVMarker []byte // want `field DVPreferredMaxLength.ByteSliceWithWrongDVMarker must have a maximum length, add k8s:maxLength marker`
67+
68+
// Raw []string — needs both MaxItems and items:MaxLength.
69+
// +k8s:maxItems=16
70+
// +kubebuilder:validation:items:MaxLength:=64
71+
StringArrayWithMaxItemsAndElementLength []string // no lint
72+
73+
// +k8s:maxItems=16
74+
StringArrayWithMaxItemsWithoutElementLength []string // want `field DVPreferredMaxLength.StringArrayWithMaxItemsWithoutElementLength array element must have a maximum length, add kubebuilder:validation:items:MaxLength`
75+
76+
StringArrayWithoutMaxItemsOrElementLength []string // want `field DVPreferredMaxLength.StringArrayWithoutMaxItemsOrElementLength must have a maximum items, add k8s:maxItems marker` `field DVPreferredMaxLength.StringArrayWithoutMaxItemsOrElementLength array element must have a maximum length, add kubebuilder:validation:items:MaxLength`
77+
}
78+
79+
// StringAliasDVMaxLength is a string alias carrying a DV maxLength marker.
80+
// +k8s:maxLength=512
81+
type StringAliasDVMaxLength string
82+
83+
// StringAliasNoMaxLength is a string alias without any max-length marker.
84+
type StringAliasNoMaxLength string
85+
86+
// DVPreferredAliases exercises alias-level DV markers.
87+
type DVPreferredAliases struct {
88+
StringWithAliasMaxLength StringAliasDVMaxLength // satisfied by alias marker — no lint
89+
90+
StringWithoutMaxLength StringAliasNoMaxLength // want `field DVPreferredAliases.StringWithoutMaxLength type StringAliasNoMaxLength must have a maximum length, add k8s:maxLength marker`
91+
92+
// +k8s:maxItems=64
93+
AliasArrayWithMaxItems []StringAliasDVMaxLength // array element max-length satisfied by alias — no lint
94+
95+
AliasArrayWithoutMaxItems []StringAliasDVMaxLength // want `field DVPreferredAliases.AliasArrayWithoutMaxItems must have a maximum items, add k8s:maxItems marker`
96+
}

0 commit comments

Comments
 (0)