Skip to content

Commit 564720a

Browse files
authored
feat(conformance): validate implementation flags (#3715)
* feat(conformance): validate implementation flags Signed-off-by: Mattia Lavacca <[email protected]> * chore: gofumpt Signed-off-by: Mattia Lavacca <[email protected]> --------- Signed-off-by: Mattia Lavacca <[email protected]>
1 parent 3842b4c commit 564720a

File tree

4 files changed

+114
-6
lines changed

4 files changed

+114
-6
lines changed

conformance/conformance.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,14 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions {
7272
namespaceAnnotations := suite.ParseKeyValuePairs(*flags.NamespaceAnnotations)
7373
conformanceProfiles := suite.ParseConformanceProfiles(*flags.ConformanceProfiles)
7474

75-
implementation := suite.ParseImplementation(
75+
implementation, err := suite.ParseImplementation(
7676
*flags.ImplementationOrganization,
7777
*flags.ImplementationProject,
7878
*flags.ImplementationURL,
7979
*flags.ImplementationVersion,
8080
*flags.ImplementationContact,
8181
)
82+
require.NoError(t, err, "error parsing implementation details")
8283

8384
return suite.ConformanceOptions{
8485
AllowCRDsMismatch: *flags.AllowCRDsMismatch,
@@ -92,7 +93,7 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions {
9293
ExemptFeatures: exemptFeatures,
9394
ManifestFS: []fs.FS{&Manifests},
9495
GatewayClassName: *flags.GatewayClassName,
95-
Implementation: implementation,
96+
Implementation: *implementation,
9697
Mode: *flags.Mode,
9798
NamespaceAnnotations: namespaceAnnotations,
9899
NamespaceLabels: namespaceLabels,

conformance/utils/suite/suite.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"io/fs"
24+
neturl "net/url"
2425
"slices"
2526
"sort"
2627
"strings"
@@ -558,14 +559,33 @@ func (suite *ConformanceTestSuite) Report() (*confv1.ConformanceReport, error) {
558559

559560
// ParseImplementation parses implementation-specific flag arguments and
560561
// creates a *confv1a1.Implementation.
561-
func ParseImplementation(org, project, url, version, contact string) confv1.Implementation {
562-
return confv1.Implementation{
562+
func ParseImplementation(org, project, url, version, contact string) (*confv1.Implementation, error) {
563+
if org == "" {
564+
return nil, errors.New("organization must be set")
565+
}
566+
if project == "" {
567+
return nil, errors.New("project must be set")
568+
}
569+
if url == "" {
570+
return nil, errors.New("url must be set")
571+
}
572+
if version == "" {
573+
return nil, errors.New("version must be set")
574+
}
575+
if contact == "" {
576+
return nil, errors.New("contact must be set")
577+
}
578+
if _, err := neturl.ParseRequestURI(url); err != nil {
579+
return nil, errors.New("url is malformed")
580+
}
581+
582+
return &confv1.Implementation{
563583
Organization: org,
564584
Project: project,
565585
URL: url,
566586
Version: version,
567587
Contact: strings.Split(contact, ","),
568-
}
588+
}, nil
569589
}
570590

571591
// ParseConformanceProfiles parses flag arguments and converts the string to

conformance/utils/suite/suite_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,89 @@ func namesToFeatureSet(names []string) FeaturesSet {
538538
}
539539
return featureSet
540540
}
541+
542+
func TestParseImplementation(t *testing.T) {
543+
testCases := []struct {
544+
name string
545+
org string
546+
project string
547+
url string
548+
version string
549+
contact string
550+
expected *confv1.Implementation
551+
expectedErr error
552+
}{
553+
{
554+
name: "missing organization",
555+
project: "test-project",
556+
url: "https://example.com",
557+
version: "v1.0.0",
558+
contact: "[email protected]",
559+
expectedErr: errors.New("organization must be set"),
560+
},
561+
{
562+
name: "missing project",
563+
org: "test-org",
564+
url: "https://example.com",
565+
version: "v1.0.0",
566+
contact: "[email protected]",
567+
expectedErr: errors.New("project must be set"),
568+
},
569+
{
570+
name: "missing url",
571+
org: "test-org",
572+
project: "test-project",
573+
version: "v1.0.0",
574+
contact: "[email protected]",
575+
expectedErr: errors.New("url must be set"),
576+
},
577+
{
578+
name: "missing version",
579+
org: "test-org",
580+
project: "test-project",
581+
url: "https://example.com",
582+
contact: "[email protected]",
583+
expectedErr: errors.New("version must be set"),
584+
},
585+
{
586+
name: "missing contact",
587+
org: "test-org",
588+
project: "test-project",
589+
url: "https://example.com",
590+
version: "v1.0.0",
591+
expectedErr: errors.New("contact must be set"),
592+
},
593+
{
594+
name: "malformed url",
595+
org: "test-org",
596+
project: "test-project",
597+
url: "invalid-url",
598+
version: "v1.0.0",
599+
contact: "[email protected]",
600+
expectedErr: errors.New("url is malformed"),
601+
},
602+
{
603+
name: "valid input",
604+
org: "test-org",
605+
project: "test-project",
606+
url: "https://example.com",
607+
version: "v1.0.0",
608+
609+
expected: &confv1.Implementation{
610+
Organization: "test-org",
611+
Project: "test-project",
612+
URL: "https://example.com",
613+
Version: "v1.0.0",
614+
Contact: []string{"[email protected]", "[email protected]"},
615+
},
616+
},
617+
}
618+
619+
for _, tc := range testCases {
620+
t.Run(tc.name, func(t *testing.T) {
621+
result, err := ParseImplementation(tc.org, tc.project, tc.url, tc.version, tc.contact)
622+
assert.Equal(t, tc.expected, result)
623+
assert.Equal(t, tc.expectedErr, err)
624+
})
625+
}
626+
}

pkg/test/cel/grpcroute_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ func TestGRPCRouteRule(t *testing.T) {
341341
}
342342
return rules
343343
}(),
344-
}}
344+
},
345+
}
345346

346347
for _, tc := range tests {
347348
t.Run(tc.name, func(t *testing.T) {

0 commit comments

Comments
 (0)