1use crate::{
8 gen_audio_code_v0, gen_data_code_v0, gen_image_code_v0, gen_instance_code_v0, gen_iscc_code_v0,
9 gen_meta_code_v0, gen_mixed_code_v0, gen_text_code_v0, gen_video_code_v0,
10};
11
12const TEST_DATA: &str = include_str!("../tests/data.json");
14
15pub fn conformance_selftest() -> bool {
23 let data: serde_json::Value = match serde_json::from_str(TEST_DATA) {
24 Ok(v) => v,
25 Err(e) => {
26 eprintln!("FAILED: could not parse conformance data: {e}");
27 return false;
28 }
29 };
30
31 let mut passed = true;
32
33 passed &= run_meta_tests(&data);
34 passed &= run_text_tests(&data);
35 passed &= run_image_tests(&data);
36 passed &= run_audio_tests(&data);
37 passed &= run_video_tests(&data);
38 passed &= run_mixed_tests(&data);
39 passed &= run_data_tests(&data);
40 passed &= run_instance_tests(&data);
41 passed &= run_iscc_tests(&data);
42
43 passed
44}
45
46fn run_meta_tests(data: &serde_json::Value) -> bool {
48 let mut passed = true;
49 let section = &data["gen_meta_code_v0"];
50 let cases = match section.as_object() {
51 Some(c) => c,
52 None => {
53 eprintln!("FAILED: gen_meta_code_v0 section missing from conformance data");
54 return false;
55 }
56 };
57
58 for (tc_name, tc) in cases {
59 let func_name = "gen_meta_code_v0";
60 let result = (|| {
61 let inputs = tc["inputs"].as_array()?;
62 let name = inputs[0].as_str()?;
63 let desc_str = inputs[1].as_str()?;
64 let meta_val = &inputs[2];
65 let bits = inputs[3].as_u64()? as u32;
66
67 let meta_arg: Option<String> = match meta_val {
68 serde_json::Value::Null => None,
69 serde_json::Value::String(s) => Some(s.clone()),
70 serde_json::Value::Object(_) => serde_json::to_string(meta_val).ok(),
71 _ => None,
72 };
73
74 let desc = if desc_str.is_empty() {
75 None
76 } else {
77 Some(desc_str)
78 };
79
80 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
81 match gen_meta_code_v0(name, desc, meta_arg.as_deref(), bits) {
82 Ok(result) if result.iscc == expected_iscc => Some(true),
83 Ok(result) => {
84 eprintln!(
85 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
86 result.iscc
87 );
88 Some(false)
89 }
90 Err(e) => {
91 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
92 Some(false)
93 }
94 }
95 })();
96
97 match result {
98 Some(true) => {}
99 Some(false) => passed = false,
100 None => {
101 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
102 passed = false;
103 }
104 }
105 }
106 passed
107}
108
109fn run_text_tests(data: &serde_json::Value) -> bool {
111 let mut passed = true;
112 let section = &data["gen_text_code_v0"];
113 let cases = match section.as_object() {
114 Some(c) => c,
115 None => {
116 eprintln!("FAILED: gen_text_code_v0 section missing from conformance data");
117 return false;
118 }
119 };
120
121 for (tc_name, tc) in cases {
122 let func_name = "gen_text_code_v0";
123 let result = (|| {
124 let inputs = tc["inputs"].as_array()?;
125 let text = inputs[0].as_str()?;
126 let bits = inputs[1].as_u64()? as u32;
127 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
128
129 match gen_text_code_v0(text, bits) {
130 Ok(result) if result.iscc == expected_iscc => Some(true),
131 Ok(result) => {
132 eprintln!(
133 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
134 result.iscc
135 );
136 Some(false)
137 }
138 Err(e) => {
139 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
140 Some(false)
141 }
142 }
143 })();
144
145 match result {
146 Some(true) => {}
147 Some(false) => passed = false,
148 None => {
149 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
150 passed = false;
151 }
152 }
153 }
154 passed
155}
156
157fn run_image_tests(data: &serde_json::Value) -> bool {
159 let mut passed = true;
160 let section = &data["gen_image_code_v0"];
161 let cases = match section.as_object() {
162 Some(c) => c,
163 None => {
164 eprintln!("FAILED: gen_image_code_v0 section missing from conformance data");
165 return false;
166 }
167 };
168
169 for (tc_name, tc) in cases {
170 let func_name = "gen_image_code_v0";
171 let result = (|| {
172 let inputs = tc["inputs"].as_array()?;
173 let pixels_json = inputs[0].as_array()?;
174 let bits = inputs[1].as_u64()? as u32;
175 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
176
177 let pixels: Vec<u8> = pixels_json
178 .iter()
179 .map(|v| v.as_u64().map(|n| n as u8))
180 .collect::<Option<Vec<u8>>>()?;
181
182 match gen_image_code_v0(&pixels, bits) {
183 Ok(result) if result.iscc == expected_iscc => Some(true),
184 Ok(result) => {
185 eprintln!(
186 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
187 result.iscc
188 );
189 Some(false)
190 }
191 Err(e) => {
192 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
193 Some(false)
194 }
195 }
196 })();
197
198 match result {
199 Some(true) => {}
200 Some(false) => passed = false,
201 None => {
202 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
203 passed = false;
204 }
205 }
206 }
207 passed
208}
209
210fn run_audio_tests(data: &serde_json::Value) -> bool {
212 let mut passed = true;
213 let section = &data["gen_audio_code_v0"];
214 let cases = match section.as_object() {
215 Some(c) => c,
216 None => {
217 eprintln!("FAILED: gen_audio_code_v0 section missing from conformance data");
218 return false;
219 }
220 };
221
222 for (tc_name, tc) in cases {
223 let func_name = "gen_audio_code_v0";
224 let result = (|| {
225 let inputs = tc["inputs"].as_array()?;
226 let cv_json = inputs[0].as_array()?;
227 let bits = inputs[1].as_u64()? as u32;
228 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
229
230 let cv: Vec<i32> = cv_json
231 .iter()
232 .map(|v| v.as_i64().map(|n| n as i32))
233 .collect::<Option<Vec<i32>>>()?;
234
235 match gen_audio_code_v0(&cv, bits) {
236 Ok(result) if result.iscc == expected_iscc => Some(true),
237 Ok(result) => {
238 eprintln!(
239 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
240 result.iscc
241 );
242 Some(false)
243 }
244 Err(e) => {
245 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
246 Some(false)
247 }
248 }
249 })();
250
251 match result {
252 Some(true) => {}
253 Some(false) => passed = false,
254 None => {
255 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
256 passed = false;
257 }
258 }
259 }
260 passed
261}
262
263fn run_video_tests(data: &serde_json::Value) -> bool {
265 let mut passed = true;
266 let section = &data["gen_video_code_v0"];
267 let cases = match section.as_object() {
268 Some(c) => c,
269 None => {
270 eprintln!("FAILED: gen_video_code_v0 section missing from conformance data");
271 return false;
272 }
273 };
274
275 for (tc_name, tc) in cases {
276 let func_name = "gen_video_code_v0";
277 let result = (|| {
278 let inputs = tc["inputs"].as_array()?;
279 let frames_json = inputs[0].as_array()?;
280 let bits = inputs[1].as_u64()? as u32;
281 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
282
283 let frame_sigs: Option<Vec<Vec<i32>>> = frames_json
284 .iter()
285 .map(|frame| {
286 frame
287 .as_array()?
288 .iter()
289 .map(|v| v.as_i64().map(|n| n as i32))
290 .collect::<Option<Vec<i32>>>()
291 })
292 .collect();
293 let frame_sigs = frame_sigs?;
294
295 match gen_video_code_v0(&frame_sigs, bits) {
296 Ok(result) if result.iscc == expected_iscc => Some(true),
297 Ok(result) => {
298 eprintln!(
299 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
300 result.iscc
301 );
302 Some(false)
303 }
304 Err(e) => {
305 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
306 Some(false)
307 }
308 }
309 })();
310
311 match result {
312 Some(true) => {}
313 Some(false) => passed = false,
314 None => {
315 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
316 passed = false;
317 }
318 }
319 }
320 passed
321}
322
323fn run_mixed_tests(data: &serde_json::Value) -> bool {
325 let mut passed = true;
326 let section = &data["gen_mixed_code_v0"];
327 let cases = match section.as_object() {
328 Some(c) => c,
329 None => {
330 eprintln!("FAILED: gen_mixed_code_v0 section missing from conformance data");
331 return false;
332 }
333 };
334
335 for (tc_name, tc) in cases {
336 let func_name = "gen_mixed_code_v0";
337 let result = (|| {
338 let inputs = tc["inputs"].as_array()?;
339 let codes_json = inputs[0].as_array()?;
340 let bits = inputs[1].as_u64()? as u32;
341 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
342
343 let codes_owned: Vec<String> = codes_json
344 .iter()
345 .filter_map(|v| v.as_str().map(String::from))
346 .collect();
347 let codes: Vec<&str> = codes_owned.iter().map(|s| s.as_str()).collect();
348
349 match gen_mixed_code_v0(&codes, bits) {
350 Ok(result) if result.iscc == expected_iscc => Some(true),
351 Ok(result) => {
352 eprintln!(
353 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
354 result.iscc
355 );
356 Some(false)
357 }
358 Err(e) => {
359 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
360 Some(false)
361 }
362 }
363 })();
364
365 match result {
366 Some(true) => {}
367 Some(false) => passed = false,
368 None => {
369 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
370 passed = false;
371 }
372 }
373 }
374 passed
375}
376
377fn decode_stream(s: &str) -> Option<Vec<u8>> {
379 let hex_data = s.strip_prefix("stream:")?;
380 hex::decode(hex_data).ok()
381}
382
383fn run_data_tests(data: &serde_json::Value) -> bool {
385 let mut passed = true;
386 let section = &data["gen_data_code_v0"];
387 let cases = match section.as_object() {
388 Some(c) => c,
389 None => {
390 eprintln!("FAILED: gen_data_code_v0 section missing from conformance data");
391 return false;
392 }
393 };
394
395 for (tc_name, tc) in cases {
396 let func_name = "gen_data_code_v0";
397 let result = (|| {
398 let inputs = tc["inputs"].as_array()?;
399 let stream_str = inputs[0].as_str()?;
400 let bits = inputs[1].as_u64()? as u32;
401 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
402 let input_bytes = decode_stream(stream_str)?;
403
404 match gen_data_code_v0(&input_bytes, bits) {
405 Ok(result) if result.iscc == expected_iscc => Some(true),
406 Ok(result) => {
407 eprintln!(
408 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
409 result.iscc
410 );
411 Some(false)
412 }
413 Err(e) => {
414 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
415 Some(false)
416 }
417 }
418 })();
419
420 match result {
421 Some(true) => {}
422 Some(false) => passed = false,
423 None => {
424 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
425 passed = false;
426 }
427 }
428 }
429 passed
430}
431
432fn run_instance_tests(data: &serde_json::Value) -> bool {
434 let mut passed = true;
435 let section = &data["gen_instance_code_v0"];
436 let cases = match section.as_object() {
437 Some(c) => c,
438 None => {
439 eprintln!("FAILED: gen_instance_code_v0 section missing from conformance data");
440 return false;
441 }
442 };
443
444 for (tc_name, tc) in cases {
445 let func_name = "gen_instance_code_v0";
446 let result = (|| {
447 let inputs = tc["inputs"].as_array()?;
448 let stream_str = inputs[0].as_str()?;
449 let bits = inputs[1].as_u64()? as u32;
450 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
451 let input_bytes = decode_stream(stream_str)?;
452
453 match gen_instance_code_v0(&input_bytes, bits) {
454 Ok(result) if result.iscc == expected_iscc => Some(true),
455 Ok(result) => {
456 eprintln!(
457 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
458 result.iscc
459 );
460 Some(false)
461 }
462 Err(e) => {
463 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
464 Some(false)
465 }
466 }
467 })();
468
469 match result {
470 Some(true) => {}
471 Some(false) => passed = false,
472 None => {
473 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
474 passed = false;
475 }
476 }
477 }
478 passed
479}
480
481fn run_iscc_tests(data: &serde_json::Value) -> bool {
483 let mut passed = true;
484 let section = &data["gen_iscc_code_v0"];
485 let cases = match section.as_object() {
486 Some(c) => c,
487 None => {
488 eprintln!("FAILED: gen_iscc_code_v0 section missing from conformance data");
489 return false;
490 }
491 };
492
493 for (tc_name, tc) in cases {
494 let func_name = "gen_iscc_code_v0";
495 let result = (|| {
496 let inputs = tc["inputs"].as_array()?;
497 let codes_json = inputs[0].as_array()?;
498 let expected_iscc = tc["outputs"]["iscc"].as_str()?;
499
500 let codes_owned: Vec<String> = codes_json
501 .iter()
502 .filter_map(|v| v.as_str().map(String::from))
503 .collect();
504 let codes: Vec<&str> = codes_owned.iter().map(|s| s.as_str()).collect();
505
506 match gen_iscc_code_v0(&codes, false) {
508 Ok(result) if result.iscc == expected_iscc => Some(true),
509 Ok(result) => {
510 eprintln!(
511 "FAILED: {func_name}.{tc_name} — expected {expected_iscc}, got {}",
512 result.iscc
513 );
514 Some(false)
515 }
516 Err(e) => {
517 eprintln!("FAILED: {func_name}.{tc_name} — error: {e}");
518 Some(false)
519 }
520 }
521 })();
522
523 match result {
524 Some(true) => {}
525 Some(false) => passed = false,
526 None => {
527 eprintln!("FAILED: {func_name}.{tc_name} — could not parse test inputs");
528 passed = false;
529 }
530 }
531 }
532 passed
533}
534
535#[cfg(test)]
536mod tests {
537 use super::*;
538
539 #[test]
540 fn test_conformance_selftest_passes() {
541 assert!(conformance_selftest());
542 }
543}