X Tutup
Skip to content

Commit f1fbfdf

Browse files
committed
Fix up bug in RemoveEntry and add tests for config_map
1 parent a394002 commit f1fbfdf

File tree

2 files changed

+162
-31
lines changed

2 files changed

+162
-31
lines changed

internal/config/config_map.go

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"gopkg.in/yaml.v3"
77
)
88

9-
// This type implements a low-level get/set config that is backed by an in-memory tree of Yaml
9+
// This type implements a low-level get/set config that is backed by an in-memory tree of yaml
1010
// nodes. It allows us to interact with a yaml-based config programmatically, preserving any
1111
// comments that were present when the yaml was parsed.
1212
type ConfigMap struct {
@@ -37,41 +37,41 @@ func (cm *ConfigMap) GetStringValue(key string) (string, error) {
3737

3838
func (cm *ConfigMap) SetStringValue(key, value string) error {
3939
entry, err := cm.FindEntry(key)
40+
if err == nil {
41+
entry.ValueNode.Value = value
42+
return nil
43+
}
4044

4145
var notFound *NotFoundError
42-
43-
valueNode := entry.ValueNode
44-
45-
if err != nil && errors.As(err, &notFound) {
46-
keyNode := &yaml.Node{
47-
Kind: yaml.ScalarNode,
48-
Value: key,
49-
}
50-
valueNode = &yaml.Node{
51-
Kind: yaml.ScalarNode,
52-
Tag: "!!str",
53-
Value: "",
54-
}
55-
56-
cm.Root.Content = append(cm.Root.Content, keyNode, valueNode)
57-
} else if err != nil {
46+
if err != nil && !errors.As(err, &notFound) {
5847
return err
5948
}
6049

61-
valueNode.Value = value
50+
keyNode := &yaml.Node{
51+
Kind: yaml.ScalarNode,
52+
Value: key,
53+
}
54+
valueNode := &yaml.Node{
55+
Kind: yaml.ScalarNode,
56+
Tag: "!!str",
57+
Value: value,
58+
}
6259

60+
cm.Root.Content = append(cm.Root.Content, keyNode, valueNode)
6361
return nil
6462
}
6563

66-
func (cm *ConfigMap) FindEntry(key string) (ce *ConfigEntry, err error) {
67-
err = nil
64+
func (cm *ConfigMap) FindEntry(key string) (*ConfigEntry, error) {
65+
ce := &ConfigEntry{}
6866

69-
ce = &ConfigEntry{}
67+
if cm.Empty() {
68+
return ce, &NotFoundError{errors.New("not found")}
69+
}
7070

71-
// Content slice goes [key1, value1, key2, value2, ...]
71+
// Content slice goes [key1, value1, key2, value2, ...].
7272
topLevelPairs := cm.Root.Content
7373
for i, v := range topLevelPairs {
74-
// Skip every other slice item since we only want to check against keys
74+
// Skip every other slice item since we only want to check against keys.
7575
if i%2 != 0 {
7676
continue
7777
}
@@ -81,22 +81,31 @@ func (cm *ConfigMap) FindEntry(key string) (ce *ConfigEntry, err error) {
8181
if i+1 < len(topLevelPairs) {
8282
ce.ValueNode = topLevelPairs[i+1]
8383
}
84-
return
84+
return ce, nil
8585
}
8686
}
8787

8888
return ce, &NotFoundError{errors.New("not found")}
8989
}
9090

9191
func (cm *ConfigMap) RemoveEntry(key string) {
92+
if cm.Empty() {
93+
return
94+
}
95+
9296
newContent := []*yaml.Node{}
9397

94-
content := cm.Root.Content
95-
for i := 0; i < len(content); i++ {
96-
if content[i].Value == key {
97-
i++ // skip the next node which is this key's value
98+
var skipNext bool
99+
for i, v := range cm.Root.Content {
100+
if skipNext {
101+
skipNext = false
102+
continue
103+
}
104+
if i%2 != 0 || v.Value != key {
105+
newContent = append(newContent, v)
98106
} else {
99-
newContent = append(newContent, content[i])
107+
// Don't append current node and skip the next which is this key's value.
108+
skipNext = true
100109
}
101110
}
102111

internal/config/config_map_test.go

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package config
22

33
import (
4-
"fmt"
54
"testing"
65

76
"github.com/stretchr/testify/assert"
@@ -46,12 +45,135 @@ func TestFindEntry(t *testing.T) {
4645
return
4746
}
4847
assert.NoError(t, err)
49-
fmt.Println(out)
5048
assert.Equal(t, tt.output, out.ValueNode.Value)
5149
})
5250
}
5351
}
5452

53+
func TestEmpty(t *testing.T) {
54+
cm := ConfigMap{}
55+
assert.Equal(t, true, cm.Empty())
56+
cm.Root = &yaml.Node{
57+
Content: []*yaml.Node{
58+
{
59+
Value: "test",
60+
},
61+
},
62+
}
63+
assert.Equal(t, false, cm.Empty())
64+
}
65+
66+
func TestGetStringValue(t *testing.T) {
67+
tests := []struct {
68+
name string
69+
key string
70+
wantValue string
71+
wantErr bool
72+
}{
73+
{
74+
name: "get key",
75+
key: "valid",
76+
wantValue: "present",
77+
},
78+
{
79+
name: "get key that is not present",
80+
key: "invalid",
81+
wantErr: true,
82+
},
83+
{
84+
name: "get key that has same content as a value",
85+
key: "same",
86+
wantValue: "logical",
87+
},
88+
}
89+
90+
for _, tt := range tests {
91+
cm := ConfigMap{Root: testYaml()}
92+
t.Run(tt.name, func(t *testing.T) {
93+
val, err := cm.GetStringValue(tt.key)
94+
if tt.wantErr {
95+
assert.EqualError(t, err, "not found")
96+
return
97+
}
98+
assert.Equal(t, tt.wantValue, val)
99+
})
100+
}
101+
}
102+
103+
func TestSetStringValue(t *testing.T) {
104+
tests := []struct {
105+
name string
106+
key string
107+
value string
108+
}{
109+
{
110+
name: "set key that is not present",
111+
key: "notPresent",
112+
value: "test1",
113+
},
114+
{
115+
name: "set key that is present",
116+
key: "erroneous",
117+
value: "test2",
118+
},
119+
{
120+
name: "set key that is blank",
121+
key: "blank",
122+
value: "test3",
123+
},
124+
{
125+
name: "set key that has same content as a value",
126+
key: "present",
127+
value: "test4",
128+
},
129+
}
130+
131+
for _, tt := range tests {
132+
cm := ConfigMap{Root: testYaml()}
133+
t.Run(tt.name, func(t *testing.T) {
134+
err := cm.SetStringValue(tt.key, tt.value)
135+
assert.NoError(t, err)
136+
val, err := cm.GetStringValue(tt.key)
137+
assert.NoError(t, err)
138+
assert.Equal(t, tt.value, val)
139+
})
140+
}
141+
}
142+
143+
func TestRemoveEntry(t *testing.T) {
144+
tests := []struct {
145+
name string
146+
key string
147+
wantLength int
148+
}{
149+
{
150+
name: "remove key",
151+
key: "erroneous",
152+
wantLength: 6,
153+
},
154+
{
155+
name: "remove key that is not present",
156+
key: "invalid",
157+
wantLength: 8,
158+
},
159+
{
160+
name: "remove key that has same content as a value",
161+
key: "same",
162+
wantLength: 6,
163+
},
164+
}
165+
166+
for _, tt := range tests {
167+
cm := ConfigMap{Root: testYaml()}
168+
t.Run(tt.name, func(t *testing.T) {
169+
cm.RemoveEntry(tt.key)
170+
assert.Equal(t, tt.wantLength, len(cm.Root.Content))
171+
_, err := cm.FindEntry(tt.key)
172+
assert.EqualError(t, err, "not found")
173+
})
174+
}
175+
}
176+
55177
func testYaml() *yaml.Node {
56178
var root yaml.Node
57179
var data = `

0 commit comments

Comments
 (0)
X Tutup