diff --git a/bdpl/analyze/__init__.py b/bdpl/analyze/__init__.py
index 1f4dcc0..b90bcc0 100644
--- a/bdpl/analyze/__init__.py
+++ b/bdpl/analyze/__init__.py
@@ -310,11 +310,26 @@ def _detect_special_features(
# chapter-selection / main-play page.
if h.jump_title in chapter_selection_jt:
continue
+ # Skip if this page also has buttons targeting non-episode
+ # playlists — the episode button is likely navigation (e.g.
+ # "back to movie") rather than a commentary feature.
+ page_has_non_ep_target = any(
+ title_to_mpls.get(jt_val - 1) not in ep_playlists
+ for jt_val in page_jt.get(h.page_id, set())
+ if title_to_mpls.get(jt_val - 1) is not None
+ )
+ if page_has_non_ep_target:
+ continue
category = "commentary"
else:
category = classifications.get(mpls, "extra")
ch_start = h.register_sets.get(2)
+ # For digital_archive playlists, ch_start=0 means "play from
+ # beginning" — normalise to None so it deduplicates with the
+ # title-hint fallback entry for the whole playlist.
+ if category == "digital_archive" and ch_start == 0:
+ ch_start = None
key = (mpls, ch_start)
if key in seen:
continue
@@ -864,6 +879,7 @@ def _maybe_collapse_variant_episodes(
episodes: list[Episode],
playlists: list[Playlist],
variant_mpls: set[str],
+ all_playlists: list[Playlist] | None = None,
) -> list[Episode]:
"""Collapse chapter-split episodes back to one when variant dedup caused it.
@@ -897,6 +913,18 @@ def _maybe_collapse_variant_episodes(
if playlist is None:
return episodes
+ # Only collapse when a removed variant actually shares clips with the
+ # episode playlist. Unrelated variant groups (e.g. duplicate specials)
+ # should not trigger a collapse.
+ if all_playlists and playlist.play_items:
+ ep_clips = {pi.clip_id for pi in playlist.play_items}
+ has_related_variant = any(
+ pl.mpls in variant_mpls and any(pi.clip_id in ep_clips for pi in pl.play_items)
+ for pl in all_playlists
+ )
+ if not has_related_variant:
+ return episodes
+
segments = [
SegmentRef(
key=pi.segment_key(),
@@ -1075,11 +1103,20 @@ def scan_disc(
label_segments(unique_playlists, segment_freq)
# 5. Classify playlists
- classifications = classify_playlists(unique_playlists, play_all)
+ title_hint_mpls: set[str] = set()
+ for pl_nums in hints.get("title_playlists", {}).values():
+ for n in pl_nums:
+ title_hint_mpls.add(f"{n:05d}.mpls")
+ classifications = classify_playlists(
+ unique_playlists, play_all, title_hint_mpls=title_hint_mpls
+ )
analysis["classifications"] = classifications
# 6. Order episodes
- episodes = order_episodes(unique_playlists, play_all, classifications)
+ ig_marks = hints.get("ig_menu", {}).get("chapter_marks")
+ episodes = order_episodes(
+ unique_playlists, play_all, classifications, ig_chapter_marks=ig_marks
+ )
episodes = _maybe_keep_single_title_episode(
episodes,
@@ -1094,6 +1131,7 @@ def scan_disc(
episodes,
unique_playlists,
variant_mpls,
+ all_playlists=playlists,
)
# If episodes came from Play All decomposition, reclassify playlists
diff --git a/bdpl/analyze/classify.py b/bdpl/analyze/classify.py
index 5f67081..933ce85 100644
--- a/bdpl/analyze/classify.py
+++ b/bdpl/analyze/classify.py
@@ -12,19 +12,58 @@
_PREVIEW_MAX = 60
_BODY_MIN_S = 300 # 5 minutes
_DIGITAL_ARCHIVE_MIN_ITEMS = 20
+_DIGITAL_ARCHIVE_HINT_MIN_ITEMS = 5
_DIGITAL_ARCHIVE_MAX_TOTAL_S = 300
_DIGITAL_ARCHIVE_MAX_AVG_ITEM_S = 0.5
_DIGITAL_ARCHIVE_MIN_UNIQUE_RATIO = 0.8
+_DIGITAL_ARCHIVE_NO_AUDIO_RATIO = 0.8
+_AUDIO_CODECS = frozenset(
+ {
+ "LPCM",
+ "AC3",
+ "E-AC3",
+ "DTS",
+ "DTS-HD",
+ "DTS-HD MA",
+ "TrueHD",
+ }
+)
+
+
+def _items_lack_audio(pl: Playlist) -> bool:
+ """Return True when most play items have no audio streams (still images)."""
+ if not pl.play_items:
+ return False
+ no_audio = sum(
+ 1 for pi in pl.play_items if not any(s.codec in _AUDIO_CODECS for s in pi.streams)
+ )
+ return no_audio / len(pl.play_items) >= _DIGITAL_ARCHIVE_NO_AUDIO_RATIO
-def is_digital_archive_playlist(pl: Playlist) -> bool:
+def is_digital_archive_playlist(
+ pl: Playlist,
+ *,
+ has_title_hint: bool = False,
+) -> bool:
"""Return True when playlist shape resembles an image archive.
- Heuristic targets menu-like playlists made of many ultra-short items
- (often one still image per clip) and avoids short video extras.
+ Three independent signals lower the item-count floor when combined
+ with the base shape checks (avg duration ≤ 0.5 s, unique ratio ≥ 0.8):
+
+ 1. **Item count ≥ 20** — strong shape signal, sufficient alone.
+ 2. **Title hint** — disc navigation references the playlist as real
+ content. Lowers floor to 5 items.
+ 3. **No audio streams** — play items contain only video (+ IG overlay),
+ characteristic of still-image galleries. Lowers floor to 5 items.
"""
item_count = len(pl.play_items)
- if item_count < _DIGITAL_ARCHIVE_MIN_ITEMS:
+
+ # Determine minimum item threshold based on available evidence.
+ has_structural_evidence = has_title_hint or _items_lack_audio(pl)
+ min_items = (
+ _DIGITAL_ARCHIVE_HINT_MIN_ITEMS if has_structural_evidence else _DIGITAL_ARCHIVE_MIN_ITEMS
+ )
+ if item_count < min_items:
return False
total_s = pl.duration_seconds
@@ -110,13 +149,23 @@ def label_segments(playlists: list[Playlist], segment_freq: dict[tuple, int]) ->
pi.label = "UNKNOWN"
-def classify_playlists(playlists: list[Playlist], play_all: list[Playlist]) -> dict[str, str]:
+def classify_playlists(
+ playlists: list[Playlist],
+ play_all: list[Playlist],
+ title_hint_mpls: set[str] | None = None,
+) -> dict[str, str]:
"""Return dict mpls_name -> category string.
+ Parameters:
+ title_hint_mpls: MPLS names referenced by disc title navigation
+ hints. Used as structural evidence for digital archive
+ detection when the item count is below the strict threshold.
+
Categories: 'episode', 'play_all', 'menu', 'extra', 'bumper',
'creditless_op', 'creditless_ed', 'digital_archive'.
"""
play_all_names = {pl.mpls for pl in play_all}
+ hint_names = title_hint_mpls or set()
result: dict[str, str] = {}
for pl in playlists:
@@ -126,7 +175,7 @@ def classify_playlists(playlists: list[Playlist], play_all: list[Playlist]) -> d
result[pl.mpls] = "play_all"
continue
- if is_digital_archive_playlist(pl):
+ if is_digital_archive_playlist(pl, has_title_hint=pl.mpls in hint_names):
result[pl.mpls] = "digital_archive"
continue
diff --git a/bdpl/analyze/ordering.py b/bdpl/analyze/ordering.py
index 7a49282..6f09d52 100644
--- a/bdpl/analyze/ordering.py
+++ b/bdpl/analyze/ordering.py
@@ -106,12 +106,18 @@ def _episodes_from_play_all(
def _episodes_from_chapters(
playlist: Playlist,
+ ig_chapter_marks: list[int] | None = None,
) -> list[Episode]:
"""Split a single long playlist into episodes using chapter marks.
Used when a playlist contains one (or few) very long play item(s) with
multiple episodes encoded back-to-back, distinguishable only by chapters.
+ When *ig_chapter_marks* are provided (from IG menu buttons), they serve as
+ structural confirmation that the playlist contains multiple episodes.
+ Without such evidence, a minimum of 3 estimated episodes is required —
+ an ``est_count`` of 2 is ambiguous (could be a single ~50 min movie).
+
Heuristic: group consecutive chapters into blocks whose total duration
falls within episode range (10–45 min). When a running block exceeds the
expected episode length, start a new episode at the chapter boundary.
@@ -139,6 +145,13 @@ def _episodes_from_chapters(
if est_count <= 1:
return [] # Not worth splitting
+ # IG chapter marks provide structural evidence of multiple episodes.
+ # Without such evidence, require est_count >= 3 because est_count == 2
+ # (~50 min total) is ambiguous — could be a single movie.
+ has_ig_confirmation = ig_chapter_marks is not None and len(ig_chapter_marks) >= 2
+ if est_count <= 2 and not has_ig_confirmation:
+ return []
+
# Target duration per episode
target_dur_ms = total_dur_ms / est_count
# Tolerance: 60% to 140% of target
@@ -222,9 +235,14 @@ def order_episodes(
playlists: list[Playlist],
play_all_playlists: list[Playlist],
classifications: dict[str, str] | None = None,
+ ig_chapter_marks: list[int] | None = None,
) -> list[Episode]:
"""Infer ordered episode list.
+ Parameters:
+ ig_chapter_marks: Chapter indices from IG menu buttons that confirm
+ episode boundaries. Passed through to chapter-splitting logic.
+
Strategy:
1. If there are individual episode-length playlists (>10 min, not in
play_all list) with unique body segments, use those.
@@ -255,7 +273,7 @@ def order_episodes(
pa_episodes = _episodes_from_play_all(best_pa)
# If play-all decomposition yields only 1 episode, try chapter-based
if len(pa_episodes) <= 1 and best_pa.chapters:
- ch_episodes = _episodes_from_chapters(best_pa)
+ ch_episodes = _episodes_from_chapters(best_pa, ig_chapter_marks)
if len(ch_episodes) > len(pa_episodes):
pa_episodes = ch_episodes
@@ -285,7 +303,7 @@ def order_episodes(
# it likely contains multiple episodes in a single m2ts
if len(individual_eps) == 1:
candidate = individual_eps[0]
- ch_episodes = _episodes_from_chapters(candidate)
+ ch_episodes = _episodes_from_chapters(candidate, ig_chapter_marks)
if len(ch_episodes) >= 2:
return ch_episodes
return _episodes_from_individual(individual_eps)
diff --git a/tests/conftest.py b/tests/conftest.py
index 2d373dd..6a3ef83 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -208,6 +208,66 @@ def disc13_analysis(disc13_path):
return _analyze_fixture(disc13_path)
+@pytest.fixture(scope="session")
+def disc15_path() -> Path:
+ """Return path to bundled disc15 fixture."""
+ return _fixture_path("disc15")
+
+
+@pytest.fixture(scope="session")
+def disc15_analysis(disc15_path):
+ """Run and cache full analysis for the bundled disc15 fixture."""
+ return _analyze_fixture(disc15_path)
+
+
+@pytest.fixture(scope="session")
+def disc16_path() -> Path:
+ """Return path to bundled disc16 fixture."""
+ return _fixture_path("disc16")
+
+
+@pytest.fixture(scope="session")
+def disc16_analysis(disc16_path):
+ """Run and cache full analysis for the bundled disc16 fixture."""
+ return _analyze_fixture(disc16_path)
+
+
+@pytest.fixture(scope="session")
+def disc17_path() -> Path:
+ """Return path to bundled disc17 fixture."""
+ return _fixture_path("disc17")
+
+
+@pytest.fixture(scope="session")
+def disc17_analysis(disc17_path):
+ """Run and cache full analysis for the bundled disc17 fixture."""
+ return _analyze_fixture(disc17_path)
+
+
+@pytest.fixture(scope="session")
+def disc18_path() -> Path:
+ """Return path to bundled disc18 fixture."""
+ return _fixture_path("disc18")
+
+
+@pytest.fixture(scope="session")
+def disc18_analysis(disc18_path):
+ """Run and cache full analysis for the bundled disc18 fixture."""
+ return _analyze_fixture(disc18_path)
+
+
+@pytest.fixture(scope="session")
+def disc19_path() -> Path:
+ """Return path to bundled disc19 fixture."""
+ return _fixture_path("disc19")
+
+
+@pytest.fixture(scope="session")
+def disc19_analysis(disc19_path):
+ """Run and cache full analysis for the bundled disc19 fixture."""
+ return _analyze_fixture(disc19_path)
+
+
@pytest.fixture
def cli_runner() -> Callable[..., subprocess.CompletedProcess[str]]:
"""Return helper to invoke `python -m bdpl.cli` consistently in tests."""
diff --git a/tests/fixtures/disc15/CLIPINF/00000.clpi b/tests/fixtures/disc15/CLIPINF/00000.clpi
new file mode 100644
index 0000000..271ec5f
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc15/CLIPINF/00001.clpi b/tests/fixtures/disc15/CLIPINF/00001.clpi
new file mode 100644
index 0000000..45f295d
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc15/CLIPINF/00002.clpi b/tests/fixtures/disc15/CLIPINF/00002.clpi
new file mode 100644
index 0000000..3473286
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc15/CLIPINF/00003.clpi b/tests/fixtures/disc15/CLIPINF/00003.clpi
new file mode 100644
index 0000000..8a17694
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc15/CLIPINF/00004.clpi b/tests/fixtures/disc15/CLIPINF/00004.clpi
new file mode 100644
index 0000000..319f0a8
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc15/CLIPINF/00006.clpi b/tests/fixtures/disc15/CLIPINF/00006.clpi
new file mode 100644
index 0000000..844e126
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc15/CLIPINF/00007.clpi b/tests/fixtures/disc15/CLIPINF/00007.clpi
new file mode 100644
index 0000000..f851f70
Binary files /dev/null and b/tests/fixtures/disc15/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc15/META/DL/bdmt_eng.xml b/tests/fixtures/disc15/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..c381c3e
--- /dev/null
+++ b/tests/fixtures/disc15/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 15
+
+
diff --git a/tests/fixtures/disc15/MovieObject.bdmv b/tests/fixtures/disc15/MovieObject.bdmv
new file mode 100644
index 0000000..f9fc9fc
Binary files /dev/null and b/tests/fixtures/disc15/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc15/PLAYLIST/00000.mpls b/tests/fixtures/disc15/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..cbf16f4
Binary files /dev/null and b/tests/fixtures/disc15/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc15/PLAYLIST/00001.mpls b/tests/fixtures/disc15/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..7576fcd
Binary files /dev/null and b/tests/fixtures/disc15/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc15/PLAYLIST/00002.mpls b/tests/fixtures/disc15/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..3e0b22d
Binary files /dev/null and b/tests/fixtures/disc15/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc15/ics_menu.bin b/tests/fixtures/disc15/ics_menu.bin
new file mode 100644
index 0000000..3302e91
Binary files /dev/null and b/tests/fixtures/disc15/ics_menu.bin differ
diff --git a/tests/fixtures/disc15/index.bdmv b/tests/fixtures/disc15/index.bdmv
new file mode 100644
index 0000000..9ebd6bd
Binary files /dev/null and b/tests/fixtures/disc15/index.bdmv differ
diff --git a/tests/fixtures/disc16/CLIPINF/00000.clpi b/tests/fixtures/disc16/CLIPINF/00000.clpi
new file mode 100644
index 0000000..271ec5f
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00001.clpi b/tests/fixtures/disc16/CLIPINF/00001.clpi
new file mode 100644
index 0000000..45f295d
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00002.clpi b/tests/fixtures/disc16/CLIPINF/00002.clpi
new file mode 100644
index 0000000..3473286
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00003.clpi b/tests/fixtures/disc16/CLIPINF/00003.clpi
new file mode 100644
index 0000000..278aa33
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00004.clpi b/tests/fixtures/disc16/CLIPINF/00004.clpi
new file mode 100644
index 0000000..ef71722
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00005.clpi b/tests/fixtures/disc16/CLIPINF/00005.clpi
new file mode 100644
index 0000000..f9dbbb4
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00005.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00006.clpi b/tests/fixtures/disc16/CLIPINF/00006.clpi
new file mode 100644
index 0000000..ea669d9
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00007.clpi b/tests/fixtures/disc16/CLIPINF/00007.clpi
new file mode 100644
index 0000000..b1bc4d6
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00008.clpi b/tests/fixtures/disc16/CLIPINF/00008.clpi
new file mode 100644
index 0000000..588be3e
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00008.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00009.clpi b/tests/fixtures/disc16/CLIPINF/00009.clpi
new file mode 100644
index 0000000..e2b1cf5
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00009.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00010.clpi b/tests/fixtures/disc16/CLIPINF/00010.clpi
new file mode 100644
index 0000000..7eb347b
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00010.clpi differ
diff --git a/tests/fixtures/disc16/CLIPINF/00011.clpi b/tests/fixtures/disc16/CLIPINF/00011.clpi
new file mode 100644
index 0000000..36f86db
Binary files /dev/null and b/tests/fixtures/disc16/CLIPINF/00011.clpi differ
diff --git a/tests/fixtures/disc16/META/DL/bdmt_eng.xml b/tests/fixtures/disc16/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..2768744
--- /dev/null
+++ b/tests/fixtures/disc16/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 16
+
+
diff --git a/tests/fixtures/disc16/MovieObject.bdmv b/tests/fixtures/disc16/MovieObject.bdmv
new file mode 100644
index 0000000..494e383
Binary files /dev/null and b/tests/fixtures/disc16/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00000.mpls b/tests/fixtures/disc16/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..cbf16f4
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00001.mpls b/tests/fixtures/disc16/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..7576fcd
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00002.mpls b/tests/fixtures/disc16/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..e0c9b6e
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00003.mpls b/tests/fixtures/disc16/PLAYLIST/00003.mpls
new file mode 100644
index 0000000..4c6143e
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00003.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00004.mpls b/tests/fixtures/disc16/PLAYLIST/00004.mpls
new file mode 100644
index 0000000..c3f1ae9
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00004.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00005.mpls b/tests/fixtures/disc16/PLAYLIST/00005.mpls
new file mode 100644
index 0000000..e0b215c
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00005.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00006.mpls b/tests/fixtures/disc16/PLAYLIST/00006.mpls
new file mode 100644
index 0000000..5112d4f
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00006.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00007.mpls b/tests/fixtures/disc16/PLAYLIST/00007.mpls
new file mode 100644
index 0000000..b4d76cf
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00007.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00008.mpls b/tests/fixtures/disc16/PLAYLIST/00008.mpls
new file mode 100644
index 0000000..335ce68
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00008.mpls differ
diff --git a/tests/fixtures/disc16/PLAYLIST/00009.mpls b/tests/fixtures/disc16/PLAYLIST/00009.mpls
new file mode 100644
index 0000000..086e939
Binary files /dev/null and b/tests/fixtures/disc16/PLAYLIST/00009.mpls differ
diff --git a/tests/fixtures/disc16/ics_menu.bin b/tests/fixtures/disc16/ics_menu.bin
new file mode 100644
index 0000000..528ed01
Binary files /dev/null and b/tests/fixtures/disc16/ics_menu.bin differ
diff --git a/tests/fixtures/disc16/index.bdmv b/tests/fixtures/disc16/index.bdmv
new file mode 100644
index 0000000..e168cf5
Binary files /dev/null and b/tests/fixtures/disc16/index.bdmv differ
diff --git a/tests/fixtures/disc17/CLIPINF/00000.clpi b/tests/fixtures/disc17/CLIPINF/00000.clpi
new file mode 100644
index 0000000..12b474d
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00001.clpi b/tests/fixtures/disc17/CLIPINF/00001.clpi
new file mode 100644
index 0000000..a90358d
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00002.clpi b/tests/fixtures/disc17/CLIPINF/00002.clpi
new file mode 100644
index 0000000..3097df8
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00003.clpi b/tests/fixtures/disc17/CLIPINF/00003.clpi
new file mode 100644
index 0000000..4625220
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00004.clpi b/tests/fixtures/disc17/CLIPINF/00004.clpi
new file mode 100644
index 0000000..1898dda
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00005.clpi b/tests/fixtures/disc17/CLIPINF/00005.clpi
new file mode 100644
index 0000000..50041ef
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00005.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00006.clpi b/tests/fixtures/disc17/CLIPINF/00006.clpi
new file mode 100644
index 0000000..6d63c68
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00007.clpi b/tests/fixtures/disc17/CLIPINF/00007.clpi
new file mode 100644
index 0000000..62486ee
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00008.clpi b/tests/fixtures/disc17/CLIPINF/00008.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00008.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00009.clpi b/tests/fixtures/disc17/CLIPINF/00009.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00009.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00010.clpi b/tests/fixtures/disc17/CLIPINF/00010.clpi
new file mode 100644
index 0000000..1982c1c
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00010.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00011.clpi b/tests/fixtures/disc17/CLIPINF/00011.clpi
new file mode 100644
index 0000000..963d2fd
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00011.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00012.clpi b/tests/fixtures/disc17/CLIPINF/00012.clpi
new file mode 100644
index 0000000..d20821d
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00012.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00013.clpi b/tests/fixtures/disc17/CLIPINF/00013.clpi
new file mode 100644
index 0000000..d49899f
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00013.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00014.clpi b/tests/fixtures/disc17/CLIPINF/00014.clpi
new file mode 100644
index 0000000..1514c97
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00014.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00015.clpi b/tests/fixtures/disc17/CLIPINF/00015.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00015.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00016.clpi b/tests/fixtures/disc17/CLIPINF/00016.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00016.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00017.clpi b/tests/fixtures/disc17/CLIPINF/00017.clpi
new file mode 100644
index 0000000..67792e2
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00017.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00018.clpi b/tests/fixtures/disc17/CLIPINF/00018.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00018.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00019.clpi b/tests/fixtures/disc17/CLIPINF/00019.clpi
new file mode 100644
index 0000000..67792e2
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00019.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00020.clpi b/tests/fixtures/disc17/CLIPINF/00020.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00020.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00021.clpi b/tests/fixtures/disc17/CLIPINF/00021.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00021.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00022.clpi b/tests/fixtures/disc17/CLIPINF/00022.clpi
new file mode 100644
index 0000000..d130141
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00022.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00023.clpi b/tests/fixtures/disc17/CLIPINF/00023.clpi
new file mode 100644
index 0000000..cbfb318
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00023.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00024.clpi b/tests/fixtures/disc17/CLIPINF/00024.clpi
new file mode 100644
index 0000000..1514c97
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00024.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00025.clpi b/tests/fixtures/disc17/CLIPINF/00025.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00025.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00026.clpi b/tests/fixtures/disc17/CLIPINF/00026.clpi
new file mode 100644
index 0000000..902cb8e
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00026.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00027.clpi b/tests/fixtures/disc17/CLIPINF/00027.clpi
new file mode 100644
index 0000000..0084330
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00027.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00028.clpi b/tests/fixtures/disc17/CLIPINF/00028.clpi
new file mode 100644
index 0000000..cbfb318
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00028.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00029.clpi b/tests/fixtures/disc17/CLIPINF/00029.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00029.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00030.clpi b/tests/fixtures/disc17/CLIPINF/00030.clpi
new file mode 100644
index 0000000..0edfb9f
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00030.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00031.clpi b/tests/fixtures/disc17/CLIPINF/00031.clpi
new file mode 100644
index 0000000..71b6c77
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00031.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00032.clpi b/tests/fixtures/disc17/CLIPINF/00032.clpi
new file mode 100644
index 0000000..97c72c1
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00032.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00033.clpi b/tests/fixtures/disc17/CLIPINF/00033.clpi
new file mode 100644
index 0000000..5231d0e
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00033.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00034.clpi b/tests/fixtures/disc17/CLIPINF/00034.clpi
new file mode 100644
index 0000000..fc457ab
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00034.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00035.clpi b/tests/fixtures/disc17/CLIPINF/00035.clpi
new file mode 100644
index 0000000..4bd594e
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00035.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00036.clpi b/tests/fixtures/disc17/CLIPINF/00036.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00036.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00037.clpi b/tests/fixtures/disc17/CLIPINF/00037.clpi
new file mode 100644
index 0000000..97c72c1
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00037.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00038.clpi b/tests/fixtures/disc17/CLIPINF/00038.clpi
new file mode 100644
index 0000000..cda1227
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00038.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00039.clpi b/tests/fixtures/disc17/CLIPINF/00039.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00039.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00040.clpi b/tests/fixtures/disc17/CLIPINF/00040.clpi
new file mode 100644
index 0000000..97c72c1
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00040.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00041.clpi b/tests/fixtures/disc17/CLIPINF/00041.clpi
new file mode 100644
index 0000000..963d2fd
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00041.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00042.clpi b/tests/fixtures/disc17/CLIPINF/00042.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00042.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00043.clpi b/tests/fixtures/disc17/CLIPINF/00043.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00043.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00044.clpi b/tests/fixtures/disc17/CLIPINF/00044.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00044.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00045.clpi b/tests/fixtures/disc17/CLIPINF/00045.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00045.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00046.clpi b/tests/fixtures/disc17/CLIPINF/00046.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00046.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00047.clpi b/tests/fixtures/disc17/CLIPINF/00047.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00047.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00048.clpi b/tests/fixtures/disc17/CLIPINF/00048.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00048.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00049.clpi b/tests/fixtures/disc17/CLIPINF/00049.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00049.clpi differ
diff --git a/tests/fixtures/disc17/CLIPINF/00050.clpi b/tests/fixtures/disc17/CLIPINF/00050.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc17/CLIPINF/00050.clpi differ
diff --git a/tests/fixtures/disc17/META/DL/bdmt_eng.xml b/tests/fixtures/disc17/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..0aa4a93
--- /dev/null
+++ b/tests/fixtures/disc17/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 17
+
+
diff --git a/tests/fixtures/disc17/MovieObject.bdmv b/tests/fixtures/disc17/MovieObject.bdmv
new file mode 100644
index 0000000..46f30df
Binary files /dev/null and b/tests/fixtures/disc17/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc17/PLAYLIST/00000.mpls b/tests/fixtures/disc17/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..9541ca8
Binary files /dev/null and b/tests/fixtures/disc17/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc17/PLAYLIST/00001.mpls b/tests/fixtures/disc17/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..92bc632
Binary files /dev/null and b/tests/fixtures/disc17/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc17/PLAYLIST/00002.mpls b/tests/fixtures/disc17/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..aa48c08
Binary files /dev/null and b/tests/fixtures/disc17/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc17/PLAYLIST/00003.mpls b/tests/fixtures/disc17/PLAYLIST/00003.mpls
new file mode 100644
index 0000000..7fe4a23
Binary files /dev/null and b/tests/fixtures/disc17/PLAYLIST/00003.mpls differ
diff --git a/tests/fixtures/disc17/ics_menu.bin b/tests/fixtures/disc17/ics_menu.bin
new file mode 100644
index 0000000..879f245
Binary files /dev/null and b/tests/fixtures/disc17/ics_menu.bin differ
diff --git a/tests/fixtures/disc17/index.bdmv b/tests/fixtures/disc17/index.bdmv
new file mode 100644
index 0000000..cee9035
Binary files /dev/null and b/tests/fixtures/disc17/index.bdmv differ
diff --git a/tests/fixtures/disc18/CLIPINF/00000.clpi b/tests/fixtures/disc18/CLIPINF/00000.clpi
new file mode 100644
index 0000000..6906fa2
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00001.clpi b/tests/fixtures/disc18/CLIPINF/00001.clpi
new file mode 100644
index 0000000..c8fc749
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00002.clpi b/tests/fixtures/disc18/CLIPINF/00002.clpi
new file mode 100644
index 0000000..89b52c1
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00003.clpi b/tests/fixtures/disc18/CLIPINF/00003.clpi
new file mode 100644
index 0000000..1402ce9
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00004.clpi b/tests/fixtures/disc18/CLIPINF/00004.clpi
new file mode 100644
index 0000000..8fe4ae0
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00005.clpi b/tests/fixtures/disc18/CLIPINF/00005.clpi
new file mode 100644
index 0000000..36f86db
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00005.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00006.clpi b/tests/fixtures/disc18/CLIPINF/00006.clpi
new file mode 100644
index 0000000..f11087e
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00007.clpi b/tests/fixtures/disc18/CLIPINF/00007.clpi
new file mode 100644
index 0000000..57eb58f
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00008.clpi b/tests/fixtures/disc18/CLIPINF/00008.clpi
new file mode 100644
index 0000000..00f9a0d
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00008.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00009.clpi b/tests/fixtures/disc18/CLIPINF/00009.clpi
new file mode 100644
index 0000000..e7d0a20
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00009.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00010.clpi b/tests/fixtures/disc18/CLIPINF/00010.clpi
new file mode 100644
index 0000000..5f21ca0
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00010.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00011.clpi b/tests/fixtures/disc18/CLIPINF/00011.clpi
new file mode 100644
index 0000000..43d83f4
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00011.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00012.clpi b/tests/fixtures/disc18/CLIPINF/00012.clpi
new file mode 100644
index 0000000..457a9be
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00012.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00013.clpi b/tests/fixtures/disc18/CLIPINF/00013.clpi
new file mode 100644
index 0000000..34fc0cb
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00013.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00014.clpi b/tests/fixtures/disc18/CLIPINF/00014.clpi
new file mode 100644
index 0000000..1e975bc
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00014.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00015.clpi b/tests/fixtures/disc18/CLIPINF/00015.clpi
new file mode 100644
index 0000000..1cad91e
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00015.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00016.clpi b/tests/fixtures/disc18/CLIPINF/00016.clpi
new file mode 100644
index 0000000..32b93e1
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00016.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00017.clpi b/tests/fixtures/disc18/CLIPINF/00017.clpi
new file mode 100644
index 0000000..25dd914
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00017.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00018.clpi b/tests/fixtures/disc18/CLIPINF/00018.clpi
new file mode 100644
index 0000000..66dd0bb
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00018.clpi differ
diff --git a/tests/fixtures/disc18/CLIPINF/00019.clpi b/tests/fixtures/disc18/CLIPINF/00019.clpi
new file mode 100644
index 0000000..bae3d4b
Binary files /dev/null and b/tests/fixtures/disc18/CLIPINF/00019.clpi differ
diff --git a/tests/fixtures/disc18/META/DL/bdmt_eng.xml b/tests/fixtures/disc18/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..e2cf2de
--- /dev/null
+++ b/tests/fixtures/disc18/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 18
+
+
diff --git a/tests/fixtures/disc18/MovieObject.bdmv b/tests/fixtures/disc18/MovieObject.bdmv
new file mode 100644
index 0000000..c55806e
Binary files /dev/null and b/tests/fixtures/disc18/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc18/PLAYLIST/00000.mpls b/tests/fixtures/disc18/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..cbf16f4
Binary files /dev/null and b/tests/fixtures/disc18/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc18/PLAYLIST/00001.mpls b/tests/fixtures/disc18/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..92bc632
Binary files /dev/null and b/tests/fixtures/disc18/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc18/PLAYLIST/00002.mpls b/tests/fixtures/disc18/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..dbd2ed3
Binary files /dev/null and b/tests/fixtures/disc18/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc18/PLAYLIST/00003.mpls b/tests/fixtures/disc18/PLAYLIST/00003.mpls
new file mode 100644
index 0000000..b4b9ec8
Binary files /dev/null and b/tests/fixtures/disc18/PLAYLIST/00003.mpls differ
diff --git a/tests/fixtures/disc18/PLAYLIST/00004.mpls b/tests/fixtures/disc18/PLAYLIST/00004.mpls
new file mode 100644
index 0000000..e913bf0
Binary files /dev/null and b/tests/fixtures/disc18/PLAYLIST/00004.mpls differ
diff --git a/tests/fixtures/disc18/PLAYLIST/00005.mpls b/tests/fixtures/disc18/PLAYLIST/00005.mpls
new file mode 100644
index 0000000..dd51e0c
Binary files /dev/null and b/tests/fixtures/disc18/PLAYLIST/00005.mpls differ
diff --git a/tests/fixtures/disc18/ics_menu.bin b/tests/fixtures/disc18/ics_menu.bin
new file mode 100644
index 0000000..1365edc
Binary files /dev/null and b/tests/fixtures/disc18/ics_menu.bin differ
diff --git a/tests/fixtures/disc18/index.bdmv b/tests/fixtures/disc18/index.bdmv
new file mode 100644
index 0000000..5796e01
Binary files /dev/null and b/tests/fixtures/disc18/index.bdmv differ
diff --git a/tests/fixtures/disc19/CLIPINF/00000.clpi b/tests/fixtures/disc19/CLIPINF/00000.clpi
new file mode 100644
index 0000000..12b474d
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00001.clpi b/tests/fixtures/disc19/CLIPINF/00001.clpi
new file mode 100644
index 0000000..a90358d
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00002.clpi b/tests/fixtures/disc19/CLIPINF/00002.clpi
new file mode 100644
index 0000000..89b52c1
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00003.clpi b/tests/fixtures/disc19/CLIPINF/00003.clpi
new file mode 100644
index 0000000..4625220
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00004.clpi b/tests/fixtures/disc19/CLIPINF/00004.clpi
new file mode 100644
index 0000000..1898dda
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00005.clpi b/tests/fixtures/disc19/CLIPINF/00005.clpi
new file mode 100644
index 0000000..e5e83ed
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00005.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00006.clpi b/tests/fixtures/disc19/CLIPINF/00006.clpi
new file mode 100644
index 0000000..6d63c68
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00007.clpi b/tests/fixtures/disc19/CLIPINF/00007.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00008.clpi b/tests/fixtures/disc19/CLIPINF/00008.clpi
new file mode 100644
index 0000000..4bd594e
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00008.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00009.clpi b/tests/fixtures/disc19/CLIPINF/00009.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00009.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00010.clpi b/tests/fixtures/disc19/CLIPINF/00010.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00010.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00011.clpi b/tests/fixtures/disc19/CLIPINF/00011.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00011.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00012.clpi b/tests/fixtures/disc19/CLIPINF/00012.clpi
new file mode 100644
index 0000000..cbfb318
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00012.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00013.clpi b/tests/fixtures/disc19/CLIPINF/00013.clpi
new file mode 100644
index 0000000..4bd594e
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00013.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00014.clpi b/tests/fixtures/disc19/CLIPINF/00014.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00014.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00015.clpi b/tests/fixtures/disc19/CLIPINF/00015.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00015.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00016.clpi b/tests/fixtures/disc19/CLIPINF/00016.clpi
new file mode 100644
index 0000000..807ab6d
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00016.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00017.clpi b/tests/fixtures/disc19/CLIPINF/00017.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00017.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00018.clpi b/tests/fixtures/disc19/CLIPINF/00018.clpi
new file mode 100644
index 0000000..345e09e
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00018.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00019.clpi b/tests/fixtures/disc19/CLIPINF/00019.clpi
new file mode 100644
index 0000000..2094fc1
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00019.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00020.clpi b/tests/fixtures/disc19/CLIPINF/00020.clpi
new file mode 100644
index 0000000..2ae1744
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00020.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00021.clpi b/tests/fixtures/disc19/CLIPINF/00021.clpi
new file mode 100644
index 0000000..f9d9262
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00021.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00022.clpi b/tests/fixtures/disc19/CLIPINF/00022.clpi
new file mode 100644
index 0000000..4108b33
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00022.clpi differ
diff --git a/tests/fixtures/disc19/CLIPINF/00023.clpi b/tests/fixtures/disc19/CLIPINF/00023.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc19/CLIPINF/00023.clpi differ
diff --git a/tests/fixtures/disc19/META/DL/bdmt_eng.xml b/tests/fixtures/disc19/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..24f33a6
--- /dev/null
+++ b/tests/fixtures/disc19/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 19
+
+
diff --git a/tests/fixtures/disc19/MovieObject.bdmv b/tests/fixtures/disc19/MovieObject.bdmv
new file mode 100644
index 0000000..46f30df
Binary files /dev/null and b/tests/fixtures/disc19/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc19/PLAYLIST/00000.mpls b/tests/fixtures/disc19/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..9541ca8
Binary files /dev/null and b/tests/fixtures/disc19/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc19/PLAYLIST/00001.mpls b/tests/fixtures/disc19/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..92bc632
Binary files /dev/null and b/tests/fixtures/disc19/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc19/PLAYLIST/00002.mpls b/tests/fixtures/disc19/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..aa48c08
Binary files /dev/null and b/tests/fixtures/disc19/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc19/PLAYLIST/00003.mpls b/tests/fixtures/disc19/PLAYLIST/00003.mpls
new file mode 100644
index 0000000..3df0a91
Binary files /dev/null and b/tests/fixtures/disc19/PLAYLIST/00003.mpls differ
diff --git a/tests/fixtures/disc19/ics_menu.bin b/tests/fixtures/disc19/ics_menu.bin
new file mode 100644
index 0000000..879f245
Binary files /dev/null and b/tests/fixtures/disc19/ics_menu.bin differ
diff --git a/tests/fixtures/disc19/index.bdmv b/tests/fixtures/disc19/index.bdmv
new file mode 100644
index 0000000..cee9035
Binary files /dev/null and b/tests/fixtures/disc19/index.bdmv differ
diff --git a/tests/test_digital_archive.py b/tests/test_digital_archive.py
index 805f1bb..626b912 100644
--- a/tests/test_digital_archive.py
+++ b/tests/test_digital_archive.py
@@ -11,6 +11,7 @@
export_digital_archive_images,
get_digital_archive_dry_run,
)
+from bdpl.model import StreamInfo
from tests.builders import (
build_disc_analysis,
build_play_item,
@@ -27,8 +28,12 @@ def test_digital_archive_playlist_detected_from_structure() -> None:
def test_digital_archive_playlist_rejects_low_item_count() -> None:
- """Few short items should not trigger digital archive classification."""
+ """Few short items with audio should not trigger digital archive classification."""
items = [build_play_item(f"{i:05d}", 0.0, 0.04) for i in range(10)]
+ # Add audio streams so the no-audio signal does not lower the threshold.
+ audio = StreamInfo(pid=0x1100, stream_type=128, codec="LPCM", lang="jpn")
+ for item in items:
+ item.streams = [audio]
pl = build_playlist("00003.mpls", items)
assert not is_digital_archive_playlist(pl)
diff --git a/tests/test_disc15_scan.py b/tests/test_disc15_scan.py
new file mode 100644
index 0000000..5ce2f02
--- /dev/null
+++ b/tests/test_disc15_scan.py
@@ -0,0 +1,45 @@
+"""Tests for disc15 fixture — chapter-split disc with 4 episodes, no specials."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc15Episodes:
+ def test_episode_count(self, disc15_analysis: DiscAnalysis) -> None:
+ assert len(disc15_analysis.episodes) == 4
+
+ def test_episodes_are_ordered(self, disc15_analysis: DiscAnalysis) -> None:
+ nums = [ep.episode for ep in disc15_analysis.episodes]
+ assert nums == [1, 2, 3, 4]
+
+ def test_episode_durations_reasonable(self, disc15_analysis: DiscAnalysis) -> None:
+ for ep in disc15_analysis.episodes:
+ dur_min = ep.duration_ms / 60000
+ assert 15 < dur_min < 35, f"Ep {ep.episode} duration {dur_min:.1f}min out of range"
+
+ def test_all_episodes_from_same_playlist(self, disc15_analysis: DiscAnalysis) -> None:
+ for ep in disc15_analysis.episodes:
+ assert ep.playlist == "00002.mpls"
+
+ def test_episode_segments_dont_overlap(self, disc15_analysis: DiscAnalysis) -> None:
+ for i in range(len(disc15_analysis.episodes) - 1):
+ seg_a = disc15_analysis.episodes[i].segments[0]
+ seg_b = disc15_analysis.episodes[i + 1].segments[0]
+ assert seg_a.out_ms <= seg_b.in_ms, (
+ f"Ep {i + 1} end {seg_a.out_ms} overlaps Ep {i + 2} start {seg_b.in_ms}"
+ )
+
+
+class TestDisc15Specials:
+ def test_no_special_features(self, disc15_analysis: DiscAnalysis) -> None:
+ assert len(disc15_analysis.special_features) == 0
+
+
+class TestDisc15Metadata:
+ def test_disc_title(self, disc15_analysis: DiscAnalysis) -> None:
+ assert disc15_analysis.disc_title == "TEST DISC 15"
diff --git a/tests/test_disc16_scan.py b/tests/test_disc16_scan.py
new file mode 100644
index 0000000..fb69a80
--- /dev/null
+++ b/tests/test_disc16_scan.py
@@ -0,0 +1,56 @@
+"""Tests for disc16 fixture — chapter-split disc with 4 episodes and 4 specials."""
+
+from __future__ import annotations
+
+from collections import Counter
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc16Episodes:
+ def test_episode_count(self, disc16_analysis: DiscAnalysis) -> None:
+ assert len(disc16_analysis.episodes) == 4
+
+ def test_episodes_are_ordered(self, disc16_analysis: DiscAnalysis) -> None:
+ nums = [ep.episode for ep in disc16_analysis.episodes]
+ assert nums == [1, 2, 3, 4]
+
+ def test_episode_durations_reasonable(self, disc16_analysis: DiscAnalysis) -> None:
+ for ep in disc16_analysis.episodes:
+ dur_min = ep.duration_ms / 60000
+ assert 15 < dur_min < 35, f"Ep {ep.episode} duration {dur_min:.1f}min out of range"
+
+ def test_all_episodes_from_same_playlist(self, disc16_analysis: DiscAnalysis) -> None:
+ for ep in disc16_analysis.episodes:
+ assert ep.playlist == "00002.mpls"
+
+ def test_episode_segments_dont_overlap(self, disc16_analysis: DiscAnalysis) -> None:
+ for i in range(len(disc16_analysis.episodes) - 1):
+ seg_a = disc16_analysis.episodes[i].segments[0]
+ seg_b = disc16_analysis.episodes[i + 1].segments[0]
+ assert seg_a.out_ms <= seg_b.in_ms, (
+ f"Ep {i + 1} end {seg_a.out_ms} overlaps Ep {i + 2} start {seg_b.in_ms}"
+ )
+
+
+class TestDisc16Specials:
+ def test_special_feature_count(self, disc16_analysis: DiscAnalysis) -> None:
+ assert len(disc16_analysis.special_features) == 4
+
+ def test_special_categories(self, disc16_analysis: DiscAnalysis) -> None:
+ cats = Counter(sf.category for sf in disc16_analysis.special_features)
+ assert cats["extra"] == 2
+ assert cats["creditless_ed"] == 2
+
+ def test_all_specials_visible(self, disc16_analysis: DiscAnalysis) -> None:
+ for sf in disc16_analysis.special_features:
+ assert sf.menu_visible
+
+
+class TestDisc16Metadata:
+ def test_disc_title(self, disc16_analysis: DiscAnalysis) -> None:
+ assert disc16_analysis.disc_title == "TEST DISC 16"
diff --git a/tests/test_disc17_scan.py b/tests/test_disc17_scan.py
new file mode 100644
index 0000000..3ba1e62
--- /dev/null
+++ b/tests/test_disc17_scan.py
@@ -0,0 +1,39 @@
+"""Tests for disc17 fixture — single OVA episode with digital archive."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc17Episodes:
+ def test_episode_count(self, disc17_analysis: DiscAnalysis) -> None:
+ assert len(disc17_analysis.episodes) == 1
+
+ def test_episode_playlist(self, disc17_analysis: DiscAnalysis) -> None:
+ assert disc17_analysis.episodes[0].playlist == "00002.mpls"
+
+ def test_episode_duration_reasonable(self, disc17_analysis: DiscAnalysis) -> None:
+ dur_min = disc17_analysis.episodes[0].duration_ms / 60000
+ assert 30 < dur_min < 60, f"Episode duration {dur_min:.1f}min out of range"
+
+
+class TestDisc17Specials:
+ def test_special_feature_count(self, disc17_analysis: DiscAnalysis) -> None:
+ assert len(disc17_analysis.special_features) == 1
+
+ def test_digital_archive_detected(self, disc17_analysis: DiscAnalysis) -> None:
+ sf = disc17_analysis.special_features[0]
+ assert sf.category == "digital_archive"
+ assert sf.playlist == "00003.mpls"
+
+ def test_digital_archive_visible(self, disc17_analysis: DiscAnalysis) -> None:
+ assert disc17_analysis.special_features[0].menu_visible
+
+
+class TestDisc17Metadata:
+ def test_disc_title(self, disc17_analysis: DiscAnalysis) -> None:
+ assert disc17_analysis.disc_title == "TEST DISC 17"
diff --git a/tests/test_disc18_scan.py b/tests/test_disc18_scan.py
new file mode 100644
index 0000000..0b7636f
--- /dev/null
+++ b/tests/test_disc18_scan.py
@@ -0,0 +1,43 @@
+"""Tests for disc18 fixture — single movie with 2 specials."""
+
+from __future__ import annotations
+
+from collections import Counter
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc18Episodes:
+ def test_episode_count(self, disc18_analysis: DiscAnalysis) -> None:
+ """Single movie should not be chapter-split."""
+ assert len(disc18_analysis.episodes) == 1
+
+ def test_episode_playlist(self, disc18_analysis: DiscAnalysis) -> None:
+ assert disc18_analysis.episodes[0].playlist == "00002.mpls"
+
+ def test_episode_duration_reasonable(self, disc18_analysis: DiscAnalysis) -> None:
+ dur_min = disc18_analysis.episodes[0].duration_ms / 60000
+ assert 40 < dur_min < 65, f"Movie duration {dur_min:.1f}min out of range"
+
+
+class TestDisc18Specials:
+ def test_special_feature_count(self, disc18_analysis: DiscAnalysis) -> None:
+ assert len(disc18_analysis.special_features) == 2
+
+ def test_special_categories(self, disc18_analysis: DiscAnalysis) -> None:
+ cats = Counter(sf.category for sf in disc18_analysis.special_features)
+ assert cats["extra"] == 1
+ assert cats["creditless_ed"] == 1
+
+ def test_all_specials_visible(self, disc18_analysis: DiscAnalysis) -> None:
+ for sf in disc18_analysis.special_features:
+ assert sf.menu_visible
+
+
+class TestDisc18Metadata:
+ def test_disc_title(self, disc18_analysis: DiscAnalysis) -> None:
+ assert disc18_analysis.disc_title == "TEST DISC 18"
diff --git a/tests/test_disc19_scan.py b/tests/test_disc19_scan.py
new file mode 100644
index 0000000..0018a6e
--- /dev/null
+++ b/tests/test_disc19_scan.py
@@ -0,0 +1,59 @@
+"""Tests for disc19 fixture — single OVA episode with digital archive (hint-backed)."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc19Episodes:
+ def test_episode_count(self, disc19_analysis: DiscAnalysis) -> None:
+ assert len(disc19_analysis.episodes) == 1
+
+ def test_episode_playlist(self, disc19_analysis: DiscAnalysis) -> None:
+ assert disc19_analysis.episodes[0].playlist == "00002.mpls"
+
+ def test_episode_duration_reasonable(self, disc19_analysis: DiscAnalysis) -> None:
+ dur_min = disc19_analysis.episodes[0].duration_ms / 60000
+ assert 30 < dur_min < 60, f"Episode duration {dur_min:.1f}min out of range"
+
+
+class TestDisc19Specials:
+ def test_special_feature_count(self, disc19_analysis: DiscAnalysis) -> None:
+ assert len(disc19_analysis.special_features) == 1
+
+ def test_digital_archive_detected(self, disc19_analysis: DiscAnalysis) -> None:
+ sf = disc19_analysis.special_features[0]
+ assert sf.category == "digital_archive"
+ assert sf.playlist == "00003.mpls"
+
+ def test_digital_archive_visible(self, disc19_analysis: DiscAnalysis) -> None:
+ assert disc19_analysis.special_features[0].menu_visible
+
+ def test_digital_archive_hint_backed(self, disc19_analysis: DiscAnalysis) -> None:
+ """Disc19 has only 17 archive items — below strict 20-item threshold.
+
+ Detection succeeds via two structural signals: title hints from
+ disc navigation and the absence of audio streams in play items.
+ """
+ from pathlib import Path
+
+ from bdpl.analyze.classify import is_digital_archive_playlist
+ from bdpl.bdmv.mpls import parse_mpls_dir
+
+ pl_dir = Path(__file__).parent / "fixtures" / "disc19" / "PLAYLIST"
+ playlists = parse_mpls_dir(pl_dir)
+ archive_pl = next(p for p in playlists if p.mpls == "00003.mpls")
+ assert len(archive_pl.play_items) < 20, "Below strict item threshold"
+ # Title hint alone is sufficient
+ assert is_digital_archive_playlist(archive_pl, has_title_hint=True)
+ # No-audio signal alone is also sufficient (items have no audio streams)
+ assert is_digital_archive_playlist(archive_pl, has_title_hint=False)
+
+
+class TestDisc19Metadata:
+ def test_disc_title(self, disc19_analysis: DiscAnalysis) -> None:
+ assert disc19_analysis.disc_title == "TEST DISC 19"
diff --git a/tests/test_disc_matrix.py b/tests/test_disc_matrix.py
index 4ee585c..8ed2b8a 100644
--- a/tests/test_disc_matrix.py
+++ b/tests/test_disc_matrix.py
@@ -25,6 +25,11 @@
("disc11_analysis", 6, ["00002.mpls"] * 6),
("disc12_analysis", 5, ["00002.mpls"] * 5),
("disc13_analysis", 6, ["00002.mpls"] * 6),
+ ("disc15_analysis", 4, ["00002.mpls"] * 4),
+ ("disc16_analysis", 4, ["00002.mpls"] * 4),
+ ("disc17_analysis", 1, ["00002.mpls"]),
+ ("disc18_analysis", 1, ["00002.mpls"]),
+ ("disc19_analysis", 1, ["00002.mpls"]),
],
)
def test_disc_episode_expectation_matrix(
@@ -55,6 +60,11 @@ def test_disc_episode_expectation_matrix(
("disc11_analysis", 1, 1), # 1 short extra
("disc12_analysis", 3, 3), # 3 commentaries (play_all-only episodes)
("disc13_analysis", 9, 9), # 2 commentary + 5 creditless + 2 extra
+ ("disc15_analysis", 0, 0), # chapter-split disc with no extras
+ ("disc16_analysis", 4, 4), # 2 extras + 2 creditless EDs
+ ("disc17_analysis", 1, 1), # 1 digital archive
+ ("disc18_analysis", 2, 2), # 1 extra + 1 creditless ED
+ ("disc19_analysis", 1, 1), # 1 digital archive (hint-backed)
],
)
def test_disc_special_visibility_expectation_matrix(
@@ -89,6 +99,11 @@ def test_disc_special_visibility_expectation_matrix(
"disc11_analysis",
"disc12_analysis",
"disc13_analysis",
+ "disc15_analysis",
+ "disc16_analysis",
+ "disc17_analysis",
+ "disc18_analysis",
+ "disc19_analysis",
],
)
def test_disc_episode_segment_boundaries_matrix(
@@ -127,6 +142,11 @@ def test_disc_episode_segment_boundaries_matrix(
"disc11_analysis",
"disc12_analysis",
"disc13_analysis",
+ "disc15_analysis",
+ "disc16_analysis",
+ "disc17_analysis",
+ "disc18_analysis",
+ "disc19_analysis",
],
)
def test_disc_special_boundary_semantics_matrix(
@@ -172,6 +192,11 @@ def test_disc_special_boundary_semantics_matrix(
("disc11_analysis", 0),
("disc12_analysis", 0),
("disc13_analysis", 0),
+ ("disc15_analysis", 0),
+ ("disc16_analysis", 0),
+ ("disc17_analysis", 0),
+ ("disc18_analysis", 0),
+ ("disc19_analysis", 0),
],
)
def test_disc_special_chapter_split_expectation_matrix(
@@ -200,6 +225,11 @@ def test_disc_special_chapter_split_expectation_matrix(
("disc11_analysis", "TEST DISC 11"),
("disc12_analysis", "TEST DISC 12"),
("disc13_analysis", "TEST DISC 13"),
+ ("disc15_analysis", "TEST DISC 15"),
+ ("disc16_analysis", "TEST DISC 16"),
+ ("disc17_analysis", "TEST DISC 17"),
+ ("disc18_analysis", "TEST DISC 18"),
+ ("disc19_analysis", "TEST DISC 19"),
],
)
def test_disc_title_extraction_matrix(