From d1d805764e61e0c172c00cdcc170c3eee70f03dc Mon Sep 17 00:00:00 2001 From: Mustafa Elbehery Date: Mon, 29 Jan 2024 20:18:55 +0100 Subject: [PATCH] fix cli cmds panics Signed-off-by: Mustafa Elbehery --- cmd/bbolt/main.go | 13 ++++++++++ cmd/bbolt/main_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/cmd/bbolt/main.go b/cmd/bbolt/main.go index f76cd82c4..7349596ef 100644 --- a/cmd/bbolt/main.go +++ b/cmd/bbolt/main.go @@ -60,6 +60,9 @@ var ( // ErrKeyNotFound is returned when a key is not found. ErrKeyNotFound = errors.New("key not found") + + // ErrNotEnoughArgs is returned with a cmd is being executed with fewer arguments. + ErrNotEnoughArgs = errors.New("not enough arguments") ) func main() { @@ -908,6 +911,11 @@ func (cmd *keysCommand) Run(args ...string) error { // Require database path and bucket. relevantArgs := fs.Args() + if len(relevantArgs) < 2 { + err := fmt.Errorf("Error: %w.\n", ErrNotEnoughArgs) + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return err + } path, buckets := relevantArgs[0], relevantArgs[1:] if path == "" { return ErrPathRequired @@ -993,6 +1001,11 @@ func (cmd *getCommand) Run(args ...string) error { // Require database path, bucket and key. relevantArgs := fs.Args() + if len(relevantArgs) < 3 { + err := fmt.Errorf("Error: %w.\n", ErrNotEnoughArgs) + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return err + } path, buckets := relevantArgs[0], relevantArgs[1:len(relevantArgs)-1] key, err := parseBytes(relevantArgs[len(relevantArgs)-1], parseFormat) if err != nil { diff --git a/cmd/bbolt/main_test.go b/cmd/bbolt/main_test.go index 7d0cfd249..fc065cf2e 100644 --- a/cmd/bbolt/main_test.go +++ b/cmd/bbolt/main_test.go @@ -397,6 +397,60 @@ func TestCompactCommand_Run(t *testing.T) { } } +func TestCommands_Run_NoArgs(t *testing.T) { + testCases := []struct { + name string + cmd string + expErr error + expStdErr string + }{ + { + name: "get", + cmd: "get", + expErr: main.ErrNotEnoughArgs, + expStdErr: `usage: bolt get PATH [BUCKET..] KEY + +Print the value of the given key in the given (sub)bucket. + +Additional options include: + + --format + Output format. One of: auto|ascii-encoded|hex|bytes|redacted (default=auto) + --parse-format + Input format (of key). One of: ascii-encoded|hex (default=ascii-encoded)" + +`, + }, + { + name: "keys", + cmd: "keys", + expErr: main.ErrNotEnoughArgs, + expStdErr: `usage: bolt keys PATH [BUCKET...] + +Print a list of keys in the given (sub)bucket. +======= + +Additional options include: + + --format + Output format. One of: auto|ascii-encoded|hex|bytes|redacted (default=auto) + +Print a list of keys in the given bucket. + +`, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + m := NewMain() + err := m.Run(tc.cmd) + require.ErrorIs(t, err, main.ErrNotEnoughArgs) + require.Equal(t, tc.expStdErr, m.Stderr.String()) + }) + } +} + func fillBucket(b *bolt.Bucket, prefix []byte) error { n := 10 + rand.Intn(50) for i := 0; i < n; i++ {