mod common;
use boko::model::Format;
use common::{Doc, EpubBuilder, Nav, count_toc, export_to_bytes, roundtrip};
const CHAPTERS: usize = 3500;
const _: () = assert!(CHAPTERS > 2800);
fn chapter_title(i: usize) -> String {
format!("Chapter {i:04} of the Extraordinarily Verbose Compendium of Split Indexes")
}
#[test]
fn azw3_export_splits_large_indexes_and_roundtrips() {
let mut builder = EpubBuilder::new("Large Split Book");
let mut nav = Vec::new();
for i in 0..CHAPTERS {
let file = format!("text/ch{i:04}.xhtml");
let title = chapter_title(i);
let marker = match i {
0 => " The aardwolfen prowls here.",
1750 => " The midpointer balances here.",
i if i == CHAPTERS - 1 => " The zymurgist ferments here.",
_ => "",
};
let body = format!(
"<h1 id=\"c{i}\">{title}</h1>\
<p>Body paragraph of chapter {i} with enough prose to be a real \
chunk of content.{marker}</p>"
);
builder = builder.doc(Doc::new(&file, &title, &body));
nav.push(Nav::new(&title, &format!("{file}#c{i}")));
}
let builder = builder.nav(nav);
let title_bytes: usize = (0..CHAPTERS).map(|i| chapter_title(i).len() + 2).sum();
assert!(
title_bytes > 2 * 0x10000,
"fixture must overflow multiple CNCX records ({title_bytes} bytes of labels)"
);
let mut book = builder.book();
assert_eq!(book.spine().len(), CHAPTERS);
assert_eq!(count_toc(book.toc()), CHAPTERS);
let mut rt = roundtrip(&mut book, Format::Azw3);
assert_eq!(
rt.spine().len(),
CHAPTERS,
"spine length must survive the multi-record skeleton index"
);
assert_eq!(
count_toc(rt.toc()),
CHAPTERS,
"TOC entry count must survive the multi-record NCX index"
);
let toc = rt.toc();
for i in [0, 1, 1170, 1750, 2339, 3000, CHAPTERS - 1] {
assert_eq!(
toc[i].title,
chapter_title(i),
"TOC title {i} must match (CNCX record-boundary regression)"
);
}
let markdown = String::from_utf8(export_to_bytes(&mut rt, Format::Markdown))
.expect("markdown output is utf-8");
for marker in ["aardwolfen", "midpointer", "zymurgist"] {
assert!(
markdown.contains(marker),
"marker {marker:?} lost in AZW3 roundtrip"
);
}
}