From 7d646a828a363db3d11ece2c2c2c9c560494e95c Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Sat, 1 Jun 2024 17:26:53 -0400 Subject: feat(strings): Update strings.Indent to error on bad input instead of silently doing nothing (#2089) Signed-off-by: Dave Henderson --- strings/strings.go | 16 ++++++++------ strings/strings_fuzz_test.go | 15 ++++++++++++- strings/strings_test.go | 52 ++++++++++++++++++++++++++++---------------- 3 files changed, 56 insertions(+), 27 deletions(-) (limited to 'strings') diff --git a/strings/strings.go b/strings/strings.go index f333b570..248ae9b1 100644 --- a/strings/strings.go +++ b/strings/strings.go @@ -15,12 +15,13 @@ import ( // Indent - indent each line of the string with the given indent string. // Any indent characters are permitted, except for '\n'. -// -// TODO: return an error if the indent string contains '\n' instead of -// succeeding -func Indent(width int, indent, s string) string { - if width <= 0 || strings.Contains(indent, "\n") { - return s +func Indent(width int, indent, s string) (string, error) { + if width <= 0 { + return "", fmt.Errorf("width must be > 0") + } + + if strings.Contains(indent, "\n") { + return "", fmt.Errorf("indent must not contain '\\n'") } if width > 1 { @@ -39,7 +40,8 @@ func Indent(width int, indent, s string) string { res = append(res, c) bol = c == '\n' } - return string(res) + + return string(res), nil } // ShellQuote - generate a POSIX shell literal evaluating to a string diff --git a/strings/strings_fuzz_test.go b/strings/strings_fuzz_test.go index 4a1fa671..52472c4a 100644 --- a/strings/strings_fuzz_test.go +++ b/strings/strings_fuzz_test.go @@ -6,6 +6,7 @@ import ( "unicode" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func FuzzIndent(f *testing.F) { @@ -16,7 +17,19 @@ func FuzzIndent(f *testing.F) { f.Add(15, "\n0", "\n0") f.Fuzz(func(t *testing.T, width int, indent, s string) { - out := Indent(width, indent, s) + out, err := Indent(width, indent, s) + + if width <= 0 { + require.Error(t, err) + return + } + + if strings.Contains(indent, "\n") { + require.Error(t, err) + return + } + + require.NoError(t, err) // out should be equal to s when both have the indent character // completely removed. diff --git a/strings/strings_test.go b/strings/strings_test.go index 4d16f5ea..0fec6925 100644 --- a/strings/strings_test.go +++ b/strings/strings_test.go @@ -9,18 +9,32 @@ import ( ) func TestIndent(t *testing.T) { - actual := "hello\nworld\n!" + in := "hello\nworld\n!" expected := " hello\n world\n !" - require.Equal(t, actual, Indent(0, " ", actual)) - require.Equal(t, actual, Indent(-1, " ", actual)) - require.Equal(t, expected, Indent(1, " ", actual)) - require.Equal(t, "\n", Indent(1, " ", "\n")) - require.Equal(t, " foo\n", Indent(1, " ", "foo\n")) - require.Equal(t, " foo", Indent(1, " ", "foo")) - require.Equal(t, " foo", Indent(3, " ", "foo")) - - // indenting with newline is not permitted - require.Equal(t, "foo", Indent(3, "\n", "foo")) + + actual, err := Indent(1, " ", in) + require.NoError(t, err) + require.Equal(t, expected, actual) + actual, err = Indent(1, " ", "\n") + require.NoError(t, err) + require.Equal(t, "\n", actual) + actual, err = Indent(1, " ", "foo\n") + require.NoError(t, err) + require.Equal(t, " foo\n", actual) + actual, err = Indent(1, " ", "foo") + require.NoError(t, err) + require.Equal(t, " foo", actual) + actual, err = Indent(3, " ", "foo") + require.NoError(t, err) + require.Equal(t, " foo", actual) + + // error cases + _, err = Indent(3, "\n", "foo") + require.Error(t, err) + _, err = Indent(-1, " ", in) + require.Error(t, err) + _, err = Indent(0, " ", in) + require.Error(t, err) } func BenchmarkIndent(b *testing.B) { @@ -29,14 +43,14 @@ func BenchmarkIndent(b *testing.B) { outs := make([]string, b.N*8) b.ResetTimer() for i := 0; i < b.N; i++ { - outs[0+i*8] = Indent(20, " ", longString) - outs[1+i*8] = Indent(-1, " ", actual) - outs[2+i*8] = Indent(1, " ", actual) - outs[3+i*8] = Indent(1, " ", "\n") - outs[4+i*8] = Indent(1, " ", "foo\n") - outs[5+i*8] = Indent(1, " ", "foo") - outs[6+i*8] = Indent(3, " ", "foo") - outs[7+i*8] = Indent(3, "\n", "foo") + outs[0+i*8], _ = Indent(20, " ", longString) + outs[1+i*8], _ = Indent(-1, " ", actual) + outs[2+i*8], _ = Indent(1, " ", actual) + outs[3+i*8], _ = Indent(1, " ", "\n") + outs[4+i*8], _ = Indent(1, " ", "foo\n") + outs[5+i*8], _ = Indent(1, " ", "foo") + outs[6+i*8], _ = Indent(3, " ", "foo") + outs[7+i*8], _ = Indent(3, "\n", "foo") } b.StopTimer() -- cgit v1.2.3