Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions mcdc_supplement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,16 +338,13 @@ func TestDeleteSupplementalEdgeCases(t *testing.T) {
// MCDC SYS-REQ-009: N/A
func TestSetSupplementalArrayInsertionCoverage(t *testing.T) {
t.Run("append into existing top level array path", func(t *testing.T) {
// When setting an index beyond the current array length for a
// primitive (non-object) array, the code overwrites rather than
// appends because createInsertComponent with object=true wraps
// the value. This is the actual parser behavior.
// Setting an index beyond the current array length appends the value.
got, err := Set([]byte(`{"top":[1]}`), []byte(`2`), "top", "[1]")
if err != nil {
t.Fatalf("Set array append returned error: %v", err)
}
if string(got) != `{"top":[2]}` {
t.Fatalf("Set array append result = %s, want %s", string(got), `{"top":[2]}`)
if string(got) != `{"top":[1,2]}` {
t.Fatalf("Set array append result = %s, want %s", string(got), `{"top":[1,2]}`)
}
})

Expand Down
9 changes: 6 additions & 3 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -883,9 +883,12 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
depthOffset := endOffset
if depth != 0 {
// if subpath is a non-empty object, add to it
// or if subpath is a non-empty array, add to it
if (data[startOffset] == '{' && data[startOffset+1+nextToken(data[startOffset+1:])] != '}') ||
(data[startOffset] == '[' && data[startOffset+1+nextToken(data[startOffset+1:])] == '{') && keys[depth:][0][0] == 91 {
// or if subpath is a non-empty array and next key is an index, append to it
nextInside := data[startOffset+1+nextToken(data[startOffset+1:])]
nextKeyIsIndex := len(keys[depth:]) > 0 && len(keys[depth:][0]) > 0 && keys[depth:][0][0] == '['
canExtendObject := data[startOffset] == '{' && nextInside != '}'
canExtendArray := data[startOffset] == '[' && nextInside != ']' && nextKeyIsIndex
if canExtendObject || canExtendArray {
depthOffset--
startOffset = depthOffset
// otherwise, over-write it with a new object
Expand Down
23 changes: 23 additions & 0 deletions set_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,26 @@ func TestFuzzSetHarnessCoverage(t *testing.T) {
t.Fatalf("expected FuzzSet failure path to return 0, got %d", got)
}
}


// Regression for issue #267: Set with successive array indexes must append scalars.
func TestSetAppendsScalarToExistingArrayByIndex(t *testing.T) {
value := []byte(`{}`)
var err error
value, err = Set(value, []byte(`1`), "test", "[0]")
if err != nil {
t.Fatalf("Set [0]: %v", err)
}
value, err = Set(value, []byte(`2`), "test", "[1]")
if err != nil {
t.Fatalf("Set [1]: %v", err)
}
value, err = Set(value, []byte(`3`), "test", "[2]")
if err != nil {
t.Fatalf("Set [2]: %v", err)
}
expected := `{"test":[1,2,3]}`
if string(value) != expected {
t.Fatalf("Set result mismatch: expected %s, got %s", expected, string(value))
}
}