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.6\"",
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.1\"",
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-ktool-set-launch-node = \"0.1.1\"",
29 "kcode-k1-ktool-social = \"0.1.1\"",
30 "kcode-k1-launch-nodes = \"0.4.0\"",
31 "kcode-k1-peering = \"0.3.1\"",
32 "kcode-k1-rust-code-ktool-service = \"0.1.0\"",
33 "kcode-k1-rust-coding = \"0.2.1\"",
34 "kcode-k1-rust-projection = \"0.2.0\"",
35 "kcode-k1-txn-ordering = \"0.5.1\"",
36 "kcode-k1-web-code-ktool-service = \"0.1.2\"",
37 "kcode-k1-web-podman = \"0.1.2\"",
38 "kcode-speaker-v3-analysis = \"0.3.5\"",
39];
40
41const OBSOLETE_LINES: &[&str] = &[
42 "kcode-k1-access = \"0.6.1\"",
43 "kcode-k1-access-full-audio = \"0.9.1\"",
44 "kcode-k1-access-full-audio = \"0.9.4\"",
45 "kcode-k1-access-launch-nodes = \"0.2.0\"",
46 "kcode-k1-audio-classification = \"0.5.9\"",
47 "kcode-k1-audio-classification = \"0.5.10\"",
48 "kcode-k1-chat-service = \"0.3.0\"",
49 "kcode-k1-chat-service = \"0.6.0\"",
50 "kcode-k1-chat-service = \"0.7.0\"",
51 "kcode-k1-chat-service = \"0.8.0\"",
52 "kcode-k1-chat-service = \"0.9.0\"",
53 "kcode-k1-chat-service = \"0.10.0\"",
54 "kcode-k1-chat-service = \"0.10.1\"",
55 "kcode-k1-chat-service = \"0.10.2\"",
56 "kcode-k1-chat-service = \"0.10.3\"",
57 "kcode-k1-chat-service = \"0.10.4\"",
58 "kcode-k1-chat-service = \"0.10.5\"",
59 "kcode-k1-codex-adapter = \"0.5.0\"",
60 "kcode-k1-codex-adapter = \"0.5.1\"",
61 "kcode-k1-codex-websearch = \"0.1.0\"",
62 "kcode-k1-daemon-http-boundary = \"0.1.0\"",
63 "kcode-k1-daemon-provider-config = \"0.1.4\"",
64 "kcode-k1-daemon-provider-config = \"0.1.5\"",
65 "kcode-k1-daemon-web-startup = \"0.1.0\"",
66 "kcode-k1-full-audio = \"0.3.7\"",
67 "kcode-k1-http-audio = \"0.3.0\"",
68 "kcode-k1-http-audio = \"0.3.1\"",
69 "kcode-k1-http-chat = \"0.2.0\"",
70 "kcode-k1-http-chat = \"0.5.0\"",
71 "kcode-k1-http-chat = \"0.6.0\"",
72 "kcode-k1-http-chat = \"0.6.1\"",
73 "kcode-k1-http-chat = \"0.7.0\"",
74 "kcode-k1-http-chat = \"0.7.1\"",
75 "kcode-k1-http-launch-nodes = \"0.2.0\"",
76 "kcode-k1-ktool-set-launch-node = \"0.1.0\"",
77 "kcode-k1-ktool-social = \"0.1.0\"",
78 "kcode-k1-launch-nodes = \"0.3.0\"",
79 "kcode-k1-peering = \"0.3.0\"",
80 "kcode-k1-web-code-ktool-service = \"0.1.1\"",
81 "kcode-k1-web-http = \"0.1.0\"",
82];
83
84const REQUIRED_SOURCE: &[&str] = &[
85 "AudioClassification::open(",
86 ".shutdown()",
87 "kcode_k1_http_audio::authenticated_routes",
88 "SocialKtools::new(",
89 "SetLaunchNodeKtool::new(",
90 "let web = open(",
91 "web.router()",
92 "web.projection()",
93 "RustCodeKtoolService::new(",
94 "K1WebCodeKtoolService::new(",
95 "K1ChatService::open_with_social_and_set_launch_node_and_rust_code_and_web_code(",
96];
97
98const PROHIBITED_SOURCE: &[&str] = &[
99 "audio-classification-v2",
100 "http_audio_artifacts",
101 "retry_fragment",
102 "artifact_route",
103 "open_router(",
104 "let chat = K1ChatService::open(",
105 "K1ChatService::open_with_social(",
106 "K1ChatService::open_with_social_and_set_launch_node(",
107];
108
109pub fn verify_manifest(manifest: &str) {
110 for required in REQUIRED_LINES {
111 assert!(
112 manifest.lines().any(|line| line == *required),
113 "missing required manifest line: {required}"
114 );
115 }
116 for obsolete in OBSOLETE_LINES {
117 assert!(
118 !manifest.lines().any(|line| line == *obsolete),
119 "obsolete manifest line: {obsolete}"
120 );
121 }
122 assert!(
123 !manifest.lines().any(|line| line
124 .trim_start()
125 .starts_with("kcode-k1-http-audio-artifacts")),
126 "artifact manifest selection"
127 );
128 assert!(
129 !manifest.lines().any(|line| line.contains(" = \"=")),
130 "manifest contains an exact internal pin"
131 );
132}
133
134pub fn verify_source(source: &str) {
135 for required in REQUIRED_SOURCE {
136 assert!(
137 source.contains(required),
138 "missing required source evidence: {required}"
139 );
140 }
141 for prohibited in PROHIBITED_SOURCE {
142 assert!(
143 !source.contains(prohibited),
144 "prohibited source token: {prohibited}"
145 );
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 fn good_manifest() -> String {
154 REQUIRED_LINES.join("\n")
155 }
156
157 fn good_source() -> &'static str {
158 "AudioClassification::open(\nservice.shutdown()\nkcode_k1_http_audio::authenticated_routes\nSocialKtools::new(\nSetLaunchNodeKtool::new(\nlet web = open(\nweb.router()\nweb.projection()\nRustCodeKtoolService::new(\nK1WebCodeKtoolService::new(\nK1ChatService::open_with_social_and_set_launch_node_and_rust_code_and_web_code("
159 }
160
161 #[test]
162 fn accepts_current_inputs() {
163 verify_manifest(&good_manifest());
164 verify_source(good_source());
165 }
166
167 #[test]
168 fn rejects_missing_audio_requirements() {
169 for line in [
170 "kcode-k1-access-full-audio = \"0.10.0\"",
171 "kcode-k1-audio-classification = \"0.6.0\"",
172 "kcode-k1-full-audio = \"0.4.0\"",
173 "kcode-k1-http-audio = \"0.4.0\"",
174 "kcode-k1-peering = \"0.3.1\"",
175 "kcode-speaker-v3-analysis = \"0.3.5\"",
176 ] {
177 assert!(
178 std::panic::catch_unwind(|| verify_manifest(&good_manifest().replace(line, "")))
179 .is_err()
180 );
181 }
182 }
183
184 #[test]
185 fn rejects_missing_code_composition_requirements() {
186 for line in [
187 "kcode-k1-chat-service = \"0.10.6\"",
188 "kcode-k1-daemon-web-startup = \"0.1.1\"",
189 "kcode-k1-rust-code-ktool-service = \"0.1.0\"",
190 "kcode-k1-rust-coding = \"0.2.1\"",
191 "kcode-k1-rust-projection = \"0.2.0\"",
192 "kcode-k1-web-code-ktool-service = \"0.1.2\"",
193 "kcode-k1-web-podman = \"0.1.2\"",
194 ] {
195 assert!(
196 std::panic::catch_unwind(|| verify_manifest(&good_manifest().replace(line, "")))
197 .is_err()
198 );
199 }
200 }
201
202 #[test]
203 fn rejects_missing_source_evidence() {
204 for evidence in REQUIRED_SOURCE {
205 assert!(
206 std::panic::catch_unwind(|| verify_source(&good_source().replace(evidence, "")))
207 .is_err()
208 );
209 }
210 }
211
212 #[test]
213 fn rejects_prohibited_source_tokens() {
214 for token in PROHIBITED_SOURCE {
215 assert!(
216 std::panic::catch_unwind(|| verify_source(&format!("{} {token}", good_source())))
217 .is_err()
218 );
219 }
220 }
221
222 #[test]
223 fn rejects_artifact_package_selection() {
224 assert!(
225 std::panic::catch_unwind(|| verify_manifest(&format!(
226 "{}\n kcode-k1-http-audio-artifacts = \"0.4.0\"",
227 good_manifest()
228 )))
229 .is_err()
230 );
231 }
232
233 #[test]
234 fn rejects_old_audio_and_displaced_composition_lines() {
235 for line in [
236 "kcode-k1-audio-classification = \"0.5.10\"",
237 "kcode-k1-full-audio = \"0.3.7\"",
238 "kcode-k1-access-full-audio = \"0.9.4\"",
239 "kcode-k1-http-audio = \"0.3.1\"",
240 "kcode-k1-peering = \"0.3.0\"",
241 "kcode-k1-chat-service = \"0.10.5\"",
242 "kcode-k1-daemon-web-startup = \"0.1.0\"",
243 "kcode-k1-web-code-ktool-service = \"0.1.1\"",
244 ] {
245 assert!(
246 std::panic::catch_unwind(|| verify_manifest(&format!(
247 "{}\n{line}",
248 good_manifest()
249 )))
250 .is_err()
251 );
252 }
253 }
254
255 #[test]
256 fn full_chat_composition_does_not_match_former_names() {
257 let current =
258 "K1ChatService::open_with_social_and_set_launch_node_and_rust_code_and_web_code(";
259 assert!(!current.contains("K1ChatService::open_with_social("));
260 assert!(!current.contains("K1ChatService::open_with_social_and_set_launch_node("));
261 }
262
263 #[test]
264 fn rejects_exact_internal_pin() {
265 assert!(
266 std::panic::catch_unwind(|| verify_manifest(&format!(
267 "{}\nkcode-k1-peering = \"=0.3.1\"",
268 good_manifest()
269 )))
270 .is_err()
271 );
272 }
273
274 #[test]
275 fn rejects_unrelated_obsolete_line() {
276 assert!(
277 std::panic::catch_unwind(|| verify_manifest(&format!(
278 "{}\nkcode-k1-http-chat = \"0.7.1\"",
279 good_manifest()
280 )))
281 .is_err()
282 );
283 }
284}