返回 DeepSeek-Reasonix
permission_rule_notice_test.go
根目录 / internal / boot / permission_rule_notice_test.go
1 package boot
2
3 import (
4 "strings"
5 "testing"
6
7 "reasonix/internal/event"
8 )
9
10 type captureSink struct{ events []event.Event }
11
12 func (c *captureSink) Emit(e event.Event) { c.events = append(c.events, e) }
13
14 // TestUnmatchableRuleNoticeReachesTheSink is the reason this warning exists:
15 // config load warnings are only read by the desktop, so a rule typed into
16 // config.toml had to reach the transport-agnostic sink to be seen by a CLI
17 // user at all.
18 func TestUnmatchableRuleNoticeReachesTheSink(t *testing.T) {
19 sink := &captureSink{}
20 emitUnmatchableRuleNotice(sink, nil, nil, []string{"git push --force"})
21 if len(sink.events) != 1 {
22 t.Fatalf("got %d events, want 1", len(sink.events))
23 }
24 got := sink.events[0]
25 if got.Kind != event.Notice || got.Level != event.LevelWarn {
26 t.Fatalf("event = %v/%v, want Notice/LevelWarn", got.Kind, got.Level)
27 }
28 if !strings.Contains(got.Detail, "permissions.deny") {
29 t.Errorf("detail does not name the setting: %q", got.Detail)
30 }
31 if !strings.Contains(got.Detail, `Bash(git push --force:*)`) {
32 t.Errorf("detail does not carry the rewrite: %q", got.Detail)
33 }
34 }
35
36 // TestUnmatchableRuleNoticeSilentWhenRulesWork keeps startup quiet for the
37 // configs that are already correct.
38 func TestUnmatchableRuleNoticeSilentWhenRulesWork(t *testing.T) {
39 sink := &captureSink{}
40 emitUnmatchableRuleNotice(sink, []string{"Bash(git status:*)"}, nil, []string{"edit_file"})
41 if len(sink.events) != 0 {
42 t.Fatalf("a correct config emitted %d events: %+v", len(sink.events), sink.events)
43 }
44 }
45
46 // TestUnmatchableRuleNoticeNamesAnUnclosedParenthesis keeps the warning
47 // diagnostic: an entry that only lacks its ")" should be described as that,
48 // not as a rule that names no tool.
49 func TestUnmatchableRuleNoticeNamesAnUnclosedParenthesis(t *testing.T) {
50 sink := &captureSink{}
51 emitUnmatchableRuleNotice(sink, nil, nil, []string{"Bash(git status:*"})
52 if len(sink.events) != 1 {
53 t.Fatalf("got %d events, want 1", len(sink.events))
54 }
55 detail := sink.events[0].Detail
56 if !strings.Contains(detail, "without a closing") {
57 t.Errorf("detail does not name the missing parenthesis: %q", detail)
58 }
59 if !strings.Contains(detail, `write Bash(git status:*) instead`) {
60 t.Errorf("detail does not carry the repaired rule: %q", detail)
61 }
62 if strings.Contains(detail, "Bash(Bash(") {
63 t.Errorf("detail wraps the entry in a second Bash(...): %q", detail)
64 }
65 }
66
66 lines GO