Skip to main content

kcode_k1_daemon_lib_testkit/
lib.rs

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