Fix validation test for ReplicationController

I discovered this by changing the validation in a way that SHOULD fail
(by allowing something it should not).  But it didn't.  A different
error happens which totally masks the non-failure I expected.  New test
is much more explicit about what failures are expected.

This does not focus on adding test coverage, just making sure the test
is not terrible.
This commit is contained in:
Tim Hockin 2024-12-01 10:21:07 -08:00
parent 133d5d612e
commit 46ac2af06a
No known key found for this signature in database

View File

@ -16606,435 +16606,267 @@ func TestValidateReplicationControllerStatusUpdate(t *testing.T) {
} }
func TestValidateReplicationControllerUpdate(t *testing.T) { // Helper function for RC tests.
validSelector := map[string]string{"a": "b"} func mkValidReplicationController(tweaks ...func(rc *core.ReplicationController)) core.ReplicationController {
validPodTemplate := core.PodTemplate{ rc := core.ReplicationController{
Template: core.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: validSelector,
},
Spec: podtest.MakePodSpec(),
},
}
readWriteVolumePodTemplate := core.PodTemplate{
Template: core.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: validSelector,
},
Spec: podtest.MakePodSpec(
podtest.SetVolumes(core.Volume{Name: "gcepd", VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}),
),
},
}
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
invalidPodTemplate := core.PodTemplate{
Template: core.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: invalidSelector,
},
Spec: podtest.MakePodSpec(),
},
}
type rcUpdateTest struct {
old core.ReplicationController
update core.ReplicationController
}
successCases := []rcUpdateTest{{
old: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
update: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: 3,
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
}, {
old: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
update: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{ Spec: core.ReplicationControllerSpec{
Replicas: 1, Replicas: 1,
Selector: validSelector, Selector: map[string]string{"a": "b"},
Template: &readWriteVolumePodTemplate.Template, Template: &core.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"a": "b"},
}, },
Spec: podtest.MakePodSpec(),
}, },
}, },
} }
for _, successCase := range successCases { for _, tweak := range tweaks {
successCase.old.ObjectMeta.ResourceVersion = "1" tweak(&rc)
successCase.update.ObjectMeta.ResourceVersion = "1"
if errs := ValidateReplicationControllerUpdate(&successCase.update, &successCase.old, PodValidationOptions{}); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
}
errorCases := map[string]rcUpdateTest{
"more than one read/write": {
old: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
update: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: 2,
Selector: validSelector,
Template: &readWriteVolumePodTemplate.Template,
},
},
},
"invalid selector": {
old: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
update: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: 2,
Selector: invalidSelector,
Template: &validPodTemplate.Template,
},
},
},
"invalid pod": {
old: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
update: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: 2,
Selector: validSelector,
Template: &invalidPodTemplate.Template,
},
},
},
"negative replicas": {
old: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
update: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: -1,
Selector: validSelector,
Template: &validPodTemplate.Template,
},
},
},
}
for testName, errorCase := range errorCases {
if errs := ValidateReplicationControllerUpdate(&errorCase.update, &errorCase.old, PodValidationOptions{}); len(errs) == 0 {
t.Errorf("expected failure: %s", testName)
}
} }
return rc
} }
func TestValidateReplicationController(t *testing.T) { func TestValidateReplicationControllerUpdate(t *testing.T) {
validSelector := map[string]string{"a": "b"} successCases := []struct {
validPodTemplate := core.PodTemplate{ old core.ReplicationController
Template: core.PodTemplateSpec{ update core.ReplicationController
ObjectMeta: metav1.ObjectMeta{ }{{
Labels: validSelector, old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
}, update: mkValidReplicationController(func(rc *core.ReplicationController) {
Spec: podtest.MakePodSpec(), rc.Spec.Replicas = 0
},
}
readWriteVolumePodTemplate := core.PodTemplate{
Template: core.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: validSelector,
},
Spec: podtest.MakePodSpec(
podtest.SetVolumes(core.Volume{Name: "gcepd", VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}),
),
},
}
hostnetPodTemplate := core.PodTemplate{
Template: core.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: validSelector,
},
Spec: podtest.MakePodSpec(
podtest.SetSecurityContext(&core.PodSecurityContext{
HostNetwork: true,
}), }),
podtest.SetContainers(podtest.MakeContainer("abc", podtest.SetContainerPorts(
core.ContainerPort{
ContainerPort: 12345,
Protocol: core.ProtocolTCP,
}))),
),
},
}
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
invalidPodTemplate := core.PodTemplate{
Template: core.PodTemplateSpec{
Spec: podtest.MakePodSpec(),
ObjectMeta: metav1.ObjectMeta{
Labels: invalidSelector,
},
},
}
successCases := []core.ReplicationController{{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
},
}, { }, {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault}, old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
Spec: core.ReplicationControllerSpec{ update: mkValidReplicationController(func(rc *core.ReplicationController) {
Selector: validSelector, rc.Spec.Replicas = 3
Template: &validPodTemplate.Template, }),
},
}, { }, {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault}, old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
Spec: core.ReplicationControllerSpec{ update: mkValidReplicationController(func(rc *core.ReplicationController) {
Replicas: 1, rc.Spec.Replicas = 2
Selector: validSelector, rc.Spec.Template.Spec = podtest.MakePodSpec(
Template: &readWriteVolumePodTemplate.Template, podtest.SetVolumes(
core.Volume{
Name: "gcepd",
VolumeSource: core.VolumeSource{
GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{
PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false,
}, },
}, {
ObjectMeta: metav1.ObjectMeta{Name: "hostnet", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: 1,
Selector: validSelector,
Template: &hostnetPodTemplate.Template,
}, },
}))
}),
}} }}
for _, successCase := range successCases { for _, tc := range successCases {
if errs := ValidateReplicationController(&successCase, PodValidationOptions{}); len(errs) != 0 { tc.old.ObjectMeta.ResourceVersion = "1"
tc.update.ObjectMeta.ResourceVersion = "1"
if errs := ValidateReplicationControllerUpdate(&tc.update, &tc.old, PodValidationOptions{}); len(errs) != 0 {
t.Errorf("expected success: %v", errs) t.Errorf("expected success: %v", errs)
} }
} }
errorCases := map[string]struct { errorCases := map[string]struct {
rc core.ReplicationController old core.ReplicationController
expectedOrigin []string update core.ReplicationController
expectedErrs field.ErrorList
}{ }{
"zero-length ID": { "unmatched selector": {
rc: core.ReplicationController{ old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, update: mkValidReplicationController(func(rc *core.ReplicationController) {
Spec: core.ReplicationControllerSpec{ rc.Spec.Selector["another"] = "value"
Selector: validSelector, }),
Template: &validPodTemplate.Template, expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
}, },
}, },
"invalid selector": {
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
update: mkValidReplicationController(func(rc *core.ReplicationController) {
invalid := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
rc.Spec.Template.Labels = invalid
rc.Spec.Selector = invalid
}),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec.template.labels"), nil, "").WithOrigin("labelKey"),
}, },
"missing-namespace": {
rc: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{Name: "abc-123"},
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &validPodTemplate.Template,
}, },
"invalid pod": {
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
update: mkValidReplicationController(func(rc *core.ReplicationController) {
rc.Spec.Template = nil
}),
expectedErrs: field.ErrorList{
field.Required(field.NewPath("spec.template"), ""),
},
},
"negative replicas": {
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
update: mkValidReplicationController(func(rc *core.ReplicationController) {
rc.Spec.Replicas = -1
}),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec.replicas"), nil, "").WithOrigin("minimum"),
},
},
}
for k, tc := range errorCases {
t.Run(k, func(t *testing.T) {
tc.old.ObjectMeta.ResourceVersion = "1"
tc.update.ObjectMeta.ResourceVersion = "1"
errs := ValidateReplicationControllerUpdate(&tc.update, &tc.old, PodValidationOptions{})
matcher := fldtest.ErrorMatcher{}.ByType().ByField().ByOrigin().ByDetailSubstring()
matcher.Test(t, tc.expectedErrs, errs)
})
}
}
func TestValidateReplicationController(t *testing.T) {
successCases := []core.ReplicationController{
mkValidReplicationController(func(rc *core.ReplicationController) {}),
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Name = "abc-123" }),
mkValidReplicationController(func(rc *core.ReplicationController) {
rc.Spec.Replicas = 2
rc.Spec.Template.Spec = podtest.MakePodSpec(
podtest.SetVolumes(
core.Volume{
Name: "gcepd",
VolumeSource: core.VolumeSource{
GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{
PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false,
},
},
}))
}),
mkValidReplicationController(func(rc *core.ReplicationController) {
rc.Spec.Template.Spec = podtest.MakePodSpec(
podtest.SetSecurityContext(&core.PodSecurityContext{HostNetwork: true}),
podtest.SetContainers(podtest.MakeContainer("abc",
podtest.SetContainerPorts(core.ContainerPort{
ContainerPort: 12345, Protocol: core.ProtocolTCP,
}))),
)
}),
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 0 }),
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 1 }),
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 100 }),
}
for _, tc := range successCases {
if errs := ValidateReplicationController(&tc, PodValidationOptions{}); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
}
errorCases := map[string]struct {
input core.ReplicationController
expectedErrs field.ErrorList
}{
"missing name": {
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Name = "" }),
expectedErrs: field.ErrorList{
field.Required(field.NewPath("metadata.name"), ""),
},
},
"missing namespace": {
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Namespace = "" }),
expectedErrs: field.ErrorList{
field.Required(field.NewPath("metadata.namespace"), ""),
}, },
}, },
"empty selector": { "empty selector": {
rc: core.ReplicationController{ input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Selector = nil }),
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, expectedErrs: field.ErrorList{
Spec: core.ReplicationControllerSpec{ field.Required(field.NewPath("spec.selector"), ""),
Template: &validPodTemplate.Template,
}, },
}, },
}, "selector doesnt match": {
"selector_doesnt_match": { input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Selector = map[string]string{"foo": "bar"} }),
rc: core.ReplicationController{ expectedErrs: field.ErrorList{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
Spec: core.ReplicationControllerSpec{
Selector: map[string]string{"foo": "bar"},
Template: &validPodTemplate.Template,
},
}, },
}, },
"invalid manifest": { "invalid manifest": {
rc: core.ReplicationController{ input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Template = nil }),
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, expectedErrs: field.ErrorList{
Spec: core.ReplicationControllerSpec{ field.Required(field.NewPath("spec.template"), ""),
Selector: validSelector,
}, },
}, },
}, "negative replicas": {
"read-write persistent disk with > 1 pod": { input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = -1 }),
rc: core.ReplicationController{ expectedErrs: field.ErrorList{
ObjectMeta: metav1.ObjectMeta{Name: "abc"}, field.Invalid(field.NewPath("spec.replicas"), nil, "").WithOrigin("minimum"),
Spec: core.ReplicationControllerSpec{
Replicas: 2,
Selector: validSelector,
Template: &readWriteVolumePodTemplate.Template,
}, },
}, },
}, "invalid label": {
"negative_replicas": { input: mkValidReplicationController(func(rc *core.ReplicationController) {
rc: core.ReplicationController{ rc.Labels = map[string]string{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: core.ReplicationControllerSpec{
Replicas: -1,
Selector: validSelector,
},
},
expectedOrigin: []string{
"minimum",
},
},
"invalid_label": {
rc: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{
Name: "abc-123",
Namespace: metav1.NamespaceDefault,
Labels: map[string]string{
"NoUppercaseOrSpecialCharsLike=Equals": "bar", "NoUppercaseOrSpecialCharsLike=Equals": "bar",
}
}),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("metadata.labels"), nil, "").WithOrigin("labelKey"),
}, },
}, },
Spec: core.ReplicationControllerSpec{ "invalid label 2": {
Selector: validSelector, input: mkValidReplicationController(func(rc *core.ReplicationController) {
Template: &validPodTemplate.Template, rc.Spec.Template.Labels = map[string]string{
},
},
},
"invalid_label 2": {
rc: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{
Name: "abc-123",
Namespace: metav1.NamespaceDefault,
Labels: map[string]string{
"NoUppercaseOrSpecialCharsLike=Equals": "bar", "NoUppercaseOrSpecialCharsLike=Equals": "bar",
}
}),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
field.Invalid(field.NewPath("spec.template.labels"), nil, "").WithOrigin("labelKey"),
}, },
}, },
Spec: core.ReplicationControllerSpec{ "invalid annotation": {
Template: &invalidPodTemplate.Template, input: mkValidReplicationController(func(rc *core.ReplicationController) {
}, rc.Annotations = map[string]string{
},
},
"invalid_annotation": {
rc: core.ReplicationController{
ObjectMeta: metav1.ObjectMeta{
Name: "abc-123",
Namespace: metav1.NamespaceDefault,
Annotations: map[string]string{
"NoUppercaseOrSpecialCharsLike=Equals": "bar", "NoUppercaseOrSpecialCharsLike=Equals": "bar",
}, }
}, }),
Spec: core.ReplicationControllerSpec{ expectedErrs: field.ErrorList{
Selector: validSelector, field.Invalid(field.NewPath("metadata.annotations"), nil, "name part must consist of"),
Template: &validPodTemplate.Template,
},
}, },
}, },
"invalid restart policy 1": { "invalid restart policy 1": {
rc: core.ReplicationController{ input: mkValidReplicationController(func(rc *core.ReplicationController) {
ObjectMeta: metav1.ObjectMeta{ rc.Spec.Template.Spec.RestartPolicy = core.RestartPolicyOnFailure
Name: "abc-123", }),
Namespace: metav1.NamespaceDefault, expectedErrs: field.ErrorList{
}, field.NotSupported[core.RestartPolicy](field.NewPath("spec.template.spec.restartPolicy"), nil, nil),
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &core.PodTemplateSpec{
Spec: podtest.MakePodSpec(podtest.SetRestartPolicy(core.RestartPolicyOnFailure)),
ObjectMeta: metav1.ObjectMeta{
Labels: validSelector,
},
},
},
}, },
}, },
"invalid restart policy 2": { "invalid restart policy 2": {
rc: core.ReplicationController{ input: mkValidReplicationController(func(rc *core.ReplicationController) {
ObjectMeta: metav1.ObjectMeta{ rc.Spec.Template.Spec.RestartPolicy = core.RestartPolicyNever
Name: "abc-123", }),
Namespace: metav1.NamespaceDefault, expectedErrs: field.ErrorList{
}, field.NotSupported[core.RestartPolicy](field.NewPath("spec.template.spec.restartPolicy"), nil, nil),
Spec: core.ReplicationControllerSpec{
Selector: validSelector,
Template: &core.PodTemplateSpec{
Spec: podtest.MakePodSpec(podtest.SetRestartPolicy(core.RestartPolicyNever)),
ObjectMeta: metav1.ObjectMeta{
Labels: validSelector,
},
},
},
}, },
}, },
"template may not contain ephemeral containers": { "template may not contain ephemeral containers": {
rc: core.ReplicationController{ input: mkValidReplicationController(func(rc *core.ReplicationController) {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault}, rc.Spec.Template.Spec = podtest.MakePodSpec(
Spec: core.ReplicationControllerSpec{ podtest.SetEphemeralContainers(
Replicas: 1, core.EphemeralContainer{
Selector: validSelector, EphemeralContainerCommon: core.EphemeralContainerCommon{
Template: &core.PodTemplateSpec{ Name: "debug",
ObjectMeta: metav1.ObjectMeta{ Image: "image",
Labels: validSelector, ImagePullPolicy: "IfNotPresent",
}, TerminationMessagePolicy: "File",
Spec: podtest.MakePodSpec(
podtest.SetEphemeralContainers(core.EphemeralContainer{EphemeralContainerCommon: core.EphemeralContainerCommon{Name: "debug", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}),
),
},
}, },
}))
}),
expectedErrs: field.ErrorList{
field.Forbidden(field.NewPath("spec.template.spec.ephemeralContainers"), "not allowed in pod template"),
}, },
}, },
} }
for k, v := range errorCases { for k, tc := range errorCases {
errs := ValidateReplicationController(&v.rc, PodValidationOptions{}) t.Run(k, func(t *testing.T) {
if len(errs) == 0 { errs := ValidateReplicationController(&tc.input, PodValidationOptions{})
t.Errorf("expected failure for %s", k) matcher := fldtest.ErrorMatcher{}.ByType().ByField().ByOrigin().ByDetailSubstring()
} matcher.Test(t, tc.expectedErrs, errs)
})
expectedOrigins := sets.NewString(v.expectedOrigin...)
for i := range errs {
field := errs[i].Field
if !strings.HasPrefix(field, "spec.template.") &&
field != "metadata.name" &&
field != "metadata.namespace" &&
field != "spec.selector" &&
field != "spec.template" &&
field != "GCEPersistentDisk.ReadOnly" &&
field != "spec.replicas" &&
field != "spec.template.labels" &&
field != "metadata.annotations" &&
field != "metadata.labels" &&
field != "status.replicas" {
t.Errorf("%s: missing prefix for: %v", k, errs[i])
}
if len(v.expectedOrigin) > 0 && errs[i].Origin != "" {
if !expectedOrigins.Has(errs[i].Origin) {
t.Errorf("%s: unexpected origin for: %v, expected one of %v", k, errs[i].Origin, v.expectedOrigin)
}
expectedOrigins.Delete(errs[i].Origin)
}
}
if len(expectedOrigins) > 0 {
t.Errorf("%s: missing errors with origin: %v", k, expectedOrigins.List())
}
} }
} }