From f0f38d5cb979958fadfb17158a24fd4be4c3d23d Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 1 Sep 2026 21:09:39 +0200 Subject: [PATCH 1/2] cmd/docker: rewrite TestStringSliceReplaceAt to table test Signed-off-by: Sebastiaan van Stijn --- cmd/docker/aliases_utils_test.go | 88 ++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 22 deletions(-) diff --git a/cmd/docker/aliases_utils_test.go b/cmd/docker/aliases_utils_test.go index 7557d388bbc8..3afc964783be 100644 --- a/cmd/docker/aliases_utils_test.go +++ b/cmd/docker/aliases_utils_test.go @@ -7,27 +7,71 @@ import ( ) func TestStringSliceReplaceAt(t *testing.T) { - out, ok := stringSliceReplaceAt([]string{"abc", "foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, -1) - assert.Assert(t, ok) - assert.DeepEqual(t, []string{"abc", "baz", "bax"}, out) + tests := []struct { + name string + s []string + find []string + replace []string + requireIndex int + expected []string + ok bool + }{ + { + name: "replace", + s: []string{"abc", "foo", "bar", "bax"}, + find: []string{"foo", "bar"}, + replace: []string{"baz"}, + requireIndex: -1, + expected: []string{"abc", "baz", "bax"}, + ok: true, + }, + { + name: "find longer than input", + s: []string{"foo"}, + find: []string{"foo", "bar"}, + replace: []string{"baz"}, + requireIndex: -1, + expected: []string{"foo"}, + }, + { + name: "wrong required index", + s: []string{"abc", "foo", "bar", "bax"}, + find: []string{"foo", "bar"}, + replace: []string{"baz"}, + requireIndex: 0, + expected: []string{"abc", "foo", "bar", "bax"}, + }, + { + name: "required index", + s: []string{"foo", "bar", "bax"}, + find: []string{"foo", "bar"}, + replace: []string{"baz"}, + requireIndex: 0, + expected: []string{"baz", "bax"}, + ok: true, + }, + { + name: "remove", + s: []string{"abc", "foo", "bar", "baz"}, + find: []string{"foo", "bar"}, + requireIndex: -1, + expected: []string{"abc", "baz"}, + ok: true, + }, + { + name: "empty find", + s: []string{"foo"}, + replace: []string{"baz"}, + requireIndex: -1, + expected: []string{"foo"}, + }, + } - out, ok = stringSliceReplaceAt([]string{"foo"}, []string{"foo", "bar"}, []string{"baz"}, -1) - assert.Assert(t, !ok) - assert.DeepEqual(t, []string{"foo"}, out) - - out, ok = stringSliceReplaceAt([]string{"abc", "foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, 0) - assert.Assert(t, !ok) - assert.DeepEqual(t, []string{"abc", "foo", "bar", "bax"}, out) - - out, ok = stringSliceReplaceAt([]string{"foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, 0) - assert.Assert(t, ok) - assert.DeepEqual(t, []string{"baz", "bax"}, out) - - out, ok = stringSliceReplaceAt([]string{"abc", "foo", "bar", "baz"}, []string{"foo", "bar"}, nil, -1) - assert.Assert(t, ok) - assert.DeepEqual(t, []string{"abc", "baz"}, out) - - out, ok = stringSliceReplaceAt([]string{"foo"}, nil, []string{"baz"}, -1) - assert.Assert(t, !ok) - assert.DeepEqual(t, []string{"foo"}, out) + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + out, ok := stringSliceReplaceAt(tc.s, tc.find, tc.replace, tc.requireIndex) + assert.Equal(t, tc.ok, ok) + assert.DeepEqual(t, tc.expected, out) + }) + } } From bcc4be9f8be792332494453042fe3357e93262d9 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 1 Sep 2026 21:10:29 +0200 Subject: [PATCH 2/2] cmd/docker: fix stringSliceReplaceAt with overlapping matches Inline the sub-slice lookup into stringSliceReplaceAt and use slices.Equal to compare candidate ranges. When a specific index is required, check that position directly instead of searching the full slice. This also fixes overlapping matches and uses slices.Concat to construct the replacement result. Signed-off-by: Sebastiaan van Stijn --- cmd/docker/aliases_utils.go | 44 ++++++++++++++------------------ cmd/docker/aliases_utils_test.go | 9 +++++++ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/cmd/docker/aliases_utils.go b/cmd/docker/aliases_utils.go index b14fee0a9208..fbf1c7e98e8b 100644 --- a/cmd/docker/aliases_utils.go +++ b/cmd/docker/aliases_utils.go @@ -1,32 +1,26 @@ package main -func stringSliceIndex(s, subs []string) int { - j := 0 - if len(subs) > 0 { - for i, x := range s { - if j < len(subs) && subs[j] == x { - j++ - } else { - j = 0 - } - if len(subs) == j { - return i + 1 - j - } - } - } - return -1 -} +import "slices" -// stringSliceReplaceAt replaces the sub-slice find, with the sub-slice replace, in the string -// slice s, returning a new slice and a boolean indicating if the replacement happened. -// requireIdx is the index at which old needs to be found at (or -1 to disregard that). +// stringSliceReplaceAt replaces the sub-slice find with the sub-slice replace in s, +// returning a new slice and a boolean indicating whether the replacement happened. +// requireIndex is the index at which find must be found, or -1 to disregard it. func stringSliceReplaceAt(s, find, replace []string, requireIndex int) ([]string, bool) { - idx := stringSliceIndex(s, find) - if (requireIndex != -1 && requireIndex != idx) || idx == -1 { + if len(find) == 0 { return s, false } - out := append([]string{}, s[:idx]...) - out = append(out, replace...) - out = append(out, s[idx+len(find):]...) - return out, true + + if requireIndex >= 0 { + if requireIndex+len(find) > len(s) || !slices.Equal(s[requireIndex:requireIndex+len(find)], find) { + return s, false + } + return slices.Concat(s[:requireIndex], replace, s[requireIndex+len(find):]), true + } + + for i := range len(s) - len(find) + 1 { + if slices.Equal(s[i:i+len(find)], find) { + return slices.Concat(s[:i], replace, s[i+len(find):]), true + } + } + return s, false } diff --git a/cmd/docker/aliases_utils_test.go b/cmd/docker/aliases_utils_test.go index 3afc964783be..38db6caf9426 100644 --- a/cmd/docker/aliases_utils_test.go +++ b/cmd/docker/aliases_utils_test.go @@ -65,6 +65,15 @@ func TestStringSliceReplaceAt(t *testing.T) { requireIndex: -1, expected: []string{"foo"}, }, + { + name: "overlapping match", + s: []string{"a", "a", "b"}, + find: []string{"a", "b"}, + replace: []string{"c"}, + requireIndex: -1, + expected: []string{"a", "c"}, + ok: true, + }, } for _, tc := range tests {