aboutsummaryrefslogtreecommitdiff
path: root/tests/dedo.go
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2025-01-27 10:00:24 -0300
committerEuAndreh <eu@euandre.org>2025-01-27 10:00:24 -0300
commitbbfc283e76821f6fead9e0da60f59fe54a6dff91 (patch)
treebd330715640a5261f9c99b1e984f720d1b077af0 /tests/dedo.go
parentsrc/dedo.go: Add "rm" command (diff)
downloaddedo-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.go256
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{