The review of 2026-10-09 (H4): a link's code shown on the desk stayed in dunst's history, which node-notifier.history serves to every caller of the mesh's verbs, agents among them; and a code sent to a paused notifier is held and shown later, to whoever is then at the screen. send now takes secret (transient, category mesh.secret) and transient; the dunstrc's rules keep both out of the history, and history leaves out any that got there. The pause, read from dunst itself, is said as the event paused at start, on change and every two minutes, for the desk to read.
89 lines
3.2 KiB
Go
89 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// A notification carrying something shown once — a link's code — is sent transient and in the category
|
|
// mesh.secret, whatever category the caller names (the review of 2026-10-09, H4): the dunstrc's rules keep
|
|
// both out of dunst's history, and the history verb leaves out any that got there anyway, so no agent reads
|
|
// the code back through node-notifier.history.
|
|
func TestASecretNotificationIsTransientAndKeptOutOfTheHistory(t *testing.T) {
|
|
withBus(t)
|
|
bin := fakeBinaries(t, map[string]string{"notify-send": `for a in "$@"; do printf '[%s]' "$a"; done > "$LOG"; echo 42`})
|
|
t.Setenv("LOG", filepath.Join(bin, "log"))
|
|
n, err := notificationOf(map[string]any{"summary": "Link code", "body": "123 456", "secret": true, "category": "email"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := Send(n); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
asked, _ := os.ReadFile(filepath.Join(bin, "log"))
|
|
for _, want := range []string{"[--transient]", "[--category=" + SecretCategory + "]"} {
|
|
if !strings.Contains(string(asked), want) {
|
|
t.Errorf("notify-send was not asked %s: %s", want, asked)
|
|
}
|
|
}
|
|
if strings.Contains(string(asked), "--category=email") {
|
|
t.Error("a secret notification kept the caller's category")
|
|
}
|
|
if n, err := notificationOf(map[string]any{"summary": "x", "transient": true}); err != nil || !n.Transient || n.Secret {
|
|
t.Errorf("transient alone: %+v %v", n, err)
|
|
}
|
|
|
|
// The history leaves a secret one out, and says how many it left out.
|
|
withSecret := strings.Replace(history, `"category":{"type":"s","data":"device"}`,
|
|
`"category":{"type":"s","data":"`+SecretCategory+`"}`, 1)
|
|
got, err := parseHistory(withSecret, 200_000_000, 20)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got.Notifications) != 1 || got.Notifications[0].ID != 7 || got.Total != 1 || got.Withheld != 1 {
|
|
t.Fatalf("the history showed a secret notification: %+v", got)
|
|
}
|
|
|
|
// The decided file holds the rules that keep them out of dunst's own history.
|
|
rc, err := os.ReadFile(filepath.Join("..", "..", "files", "dunstrc"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{"category = \"" + SecretCategory + "\"", "match_transient = yes", "history_ignore = yes"} {
|
|
if !strings.Contains(string(rc), want) {
|
|
t.Errorf("dunstrc does not say %q", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Whether notifications are paused is said as the event `paused` {paused, machine}: at once, on every change,
|
|
// and again every PausedEvery, so the desk knows a link's code would not be seen (C4); nothing is said while
|
|
// dunst cannot be asked.
|
|
func TestWhetherPausedIsSaidOnChangeAndEveryFewMinutes(t *testing.T) {
|
|
var said []bool
|
|
paused, fails := false, false
|
|
w := pauseWatch{
|
|
isPaused: func() (bool, error) {
|
|
if fails {
|
|
return false, os.ErrNotExist
|
|
}
|
|
return paused, nil
|
|
},
|
|
say: func(p bool) error { said = append(said, p); return nil },
|
|
}
|
|
at := time.Date(2026, 10, 9, 12, 0, 0, 0, time.UTC)
|
|
w.step(at)
|
|
w.step(at.Add(5 * time.Second))
|
|
paused = true
|
|
w.step(at.Add(10 * time.Second))
|
|
w.step(at.Add(10*time.Second + PausedEvery))
|
|
fails = true
|
|
w.step(at.Add(10*time.Second + 3*PausedEvery))
|
|
if len(said) != 3 || said[0] || !said[1] || !said[2] {
|
|
t.Fatalf("said %v", said)
|
|
}
|
|
}
|