github.com/openebs/api@v1.12.0/pkg/util/unstructured_test.go (about)

     1  /*
     2  Copyright 2020 The OpenEBS Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  )
    23  
    24  func TestMergeMapOfObjects(t *testing.T) {
    25  	tests := map[string]struct {
    26  		destMap      map[string]interface{}
    27  		srcMap       map[string]interface{}
    28  		isMerge      bool
    29  		expectedKeys []string
    30  	}{
    31  		"merge map of objects - +ve test case - dest & src maps are exclusive": {
    32  			destMap: map[string]interface{}{
    33  				"k1": "v1",
    34  			},
    35  			srcMap: map[string]interface{}{
    36  				"k2": "v2",
    37  			},
    38  			isMerge:      true,
    39  			expectedKeys: []string{"k1", "k2"},
    40  		},
    41  		"merge map of objects - +ve test case - dest & src maps are same": {
    42  			destMap: map[string]interface{}{
    43  				"k1": "v1",
    44  			},
    45  			srcMap: map[string]interface{}{
    46  				"k1": "v2",
    47  			},
    48  			isMerge:      true,
    49  			expectedKeys: []string{"k1"},
    50  		},
    51  		"merge map of objects - +ve test case - some elements of dest & src maps are common": {
    52  			destMap: map[string]interface{}{
    53  				"k1": "v1",
    54  			},
    55  			srcMap: map[string]interface{}{
    56  				"k1": "v1.1",
    57  				"k2": "v2",
    58  			},
    59  			isMerge:      true,
    60  			expectedKeys: []string{"k1", "k2"},
    61  		},
    62  		"merge map of objects - +ve test case - dest map is empty": {
    63  			destMap: map[string]interface{}{},
    64  			srcMap: map[string]interface{}{
    65  				"k2": "v2",
    66  			},
    67  			isMerge:      true,
    68  			expectedKeys: []string{"k2"},
    69  		},
    70  		"merge map of objects - +ve test case - dest map is nil": {
    71  			destMap: nil,
    72  			srcMap: map[string]interface{}{
    73  				"k2": "v2",
    74  			},
    75  			isMerge: false,
    76  		},
    77  		"merge map of objects - +ve test case - src map is empty": {
    78  			destMap: map[string]interface{}{
    79  				"k1": "v1",
    80  			},
    81  			srcMap:       nil,
    82  			isMerge:      true,
    83  			expectedKeys: []string{"k1"},
    84  		},
    85  		"merge map of objects - +ve test case - src map is nil": {
    86  			destMap: map[string]interface{}{
    87  				"k1": "v1",
    88  			},
    89  			srcMap:       nil,
    90  			isMerge:      true,
    91  			expectedKeys: []string{"k1"},
    92  		},
    93  	}
    94  
    95  	for name, mock := range tests {
    96  		t.Run(name, func(t *testing.T) {
    97  			ok := MergeMapOfObjects(mock.destMap, mock.srcMap)
    98  
    99  			if mock.isMerge != ok {
   100  				t.Fatalf("failed to test merge map of objects: expected merge '%t': actual merge '%t'", mock.isMerge, ok)
   101  			}
   102  
   103  			if mock.isMerge && !ContainKeys(mock.destMap, mock.expectedKeys) {
   104  				t.Fatalf("failed to test merge map of objects: expected keys '%s': actual 'missing key(s)': dest after merge '%#v'", mock.expectedKeys, mock.destMap)
   105  			}
   106  
   107  			if mock.isMerge && len(mock.destMap) != len(mock.expectedKeys) {
   108  				t.Fatalf("failed to test merge map of objects: expected key count '%d': actual key count '%d'", len(mock.expectedKeys), len(mock.destMap))
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestSetNestedField(t *testing.T) {
   115  	tests := map[string]struct {
   116  		obj    map[string]interface{}
   117  		value  interface{}
   118  		fields []string
   119  	}{
   120  		"Negative test - set nested key value pair to empty original": {
   121  			// this is empty
   122  			obj: map[string]interface{}{},
   123  			// value to be set in above obj
   124  			value: "hello there",
   125  			// above value will be set at path obj[k1][k1.1]
   126  			fields: []string{"k1", "k1.1"},
   127  		},
   128  		"Negative test - set nested key with complex value to empty original": {
   129  			// this is empty
   130  			obj: map[string]interface{}{},
   131  			// value to be set in above obj
   132  			value: map[string]interface{}{
   133  				"k1.1.1": map[string]interface{}{
   134  					"k1.1.1.1": "hi there",
   135  				},
   136  			},
   137  			// above value will be set at path obj[k1][k1.1]
   138  			fields: []string{"k1", "k1.1"},
   139  		},
   140  		"Positive test - set a new value at new nested key": {
   141  			obj: map[string]interface{}{
   142  				"k1": "v1",
   143  				"k2": map[string]string{
   144  					"k2.1": "v2.1",
   145  					"k2.2": "v2.2",
   146  				},
   147  			},
   148  			// value to be set in above obj
   149  			value: "v2.3",
   150  			// above value will be set at path obj[k2][k2.3]
   151  			fields: []string{"k2", "k2.3"},
   152  		},
   153  		"Positive test - override an existing value of a nested key": {
   154  			obj: map[string]interface{}{
   155  				"k1": "v1",
   156  				"k2": map[string]string{
   157  					"k2.1": "v2.1",
   158  					"k2.2": "v2.2",
   159  				},
   160  			},
   161  			// value to be set in above obj
   162  			value: "v2.2'",
   163  			// above value will be set at path obj[k2][k2.2]
   164  			fields: []string{"k2", "k2.2"},
   165  		},
   166  		"Positive test - override an existing nested value of a parent key": {
   167  			obj: map[string]interface{}{
   168  				"k1": "v1",
   169  				"k2": map[string]string{
   170  					"k2.1": "v2.1",
   171  					"k2.2": "v2.2",
   172  				},
   173  			},
   174  			// value to be set in above obj
   175  			value: "hello",
   176  			// above value will be set against the obj[k2]
   177  			fields: []string{"k2"},
   178  		},
   179  		"Positive test - add a new parent key value pair": {
   180  			obj: map[string]interface{}{
   181  				"k1": "v1",
   182  				"k2": map[string]string{
   183  					"k2.1": "v2.1",
   184  					"k2.2": "v2.2",
   185  				},
   186  			},
   187  			// value to be set in above obj
   188  			value: "hello",
   189  			// above value will be set against the obj[k3]
   190  			fields: []string{"k3"},
   191  		},
   192  		"Negative test - no changes to original obj due to empty fields": {
   193  			obj: map[string]interface{}{
   194  				"k1": "v1",
   195  				"k2": map[string]string{
   196  					"k2.1": "v2.1",
   197  					"k2.2": "v2.2",
   198  				},
   199  			},
   200  			// resulting obj
   201  			value: map[string]interface{}{
   202  				"k1": "v1",
   203  				"k2": map[string]string{
   204  					"k2.1": "v2.1",
   205  					"k2.2": "v2.2",
   206  				},
   207  			},
   208  			// there will be no changes to obj since there are no fields
   209  			fields: []string{},
   210  		},
   211  		"Negative test - no changes to original obj due to nil object": {
   212  			obj: nil,
   213  			// resulting obj
   214  			value: nil,
   215  			// there will be no changes to obj even with provided fields
   216  			fields: []string{"k1", "k2"},
   217  		},
   218  	}
   219  
   220  	for name, mock := range tests {
   221  		t.Run(name, func(t *testing.T) {
   222  			SetNestedField(mock.obj, mock.value, mock.fields...)
   223  
   224  			if !reflect.DeepEqual(GetNestedField(mock.obj, mock.fields...), mock.value) {
   225  				t.Fatalf("failed to test set nested field: expected '%#v': actual '%#v'", mock.value, GetNestedField(mock.obj, mock.fields...))
   226  			}
   227  		})
   228  	}
   229  }