kcode_k1_daemon_lib_testkit/
lib.rs1#![forbid(unsafe_code)]
2
3const REQUIRED_LINES: &[&str] = &[
4 "kcode-k1-access = \"0.6.2\"",
5 "kcode-k1-access-audio-classifier = \"0.1.0\"",
6 "kcode-k1-access-full-audio = \"0.10.0\"",
7 "kcode-k1-access-launch-nodes = \"0.2.2\"",
8 "kcode-k1-access-persons = \"0.3.0\"",
9 "kcode-k1-access-profiles = \"0.6.2\"",
10 "kcode-k1-audio-classification = \"0.6.0\"",
11 "kcode-k1-audio-classifier = \"0.1.1\"",
12 "kcode-k1-authority-filters = \"0.2.0\"",
13 "kcode-k1-chat-service = \"0.10.1\"",
14 "kcode-k1-codex-adapter = \"0.5.3\"",
15 "kcode-k1-codex-websearch = \"0.2.0\"",
16 "kcode-k1-daemon-http-boundary = \"0.1.1\"",
17 "kcode-k1-daemon-provider-config = \"0.1.6\"",
18 "kcode-k1-daemon-web-startup = \"0.1.0\"",
19 "kcode-k1-full-audio = \"0.4.0\"",
20 "kcode-k1-http-access-context = \"0.2.0\"",
21 "kcode-k1-http-access-profile-presentation = \"0.1.0\"",
22 "kcode-k1-http-audio = \"0.4.0\"",
23 "kcode-k1-http-chat = \"0.7.2\"",
24 "kcode-k1-http-kmap = \"0.1.0\"",
25 "kcode-k1-http-launch-nodes = \"0.3.0\"",
26 "kcode-k1-http-people = \"0.9.0\"",
27 "kcode-k1-http-persons = \"0.3.0\"",
28 "kcode-k1-launch-nodes = \"0.4.0\"",
29 "kcode-k1-peering = \"0.3.1\"",
30 "kcode-k1-txn-ordering = \"0.5.1\"",
31 "kcode-speaker-v3-analysis = \"0.3.5\"",
32];
33
34const OBSOLETE_LINES: &[&str] = &[
35 "kcode-k1-access = \"0.6.1\"",
36 "kcode-k1-access-full-audio = \"0.9.1\"",
37 "kcode-k1-access-full-audio = \"0.9.4\"",
38 "kcode-k1-access-launch-nodes = \"0.2.0\"",
39 "kcode-k1-audio-classification = \"0.5.9\"",
40 "kcode-k1-audio-classification = \"0.5.10\"",
41 "kcode-k1-chat-service = \"0.3.0\"",
42 "kcode-k1-chat-service = \"0.6.0\"",
43 "kcode-k1-chat-service = \"0.7.0\"",
44 "kcode-k1-chat-service = \"0.8.0\"",
45 "kcode-k1-chat-service = \"0.9.0\"",
46 "kcode-k1-chat-service = \"0.10.0\"",
47 "kcode-k1-codex-adapter = \"0.5.0\"",
48 "kcode-k1-codex-adapter = \"0.5.1\"",
49 "kcode-k1-codex-websearch = \"0.1.0\"",
50 "kcode-k1-daemon-http-boundary = \"0.1.0\"",
51 "kcode-k1-daemon-provider-config = \"0.1.4\"",
52 "kcode-k1-daemon-provider-config = \"0.1.5\"",
53 "kcode-k1-full-audio = \"0.3.7\"",
54 "kcode-k1-http-audio = \"0.3.0\"",
55 "kcode-k1-http-audio = \"0.3.1\"",
56 "kcode-k1-http-chat = \"0.2.0\"",
57 "kcode-k1-http-chat = \"0.5.0\"",
58 "kcode-k1-http-chat = \"0.6.0\"",
59 "kcode-k1-http-chat = \"0.6.1\"",
60 "kcode-k1-http-chat = \"0.7.0\"",
61 "kcode-k1-http-chat = \"0.7.1\"",
62 "kcode-k1-http-launch-nodes = \"0.2.0\"",
63 "kcode-k1-launch-nodes = \"0.3.0\"",
64 "kcode-k1-peering = \"0.3.0\"",
65 "kcode-k1-web-http = \"0.1.0\"",
66];
67
68const REQUIRED_SOURCE: &[&str] = &[
69 "AudioClassification::open(",
70 ".shutdown()",
71 "kcode_k1_http_audio::authenticated_routes",
72];
73
74const PROHIBITED_SOURCE: &[&str] = &[
75 "audio-classification-v2",
76 "http_audio_artifacts",
77 "retry_fragment",
78 "artifact_route",
79];
80
81pub fn verify_manifest(manifest: &str) {
82 for required in REQUIRED_LINES {
83 assert!(
84 manifest.lines().any(|line| line == *required),
85 "missing required manifest line: {required}"
86 );
87 }
88 for obsolete in OBSOLETE_LINES {
89 assert!(
90 !manifest.lines().any(|line| line == *obsolete),
91 "obsolete manifest line: {obsolete}"
92 );
93 }
94 assert!(
95 !manifest.lines().any(|line| line
96 .trim_start()
97 .starts_with("kcode-k1-http-audio-artifacts")),
98 "artifact manifest selection"
99 );
100 assert!(
101 !manifest.lines().any(|line| line.contains(" = \"=")),
102 "manifest contains an exact internal pin"
103 );
104}
105
106pub fn verify_source(source: &str) {
107 for required in REQUIRED_SOURCE {
108 assert!(
109 source.contains(required),
110 "missing required source evidence: {required}"
111 );
112 }
113 for prohibited in PROHIBITED_SOURCE {
114 assert!(
115 !source.contains(prohibited),
116 "prohibited source token: {prohibited}"
117 );
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 fn good_manifest() -> String {
126 REQUIRED_LINES.join("\n")
127 }
128
129 fn good_source() -> &'static str {
130 "AudioClassification::open(\nservice.shutdown()\nkcode_k1_http_audio::authenticated_routes"
131 }
132
133 #[test]
134 fn accepts_current_inputs() {
135 verify_manifest(&good_manifest());
136 verify_source(good_source());
137 }
138
139 #[test]
140 fn rejects_missing_audio_requirements() {
141 for line in [
142 "kcode-k1-access-full-audio = \"0.10.0\"",
143 "kcode-k1-audio-classification = \"0.6.0\"",
144 "kcode-k1-full-audio = \"0.4.0\"",
145 "kcode-k1-http-audio = \"0.4.0\"",
146 "kcode-k1-peering = \"0.3.1\"",
147 "kcode-speaker-v3-analysis = \"0.3.5\"",
148 ] {
149 assert!(
150 std::panic::catch_unwind(|| verify_manifest(&good_manifest().replace(line, "")))
151 .is_err()
152 );
153 }
154 }
155
156 #[test]
157 fn rejects_missing_source_evidence() {
158 for evidence in REQUIRED_SOURCE {
159 assert!(
160 std::panic::catch_unwind(|| verify_source(&good_source().replace(evidence, "")))
161 .is_err()
162 );
163 }
164 }
165
166 #[test]
167 fn rejects_prohibited_source_tokens() {
168 for token in PROHIBITED_SOURCE {
169 assert!(
170 std::panic::catch_unwind(|| verify_source(&format!("{} {token}", good_source())))
171 .is_err()
172 );
173 }
174 }
175
176 #[test]
177 fn rejects_artifact_package_selection() {
178 assert!(
179 std::panic::catch_unwind(|| verify_manifest(&format!(
180 "{}\n kcode-k1-http-audio-artifacts = \"0.4.0\"",
181 good_manifest()
182 )))
183 .is_err()
184 );
185 }
186
187 #[test]
188 fn rejects_old_audio_lines() {
189 for line in [
190 "kcode-k1-audio-classification = \"0.5.10\"",
191 "kcode-k1-full-audio = \"0.3.7\"",
192 "kcode-k1-access-full-audio = \"0.9.4\"",
193 "kcode-k1-http-audio = \"0.3.1\"",
194 "kcode-k1-peering = \"0.3.0\"",
195 ] {
196 assert!(
197 std::panic::catch_unwind(|| verify_manifest(&format!(
198 "{}\n{line}",
199 good_manifest()
200 )))
201 .is_err()
202 );
203 }
204 }
205
206 #[test]
207 fn rejects_exact_internal_pin() {
208 assert!(
209 std::panic::catch_unwind(|| verify_manifest(&format!(
210 "{}\nkcode-k1-peering = \"=0.3.1\"",
211 good_manifest()
212 )))
213 .is_err()
214 );
215 }
216
217 #[test]
218 fn rejects_unrelated_obsolete_line() {
219 assert!(
220 std::panic::catch_unwind(|| verify_manifest(&format!(
221 "{}\nkcode-k1-http-chat = \"0.7.1\"",
222 good_manifest()
223 )))
224 .is_err()
225 );
226 }
227}