From 32ba02daa1b65a84929224cd84a891b824045da2 Mon Sep 17 00:00:00 2001 From: Michael Bolot Date: Mon, 9 Oct 2023 12:54:34 -0500 Subject: [PATCH] Adding package comments for data package Adds package comments and extra test cases --- pkg/data/values.go | 13 +++++++ pkg/data/values_test.go | 80 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/pkg/data/values.go b/pkg/data/values.go index 1942ec24..a0f07f42 100644 --- a/pkg/data/values.go +++ b/pkg/data/values.go @@ -1,9 +1,15 @@ +// Package data contains functions for working with unstructured values like []interface or map[string]interface{}. +// It allows reading/writing to these values without having to convert to structured items. package data import ( "strconv" ) +// RemoveValue removes a value from data. Keys should be in order denoting the path to the value in the nested +// structure of the map. For example, passing []string{"metadata", "annotations"} will make the function remove the +// "annotations" key from the "metadata" sub-map. Returns the removed value (if any) and a bool indicating if the value +// was found. func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) { for i, key := range keys { if i == len(keys)-1 { @@ -22,6 +28,11 @@ func GetValueN(data map[string]interface{}, keys ...string) interface{} { return val } +// GetValue retrieves a value from the provided collection, which must be a map[string]interface or a []interface. +// Keys are always strings. +// For a map, a key denotes the key in the map whose value we want to retrieve. +// For the slice, it denotes the index (starting at 0) of the value we want to retrieve. +// Returns the retrieved value (if any) and a bool indicating if the value was found. func GetValue(data interface{}, keys ...string) (interface{}, bool) { for i, key := range keys { if i == len(keys)-1 { @@ -54,6 +65,8 @@ func itemByIndex(dataSlice []interface{}, key string) (interface{}, bool) { return dataSlice[keyInt], true } +// PutValue updates the value of a given map at the index specified by keys that denote the path to the value in the +// nested structure of the map. If there is no current entry at a key, a new map is created for that value. func PutValue(data map[string]interface{}, val interface{}, keys ...string) { if data == nil { return diff --git a/pkg/data/values_test.go b/pkg/data/values_test.go index 6b01f6b7..231e3ffa 100644 --- a/pkg/data/values_test.go +++ b/pkg/data/values_test.go @@ -82,7 +82,7 @@ func TestGetValue(t *testing.T) { wantSuccess: true, }, { - name: "get index of top levelslice", + name: "get index of top level slice", data: []interface{}{ "alice", "bob", @@ -92,6 +92,26 @@ func TestGetValue(t *testing.T) { wantValue: "eve", wantSuccess: true, }, + { + name: "slice of maps", + data: []interface{}{ + map[string]interface{}{ + "notthisone": "val", + }, + map[string]interface{}{ + "parent": map[string]interface{}{ + "children": []interface{}{ + "alice", + "bob", + "eve", + }, + }, + }, + }, + keys: []string{"1", "parent", "children", "0"}, + wantValue: "alice", + wantSuccess: true, + }, { name: "index is too big", data: map[string]interface{}{ @@ -122,6 +142,64 @@ func TestGetValue(t *testing.T) { wantValue: nil, wantSuccess: false, }, + { + name: "index not parseable to int", + data: map[string]interface{}{ + "parent": map[string]interface{}{ + "children": []interface{}{ + "alice", + "bob", + "eve", + }, + }, + }, + keys: []string{"parent", "children", "notanint"}, + wantValue: nil, + wantSuccess: false, + }, + { + name: "slice blank index", + data: []interface{}{ + "bob", + }, + keys: []string{""}, + wantValue: nil, + wantSuccess: false, + }, + { + name: "slice no index", + data: []interface{}{ + "bob", + }, + wantValue: nil, + wantSuccess: false, + }, + { + name: "map blank key with value", + data: map[string]interface{}{ + "": "bob", + }, + keys: []string{""}, + wantValue: "bob", + wantSuccess: true, + }, + { + name: "map blank key no value", + data: map[string]interface{}{ + "alice": "bob", + }, + keys: []string{""}, + wantValue: nil, + wantSuccess: false, + }, + { + name: "map no key", + data: map[string]interface{}{ + "": "bob", + }, + wantValue: nil, + wantSuccess: false, + }, } for _, test := range tests { test := test