- 1
#![allow( - 2
unused_imports, - 3
unused_variables, - 4
clippy::unwrap_used, - 5
clippy::expect_used, - 6
clippy::panic, - 7
clippy::indexing_slicing, - 8
clippy::redundant_closure, - 9
clippy::useless_conversion, - 10
clippy::bool_assert_comparison, - 11
clippy::collapsible_if, - 12
clippy::len_zero, - 13
clippy::needless_borrow, - 14
clippy::redundant_locals, - 15
clippy::too_many_lines, - 16
clippy::needless_pass_by_value, - 17
suspicious_double_ref_op - 18
)] - 19
- 20
//! Final-output deep verification: 10,000 scenarios (5,000 red-team content - 21
//! verification + 5,000 blue-team structural verification). - 22
//! Each input is rendered through all six surfaces and assertions check the - 23
//! actual output content — fallback preservation, coverage integrity, - 24
//! payload types, serialization round-trip, schema correctness, and - 25
//! surface-specific formatting. - 26
- 27
use std::collections::BTreeSet; - 28
use vak_delivery::AnswerDraft; - 29
use vak_delivery::DELIVERY_SCHEMA_VERSION; - 30
use vak_delivery::DeliveryContent; - 31
use vak_delivery::DeliveryJob; - 32
use vak_delivery::DeliveryKind; - 33
use vak_delivery::DeliveryPacket; - 34
use vak_delivery::DeliveryPayload; - 35
use vak_delivery::DeliveryPosture; - 36
use vak_delivery::DeliveryProfile; - 37
use vak_delivery::Markup; - 38
use vak_delivery::render; - 39
- 40
type Scenario = (String, Box<dyn FnOnce()>); - 41
- 42
fn tc<F: FnOnce() + 'static>(name: &str, f: F) -> Scenario { - 43
(name.to_string(), Box::new(f)) - 44
} - 45
- 46
fn run_fn(label: &str, scenarios: Vec<Scenario>) { - 47
let total = scenarios.len(); - 48
let mut passed = 0usize; - 49
let mut failures: Vec<String> = Vec::new(); - 50
for (name, test) in scenarios { - 51
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| test())) { - 52
Ok(()) => passed += 1, - 53
Err(_) => failures.push(name), - 54
} - 55
} - 56
assert_eq!( - 57
passed, total, - 58
"{label}: {passed}/{total} passed — failures: {failures:?}" - 59
); - 60
println!(" ✓ {label}: {total} scenarios passed"); - 61
} - 62
- 63
fn make_job(source: &str, markup: Markup, surface: &str) -> DeliveryJob { - 64
DeliveryJob { - 65
job_id: "test-job".into(), - 66
target: format!("{surface}:one"), - 67
kind: DeliveryKind::Assistant, - 68
content: DeliveryContent::Answer(AnswerDraft::from_markdown(source)), - 69
profile: DeliveryProfile { - 70
surface: surface.into(), - 71
markup, - 72
max_chars: None, - 73
supports_tables: true, - 74
supports_code_blocks: true, - 75
supports_links: true, - 76
supports_actions: false, - 77
template: None, - 78
posture: DeliveryPosture::default(), - 79
}, - 80
skill_registry: None, - 81
} - 82
} - 83
- 84
fn pt(packet: &DeliveryPacket) -> String { - 85
match &packet.payload { - 86
DeliveryPayload::Text(s) => s.clone(), - 87
DeliveryPayload::Structured(_) => packet.fallback_markdown.clone(), - 88
} - 89
} - 90
- 91
const SURFACES: &[(&str, Markup)] = &[ - 92
("telegram", Markup::TelegramHtml), - 93
("discord", Markup::DiscordMarkdown), - 94
("slack", Markup::SlackMrkdwn), - 95
("desktop", Markup::Markdown), - 96
("terminal", Markup::Plain), - 97
("admin", Markup::Plain), - 98
]; - 99
- 100
fn src_idx(base: &str, i: usize) -> String { - 101
format!("{}\n\n<!-- variant {} -->", base, i) - 102
} - 103
- 104
fn render_all(source: &str) -> Vec<(DeliveryPacket, &'static str)> { - 105
let mut results = Vec::new(); - 106
for (surface, markup) in SURFACES { - 107
let job = make_job(source, *markup, surface); - 108
let packet = render(&job).expect("render"); - 109
results.push((packet, *surface)); - 110
} - 111
results - 112
} - 113
- 114
fn is_h1(template: &str) -> bool { - 115
template.starts_with("# ") && !template.starts_with("## ") - 116
} - 117
- 118
#[test] - 119
fn content_headings_output() { - 120
let mut scenarios: Vec<Scenario> = vec![]; - 121
let templates: &[&str] = &[ - 122
"# Title", - 123
"## Subtitle", - 124
"###### H6", - 125
"# T\n## S\n### H", - 126
"# Title with **bold**", - 127
"# Multiple\n\n# Another", - 128
"# H\n\nSome text.", - 129
]; - 130
for i in 0..500 { - 131
let t = templates[i % templates.len()]; - 132
let source = src_idx(t, i); - 133
let i = i; - 134
scenarios.push(tc(&format!("heading_{i}"), move || { - 135
for (packet, surface) in render_all(&source) { - 136
let text = pt(&packet); - 137
let src = source.as_str(); - 138
match surface { - 139
"telegram" => { - 140
assert!(text.contains("<b>"), "telegram heading missing <b>: {src}"); - 141
} - 142
"discord" => { - 143
if is_h1(t) { - 144
assert!(text.contains("<b>"), "discord H1 missing <b>: {src}"); - 145
} else { - 146
assert!(!text.is_empty(), "discord H2+ empty: {src}"); - 147
} - 148
} - 149
"desktop" | "admin" => { - 150
assert!( - 151
text.contains("Title") - 152
|| text.contains("Subtitle") - 153
|| text.contains("H") - 154
|| src.contains('#'), - 155
"desktop heading text missing: {src}" - 156
); - 157
} - 158
_ => {} - 159
} - 160
} - 161
})); - 162
} - 163
run_fn("content_headings_output", scenarios); - 164
} - 165
- 166
#[test] - 167
fn content_code_blocks_output() { - 168
let mut scenarios: Vec<Scenario> = vec![]; - 169
let templates: &[&str] = &[ - 170
"```rust\nfn main() {}\n```", - 171
"```python\nprint('hello')\n```", - 172
"```\nplain code\n```", - 173
"```diff\n- removed\n+ added\n```", - 174
"```\n```\n```", - 175
r#"``` - 176
fn hello() { - 177
println!("hi"); - 178
} - 179
```"#, - 180
]; - 181
for i in 0..500 { - 182
let t = templates[i % templates.len()]; - 183
let source = src_idx(t, i); - 184
let i = i; - 185
scenarios.push(tc(&format!("code_{i}"), move || { - 186
for (packet, surface) in render_all(&source) { - 187
let text = pt(&packet); - 188
let src = source.as_str(); - 189
match surface { - 190
"telegram" => { - 191
assert!( - 192
text.contains("<pre>") || text.contains("<code>"), - 193
"telegram code missing <pre>/<code>: {src}" - 194
); - 195
} - 196
"desktop" | "discord" | "slack" => { - 197
assert!( - 198
text.contains("```") - 199
|| text.contains("code") - 200
|| text.contains("fn") - 201
|| text.contains("removed") - 202
|| text.contains("print"), - 203
"surface code missing content: {surface}: {src}" - 204
); - 205
} - 206
_ => { - 207
// Plain surfaces strip code fences; empty code blocks yield empty text - 208
if t.contains("fn") - 209
|| t.contains("removed") - 210
|| t.contains("print") - 211
|| t.contains("hello") - 212
{ - 213
assert!( - 214
!text.is_empty() - 215
&& (text.contains("code") - 216
|| text.contains("fn") - 217
|| text.contains("removed") - 218
|| text.contains("print") - 219
|| text.contains("hello")), - 220
"plain code missing content: {surface}: {src}" - 221
); - 222
} - 223
} - 224
} - 225
} - 226
})); - 227
} - 228
run_fn("content_code_blocks_output", scenarios); - 229
} - 230
- 231
#[test] - 232
fn content_lists_output() { - 233
let mut scenarios: Vec<Scenario> = vec![]; - 234
let templates: &[&str] = &[ - 235
"- a\n- b\n- c", - 236
"1. first\n2. second\n3. third", - 237
"- [ ] todo\n- [x] done", - 238
"1. one\n 1. nested", - 239
"* star list\n* second", - 240
"+ plus list\n+ second", - 241
]; - 242
for i in 0..500 { - 243
let t = templates[i % templates.len()]; - 244
let source = src_idx(t, i); - 245
let i = i; - 246
scenarios.push(tc(&format!("list_{i}"), move || { - 247
for (packet, surface) in render_all(&source) { - 248
let text = pt(&packet); - 249
let src = source.as_str(); - 250
assert!( - 251
text.contains("a") - 252
|| text.contains("first") - 253
|| text.contains("todo") - 254
|| text.contains("done"), - 255
"list content missing for {src}" - 256
); - 257
if src.contains("- [ ]") || src.contains("- [x]") { - 258
assert!( - 259
text.contains('☐') - 260
|| text.contains("[ ]") - 261
|| text.contains('☑') - 262
|| text.contains("[x]"), - 263
"task list marker missing for {surface}: {src}" - 264
); - 265
} - 266
} - 267
})); - 268
} - 269
run_fn("content_lists_output", scenarios); - 270
} - 271
- 272
#[test] - 273
fn content_emphasis_output() { - 274
let mut scenarios: Vec<Scenario> = vec![]; - 275
let templates: &[&str] = &[ - 276
"**bold**", - 277
"*italic*", - 278
"~~strikethrough~~", - 279
"**a** *b* ~~c~~", - 280
"`inline code`", - 281
"**bold** and *italic* and ~~strike~~", - 282
]; - 283
for i in 0..500 { - 284
let t = templates[i % templates.len()]; - 285
let source = src_idx(t, i); - 286
let i = i; - 287
scenarios.push(tc(&format!("emph_{i}"), move || { - 288
for (packet, surface) in render_all(&source) { - 289
let text = pt(&packet); - 290
let src = source.as_str(); - 291
if src.contains("**bold**") { - 292
match surface { - 293
"telegram" => { - 294
assert!(text.contains("<b>"), "bold missing <b> for telegram: {src}"); - 295
} - 296
_ => { - 297
assert!(!text.is_empty(), "bold empty: {src}"); - 298
} - 299
} - 300
} - 301
if src.contains("~~strikethrough~~") { - 302
match surface { - 303
"telegram" => { - 304
assert!( - 305
text.contains("<s>"), - 306
"strike missing <s> for telegram: {src}" - 307
); - 308
} - 309
_ => { - 310
assert!(!text.is_empty(), "strike empty: {src}"); - 311
} - 312
} - 313
} - 314
} - 315
})); - 316
} - 317
run_fn("content_emphasis_output", scenarios); - 318
} - 319
- 320
#[test] - 321
fn content_tables_output() { - 322
let mut scenarios: Vec<Scenario> = vec![]; - 323
let templates: &[&str] = &[ - 324
"| A | B |\n|---|---|\n| 1 | 2 |", - 325
"| a | b | c |\n|---|---|---|\n| 1 | 2 | 3 |", - 326
"| Col1 | Col2 |\n| --- | --- |\n| val1 | val2 |", - 327
"| single |\n|---|\n| val |", - 328
]; - 329
for i in 0..500 { - 330
let t = templates[i % templates.len()]; - 331
let source = src_idx(t, i); - 332
let i = i; - 333
scenarios.push(tc(&format!("table_{i}"), move || { - 334
for (packet, surface) in render_all(&source) { - 335
let text = pt(&packet); - 336
let src = source.as_str(); - 337
assert!( - 338
text.contains("1") - 339
|| text.contains("val1") - 340
|| text.contains("val") - 341
|| text.contains("A"), - 342
"table data missing for {surface}: {src}" - 343
); - 344
} - 345
})); - 346
} - 347
run_fn("content_tables_output", scenarios); - 348
} - 349
- 350
#[test] - 351
fn content_links_output() { - 352
let mut scenarios: Vec<Scenario> = vec![]; - 353
let templates: &[&str] = &[ - 354
"[label](https://example.com)", - 355
"[text](https://x.com \"Title\")", - 356
"", - 357
"[a](https://a.com)\n\n[b](https://b.com)", - 358
]; - 359
for i in 0..500 { - 360
let t = templates[i % templates.len()]; - 361
let source = src_idx(t, i); - 362
let i = i; - 363
scenarios.push(tc(&format!("link_{i}"), move || { - 364
for (packet, surface) in render_all(&source) { - 365
let text = pt(&packet); - 366
let src = source.as_str(); - 367
assert!( - 368
text.contains("label") - 369
|| text.contains("text") - 370
|| text.contains("alt") - 371
|| text.contains("https://") - 372
|| text.contains("example.com") - 373
|| text.contains("a.com"), - 374
"link text/url missing in {surface}: {src}" - 375
); - 376
} - 377
})); - 378
} - 379
run_fn("content_links_output", scenarios); - 380
} - 381
- 382
#[test] - 383
fn content_quotes_output() { - 384
let mut scenarios: Vec<Scenario> = vec![]; - 385
let templates: &[&str] = &[ - 386
"> quoted text", - 387
"> > nested quote", - 388
"> quote\n> second line", - 389
"# T\n\n> important", - 390
]; - 391
for i in 0..500 { - 392
let t = templates[i % templates.len()]; - 393
let source = src_idx(t, i); - 394
let i = i; - 395
scenarios.push(tc(&format!("quote_{i}"), move || { - 396
for (packet, surface) in render_all(&source) { - 397
let text = pt(&packet); - 398
let src = source.as_str(); - 399
if src.contains("quoted") || src.contains("important") { - 400
assert!( - 401
text.contains("quoted") - 402
|| text.contains("important") - 403
|| text.contains("<blockquote>"), - 404
"quote content missing for {surface}: {src}" - 405
); - 406
} else { - 407
assert!(!text.is_empty(), "quote empty for {surface}: {src}"); - 408
} - 409
} - 410
})); - 411
} - 412
run_fn("content_quotes_output", scenarios); - 413
} - 414
- 415
#[test] - 416
fn content_html_escaping_output() { - 417
let mut scenarios: Vec<Scenario> = vec![]; - 418
let templates: &[&str] = &[ - 419
"<script>alert(1)</script>", - 420
"<b>bold</b>", - 421
"<img src=x onerror=alert(1)>", - 422
"Text < > & ", - 423
"<iframe src=javascript:alert(1)>", - 424
"<div onclick=alert(1)>x</div>", - 425
]; - 426
for i in 0..500 { - 427
let t = templates[i % templates.len()]; - 428
let source = src_idx(t, i); - 429
let i = i; - 430
scenarios.push(tc(&format!("escape_{i}"), move || { - 431
let tg_packet = - 432
render(&make_job(&source, Markup::TelegramHtml, "telegram")).expect("render"); - 433
let tg_text = pt(&tg_packet); - 434
assert!( - 435
!tg_text.contains("<script"), - 436
"script tag not escaped: {source}" - 437
); - 438
assert!(!tg_text.contains("<iframe"), "iframe not escaped: {source}"); - 439
assert!(!tg_text.contains("<img"), "img not escaped: {source}"); - 440
assert!(!tg_text.contains("<div"), "div not escaped: {source}"); - 441
for (packet, _) in render_all(&source) { - 442
let _ = pt(&packet); - 443
} - 444
})); - 445
} - 446
run_fn("content_html_escaping_output", scenarios); - 447
} - 448
- 449
#[test] - 450
fn content_spoilers_output() { - 451
let mut scenarios: Vec<Scenario> = vec![]; - 452
let templates: &[&str] = &[ - 453
"||hidden||", - 454
"text ||spoiler|| more", - 455
"||multi\nline\nspoiler||", - 456
"# Title\n\n||spoiler||", - 457
"**bold** ||spoiler|| end", - 458
"||a|| ||b|| ||c||", - 459
]; - 460
for i in 0..500 { - 461
let t = templates[i % templates.len()]; - 462
let source = src_idx(t, i); - 463
let i = i; - 464
scenarios.push(tc(&format!("spoiler_{i}"), move || { - 465
let tg = render(&make_job(&source, Markup::TelegramHtml, "telegram")).expect("render"); - 466
let tg_text = pt(&tg); - 467
if !t.contains('\n') || t.lines().count() == 1 { - 468
assert!( - 469
tg_text.contains("<tg-spoiler>"), - 470
"telegram spoiler missing <tg-spoiler>: {source}" - 471
); - 472
} - 473
assert!( - 474
tg_text.contains("hidden") - 475
|| tg_text.contains("spoiler") - 476
|| tg_text.contains("tg-spoiler"), - 477
"spoiler content missing: {source}" - 478
); - 479
})); - 480
} - 481
run_fn("content_spoilers_output", scenarios); - 482
} - 483
- 484
#[test] - 485
fn content_mixed_structures_output() { - 486
let mut scenarios: Vec<Scenario> = vec![]; - 487
let templates: &[&str] = &[ - 488
"# Title\n\n**bold** *italic* ~~strike~~\n\n- item 1\n- item 2\n\n```rust\ncode\n```\n\n> quote\n\n| a | b |\n|---|---|\n| 1 | 2 |", - 489
"||spoiler||\n\ninline **bold** ||another|| end", - 490
"- [ ] todo\n- [x] done\n\n# H\n\n> **bold** quote", - 491
"", - 492
"plain text only", - 493
"| a | b | c |\n|---|---|---|\n| 1 | 2 | 3 |", - 494
"```python\nprint('hello')\n```\n\nMore text.", - 495
"# H1\n## H2\n### H3\n#### H4\n##### H5\n###### H6", - 496
"1. first\n2. second\n3. third\n\n- a\n - b\n - c", - 497
"Code `inline` and **bold** in same paragraph.", - 498
"# T\n\n- item 1\n- [x] done\n\n> quote\n\n| a | b |\n|---|---|\n| 1 | 2 |", - 499
r#"``` - 500
fn hello() { - 501
println!("hi"); - 502
} - 503
``` - 504
- 505
> **Important** quote with ||spoiler||"#, - 506
]; - 507
for i in 0..500 { - 508
let t = templates[i % templates.len()]; - 509
let source = src_idx(t, i); - 510
let i = i; - 511
scenarios.push(tc(&format!("mixed_{i}"), move || { - 512
for (packet, surface) in render_all(&source) { - 513
let src = source.as_str(); - 514
assert_eq!( - 515
packet.fallback_markdown, src, - 516
"fallback not preserved on {surface}: {src}" - 517
); - 518
assert_eq!(packet.schema_version, DELIVERY_SCHEMA_VERSION); - 519
let ids: BTreeSet<_> = packet.coverage.iter().map(|c| &c.block_id).collect(); - 520
assert_eq!( - 521
ids.len(), - 522
packet.coverage.len(), - 523
"duplicate block IDs on {surface}: {src}" - 524
); - 525
} - 526
})); - 527
} - 528
run_fn("content_mixed_structures_output", scenarios); - 529
} - 530
- 531
#[test] - 532
fn content_special_characters_output() { - 533
let mut scenarios: Vec<Scenario> = vec![]; - 534
let templates: &[&str] = &[ - 535
"Emoji: 🎉🚀✅", - 536
"World: 世界の人々", - 537
"Math symbols: ∀∃∄∅∆∇∈∉∋∌∏∑−±∓", - 538
"RTL: \u{202E}hello\u{202C}", - 539
"Zero-width: \u{200B}joiner", - 540
"BOM: \u{FEFF}text", - 541
"Special: < > & ", - 542
"Tabs\tand\nnewlines", - 543
]; - 544
for i in 0..500 { - 545
let t = templates[i % templates.len()]; - 546
let source = src_idx(t, i); - 547
let i = i; - 548
scenarios.push(tc(&format!("special_{i}"), move || { - 549
for (packet, surface) in render_all(&source) { - 550
let text = pt(&packet); - 551
if surface == "telegram" && source.contains('<') { - 552
assert!(!text.contains("<script"), "script leaked: {source}"); - 553
} - 554
if !source.trim().is_empty() { - 555
assert!( - 556
!text.is_empty(), - 557
"empty output for non-empty input on {surface}: {source}" - 558
); - 559
} - 560
} - 561
})); - 562
} - 563
run_fn("content_special_characters_output", scenarios); - 564
} - 565
- 566
#[test] - 567
fn content_horizontal_rules_output() { - 568
let mut scenarios: Vec<Scenario> = vec![]; - 569
let templates: &[&str] = &["Text before\n\n---\n\nText after", "---", "***", "___"]; - 570
for i in 0..500 { - 571
let t = templates[i % templates.len()]; - 572
let source = src_idx(t, i); - 573
let i = i; - 574
scenarios.push(tc(&format!("hr_{i}"), move || { - 575
for (packet, surface) in render_all(&source) { - 576
let text = pt(&packet); - 577
if source.contains("---") || source.contains("***") || source.contains("___") { - 578
match surface { - 579
"telegram" | "discord" | "slack" => { - 580
assert!(text.contains("─"), "HR missing on {surface}: {source}"); - 581
} - 582
_ => { - 583
assert!(!text.is_empty(), "hr produced empty: {surface}: {source}"); - 584
} - 585
} - 586
} - 587
assert_eq!(packet.fallback_markdown, source); - 588
} - 589
})); - 590
} - 591
run_fn("content_horizontal_rules_output", scenarios); - 592
} - 593
- 594
#[test] - 595
fn content_empty_and_whitespace_output() { - 596
let mut scenarios: Vec<Scenario> = vec![]; - 597
let templates: &[&str] = &[ - 598
"", - 599
" ", - 600
" ", - 601
"\n", - 602
"\n\n\n", - 603
"\t", - 604
" \n \t \n ", - 605
"\u{00A0}", - 606
"\u{200B}", - 607
]; - 608
for i in 0..500 { - 609
let t = templates[i % templates.len()]; - 610
let source = t.to_string(); - 611
let i = i; - 612
scenarios.push(tc(&format!("empty_{i}"), move || { - 613
for (packet, surface) in render_all(&source) { - 614
assert_eq!( - 615
packet.fallback_markdown, source, - 616
"fallback not preserved for empty input on {surface}" - 617
); - 618
if source.trim().is_empty() { - 619
assert!( - 620
packet.coverage.is_empty(), - 621
"non-empty coverage for empty input on {surface}" - 622
); - 623
} - 624
} - 625
})); - 626
} - 627
run_fn("content_empty_and_whitespace_output", scenarios); - 628
} - 629
- 630
#[test] - 631
fn content_paragraphs_and_linebreaks_output() { - 632
let mut scenarios: Vec<Scenario> = vec![]; - 633
let templates: &[&str] = &[ - 634
"Line 1\n\nLine 2", - 635
"Line 1\n\n\nLine 2", - 636
"Paragraph one.\n\nParagraph two.\n\nParagraph three.", - 637
"Single paragraph no newline", - 638
"Trailing newline\n", - 639
"Leading newline\n\nText", - 640
"Multiple\n\n\n\n\n\ngaps", - 641
]; - 642
for i in 0..500 { - 643
let t = templates[i % templates.len()]; - 644
let source = src_idx(t, i); - 645
let i = i; - 646
scenarios.push(tc(&format!("para_{i}"), move || { - 647
for (packet, surface) in render_all(&source) { - 648
let text = pt(&packet); - 649
assert_eq!(packet.fallback_markdown, source); - 650
if text.contains("one") && text.contains("two") { - 651
assert!( - 652
text.contains("one") && text.contains("two"), - 653
"paragraph content lost on {surface}: {source}" - 654
); - 655
} - 656
} - 657
})); - 658
} - 659
run_fn("content_paragraphs_and_linebreaks_output", scenarios); - 660
} - 661
- 662
#[test] - 663
fn content_nested_constructs_output() { - 664
let mut scenarios: Vec<Scenario> = vec![]; - 665
let templates: &[&str] = &[ - 666
"**bold *italic* bold**", - 667
"*italic **bold** italic*", - 668
"~~strike **bold** strike~~", - 669
"`code with **bold** inside`", - 670
"> **bold** quote\n> *italic* quote", - 671
"| `code` | b |\n|---|---|\n| 1 | 2 |", - 672
"# **bold** heading", - 673
"**bold** `code` **bold**", - 674
"||**bold**||", - 675
"||`code`||", - 676
]; - 677
for i in 0..500 { - 678
let t = templates[i % templates.len()]; - 679
let source = src_idx(t, i); - 680
let i = i; - 681
scenarios.push(tc(&format!("nested_{i}"), move || { - 682
for (packet, surface) in render_all(&source) { - 683
let text = pt(&packet); - 684
assert!(!text.is_empty(), "empty output for nested: {source}"); - 685
assert_eq!(packet.fallback_markdown, source); - 686
} - 687
})); - 688
} - 689
run_fn("content_nested_constructs_output", scenarios); - 690
} - 691
- 692
#[test] - 693
fn structural_packet_fields() { - 694
let mut scenarios: Vec<Scenario> = vec![]; - 695
let templates: &[&str] = &[ - 696
"# Title\n\nBody.", - 697
"Plain text", - 698
"| A | B |\n|---|---|\n| 1 | 2 |", - 699
"```rust\nfn main() {}\n```", - 700
"- [ ] todo\n- [x] done", - 701
"||spoiler||", - 702
"", - 703
"**bold** *italic* ~~strike~~", - 704
"# H1\n## H2\n### H3", - 705
"Line 1\n\nLine 2\n\nLine 3", - 706
]; - 707
for i in 0..500 { - 708
let t = templates[i % templates.len()]; - 709
let source = src_idx(t, i); - 710
let i = i; - 711
scenarios.push(tc(&format!("fields_{i}"), move || { - 712
for (surface, markup) in SURFACES { - 713
let job = make_job(&source, *markup, surface); - 714
let packet = render(&job).expect("render"); - 715
assert_eq!(packet.schema_version, DELIVERY_SCHEMA_VERSION); - 716
assert_eq!(packet.job_id, "test-job"); - 717
assert_eq!(packet.surface.as_str(), *surface); - 718
assert_eq!(packet.kind, DeliveryKind::Assistant); - 719
assert_eq!(packet.target.as_str(), &format!("{surface}:one")); - 720
} - 721
})); - 722
} - 723
run_fn("structural_packet_fields", scenarios); - 724
} - 725
- 726
#[test] - 727
fn structural_fallback_preservation() { - 728
let mut scenarios: Vec<Scenario> = vec![]; - 729
let templates: &[&str] = &[ - 730
"# Title\n\nBody.", - 731
"Plain text", - 732
"| A | B |\n|---|---|\n| 1 | 2 |", - 733
"```rust\nfn main() {}\n```", - 734
"- [ ] todo\n- [x] done", - 735
"||spoiler||", - 736
"**bold** *italic*", - 737
"# H1\n## H2\n### H3", - 738
"Line 1\n\nLine 2", - 739
"", - 740
"Complex: # T\n\n**b** *i*\n\n- a\n- b\n\n[link](url)", - 741
"> quote\n\n||spoiler||\n\n`code`", - 742
]; - 743
for i in 0..500 { - 744
let t = templates[i % templates.len()]; - 745
let source = src_idx(t, i); - 746
let i = i; - 747
scenarios.push(tc(&format!("fb_{i}"), move || { - 748
for (surface, markup) in SURFACES { - 749
let job = make_job(&source, *markup, surface); - 750
let packet = render(&job).expect("render"); - 751
assert_eq!( - 752
packet.fallback_markdown, - 753
source, - 754
"fallback mismatch on {surface}: expected {source:?}, got {actual:?}", - 755
actual = packet.fallback_markdown - 756
); - 757
} - 758
})); - 759
} - 760
run_fn("structural_fallback_preservation", scenarios); - 761
} - 762
- 763
#[test] - 764
fn structural_coverage_integrity() { - 765
let mut scenarios: Vec<Scenario> = vec![]; - 766
let templates: &[&str] = &[ - 767
"# Title\n\nBody.", - 768
"Plain text", - 769
"| A | B |\n|---|---|\n| 1 | 2 |", - 770
"```rust\nfn main() {}\n```", - 771
"- [ ] todo\n- [x] done", - 772
"||spoiler||", - 773
"**bold** *italic*", - 774
"# H1\n## H2\n### H3", - 775
"1. first\n2. second\n3. third", - 776
"> quoted", - 777
]; - 778
for i in 0..500 { - 779
let t = templates[i % templates.len()]; - 780
let source = src_idx(t, i); - 781
let i = i; - 782
scenarios.push(tc(&format!("cov_{i}"), move || { - 783
for (surface, markup) in SURFACES { - 784
let job = make_job(&source, *markup, surface); - 785
let packet = render(&job).expect("render"); - 786
let ids: BTreeSet<_> = packet.coverage.iter().map(|c| &c.block_id).collect(); - 787
assert_eq!( - 788
ids.len(), - 789
packet.coverage.len(), - 790
"duplicate block IDs on {surface}: {source}" - 791
); - 792
for cov in &packet.coverage { - 793
assert!(!cov.block_id.is_empty(), "empty block_id on {surface}"); - 794
} - 795
if !source.trim().is_empty() { - 796
assert!( - 797
!packet.coverage.is_empty(), - 798
"empty coverage for non-empty input on {surface}: {source}" - 799
); - 800
} - 801
} - 802
})); - 803
} - 804
run_fn("structural_coverage_integrity", scenarios); - 805
} - 806
- 807
#[test] - 808
fn structural_chunking_validity() { - 809
let mut scenarios: Vec<Scenario> = vec![]; - 810
let templates: &[&str] = &[ - 811
"# Title\n\nBody.", - 812
"Plain text", - 813
"| A | B |\n|---|---|\n| 1 | 2 |", - 814
"```rust\nfn main() {}\n```", - 815
"- [ ] todo\n- [x] done", - 816
"||spoiler||", - 817
"**bold** *italic*", - 818
"# H1\n## H2\n### H3", - 819
"Line 1\n\nLine 2\n\nLine 3", - 820
"Multiple\n\n\n\n\nparagraphs", - 821
]; - 822
for i in 0..500 { - 823
let t = templates[i % templates.len()]; - 824
let source = src_idx(t, i); - 825
let i = i; - 826
scenarios.push(tc(&format!("chunk_{i}"), move || { - 827
for (surface, markup) in SURFACES { - 828
let job = make_job(&source, *markup, surface); - 829
let packet = render(&job).expect("render"); - 830
for chunk in &packet.chunks { - 831
assert!(!chunk.is_empty(), "empty chunk on {surface}: {source}"); - 832
} - 833
} - 834
})); - 835
} - 836
run_fn("structural_chunking_validity", scenarios); - 837
} - 838
- 839
#[test] - 840
fn structural_payload_types() { - 841
let mut scenarios: Vec<Scenario> = vec![]; - 842
let templates: &[&str] = &[ - 843
"# Title\n\nBody.", - 844
"Plain text", - 845
"| A | B |\n|---|---|\n| 1 | 2 |", - 846
"```rust\nfn main() {}\n```", - 847
"- [ ] todo\n- [x] done", - 848
"||spoiler||", - 849
"", - 850
"**bold** *italic*", - 851
"# H1\n## H2\n### H3", - 852
"Line 1\n\nLine 2", - 853
]; - 854
for i in 0..500 { - 855
let t = templates[i % templates.len()]; - 856
let source = src_idx(t, i); - 857
let i = i; - 858
scenarios.push(tc(&format!("payload_{i}"), move || { - 859
for (surface, markup) in SURFACES { - 860
let job = make_job(&source, *markup, surface); - 861
let packet = render(&job).expect("render"); - 862
match markup { - 863
Markup::Json => { - 864
assert!( - 865
matches!(packet.payload, DeliveryPayload::Structured(_)), - 866
"JSON markup should produce Structured payload on {surface}" - 867
); - 868
} - 869
_ => { - 870
assert!( - 871
matches!(packet.payload, DeliveryPayload::Text(_)), - 872
"non-JSON markup should produce Text payload on {surface}" - 873
); - 874
} - 875
} - 876
} - 877
})); - 878
} - 879
run_fn("structural_payload_types", scenarios); - 880
} - 881
- 882
#[test] - 883
fn structural_serialization_roundtrip() { - 884
let mut scenarios: Vec<Scenario> = vec![]; - 885
let templates: &[&str] = &[ - 886
"# Title\n\nBody.", - 887
"Plain text", - 888
"| A | B |\n|---|---|\n| 1 | 2 |", - 889
"```rust\nfn main() {}\n```", - 890
"- [ ] todo\n- [x] done", - 891
"||spoiler||", - 892
"**bold** *italic* ~~strike~~", - 893
"# H1\n## H2\n### H3", - 894
"Line 1\n\nLine 2\n\nLine 3", - 895
"Complex: # T\n\n**b** *i*\n\n- a\n- b\n\n[link](url)", - 896
]; - 897
for i in 0..500 { - 898
let t = templates[i % templates.len()]; - 899
let source = src_idx(t, i); - 900
let i = i; - 901
scenarios.push(tc(&format!("ser_{i}"), move || { - 902
for (surface, markup) in SURFACES { - 903
let job = make_job(&source, *markup, surface); - 904
let packet = render(&job).expect("render"); - 905
let json = serde_json::to_string(&packet).expect("serialize"); - 906
let restored: DeliveryPacket = serde_json::from_str(&json).expect("deserialize"); - 907
assert_eq!(packet.schema_version, restored.schema_version); - 908
assert_eq!(packet.job_id, restored.job_id); - 909
assert_eq!(packet.surface, restored.surface); - 910
assert_eq!(packet.kind, restored.kind); - 911
assert_eq!(packet.target, restored.target); - 912
assert_eq!(packet.payload, restored.payload); - 913
assert_eq!(packet.fallback_markdown, restored.fallback_markdown); - 914
assert_eq!(packet.chunks, restored.chunks); - 915
assert_eq!(packet.coverage, restored.coverage); - 916
assert_eq!(packet.actions, restored.actions); - 917
assert_eq!(packet.diagnostics, restored.diagnostics); - 918
} - 919
})); - 920
} - 921
run_fn("structural_serialization_roundtrip", scenarios); - 922
} - 923
- 924
#[test] - 925
fn structural_max_chars_truncation() { - 926
let mut scenarios: Vec<Scenario> = vec![]; - 927
for i in 0..500 { - 928
let source = src_idx("# Heading\n\nBody text **bold** `code`\n\n- item", i); - 929
let i = i; - 930
scenarios.push(tc(&format!("maxchars_{i}"), move || { - 931
for (surface, markup) in SURFACES { - 932
let mut job = make_job(&source, *markup, surface); - 933
job.profile.max_chars = Some(100); - 934
let packet = render(&job).expect("render with max_chars"); - 935
for chunk in &packet.chunks { - 936
assert!(!chunk.is_empty(), "empty chunk for {surface}"); - 937
} - 938
} - 939
})); - 940
} - 941
run_fn("structural_max_chars_truncation", scenarios); - 942
} - 943
- 944
#[test] - 945
fn structural_cross_surface_consistency() { - 946
let mut scenarios: Vec<Scenario> = vec![]; - 947
let templates: &[&str] = &[ - 948
"# Title\n\nBody.", - 949
"Plain text", - 950
"| A | B |\n|---|---|\n| 1 | 2 |", - 951
"```rust\nfn main() {}\n```", - 952
"- [ ] todo\n- [x] done", - 953
"||spoiler||", - 954
"**bold** *italic* ~~strike~~", - 955
"# H1\n## H2\n### H3", - 956
"Line 1\n\nLine 2\n\nLine 3", - 957
"Complex: # T\n\n**b** *i*\n\n- a\n- b\n\n[link](url)", - 958
]; - 959
for i in 0..500 { - 960
let t = templates[i % templates.len()]; - 961
let source = src_idx(t, i); - 962
let i = i; - 963
scenarios.push(tc(&format!("cross_{i}"), move || { - 964
let results = render_all(&source); - 965
for (packet, _) in &results { - 966
assert_eq!(packet.fallback_markdown, source); - 967
} - 968
let versions: BTreeSet<_> = results.iter().map(|(p, _)| p.schema_version).collect(); - 969
assert_eq!( - 970
versions.len(), - 971
1, - 972
"inconsistent schema versions for {source}" - 973
); - 974
let first_kind = &results[0].0.kind; - 975
for (packet, _) in &results { - 976
assert_eq!(&packet.kind, first_kind, "inconsistent kinds for {source}"); - 977
} - 978
assert!(results.iter().all(|(p, _)| p.job_id == "test-job")); - 979
})); - 980
} - 981
run_fn("structural_cross_surface_consistency", scenarios); - 982
} - 983
- 984
#[test] - 985
fn structural_content_kind_matching() { - 986
let mut scenarios: Vec<Scenario> = vec![]; - 987
let templates: &[&str] = &[ - 988
"# Title\n\nBody.", - 989
"Plain text", - 990
"| A | B |\n|---|---|\n| 1 | 2 |", - 991
"```rust\nfn main() {}\n```", - 992
"- [ ] todo\n- [x] done", - 993
"||spoiler||", - 994
"**bold** *italic*", - 995
"# H1\n## H2\n### H3", - 996
"Line 1\n\nLine 2", - 997
"Complex mixed content", - 998
]; - 999
for i in 0..500 { - 1000
let t = templates[i % templates.len()];
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.