diff options
author | EuAndreh <eu@euandre.org> | 2025-01-27 10:00:24 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2025-01-27 10:00:24 -0300 |
commit | bbfc283e76821f6fead9e0da60f59fe54a6dff91 (patch) | |
tree | bd330715640a5261f9c99b1e984f720d1b077af0 /tests/dedo.go | |
parent | src/dedo.go: Add "rm" command (diff) | |
download | dedo-bbfc283e76821f6fead9e0da60f59fe54a6dff91.tar.gz dedo-bbfc283e76821f6fead9e0da60f59fe54a6dff91.tar.xz |
tests/dedo.go: Add tests for getopt() and runCommand()
Diffstat (limited to 'tests/dedo.go')
-rw-r--r-- | tests/dedo.go | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/tests/dedo.go b/tests/dedo.go index b8404ef..0c33a59 100644 --- a/tests/dedo.go +++ b/tests/dedo.go @@ -169,6 +169,260 @@ func test_Open() { g.TestStart("Open()") } +func test_getopt() { + g.TestStart("getopt()") + + const warning = "Missing COMMAND.\n" + const usage = + "Usage: $0 [-f FILE] [-b BUCKET] COMMAND [ARGUMENTS...]\n" + + commandsMap := map[string]commandT{ + "good": commandT{ + name: "good", + getopt: func(args argsT, _ io.Writer) (argsT, bool) { + return args, true + }, + }, + "bad": commandT{ + name: "bad", + getopt: func(args argsT, w io.Writer) (argsT, bool) { + if len(args.args) == 0 { + fmt.Fprintln(w, "no required arg") + return args, false + } + + if args.args[0] != "required" { + fmt.Fprintln(w, "not correct one") + return args, false + } + + args.bucket = []byte("a bucket") + args.key = []byte("a key") + return args, true + }, + }, + } + + + g.Testing("we suppress the default error message", func() { + var w strings.Builder + argv := []string{"$0", "-h"} + _, _, rc := getopt(argv, commandsMap, &w) + + g.TAssertEqual(w.String(), usage) + g.TAssertEqual(rc, 2) + }) + + g.Testing("we get an error unsupported flag", func() { + var w strings.Builder + argv :=[]string{"$0", "-X"} + _, _, rc := getopt(argv, commandsMap, &w) + + const message = "flag provided but not defined: -X\n" + g.TAssertEqual(w.String(), message + usage) + g.TAssertEqual(rc, 2) + }) + + g.Testing("we also get an error on incorrect usage of flags", func() { + var w strings.Builder + argv := []string{"$0", "-f"} + _, _, rc := getopt(argv, commandsMap, &w) + + const message = "flag needs an argument: -f\n" + g.TAssertEqual(w.String(), message + usage) + g.TAssertEqual(rc, 2) + }) + + g.Testing("error when not given a command", func() { + var w strings.Builder + argv := []string{"$0"} + _, _, rc := getopt(argv, commandsMap, &w) + + g.TAssertEqual(w.String(), warning + usage) + g.TAssertEqual(rc, 2) + }) + + g.Testing("error on unknown command", func() { + var w strings.Builder + argv := []string{"$0", "unknown"} + _, _, rc := getopt(argv, commandsMap, &w) + + const message = `Bad COMMAND: "unknown".` + "\n" + g.TAssertEqual(w.String(), message + usage) + g.TAssertEqual(rc, 2) + }) + + g.Testing("checks the command usage", func() { + var ( + w1 strings.Builder + w2 strings.Builder + w3 strings.Builder + ) + + argv1 := []string{"$0", "bad"} + argv2 := []string{"$0", "bad", "arg"} + argv3 := []string{"$0", "bad", "required"} + _, _, rc1 := getopt(argv1, commandsMap, &w1) + _, _, rc2 := getopt(argv2, commandsMap, &w2) + args, command, rc3 := getopt(argv3, commandsMap, &w3) + expectedArgs := argsT{ + databasePath: "data.kv", + command: "bad", + allArgs: argv3, + args: argv3[2:], + bucket: []byte("a bucket"), + key: []byte("a key"), + } + + g.TAssertEqual(w1.String(), "no required arg\n" + usage) + g.TAssertEqual(w2.String(), "not correct one\n" + usage) + g.TAssertEqual(w3.String(), "") + g.TAssertEqual(rc1, 2) + g.TAssertEqual(rc2, 2) + g.TAssertEqual(rc3, 0) + g.TAssertEqual(args, expectedArgs) + g.TAssertEqual(command.name, "bad") + }) + + g.Testing("when given a command we get the default values", func() { + var w strings.Builder + args, command, rc := getopt( + []string{"$0", "good"}, + commandsMap, + &w, + ) + expectedArgs := argsT{ + databasePath: "data.kv", + command: "good", + allArgs: []string{"$0", "good"}, + args: []string{}, + bucket: []byte("default"), + } + + g.TAssertEqual(w.String(), "") + g.TAssertEqual(rc, 0) + g.TAssertEqual(args, expectedArgs) + g.TAssertEqual(command.name, "good") + }) + + g.Testing("we can customize both values", func() { + var w strings.Builder + argv := []string{"$0", "-f", "F", "-b", "B", "good"} + args, command, rc := getopt(argv, commandsMap, &w) + expectedArgs := argsT{ + databasePath: "F", + command: "good", + allArgs: argv, + args: []string{}, + bucket: []byte("B"), + } + + g.TAssertEqual(w.String(), "") + g.TAssertEqual(rc, 0) + g.TAssertEqual(args, expectedArgs) + g.TAssertEqual(command.name, "good") + }) + + g.Testing("a commmand can have its own commands and options", func() { + var w strings.Builder + argv := []string{"$0", "-f", "F", "good", "-f", "-f", "SUB"} + args, command, rc := getopt(argv, commandsMap, &w) + expectedArgs := argsT{ + databasePath: "F", + command: "good", + allArgs: argv, + args: []string{"-f", "-f", "SUB"}, + bucket: []byte("default"), + } + + g.TAssertEqual(w.String(), "") + g.TAssertEqual(rc, 0) + g.TAssertEqual(args, expectedArgs) + g.TAssertEqual(command.name, "good") + }) +} + +func test_runCommand() { + g.TestStart("runCommand()") + + + g.Testing("returns an error if can't open the file", func() { + stdin := strings.NewReader("") + var ( + stdout strings.Builder + stderr strings.Builder + ) + args := argsT{ + databasePath: "does/not/exist.kv", + command: "get", + allArgs: []string{"$0"}, + args: []string{"key-name"}, + } + rc := runCommand(args, commands["get"], stdin, &stdout, &stderr) + + const errmsg = "open does/not/exist.kv: " + + "no such file or directory\n" + g.TAssertEqual(rc, 1) + g.TAssertEqual(stdout.String(), "") + g.TAssertEqual(stderr.String(), errmsg) + }) + + g.Testing("otherwise builds a DB and calls the command", func() { + f1 := tempfile() + f2 := tempfile() + defer os.Remove(f1) + defer os.Remove(f2) + + stdin := strings.NewReader("") + var ( + stdout1 strings.Builder + stdout2 strings.Builder + stderr1 strings.Builder + stderr2 strings.Builder + ) + args1 := argsT{ + databasePath: f1, + command: "good", + } + args2 := argsT{ + databasePath: f2, + command: "bad", + } + myErr := errors.New("my specific error") + good := commandT{ + exec: func( + _ argsT, + _ *DB, + _ io.Reader, + w io.Writer, + ) error { + fmt.Fprintf(w, "good text\n") + return nil + }, + } + bad := commandT{ + exec: func( + _ argsT, + _ *DB, + _ io.Reader, + w io.Writer, + ) error { + fmt.Fprintf(w, "bad text\n") + return myErr + }, + } + rc1 := runCommand(args1, good, stdin, &stdout1, &stderr1) + rc2 := runCommand(args2, bad, stdin, &stdout2, &stderr2) + + g.TAssertEqual(stdout1.String(), "good text\n") + g.TAssertEqual(stdout2.String(), "bad text\n") + g.TAssertEqual(stderr1.String(), "") + g.TAssertEqual(stderr2.String(), "my specific error\n") + g.TAssertEqual(rc1, 0) + g.TAssertEqual(rc2, 1) + }) +} + func test_commands() { g.TestStart("commands") @@ -6275,6 +6529,8 @@ func MainTest() { test_readPageSize() test_initDB() test_Open() + test_getopt() + test_runCommand() test_commands() tests := []testing.InternalTest{ |