aboutsummaryrefslogtreecommitdiff
path: root/internal/plan/json_test.go
blob: 86c181cb862f5621d6987a7937d0e4eacd6f9cb4 (plain) (blame)
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
// SPDX-License-Identifier: GPL-3.0-or-later

package plan

import (
	"encoding/json"
	"strings"
	"testing"
	"time"
)

func TestJSONDir(t *testing.T) {
	chains := []Chain{{
		File: file("/r", "x.pdf"),
		Steps: []Step{
			{Kind: Copy, Rule: "b", Src: "/r/x.pdf", Dst: "/backup/x.pdf", Reason: `content "acme ltd"`},
			{Kind: Move, Rule: "a", Src: "/r/x.pdf", Dst: "/r/W/x.pdf", Displaces: "/r/W/x.pdf"},
			{Kind: Rename, Rule: "r", Src: "/r/W/x.pdf", Dst: "/r/W/2026-x.pdf"},
			{Kind: Trash, Rule: "t", Src: "/r/W/2026-x.pdf"},
			{Kind: DeletePermanent, Rule: "z", Src: "/r/W/x.pdf", Skip: "deleted by rule a"},
		},
		Warnings: []string{"moved more than once; a (stop) is probably missing"},
	}}
	b, err := json.MarshalIndent(JSON{Version: 1, Note: jsonNote, Dirs: []JSONDir{NewJSONDir("dl", "/r", chains, nil)}}, "", "  ")
	if err != nil {
		t.Fatal(err)
	}
	out := string(b)
	for _, want := range []string{
		`"version": 1`,
		`"note": "the shape of this document is unstable before krino 1.0"`,
		`"name": "dl"`,
		`"rel": "x.pdf"`,
		`"action": "copy"`,
		// D14: the reason a rule matched is carried into the JSON document too.
		`"reason": "content \"acme ltd\""`,
		// D7: rename and trash were previously covered only by inspection, so
		// an edit garbling either name would have passed silently.
		`"action": "rename"`,
		`"action": "trash"`,
		`"action": "move"`,
		`"displaces": "/r/W/x.pdf"`,
		`"action": "delete"`,
		`"skip": "deleted by rule a"`,
	} {
		if !strings.Contains(out, want) {
			t.Errorf("json lacks %s:\n%s", want, out)
		}
	}
	if strings.Contains(out, `"dst": ""`) {
		t.Error("empty dst must be omitted")
	}
	var round JSON
	if err := json.Unmarshal(b, &round); err != nil {
		t.Fatalf("does not round-trip: %v", err)
	}
	if !round.Dirs[0].Files[0].ModTime.Equal(time.Date(2026, 8, 15, 12, 0, 0, 0, time.UTC)) {
		t.Errorf("mtime did not survive: %v", round.Dirs[0].Files[0].ModTime)
	}
}

func TestJSONDirEmptyStepsAndFilesAreArraysNotNull(t *testing.T) {
	stepless := []Chain{{File: file("/r", "y.pdf")}}
	dir := NewJSONDir("dl", "/r", stepless, nil)
	b, err := json.Marshal(dir)
	if err != nil {
		t.Fatal(err)
	}
	if strings.Contains(string(b), `"steps":null`) {
		t.Errorf("stepless file's steps must be [], not null: %s", b)
	}
	if !strings.Contains(string(b), `"steps":[]`) {
		t.Errorf("stepless file's steps should marshal as []: %s", b)
	}

	empty := NewJSONDir("dl", "/r", nil, nil)
	b, err = json.Marshal(empty)
	if err != nil {
		t.Fatal(err)
	}
	if strings.Contains(string(b), `"files":null`) {
		t.Errorf("empty dir's files must be [], not null: %s", b)
	}
	if !strings.Contains(string(b), `"files":[]`) {
		t.Errorf("empty dir's files should marshal as []: %s", b)
	}
}