{{ message }}
Repository navigation
Expand file tree
/
Copy pathspec_test.go
More file actions
243 lines (217 loc) · 9.45 KB
/
Copy pathspec_test.go
File metadata and controls
243 lines (217 loc) · 9.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
//go:build !integration
package importinpututil_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/github/gh-aw/pkg/importinpututil"
)
// TestSpec_* functions derive from the importinpututil README.md specification.
// Each test maps to a documented section of the package contract and is written
// against the public API only — not against implementation internals.
// TestSpec_PublicAPI_ResolvePathValue validates the documented behavior of
// ResolvePathValue as described in the package README.md.
//
// Specification:
// - Resolves either a top-level input key (e.g. "count") or a one-level
// dotted object sub-key (e.g. "config.apiKey") from a map of import inputs.
// - Returns (value, true) on success.
// - Returns (nil, false) when the key is absent or the dotted path cannot be traversed.
func TestSpec_PublicAPI_ResolvePathValue(t *testing.T) {
t.Parallel()
inputs := map[string]any{
"count": 42,
"config": map[string]any{"apiKey": "secret"},
}
tests := []struct {
name string
inputPath string
wantValue any
wantOK bool
}{
{name: "documented: top-level key", inputPath: "count", wantValue: 42, wantOK: true},
{name: "documented: dotted sub-key", inputPath: "config.apiKey", wantValue: "secret", wantOK: true},
{name: "documented: missing top-level key", inputPath: "missing", wantValue: nil, wantOK: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
value, ok := importinpututil.ResolvePathValue(inputs, tt.inputPath)
assert.Equal(t, tt.wantOK, ok, "ResolvePathValue(%q) ok mismatch for: %s", tt.inputPath, tt.name)
assert.Equal(t, tt.wantValue, value, "ResolvePathValue(%q) value mismatch for: %s", tt.inputPath, tt.name)
})
}
}
// TestSpec_PublicAPI_ResolvePathValue_DottedPathTraversalFailure validates the
// documented "(nil, false)" result when a dotted path cannot be traversed.
//
// Specification:
// - Returns (nil, false) when the dotted path cannot be traversed.
func TestSpec_PublicAPI_ResolvePathValue_DottedPathTraversalFailure(t *testing.T) {
t.Parallel()
inputs := map[string]any{
"count": 42,
"config": map[string]any{"apiKey": "secret"},
}
tests := []struct {
name string
inputPath string
}{
{name: "documented: dotted lookup where top-level key is absent", inputPath: "absent.apiKey"},
{name: "documented: dotted lookup where top-level value is not an object", inputPath: "count.apiKey"},
{name: "documented: dotted lookup where sub-key is absent", inputPath: "config.missing"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
value, ok := importinpututil.ResolvePathValue(inputs, tt.inputPath)
assert.False(t, ok, "ResolvePathValue(%q) should return ok=false for: %s", tt.inputPath, tt.name)
assert.Nil(t, value, "ResolvePathValue(%q) should return nil value for: %s", tt.inputPath, tt.name)
})
}
}
// TestSpec_DesignDecision_ResolvePathValue_SingleLevelDotNotation validates the
// documented design note that only one level of dot notation is supported.
//
// Specification (Design Notes):
// - Only one level of dot notation is supported for sub-key resolution:
// "a.b" is valid; "a.b.c" is treated as a lookup for key "b.c" inside the
// top-level object "a", which will typically fail.
func TestSpec_DesignDecision_ResolvePathValue_SingleLevelDotNotation(t *testing.T) {
t.Parallel()
inputs := map[string]any{
"a": map[string]any{
"b": map[string]any{"c": "deep"},
"b.c": "literal-sub-key",
},
}
// "a.b.c" is split only on the first dot, so the sub-key looked up is the
// literal "b.c" inside object "a" — not a recursive descent into a -> b -> c.
value, ok := importinpututil.ResolvePathValue(inputs, "a.b.c")
assert.True(t, ok, "documented: 'a.b.c' resolves the literal sub-key 'b.c' inside 'a'")
assert.Equal(t, "literal-sub-key", value,
"documented: only the first dot splits the path; 'b.c' is treated as a single sub-key")
}
// TestSpec_PublicAPI_FormatResolvedValue validates the documented behavior of
// FormatResolvedValue as described in the package README.md.
//
// Specification:
// - nil returns ("", false).
// - Scalar values (int, bool, string, etc.) are formatted with fmt.Sprintf("%v", v).
// - []any and map[string]any values are JSON-marshalled.
// - Typed slices and maps are normalized to []any / map[string]any and JSON-marshalled.
// - Returns ("", false) if JSON marshalling fails.
func TestSpec_PublicAPI_FormatResolvedValue(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value any
wantStr string
wantOK bool
}{
// nil
{name: "documented: nil returns empty and false", value: nil, wantStr: "", wantOK: false},
// scalars via fmt.Sprintf("%v", v)
{name: "documented: scalar int", value: 42, wantStr: "42", wantOK: true},
{name: "documented: scalar bool", value: true, wantStr: "true", wantOK: true},
{name: "documented: scalar string", value: "hello", wantStr: "hello", wantOK: true},
// []any and map[string]any are JSON-marshalled
{name: "documented: []any slice example", value: []any{"a", "b"}, wantStr: `["a","b"]`, wantOK: true},
{name: "documented: map[string]any example", value: map[string]any{"x": 1}, wantStr: `{"x":1}`, wantOK: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
s, ok := importinpututil.FormatResolvedValue(tt.value)
assert.Equal(t, tt.wantOK, ok, "FormatResolvedValue ok mismatch for: %s", tt.name)
assert.Equal(t, tt.wantStr, s, "FormatResolvedValue string mismatch for: %s", tt.name)
})
}
}
// TestSpec_PublicAPI_FormatResolvedValue_TypedCollections validates that typed
// slices and maps are normalized and JSON-marshalled as documented.
//
// Specification (Design Notes):
// - Typed slices and maps (e.g. []string, map[string]int) are normalized to
// []any / map[string]any via reflection before marshalling.
func TestSpec_PublicAPI_FormatResolvedValue_TypedCollections(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value any
wantStr string
}{
{name: "documented: typed slice []string", value: []string{"a", "b"}, wantStr: `["a","b"]`},
{name: "documented: typed slice []int", value: []int{1, 2, 3}, wantStr: `[1,2,3]`},
{name: "documented: typed map map[string]int", value: map[string]int{"x": 1}, wantStr: `{"x":1}`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
s, ok := importinpututil.FormatResolvedValue(tt.value)
assert.True(t, ok, "FormatResolvedValue should succeed for: %s", tt.name)
assert.Equal(t, tt.wantStr, s, "FormatResolvedValue string mismatch for: %s", tt.name)
})
}
}
// TestSpec_PublicAPI_FormatResolvedValue_MarshalFailure validates the documented
// failure path of FormatResolvedValue.
//
// Specification:
// - Returns ("", false) if JSON marshalling fails.
//
// A collection value containing an unmarshalable element (a channel cannot be
// JSON-encoded) must therefore yield the documented ("", false) result.
func TestSpec_PublicAPI_FormatResolvedValue_MarshalFailure(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value any
}{
{name: "documented: []any containing an unmarshalable channel", value: []any{make(chan int)}},
{name: "documented: map[string]any containing an unmarshalable channel", value: map[string]any{"ch": make(chan int)}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
s, ok := importinpututil.FormatResolvedValue(tt.value)
assert.False(t, ok, "FormatResolvedValue should return ok=false when JSON marshalling fails: %s", tt.name)
assert.Empty(t, s, "FormatResolvedValue should return empty string when JSON marshalling fails: %s", tt.name)
})
}
}
// TestSpec_DesignDecision_FormatResolvedValue_DeterministicMapKeyOrder validates
// the documented guarantee that map keys are sorted lexicographically.
//
// Specification (Design Notes):
// - Map keys in JSON output are sorted lexicographically for deterministic output.
func TestSpec_DesignDecision_FormatResolvedValue_DeterministicMapKeyOrder(t *testing.T) {
t.Parallel()
// A typed map with keys deliberately out of lexical order.
value := map[string]int{"banana": 2, "apple": 1, "cherry": 3}
// Run multiple times to confirm the output is stable and lexically ordered.
const want = `{"apple":1,"banana":2,"cherry":3}`
for i := range 5 {
s, ok := importinpututil.FormatResolvedValue(value)
assert.True(t, ok, "FormatResolvedValue should succeed for deterministic map output")
assert.Equal(t, want, s,
"documented: map keys must be sorted lexicographically for deterministic output (iteration %d)", i)
}
}
// TestSpec_UsageExample_ResolveThenFormat validates the documented end-to-end
// usage example: resolve an import input by path, then format the resolved value.
//
// Specification (Usage Examples):
//
// value, ok := importinpututil.ResolvePathValue(importInputs, "config.endpoint")
// formatted, ok := importinpututil.FormatResolvedValue(value)
func TestSpec_UsageExample_ResolveThenFormat(t *testing.T) {
t.Parallel()
importInputs := map[string]any{
"config": map[string]any{"endpoint": "https://example.com"},
}
value, ok := importinpututil.ResolvePathValue(importInputs, "config.endpoint")
assert.True(t, ok, "usage example: 'config.endpoint' should resolve")
formatted, ok := importinpututil.FormatResolvedValue(value)
assert.True(t, ok, "usage example: resolved value should format")
assert.Equal(t, "https://example.com", formatted, "usage example: scalar string formats with %v")
}
You can’t perform that action at this time.
