blob: c666382f6f59f5bac12376c546125d885c0c24dd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package validators_test
import (
"fmt"
)
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
import (
"github.com/apache/dubbo-kubernetes/pkg/core/validators"
)
var _ = Describe("Validation Error", func() {
It("should construct errors", func() {
// given
err := validators.ValidationError{}
// when
err.AddViolation("name", "invalid name")
// and
addressErr := validators.ValidationError{}
addressErr.AddViolation("street", "invalid format")
err.AddError("address", addressErr)
// then
Expect(err.HasViolations()).To(BeTrue())
Expect(validators.IsValidationError(&err)).To(BeTrue())
Expect(err.OrNil()).To(MatchError("name: invalid name; address.street: invalid format"))
})
It("should convert to nil error when there are no violations", func() {
// given
validationErr := validators.ValidationError{}
// when
err := validationErr.OrNil()
Expect(err).ToNot(HaveOccurred())
})
Describe("Append()", func() {
It("should add a given error to the end of the list", func() {
// given
err := validators.ValidationError{}
err1 := validators.ValidationError{}
err1.AddViolationAt(validators.RootedAt("sources"), "unknown error")
err2 := validators.ValidationError{}
err2.AddViolationAt(validators.RootedAt("destinations"), "yet another error")
By("adding the first error")
// when
err.Add(err1)
// then
Expect(err).To(Equal(validators.ValidationError{
Violations: []validators.Violation{
{Field: "sources", Message: "unknown error"},
},
}))
By("adding the second error")
// when
err.Add(err2)
// then
Expect(err).To(Equal(validators.ValidationError{
Violations: []validators.Violation{
{Field: "sources", Message: "unknown error"},
{Field: "destinations", Message: "yet another error"},
},
}))
})
})
Describe("AddViolationAt()", func() {
It("should accept nil PathBuilder", func() {
// given
err := validators.ValidationError{}
// when
err.AddViolationAt(nil, "unknown error")
// then
Expect(err).To(Equal(validators.ValidationError{
Violations: []validators.Violation{
{Field: "", Message: "unknown error"},
},
}))
})
It("should accept non-nil PathBuilder", func() {
// given
err := validators.ValidationError{}
path := validators.RootedAt("sources").Index(0).Field("match").Key("service")
// when
err.AddViolationAt(path, "unknown error")
// and
Expect(err).To(Equal(validators.ValidationError{
Violations: []validators.Violation{
{Field: `sources[0].match["service"]`, Message: "unknown error"},
},
}))
})
})
Describe("AddErrorAt()", func() {
It("properly concatenates paths with index/keys", func() {
// given
path := validators.RootedAt("spec").Field("fields")
err := validators.ValidationError{}
subErr := validators.ValidationError{}
subErr.AddViolationAt(validators.Root().Index(2), "something bad")
// when
err.AddErrorAt(path, subErr)
// then
Expect(err).To(Equal(validators.ValidationError{
Violations: []validators.Violation{
{Field: "spec.fields[2]", Message: "something bad"},
},
}))
})
It("properly concatenates paths with Root().Field()", func() {
// given
path := validators.RootedAt("thing.spec")
err := validators.ValidationError{}
subErr := validators.ValidationError{}
subErr.AddViolationAt(validators.Root().Field("field"), "something bad")
// when
err.AddErrorAt(path, subErr)
// then
Expect(err).To(Equal(validators.ValidationError{
Violations: []validators.Violation{
{Field: "thing.spec.field", Message: "something bad"},
},
}))
})
})
Describe("Transform()", func() {
type testCase struct {
input *validators.ValidationError
transformFunc func(validators.Violation) validators.Violation
expected *validators.ValidationError
}
DescribeTable("should apply given transformation func to every Violation",
func(given testCase) {
// when
actual := given.input.Transform(given.transformFunc)
// then
Expect(actual).To(Equal(given.expected))
},
Entry("`nil` ValidationError", testCase{
input: nil,
expected: nil,
}),
Entry("zero value ValidationError", testCase{
input: &validators.ValidationError{},
expected: &validators.ValidationError{},
}),
Entry("`nil` transformFunc", testCase{
input: &validators.ValidationError{
Violations: []validators.Violation{
{Field: "field", Message: "invalid"},
},
},
expected: &validators.ValidationError{
Violations: []validators.Violation{
{Field: "field", Message: "invalid"},
},
},
}),
Entry("identity transform", testCase{
input: &validators.ValidationError{
Violations: []validators.Violation{
{Field: "field", Message: "invalid"},
},
},
transformFunc: func(v validators.Violation) validators.Violation {
return v
},
expected: &validators.ValidationError{
Violations: []validators.Violation{
{Field: "field", Message: "invalid"},
},
},
}),
Entry("real transform", testCase{
input: &validators.ValidationError{
Violations: []validators.Violation{
{Field: "field1", Message: "invalid1"},
{Field: "field2", Message: "invalid2"},
},
},
transformFunc: func(v validators.Violation) validators.Violation {
return validators.Violation{
Field: fmt.Sprintf("spec.%s", v.Field),
Message: fmt.Sprintf("prefix: %s", v.Message),
}
},
expected: &validators.ValidationError{
Violations: []validators.Violation{
{Field: "spec.field1", Message: "prefix: invalid1"},
{Field: "spec.field2", Message: "prefix: invalid2"},
},
},
}),
)
})
})
var _ = Describe("PathBuilder", func() {
It("should produce empty path by default", func() {
Expect(validators.Root().String()).To(Equal(""))
})
It("should produce valid root path", func() {
Expect(validators.RootedAt("spec").String()).To(Equal("spec"))
})
It("should produce valid field path", func() {
Expect(validators.RootedAt("spec").Field("sources").String()).To(Equal("spec.sources"))
})
It("should produce valid array index", func() {
Expect(validators.RootedAt("spec").Field("sources").Index(0).String()).To(Equal("spec.sources[0]"))
})
It("should produce valid array index", func() {
Expect(validators.RootedAt("spec").Field("sources").Index(0).Field("match").Key("service").String()).To(Equal(`spec.sources[0].match["service"]`))
})
It("works with Root().Field() or RootedAt()", func() {
Expect(validators.Root().Field("field").String()).To(Equal(validators.RootedAt("field").String()))
})
})