From e938d642201e32027e9c5cfab692e2d31a5b490e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Tue, 12 Nov 2024 18:42:59 +0100 Subject: [PATCH 1/2] command: add Covers() for attenuation test, fix incorrect Segments() --- pkg/command/command.go | 19 ++++++++++++++++++- pkg/command/command_test.go | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pkg/command/command.go b/pkg/command/command.go index 618f023..45b40f5 100644 --- a/pkg/command/command.go +++ b/pkg/command/command.go @@ -98,7 +98,24 @@ func (c Command) Join(segments ...string) Command { // Segments returns the ordered segments that comprise the Command as a // slice of strings. func (c Command) Segments() []string { - return strings.Split(string(c), separator) + if c == separator { + return nil + } + return strings.Split(string(c), separator)[1:] +} + +// Covers returns true if the command is identical or a parent of the given other command. +func (c Command) Covers(other Command) bool { + otherSegments := other.Segments() + if len(otherSegments) < len(c.Segments()) { + return false + } + for i, s := range c.Segments() { + if otherSegments[i] != s { + return false + } + } + return true } // String returns the composed representation the command. This is also diff --git a/pkg/command/command_test.go b/pkg/command/command_test.go index ed7b86f..07b4c01 100644 --- a/pkg/command/command_test.go +++ b/pkg/command/command_test.go @@ -73,6 +73,21 @@ func TestJoin(t *testing.T) { require.Equal(t, "/faz/boz/foo/bar", command.MustParse("/faz/boz").Join("foo", "bar").String()) } +func TestSegments(t *testing.T) { + require.Empty(t, command.Top().Segments()) + require.Equal(t, []string{"foo", "bar", "baz"}, command.MustParse("/foo/bar/baz").Segments()) +} + +func TestCovers(t *testing.T) { + require.True(t, command.MustParse("/foo/bar/baz").Covers(command.MustParse("/foo/bar/baz"))) + require.True(t, command.MustParse("/foo/bar").Covers(command.MustParse("/foo/bar/baz"))) + require.False(t, command.MustParse("/foo/bar/baz").Covers(command.MustParse("/foo/bar"))) + require.True(t, command.MustParse("/").Covers(command.MustParse("/foo"))) + require.True(t, command.MustParse("/").Covers(command.MustParse("/foo/bar/baz"))) + require.False(t, command.MustParse("/foo").Covers(command.MustParse("/foo00"))) + require.False(t, command.MustParse("/foo/bar").Covers(command.MustParse("/foo/bar00"))) +} + type testcase struct { name string inp string From 98d9cadcbd9de58b4c0629a5a70cda3024452a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Tue, 12 Nov 2024 18:59:02 +0100 Subject: [PATCH 2/2] command: fast-path for Covers() --- pkg/command/command.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/command/command.go b/pkg/command/command.go index 45b40f5..605aca8 100644 --- a/pkg/command/command.go +++ b/pkg/command/command.go @@ -106,6 +106,14 @@ func (c Command) Segments() []string { // Covers returns true if the command is identical or a parent of the given other command. func (c Command) Covers(other Command) bool { + // fast-path, equivalent to the code below (verified with fuzzing) + if !strings.HasPrefix(string(other), string(c)) { + return false + } + return c == separator || len(c) == len(other) || other[len(c)] == separator[0] + + /* ------- + otherSegments := other.Segments() if len(otherSegments) < len(c.Segments()) { return false @@ -116,6 +124,8 @@ func (c Command) Covers(other Command) bool { } } return true + + */ } // String returns the composed representation the command. This is also