AtlatestRepositorycourier

courier / tree / testtest-telegram.sgl

1(import (sigil test)
2 (sigil string)
3 (sigil math)
4 (sigil json)
5 (courier telegram)
6 (courier relay))
7
8;; ============================================================
9;; Media type detection by extension
10;; ============================================================
12(test-group "path-media-type"
13 (test "png is photo"
14 (assert-equal 'photo (path-media-type "/tmp/screenshot.png")))
16 (test "jpg is photo"
17 (assert-equal 'photo (path-media-type "/tmp/photo.jpg")))
19 (test "jpeg is photo"
20 (assert-equal 'photo (path-media-type "image.jpeg")))
22 (test "uppercase extension still detected"
23 ;; Extensions are downcased before comparison
24 (assert-equal 'photo (path-media-type "/tmp/IMG_001.JPG")))
26 (test "gif is photo"
27 (assert-equal 'photo (path-media-type "/tmp/sticker.gif")))
29 (test "webp is photo"
30 (assert-equal 'photo (path-media-type "/tmp/sticker.webp")))
32 (test "mp4 is video"
33 (assert-equal 'video (path-media-type "/tmp/recording.mp4")))
35 (test "mkv is video"
36 (assert-equal 'video (path-media-type "/tmp/clip.mkv")))
38 (test "mov is video"
39 (assert-equal 'video (path-media-type "/tmp/clip.mov")))
41 (test "webm is video"
42 (assert-equal 'video (path-media-type "/tmp/clip.webm")))
44 (test "pdf is document"
45 (assert-equal 'document (path-media-type "/tmp/report.pdf")))
47 (test "zip is document"
48 (assert-equal 'document (path-media-type "/tmp/bundle.zip")))
50 (test "no extension is document"
51 ;; Files without extensions are safest as documents — Telegram
52 ;; rejects sendPhoto/sendVideo when content type doesn't match.
53 (assert-equal 'document (path-media-type "/tmp/Makefile")))
55 (test "unknown extension is document"
56 (assert-equal 'document (path-media-type "/tmp/data.xyz"))))
58;; ============================================================
59;; Media-upload envelope shape (relay wire protocol)
60;; ============================================================
62(test-group "make-media-upload-envelope"
63 (test "minimal envelope has required fields"
64 (let* ((json (make-media-upload-envelope "/tmp/x.png"))
65 (env (json-decode json)))
66 (assert-equal "media-upload" (dict-ref env type:))
67 (assert-equal "worker" (dict-ref env sender:))
68 (assert-equal "/tmp/x.png" (dict-ref env path:))
69 (assert-false (dict-ref env to: #f))
70 (assert-false (dict-ref env caption: #f))
71 (assert-false (dict-ref env media-type: #f))))
73 (test "all optional fields round-trip"
74 (let* ((json (make-media-upload-envelope "/tmp/clip.mp4"
75 to: "999" caption: "hi" media-type: "video"))
76 (env (json-decode json)))
77 (assert-equal "/tmp/clip.mp4" (dict-ref env path:))
78 (assert-equal "999" (dict-ref env to:))
79 (assert-equal "hi" (dict-ref env caption:))
80 (assert-equal "video" (dict-ref env media-type:))))
82 (test "envelope is a single line of JSON"
83 ;; Relay wire protocol is newline-delimited; the envelope
84 ;; itself must not contain a newline.
85 (let ((json (make-media-upload-envelope "/tmp/a.gif" caption: "n")))
86 (assert-false (string-contains? json "\n")))))
88;; ============================================================
89;; format-size human-readable byte counts
90;; ============================================================
92(test-group "format-size"
93 (test "small files use bytes"
94 (assert-equal "0 B" (format-size 0))
95 (assert-equal "1023 B" (format-size 1023)))
97 (test "kilobyte range"
98 (assert-equal "1 KB" (format-size 1024))
99 (assert-equal "500 KB" (format-size (* 500 1024))))
101 (test "megabyte range with one decimal"
102 (assert-equal "1.0 MB" (format-size (* 1024 1024)))
103 ;; 2.5 MB exactly = 2621440 bytes; integer truncation gives "2.5 MB"
104 (assert-equal "2.5 MB" (format-size (quotient (* 5 1024 1024) 2)))))
106;; ============================================================
107;; Send-result strings: a caller must be able to tell delivery
108;; from non-delivery by reading the return value
109;; ============================================================
110;;
111;; The dry-run path used to return "Message sent." byte-for-byte, so every
112;; gagged send from 2026-07-06 to 2026-08-04 claimed a delivery it had not
113;; made -- and mimicked the silent-drop bug it was masking exactly, which
114;; made production observation of that bug impossible while the gag was on.
115;; These pin the property that failure cost us: the strings must be
116;; DISTINGUISHABLE. The end-to-end behaviour (what the MCP tool actually
117;; returns, and that a gagged send does not poison a later real one) is
118;; proved by repro/repro-single-poller.sh cases 5 and 6.
120(test-group "send-result strings"
121 (test "the dry-run string does not contain a bare 'Message sent'"
122 (assert-true (not (string-contains? *dry-run-not-sent-message*
123 "Message sent"))))
125 (test "the dry-run string does not begin with 'Message sent'"
126 (assert-true (not (string-starts-with? *dry-run-not-sent-message*
127 "Message sent"))))
129 (test "the dry-run string says plainly that nothing was delivered"
130 (assert-true (string-contains? *dry-run-not-sent-message* "NOT sent"))
131 (assert-true (string-contains? *dry-run-not-sent-message*
132 "COURIER_DISABLE_TELEGRAM_SEND")))
134 (test "the duplicate-suppressed string is not the plain success string"
135 (assert-true (not (string=? *duplicate-suppressed-message*
136 "Message sent.")))
137 (assert-true (string-contains? *duplicate-suppressed-message*
138 "duplicate suppressed")))
140 (test "the two non-delivery strings are distinct from each other"
141 (assert-true (not (string=? *dry-run-not-sent-message*
142 *duplicate-suppressed-message*)))))
144(run-tests)