Merge pull request #2821 from monopole/moveIsNilToMethod

Testing for nilness, nullness and emptyness.
This commit is contained in:
Jeff Regan
2020-08-10 10:23:16 -07:00
committed by GitHub
5 changed files with 169 additions and 19 deletions

View File

@@ -482,7 +482,7 @@ func (s FieldSetter) Filter(rn *RNode) (*RNode, error) {
}
// Clear the field if it is empty, or explicitly null
if s.Value == nil || IsNull(s.Value) {
if s.Value == nil || s.Value.IsTaggedNull() {
return rn.Pipe(Clear(s.Name))
}
@@ -568,7 +568,7 @@ var nodeTypeIndex = map[yaml.Kind]string{
}
func ErrorIfInvalid(rn *RNode, kind yaml.Kind) error {
if rn == nil || rn.YNode() == nil || IsNull(rn) {
if rn == nil || rn.YNode() == nil || rn.IsTaggedNull() {
// node has no type, pass validation
return nil
}

View File

@@ -56,7 +56,7 @@ func (m Merger) VisitMap(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.R
// Add
return nodes.Origin(), nil
}
if yaml.IsNull(nodes.Origin()) {
if nodes.Origin().IsTaggedNull() {
// clear the value
return walk.ClearNode, nil
}
@@ -112,7 +112,7 @@ func (m Merger) VisitList(nodes walk.Sources, s *openapi.ResourceSchema, kind wa
return nodes.Origin(), nil
}
// Clear
if yaml.IsNull(nodes.Origin()) {
if nodes.Origin().IsTaggedNull() {
return walk.ClearNode, nil
}
// Recursively Merge dest

View File

@@ -20,7 +20,7 @@ const (
type Visitor struct{}
func (m Visitor) VisitMap(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.RNode, error) {
if yaml.IsNull(nodes.Updated()) || yaml.IsNull(nodes.Dest()) {
if nodes.Updated().IsTaggedNull() || nodes.Dest().IsTaggedNull() {
// explicitly cleared from either dest or update
return walk.ClearNode, nil
}
@@ -54,7 +54,7 @@ func (m Visitor) visitAList(nodes walk.Sources, _ *openapi.ResourceSchema) (*yam
}
func (m Visitor) VisitScalar(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.RNode, error) {
if yaml.IsNull(nodes.Updated()) || yaml.IsNull(nodes.Dest()) {
if nodes.Updated().IsTaggedNull() || nodes.Dest().IsTaggedNull() {
// explicitly cleared from either dest or update
return nil, nil
}
@@ -91,7 +91,7 @@ func (m Visitor) VisitScalar(nodes walk.Sources, s *openapi.ResourceSchema) (*ya
}
func (m Visitor) visitNAList(nodes walk.Sources) (*yaml.RNode, error) {
if yaml.IsNull(nodes.Updated()) || yaml.IsNull(nodes.Dest()) {
if nodes.Updated().IsTaggedNull() || nodes.Dest().IsTaggedNull() {
// explicitly cleared from either dest or update
return walk.ClearNode, nil
}

View File

@@ -36,7 +36,7 @@ func MakeNullNode() *RNode {
// IsMissingOrNull is true if the RNode is nil or explicitly tagged null.
// TODO: make this a method on RNode.
func IsMissingOrNull(node *RNode) bool {
return IsNil(node) || node.YNode().Tag == NodeTagNull
return node.IsNil() || node.YNode().Tag == NodeTagNull
}
// Deprecated. Use IsMissingOrNull instead.
@@ -49,15 +49,6 @@ func IsEmptyMap(node *RNode) bool {
return IsMissingOrNull(node) || IsYNodeEmptyMap(node.YNode())
}
// IsNil return true if the node is nil, or its underlying YNode is nil.
func IsNil(node *RNode) bool {
return node == nil || node.YNode() == nil
}
func IsNull(node *RNode) bool {
return !IsNil(node) && node.YNode().Tag == NodeTagNull
}
func IsFieldEmpty(node *MapNode) bool {
if node == nil || node.Value == nil || node.Value.YNode() == nil ||
node.Value.YNode().Tag == NodeTagNull {
@@ -68,11 +59,16 @@ func IsFieldEmpty(node *MapNode) bool {
}
func IsYNodeEmptyMap(n *yaml.Node) bool {
return n.Kind == yaml.MappingNode && len(n.Content) == 0
return n != nil && n.Kind == yaml.MappingNode && len(n.Content) == 0
}
// IsYNodeTaggedNull returns true if the node is explicitly tagged Null.
func IsYNodeTaggedNull(n *yaml.Node) bool {
return n != nil && n.Tag == NodeTagNull
}
func IsYNodeEmptySeq(n *yaml.Node) bool {
return n.Kind == yaml.SequenceNode && len(n.Content) == 0
return n != nil && n.Kind == yaml.SequenceNode && len(n.Content) == 0
}
// IsYNodeEmptyDoc is true if the node is a Document with no content.
@@ -377,6 +373,25 @@ const (
LabelsField = "labels"
)
// IsNil is true if the node is nil, or its underlying YNode is nil.
func (rn *RNode) IsNil() bool {
return rn == nil || rn.YNode() == nil
}
// IsTaggedNull is true if a non-nil node is explicitly tagged Null.
func (rn *RNode) IsTaggedNull() bool {
return !rn.IsNil() && IsYNodeTaggedNull(rn.YNode())
}
// IsNilOrEmpty is true if the node is nil,
// has no YNode, or has YNode that appears empty.
func (rn *RNode) IsNilOrEmpty() bool {
return rn.IsNil() ||
IsYNodeTaggedNull(rn.YNode()) ||
IsYNodeEmptyMap(rn.YNode()) ||
IsYNodeEmptySeq(rn.YNode())
}
// GetMeta returns the ResourceMeta for an RNode
func (rn *RNode) GetMeta() (ResourceMeta, error) {
if IsMissingOrNull(rn) {

View File

@@ -167,6 +167,61 @@ type: string
assert.Equal(t, expected, actual)
}
func TestIsYNodeTaggedNull(t *testing.T) {
if IsYNodeTaggedNull(nil) {
t.Fatalf("nil cannot be tagged null")
}
if IsYNodeTaggedNull(&Node{}) {
t.Fatalf("untagged node is not tagged")
}
if IsYNodeTaggedNull(&Node{Tag: NodeTagFloat}) {
t.Fatalf("float tagged node is not tagged")
}
if !IsYNodeTaggedNull(&Node{Tag: NodeTagNull}) {
t.Fatalf("tagged node is tagged")
}
}
func TestIsYNodeEmptyMap(t *testing.T) {
if IsYNodeEmptyMap(nil) {
t.Fatalf("nil cannot be a map")
}
if IsYNodeEmptyMap(&Node{}) {
t.Fatalf("raw node is not a map")
}
if IsYNodeEmptyMap(&Node{Kind: SequenceNode}) {
t.Fatalf("seq node is not a map")
}
n := &Node{Kind: MappingNode}
if !IsYNodeEmptyMap(n) {
t.Fatalf("empty mapping node is an empty mapping node")
}
n.Content = append(n.Content, &Node{Kind: SequenceNode})
if IsYNodeEmptyMap(n) {
t.Fatalf("a node with content isn't empty")
}
}
func TestIsYNodeEmptySeq(t *testing.T) {
if IsYNodeEmptySeq(nil) {
t.Fatalf("nil cannot be a map")
}
if IsYNodeEmptySeq(&Node{}) {
t.Fatalf("raw node is not a map")
}
if IsYNodeEmptySeq(&Node{Kind: MappingNode}) {
t.Fatalf("map node is not a sequence")
}
n := &Node{Kind: SequenceNode}
if !IsYNodeEmptySeq(n) {
t.Fatalf("empty sequence node is an empty sequence node")
}
n.Content = append(n.Content, &Node{Kind: MappingNode})
if IsYNodeEmptySeq(n) {
t.Fatalf("a node with content isn't empty")
}
}
func TestIsMissingOrNull(t *testing.T) {
if !IsMissingOrNull(nil) {
t.Fatalf("input: nil")
@@ -220,3 +275,83 @@ func TestIsEmptyMap(t *testing.T) {
t.Fatalf("input: empty map")
}
}
func TestIsNil(t *testing.T) {
var rn *RNode
if !rn.IsNil() {
t.Fatalf("uninitialized RNode should be nil")
}
if !NewRNode(nil).IsNil() {
t.Fatalf("missing value YNode should be nil")
}
if MakeNullNode().IsNil() {
t.Fatalf("value tagged null is not nil")
}
if NewMapRNode(nil).IsNil() {
t.Fatalf("empty map not nil")
}
if NewListRNode().IsNil() {
t.Fatalf("empty list not nil")
}
}
func TestIsTaggedNull(t *testing.T) {
var rn *RNode
if rn.IsTaggedNull() {
t.Fatalf("nil RNode cannot be tagged")
}
if NewRNode(nil).IsTaggedNull() {
t.Fatalf("bare RNode should not be tagged")
}
if !MakeNullNode().IsTaggedNull() {
t.Fatalf("a null node is tagged null by definition")
}
if NewMapRNode(nil).IsTaggedNull() {
t.Fatalf("empty map should not be tagged null")
}
if NewListRNode().IsTaggedNull() {
t.Fatalf("empty list should not be tagged null")
}
}
func TestRNodeIsNilOrEmpty(t *testing.T) {
var rn *RNode
if !rn.IsNilOrEmpty() {
t.Fatalf("uninitialized RNode should be empty")
}
if !NewRNode(nil).IsNilOrEmpty() {
t.Fatalf("missing value YNode should be empty")
}
if !MakeNullNode().IsNilOrEmpty() {
t.Fatalf("value tagged null should be empty")
}
if !NewMapRNode(nil).IsNilOrEmpty() {
t.Fatalf("empty map should be empty")
}
if NewMapRNode(&map[string]string{"foo": "bar"}).IsNilOrEmpty() {
t.Fatalf("non-empty map should not be empty")
}
if !NewListRNode().IsNilOrEmpty() {
t.Fatalf("empty list should be empty")
}
if NewListRNode("foo").IsNilOrEmpty() {
t.Fatalf("non-empty list should not be empty")
}
}