1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main

import (
	"bytes"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// cliEnv points CONFIG and SECRETS at fresh files naming a database in a
// temporary directory.
func cliEnv(t *testing.T) {
	t.Helper()
	dir := t.TempDir()
	cfg := filepath.Join(dir, "config.json")
	sec := filepath.Join(dir, "secrets.json")
	db := filepath.Join(dir, "kakapo.db")
	if err := os.WriteFile(cfg, []byte(`{
		"host": "kakapo.example.org",
		"db_file": "`+db+`",
		"birb": {"user": "birb"}
	}`), 0o644); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(sec, []byte(`{}`), 0o644); err != nil {
		t.Fatal(err)
	}
	t.Setenv("CONFIG", cfg)
	t.Setenv("SECRETS", sec)
}

func cli(t *testing.T, args ...string) (status int, stdout, stderr string) {
	t.Helper()
	var out, errOut bytes.Buffer
	status = runCli(args, &out, &errOut)
	return status, out.String(), errOut.String()
}

func TestCliBlockAddListRemove(t *testing.T) {
	cliEnv(t)

	if st, _, e := cli(t, "block", "add", "https://B.example/feed", "a.example/feed", "http://b.example/feed"); st != 0 {
		t.Fatalf("block add: %d %s", st, e)
	}
	if st, out, e := cli(t, "block", "list"); st != 0 || out != "a.example/feed\nb.example/feed\n" {
		t.Errorf("block list = %d %q %s", st, out, e)
	}
	if st, _, e := cli(t, "block", "remove", "A.example/feed", "c.example/feed"); st != 1 || !strings.Contains(e, "c.example/feed") {
		t.Errorf("block remove of a missing entry = %d %q; want 1 naming it", st, e)
	}
	if st, out, _ := cli(t, "block", "list"); st != 0 || out != "b.example/feed\n" {
		t.Errorf("block list after remove = %d %q", st, out)
	}
	// The allowlist is a different list.
	if st, out, _ := cli(t, "allow", "list"); st != 0 || out != "" {
		t.Errorf("allow list = %d %q; want empty", st, out)
	}
}

func TestCliAllowNormalisesAndValidates(t *testing.T) {
	cliEnv(t)
	if st, _, e := cli(t, "allow", "add", "@Alice@Example.org", "bob@example.org"); st != 0 {
		t.Fatalf("allow add: %d %s", st, e)
	}
	if st, out, _ := cli(t, "allow", "list"); out != "alice@example.org\nbob@example.org\n" {
		t.Errorf("allow list = %d %q", st, out)
	}
	// Nothing is added if any operand is bad.
	for _, bad := range []string{"alice", "@example.org", "alice@", "https://example.org/@alice"} {
		if st, _, _ := cli(t, "allow", "add", "carol@example.org", bad); st != 2 {
			t.Errorf("allow add %q = %d; want 2", bad, st)
		}
	}
	if _, out, _ := cli(t, "allow", "list"); strings.Contains(out, "carol") {
		t.Error("a valid entry was added along with an invalid one")
	}
}

func TestCliUsage(t *testing.T) {
	for _, args := range [][]string{
		{"nope"}, {"block"}, {"block", "add"}, {"block", "list", "x"}, {"allow", "frob", "x"},
	} {
		if st, _, _ := cli(t, args...); st != 2 {
			t.Errorf("%v = %d; want 2", args, st)
		}
	}
	if st, out, _ := cli(t, "--help"); st != 0 || !strings.HasPrefix(out, "usage:") {
		t.Errorf("--help = %d %q", st, out)
	}
}