tinyrelayfile
tinyrelay/internal/daemon/custom_views_validation_test.go/

internal/daemon/custom_views_validation_test.go raw
1package daemon
2
3import (
4 "context"
5 "encoding/base64"
6 "encoding/binary"
7 "hash/crc32"
8 "net/http"
9 "strings"
10 "testing"
11 "time"
12)
13
14func TestCustomViewTransformCountsSuccessfulBlocks(t *testing.T) {
15 for _, tc := range []struct {
16 name string
17 artifacts []map[string]any
18 status string
19 stored int
20 failures int
21 retries int
22 }{
23 {"complete", []map[string]any{svgArtifact(0), svgArtifact(1)}, "ok", 2, 0, 0},
24 {"partial", []map[string]any{svgArtifact(0)}, "partial", 1, 0, 0},
25 {"duplicate", []map[string]any{svgArtifact(0), svgArtifact(0)}, "partial", 1, 0, 0},
26 {"invalid", []map[string]any{{"block": 0, "type": "image/png", "body": "invalid"}}, "no valid artifacts", 0, 1, 1},
27 {"empty", nil, "no valid artifacts", 0, 1, 1},
28 } {
29 t.Run(tc.name, func(t *testing.T) {
30 tenant, server, _ := viewTenant(t, []int{1}, nil)
31 server.answer(http.StatusOK, tc.artifacts...)
32 note := signedEvent(t, testOwnerSecret, 1, time.Now().Unix(), nil, "```mermaid\nA\n```\n\n```mermaid\nB\n```")
33 if err := publishAs(t, tenant, note); err != nil {
34 t.Fatal(err)
35 }
36 runPendingView(t, tenant, "diagrams", note.ID)
37 var status string
38 var failures, stored int
39 if err := tenant.store.DB().QueryRowContext(context.Background(), `SELECT last_status,failures FROM custom_views WHERE name='diagrams'`).Scan(&status, &failures); err != nil {
40 t.Fatal(err)
41 }
42 if err := tenant.store.DB().QueryRowContext(context.Background(), `SELECT count(*) FROM custom_view_artifacts`).Scan(&stored); err != nil {
43 t.Fatal(err)
44 }
45 retries := len(pendingViewIntents(t, tenant, "diagrams", note.ID))
46 if status != tc.status || stored != tc.stored || failures != tc.failures || retries != tc.retries {
47 t.Fatalf("status=%q stored=%d failures=%d retries=%d; want %q %d %d %d", status, stored, failures, retries, tc.status, tc.stored, tc.failures, tc.retries)
48 }
49 })
50 }
51}
52
53func TestCustomViewInvalidArtifactsRetryThenPause(t *testing.T) {
54 tenant, server, _ := viewTenant(t, []int{1}, nil)
55 server.answer(http.StatusOK, map[string]any{"block": 0, "type": "image/svg+xml", "body": "<svg><script/></svg>"})
56 note := signedEvent(t, testOwnerSecret, 1, time.Now().Unix(), nil, "```mermaid\nA\n```")
57 if err := publishAs(t, tenant, note); err != nil {
58 t.Fatal(err)
59 }
60 for range 3 {
61 runPendingView(t, tenant, "diagrams", note.ID)
62 }
63 if got := pendingViewIntents(t, tenant, "diagrams", note.ID); len(got) != 0 {
64 t.Fatalf("invalid artifacts exceeded retry limit: %+v", got)
65 }
66 ctx := context.Background()
67 if _, err := tenant.store.DB().ExecContext(ctx, `UPDATE custom_views SET failures=19 WHERE name='diagrams'`); err != nil {
68 t.Fatal(err)
69 }
70 other := signedEvent(t, testOwnerSecret, 1, time.Now().Unix(), nil, "```mermaid\nB\n```")
71 if err := publishAs(t, tenant, other); err != nil {
72 t.Fatal(err)
73 }
74 runPendingView(t, tenant, "diagrams", other.ID)
75 var failures, enabled int
76 var status string
77 if err := tenant.store.DB().QueryRowContext(ctx, `SELECT failures,enabled,last_status FROM custom_views WHERE name='diagrams'`).Scan(&failures, &enabled, &status); err != nil {
78 t.Fatal(err)
79 }
80 if failures != 20 || enabled != 0 || status != "paused after 20 failures: no valid artifacts" {
81 t.Fatalf("failures=%d enabled=%d status=%q", failures, enabled, status)
82 }
83}
84
85func TestCustomViewSVGReferenceBoundaries(t *testing.T) {
86 for _, tc := range []struct {
87 name, body string
88 valid bool
89 }{
90 {"XML declaration", `<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg"/>`, true},
91 {"literal text", `<svg><text>@import url(example)</text></svg>`, true},
92 {"CSS comment", `<svg><style>/* colors */ .x{fill:url(#paint)}</style></svg>`, true},
93 {"style chunks", `<svg><style>.x{fill:u<![CDATA[rl]]>(https://example.com/x)}</style></svg>`, false},
94 {"nested style", `<svg><style>.x{fill:url(https://example.com/x)}<style/></style></svg>`, false},
95 {"XML base", `<svg xml:base="https://example.com/"><use href="#secret"/></svg>`, false},
96 {"attribute import", `<svg style="@import 'https://example.com/a.css'"/>`, false},
97 {"other namespace", `<svg xmlns="http://www.w3.org/1999/xhtml"/>`, false},
98 {"stylesheet instruction", `<?xml-stylesheet href="https://example.com/a.css"?><svg/>`, false},
99 } {
100 t.Run(tc.name, func(t *testing.T) {
101 if err := checkSVG(tc.body); (err == nil) != tc.valid {
102 t.Fatalf("valid=%v, error=%v", tc.valid, err)
103 }
104 })
105 }
106}
107
108func TestCustomViewRejectsOversizedPNGDimensions(t *testing.T) {
109 image := []byte(testPNGRaw)
110 binary.BigEndian.PutUint32(image[16:20], 8192)
111 binary.BigEndian.PutUint32(image[20:24], 8192)
112 binary.BigEndian.PutUint32(image[29:33], crc32.ChecksumIEEE(image[12:29]))
113 _, err := checkArtifact(viewArtifact{Type: "image/png", Body: base64.StdEncoding.EncodeToString(image)}, 1024)
114 if err == nil || !strings.Contains(err.Error(), "dimensions") {
115 t.Fatalf("oversized PNG error=%v", err)
116 }
117}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs