diff --git a/.github/skills/batch-add-disc-fixtures/SKILL.md b/.github/skills/batch-add-disc-fixtures/SKILL.md
new file mode 100644
index 0000000..bf86d6b
--- /dev/null
+++ b/.github/skills/batch-add-disc-fixtures/SKILL.md
@@ -0,0 +1,304 @@
+---
+name: batch-add-disc-fixtures
+description: 'Batch-process a folder of Blu-ray ISOs: mount each, run analysis, generate a summary report for user review, then create fixtures for confirmed discs. Use when given a folder of ISOs or asked to add multiple discs at once.'
+---
+
+# Batch Add Disc Fixtures
+
+## Overview
+
+Orchestration workflow for processing multiple Blu-ray ISOs in one pass.
+Instead of the single-disc back-and-forth (mount → analyze → user confirms
+→ fixture → repeat), this skill:
+
+1. Mounts and analyzes every ISO in a folder
+2. Generates a summary report with IG menu cross-checks
+3. User reviews and confirms/corrects counts in one pass
+4. Creates all fixtures, tests, and matrix entries
+
+Delegates per-disc fixture creation to the
+[add-disc-fixture](../add-disc-fixture/SKILL.md) skill.
+
+## When to Use This Skill
+
+- User provides a folder path containing multiple ISOs
+- User asks to "add all discs from …" or "batch add"
+- User wants to process an entire series at once
+
+## Prerequisites
+
+- Windows (uses `Mount-DiskImage` / `Dismount-DiskImage`)
+- ISOs accessible via local path or UNC share
+- Python environment with bdpl installed (`pip install -e ".[dev]"`)
+- Existing test infrastructure (conftest.py, test_disc_matrix.py)
+
+## Step-by-Step Workflow
+
+### 1. Enumerate ISOs
+
+```powershell
+$folder = "\\server\share\SERIES NAME"
+Get-ChildItem $folder -Filter "*.ISO" | Select-Object Name, Length |
+ Sort-Object Name
+```
+
+List the ISOs found and confirm with the user before proceeding.
+
+### 2. Determine Next Disc Number
+
+Check existing fixtures to find the next available disc number:
+
+```python
+import re
+from pathlib import Path
+
+fixtures = Path("tests/fixtures")
+existing = sorted(
+ int(m.group(1))
+ for d in fixtures.iterdir()
+ if d.is_dir() and (m := re.match(r"disc(\d+)", d.name))
+)
+next_disc = existing[-1] + 1 if existing else 1
+print(f"Next disc number: {next_disc}")
+```
+
+### 3. Mount and Analyze All ISOs
+
+For each ISO, mount it, find the BDMV directory, and run analysis.
+Collect results into a structured report.
+
+**IMPORTANT**: Always dismount ISOs after analysis, even if errors occur.
+Use try/finally to guarantee cleanup.
+
+```python
+import json
+from pathlib import Path
+from bdpl.analyze import scan_disc
+from bdpl.bdmv.mpls import parse_mpls_dir
+from bdpl.bdmv.clpi import parse_clpi_dir
+
+results = []
+
+for iso_path in iso_files:
+ # Mount
+ # $vol = (Mount-DiskImage -ImagePath $iso -PassThru | Get-Volume)
+ # $drive = "$($vol.DriveLetter):\"
+
+ try:
+ bdmv = Path(f"{drive}/BDMV")
+ if not bdmv.exists():
+ # Some discs have BDMV directly at root, others nested
+ results.append({"iso": iso_path.name, "error": "No BDMV found"})
+ continue
+
+ playlists = parse_mpls_dir(bdmv / "PLAYLIST")
+ clips = parse_clpi_dir(bdmv / "CLIPINF")
+ result = scan_disc(bdmv, playlists, clips)
+
+ results.append({
+ "iso": iso_path.name,
+ "episodes": len(result.episodes),
+ "episode_details": [
+ {
+ "num": ep.episode,
+ "playlist": ep.playlist,
+ "duration_min": round(ep.duration_ms / 60000, 1),
+ }
+ for ep in result.episodes
+ ],
+ "specials": len(result.special_features),
+ "special_details": [
+ {
+ "index": sf.index,
+ "playlist": sf.playlist,
+ "category": sf.category,
+ "duration_min": round(sf.duration_ms / 60000, 1),
+ }
+ for sf in result.special_features
+ ],
+ "classifications": result.analysis.get("classifications", {}),
+ })
+ finally:
+ # Always dismount
+ # Dismount-DiskImage -ImagePath $iso
+ pass
+```
+
+### 4. Collect IG Menu Cross-Check Data
+
+For each disc, extract IG menu button counts per page and compare
+against detected episode/special counts. This provides a confidence
+signal — if the menu says 4 episode buttons but analysis found 5
+episodes, flag it.
+
+```python
+from bdpl.bdmv.ig_stream import parse_ics
+
+def ig_cross_check(bdmv_path, result):
+ """Return per-page button summary for cross-checking."""
+ ics_path = bdmv_path.parent / "ics_menu.bin"
+ # During batch analysis, use the live ICS from the mounted disc
+ # (the fixture ics_menu.bin doesn't exist yet)
+ hints = result.analysis.get("disc_hints", {})
+ ig_raw = hints.get("ig_hints_raw", [])
+
+ if not ig_raw:
+ return {"pages": [], "note": "No IG data available"}
+
+ # Group buttons by page
+ pages = {}
+ for h in ig_raw:
+ pid = h.page_id
+ if pid not in pages:
+ pages[pid] = {"page_id": pid, "buttons": 0, "targets": set()}
+ pages[pid]["buttons"] += 1
+ if h.jump_title is not None:
+ pages[pid]["targets"].add(f"JT({h.jump_title})")
+ elif h.playlist is not None:
+ pages[pid]["targets"].add(f"PL({h.playlist})")
+
+ # Convert sets to sorted lists for display
+ for p in pages.values():
+ p["targets"] = sorted(p["targets"])
+ p["unique_targets"] = len(p["targets"])
+
+ return {"pages": sorted(pages.values(), key=lambda x: x["page_id"])}
+```
+
+### 5. Generate Summary Report
+
+Present results in a table format. Flag any rows where IG cross-check
+disagrees with detected counts.
+
+```
+┌──────────────────────┬──────┬─────────┬────────────┬───────────────────────┐
+│ ISO │ Eps │ Specials│ IG Check │ Notes │
+├──────────────────────┼──────┼─────────┼────────────┼───────────────────────┤
+│ SERIES_D1.ISO │ 4 │ 0 │ ✅ 4 btns │ ch-split, 24min each │
+│ SERIES_D2.ISO │ 4 │ 4 │ ✅ 4+4 │ 24min eps, <3min spc │
+│ SERIES_SD.ISO │ 1 │ 1 │ ⚠️ no IG │ 1 ep + 1 dig.archive │
+└──────────────────────┴──────┴─────────┴────────────┴───────────────────────┘
+
+Episode details:
+ SERIES_D1.ISO:
+ ep1: 00002.mpls 24.0min | ep2: 00002.mpls 24.0min | ...
+ ...
+
+Special details:
+ SERIES_D2.ISO:
+ #1: 00005.mpls creditless_op 1.5min | #2: 00006.mpls creditless_ed 1.5min | ...
+ ...
+```
+
+**Key indicators:**
+- ✅ = IG button count matches detected count
+- ⚠️ = No IG data or inconclusive (common for SD/archive discs)
+- ❌ = IG button count disagrees — needs user attention
+
+### 6. User Review
+
+Present the summary and ask the user to confirm or correct. Use
+`ask_user` for each disc that needs attention:
+
+- For ✅ discs: batch confirm ("These N discs look correct?")
+- For ⚠️ discs: ask for expected counts individually
+- For ❌ discs: flag disagreement, ask user to provide correct counts
+
+After review, you'll have a confirmed list:
+```
+disc22: SERIES_D1.ISO → 4 episodes, 0 specials
+disc23: SERIES_D2.ISO → 4 episodes, 4 specials
+disc24: SERIES_SD.ISO → 1 episode, 1 digital_archive
+```
+
+### 7. Create Fixtures (Batch)
+
+For each confirmed disc, follow the [add-disc-fixture](../add-disc-fixture/SKILL.md)
+workflow steps 5–8:
+
+1. Re-mount the ISO (if dismounted after step 3)
+2. Extract ICS menu data
+3. Copy PLAYLIST/, CLIPINF/, index.bdmv, MovieObject.bdmv
+4. Create generic bdmt_eng.xml with `TEST DISC {N}`
+5. Verify size < 100KB
+6. Create integration test file
+7. Add conftest.py fixtures
+8. Add to test_disc_matrix.py (all 6 parametrizations)
+9. Dismount ISO
+
+**Tip**: Process all fixture file copies first (steps 1-5 for all discs),
+then create all test files (steps 6-8 for all discs). This minimizes
+mount/dismount cycles.
+
+### 8. Handle Analysis Mismatches
+
+If user-confirmed counts don't match analysis results for any disc:
+
+1. **Don't fix yet** — create fixtures for all matching discs first
+2. Run tests for matching discs to establish a green baseline
+3. Then debug mismatches one at a time using the
+ [debug-analysis guide](../add-disc-fixture/references/debug-analysis.md)
+4. Follow the structural-signals-over-thresholds approach (see AGENTS.md)
+5. After each fix, re-run ALL tests to verify no regressions
+
+### 9. Validate and PR
+
+```bash
+python -m pytest tests/ -x -q # All tests pass
+python -m ruff check . # No lint issues
+python -m ruff format --check . # No format issues
+```
+
+Create a single PR for all new fixtures using the
+[make-repo-contribution](../make-repo-contribution/SKILL.md) skill.
+The PR should list all discs added and any analysis fixes made.
+
+### 10. Clean Up
+
+- Dismount all ISOs
+- Delete temporary scripts
+- Verify no copyrighted content in fixtures
+
+## Execution Notes
+
+### Mount/Dismount Pattern (PowerShell)
+
+```powershell
+# Mount — returns drive letter
+$vol = Mount-DiskImage -ImagePath $isoPath -PassThru | Get-Volume
+$drive = "$($vol.DriveLetter):\"
+
+# ... do work ...
+
+# Dismount — use original ISO path
+Dismount-DiskImage -ImagePath $isoPath
+```
+
+**Gotchas:**
+- UNC paths may need to be copied locally first for Mount-DiskImage
+- Always use `-PassThru` to get the volume object
+- Some ISOs mount slowly — add a small delay or retry if drive not ready
+- `Dismount-DiskImage` uses the ISO path, not the drive letter
+
+### Parallel vs Sequential
+
+Mount ISOs **one at a time**. Windows can mount multiple, but:
+- Fewer drive letters to track
+- Cleaner error handling
+- Lower risk of forgetting to dismount
+
+### Fixture Numbering
+
+Disc numbers are assigned sequentially from the next available number.
+The order should match the ISO sort order (typically alphabetical).
+Document the ISO→disc mapping in the PR description.
+
+## Comparison with add-disc-fixture
+
+| Aspect | add-disc-fixture | batch-add-disc-fixtures |
+|--------|-----------------|------------------------|
+| Input | Single disc path | Folder of ISOs |
+| User interaction | Per-disc confirm | Bulk review table |
+| IG cross-check | Not included | Included in report |
+| When to use | One-off disc | Multiple discs/series |
+| Debugging | Inline | After green baseline |
diff --git a/.github/skills/batch-add-disc-fixtures/references/batch-analysis-report.py b/.github/skills/batch-add-disc-fixtures/references/batch-analysis-report.py
new file mode 100644
index 0000000..67c4eef
--- /dev/null
+++ b/.github/skills/batch-add-disc-fixtures/references/batch-analysis-report.py
@@ -0,0 +1,215 @@
+# Batch Analysis Report — Reference Template
+#
+# This script template is used by the batch-add-disc-fixtures skill.
+# The agent adapts it for each batch run — it is NOT meant to be
+# executed standalone.
+#
+# Usage: The agent will inline this logic in a Python session,
+# substituting actual ISO paths and drive letters.
+
+"""
+Batch-analyze mounted Blu-ray ISOs and produce a summary report.
+
+Expects a list of (iso_name, bdmv_path) tuples for already-mounted discs.
+"""
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from pathlib import Path
+
+# bdpl must be installed: pip install -e ".[dev]"
+from bdpl.analyze import scan_disc
+from bdpl.bdmv.clpi import parse_clpi_dir
+from bdpl.bdmv.mpls import parse_mpls_dir
+
+
+@dataclass
+class DiscReport:
+ iso_name: str
+ episodes: int
+ specials: int
+ episode_details: list[dict]
+ special_details: list[dict]
+ classifications: dict
+ ig_pages: list[dict]
+ ig_note: str
+ ig_match: str # "ok", "warn", "mismatch"
+
+
+def analyze_one(iso_name: str, bdmv_path: Path) -> DiscReport:
+ """Analyze a single mounted BDMV and return a structured report."""
+ playlists = parse_mpls_dir(bdmv_path / "PLAYLIST")
+ clips = parse_clpi_dir(bdmv_path / "CLIPINF")
+ result = scan_disc(bdmv_path, playlists, clips)
+
+ # Episode details
+ ep_details = [
+ {
+ "num": ep.episode,
+ "playlist": ep.playlist,
+ "duration_min": round(ep.duration_ms / 60000, 1),
+ }
+ for ep in result.episodes
+ ]
+
+ # Special details
+ sp_details = [
+ {
+ "index": sf.index,
+ "playlist": sf.playlist,
+ "category": sf.category,
+ "duration_min": round(sf.duration_ms / 60000, 1),
+ }
+ for sf in result.special_features
+ ]
+
+ # IG cross-check
+ hints = result.analysis.get("disc_hints", {})
+ ig_raw = hints.get("ig_hints_raw", [])
+ ig_pages = _extract_ig_pages(ig_raw)
+ ig_match, ig_note = _ig_cross_check(
+ ig_pages, len(result.episodes), len(result.special_features)
+ )
+
+ return DiscReport(
+ iso_name=iso_name,
+ episodes=len(result.episodes),
+ specials=len(result.special_features),
+ episode_details=ep_details,
+ special_details=sp_details,
+ classifications=result.analysis.get("classifications", {}),
+ ig_pages=ig_pages,
+ ig_note=ig_note,
+ ig_match=ig_match,
+ )
+
+
+def _extract_ig_pages(ig_raw: list) -> list[dict]:
+ """Group IG hints by page, counting buttons and unique targets."""
+ if not ig_raw:
+ return []
+
+ pages: dict[int, dict] = {}
+ for h in ig_raw:
+ pid = h.page_id
+ if pid not in pages:
+ pages[pid] = {"page_id": pid, "buttons": 0, "targets": set()}
+ pages[pid]["buttons"] += 1
+ if h.jump_title is not None:
+ pages[pid]["targets"].add(f"JT({h.jump_title})")
+ elif h.playlist is not None:
+ pages[pid]["targets"].add(f"PL({h.playlist})")
+
+ result = []
+ for p in sorted(pages.values(), key=lambda x: x["page_id"]):
+ result.append(
+ {
+ "page_id": p["page_id"],
+ "buttons": p["buttons"],
+ "unique_targets": len(p["targets"]),
+ "targets": sorted(p["targets"]),
+ }
+ )
+ return result
+
+
+def _ig_cross_check(ig_pages: list[dict], ep_count: int, sp_count: int) -> tuple[str, str]:
+ """
+ Compare IG page button counts against detected episode/special counts.
+
+ Returns (match_status, note) where match_status is one of:
+ - "ok": IG data supports the detected counts
+ - "warn": No IG data or inconclusive
+ - "mismatch": IG data disagrees with detected counts
+ """
+ if not ig_pages:
+ return "warn", "No IG data available"
+
+ # Heuristic: the page with the most buttons targeting unique playlists
+ # that roughly matches episode count is likely the episode page.
+ # Pages with fewer buttons targeting unique playlists may be special pages.
+ #
+ # This is advisory only — the user makes the final call.
+ notes = []
+ for page in ig_pages:
+ notes.append(
+ f"p{page['page_id']}: {page['buttons']} btns, {page['unique_targets']} unique targets"
+ )
+
+ # Simple match check: is there a page with unique_targets == ep_count?
+ ep_page_match = any(p["unique_targets"] == ep_count for p in ig_pages)
+ if ep_page_match:
+ return "ok", "; ".join(notes)
+
+ # Check if any page is close (off by 1, which can happen with
+ # "play all" button being counted)
+ close_match = any(abs(p["unique_targets"] - ep_count) <= 1 for p in ig_pages)
+ if close_match:
+ return "ok", "; ".join(notes) + " (close match)"
+
+ return "mismatch", "; ".join(notes)
+
+
+def format_report(reports: list[DiscReport], start_disc: int) -> str:
+ """Format batch analysis results as a readable summary table."""
+ lines = []
+ lines.append("=" * 72)
+ lines.append("BATCH ANALYSIS REPORT")
+ lines.append("=" * 72)
+ lines.append("")
+
+ # Summary table
+ match_icons = {"ok": "✅", "warn": "⚠️", "mismatch": "❌"}
+ lines.append(f"{'#':<5} {'ISO':<30} {'Eps':>4} {'Spc':>4} {'IG':>3} Notes")
+ lines.append("-" * 72)
+ for i, r in enumerate(reports):
+ disc_n = start_disc + i
+ icon = match_icons.get(r.ig_match, "?")
+ lines.append(
+ f"d{disc_n:<4} {r.iso_name:<30} {r.episodes:>4} {r.specials:>4} {icon} {r.ig_note}"
+ )
+
+ # Episode details
+ lines.append("")
+ lines.append("EPISODE DETAILS")
+ lines.append("-" * 72)
+ for i, r in enumerate(reports):
+ disc_n = start_disc + i
+ if r.episode_details:
+ eps = " | ".join(
+ f"ep{e['num']}: {e['playlist']} {e['duration_min']}min" for e in r.episode_details
+ )
+ lines.append(f" disc{disc_n}: {eps}")
+
+ # Special details
+ lines.append("")
+ lines.append("SPECIAL DETAILS")
+ lines.append("-" * 72)
+ for i, r in enumerate(reports):
+ disc_n = start_disc + i
+ if r.special_details:
+ sps = " | ".join(
+ f"#{s['index']}: {s['playlist']} {s['category']} {s['duration_min']}min"
+ for s in r.special_details
+ )
+ lines.append(f" disc{disc_n}: {sps}")
+
+ # Classifications
+ lines.append("")
+ lines.append("CLASSIFICATIONS")
+ lines.append("-" * 72)
+ for i, r in enumerate(reports):
+ disc_n = start_disc + i
+ if r.classifications:
+ cls_str = ", ".join(f"{k}: {v}" for k, v in sorted(r.classifications.items()))
+ lines.append(f" disc{disc_n}: {cls_str}")
+
+ lines.append("")
+ lines.append("=" * 72)
+ return "\n".join(lines)
+
+
+if __name__ == "__main__":
+ # Example usage — agent substitutes real values
+ print("This script is a reference template. See SKILL.md for usage.")
diff --git a/bdpl/analyze/ordering.py b/bdpl/analyze/ordering.py
index c0af3d1..b6f76ae 100644
--- a/bdpl/analyze/ordering.py
+++ b/bdpl/analyze/ordering.py
@@ -157,18 +157,26 @@ def _detect_episode_periodicity(
if len(group) < 3:
continue
+ # OP: first chapter, or second if first is a short preamble
op_ok = _OP_MIN_S <= group[0] <= _OP_MAX_S
+ if not op_ok and len(group) >= 4 and group[0] < _OP_MIN_S:
+ op_ok = _OP_MIN_S <= group[1] <= _OP_MAX_S
body_ok = any(d > _BODY_MIN_S_CH for d in group[1:-1])
- ed_ok = (_ED_MIN_S <= group[-1] <= _ED_MAX_S) or (
- len(group) >= 3 and _ED_MIN_S <= group[-2] <= _ED_MAX_S
+ # ED: within last 3 positions (covers trailing preview/transition)
+ ed_ok = any(
+ _ED_MIN_S <= group[-(i + 1)] <= _ED_MAX_S for i in range(min(3, len(group) - 1))
)
if op_ok and body_ok and ed_ok:
groups_matched += 1
- if n_groups >= 2:
+ if n_groups >= 2 and groups_matched >= 2:
score = groups_matched / n_groups
- if score >= 0.75:
+ # Majority rule: more groups match than don't. A simple
+ # majority is structural evidence rather than a magic
+ # threshold. Series finales often drop OP/ED, making one
+ # group fail without invalidating the overall pattern.
+ if groups_matched * 2 > n_groups:
if best is None or score > best[2] or (score == best[2] and n_groups > best[1]):
best = (period, n_groups, score)
@@ -374,13 +382,13 @@ def order_episodes(
return _episodes_from_individual(individual_eps)
if individual_eps:
- # Strategy 3: if only one "episode" but it's very long with chapters,
- # it likely contains multiple episodes in a single m2ts
- if len(individual_eps) == 1:
- candidate = individual_eps[0]
- ch_episodes = _episodes_from_chapters(candidate, ig_chapter_marks)
- if len(ch_episodes) >= 2:
- return ch_episodes
+ # Try chapter-splitting the longest playlist. If structural
+ # evidence (IG marks or periodicity) confirms it's a compilation,
+ # its split episodes are better than one massive "episode" entry.
+ longest = max(individual_eps, key=lambda p: p.duration_ms)
+ ch_episodes = _episodes_from_chapters(longest, ig_chapter_marks)
+ if len(ch_episodes) >= 2:
+ return ch_episodes
return _episodes_from_individual(individual_eps)
if pa_episodes:
diff --git a/tests/conftest.py b/tests/conftest.py
index ad154dd..49b1e06 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -292,6 +292,54 @@ def disc21_analysis(disc21_path):
return _analyze_fixture(disc21_path)
+@pytest.fixture(scope="session")
+def disc22_path() -> Path:
+ """Return path to bundled disc22 fixture."""
+ return _fixture_path("disc22")
+
+
+@pytest.fixture(scope="session")
+def disc22_analysis(disc22_path):
+ """Run and cache full analysis for the bundled disc22 fixture."""
+ return _analyze_fixture(disc22_path)
+
+
+@pytest.fixture(scope="session")
+def disc23_path() -> Path:
+ """Return path to bundled disc23 fixture."""
+ return _fixture_path("disc23")
+
+
+@pytest.fixture(scope="session")
+def disc23_analysis(disc23_path):
+ """Run and cache full analysis for the bundled disc23 fixture."""
+ return _analyze_fixture(disc23_path)
+
+
+@pytest.fixture(scope="session")
+def disc24_path() -> Path:
+ """Return path to bundled disc24 fixture."""
+ return _fixture_path("disc24")
+
+
+@pytest.fixture(scope="session")
+def disc24_analysis(disc24_path):
+ """Run and cache full analysis for the bundled disc24 fixture."""
+ return _analyze_fixture(disc24_path)
+
+
+@pytest.fixture(scope="session")
+def disc25_path() -> Path:
+ """Return path to bundled disc25 fixture."""
+ return _fixture_path("disc25")
+
+
+@pytest.fixture(scope="session")
+def disc25_analysis(disc25_path):
+ """Run and cache full analysis for the bundled disc25 fixture."""
+ return _analyze_fixture(disc25_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/disc22/CLIPINF/00000.clpi b/tests/fixtures/disc22/CLIPINF/00000.clpi
new file mode 100644
index 0000000..6906fa2
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc22/CLIPINF/00001.clpi b/tests/fixtures/disc22/CLIPINF/00001.clpi
new file mode 100644
index 0000000..c8fc749
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc22/CLIPINF/00002.clpi b/tests/fixtures/disc22/CLIPINF/00002.clpi
new file mode 100644
index 0000000..edf057c
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc22/CLIPINF/00003.clpi b/tests/fixtures/disc22/CLIPINF/00003.clpi
new file mode 100644
index 0000000..d8b02f2
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc22/CLIPINF/00004.clpi b/tests/fixtures/disc22/CLIPINF/00004.clpi
new file mode 100644
index 0000000..abcbdf3
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc22/CLIPINF/00006.clpi b/tests/fixtures/disc22/CLIPINF/00006.clpi
new file mode 100644
index 0000000..94eee04
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc22/CLIPINF/00007.clpi b/tests/fixtures/disc22/CLIPINF/00007.clpi
new file mode 100644
index 0000000..42c4c1f
Binary files /dev/null and b/tests/fixtures/disc22/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc22/META/DL/bdmt_eng.xml b/tests/fixtures/disc22/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..5fb7ca0
--- /dev/null
+++ b/tests/fixtures/disc22/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 22
+
+
diff --git a/tests/fixtures/disc22/MovieObject.bdmv b/tests/fixtures/disc22/MovieObject.bdmv
new file mode 100644
index 0000000..f9fc9fc
Binary files /dev/null and b/tests/fixtures/disc22/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc22/PLAYLIST/00000.mpls b/tests/fixtures/disc22/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..cbf16f4
Binary files /dev/null and b/tests/fixtures/disc22/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc22/PLAYLIST/00001.mpls b/tests/fixtures/disc22/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..7576fcd
Binary files /dev/null and b/tests/fixtures/disc22/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc22/PLAYLIST/00002.mpls b/tests/fixtures/disc22/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..2bfaeb3
Binary files /dev/null and b/tests/fixtures/disc22/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc22/ics_menu.bin b/tests/fixtures/disc22/ics_menu.bin
new file mode 100644
index 0000000..df8f0ff
Binary files /dev/null and b/tests/fixtures/disc22/ics_menu.bin differ
diff --git a/tests/fixtures/disc22/index.bdmv b/tests/fixtures/disc22/index.bdmv
new file mode 100644
index 0000000..9ebd6bd
Binary files /dev/null and b/tests/fixtures/disc22/index.bdmv differ
diff --git a/tests/fixtures/disc23/CLIPINF/00000.clpi b/tests/fixtures/disc23/CLIPINF/00000.clpi
new file mode 100644
index 0000000..6906fa2
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc23/CLIPINF/00001.clpi b/tests/fixtures/disc23/CLIPINF/00001.clpi
new file mode 100644
index 0000000..c8fc749
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc23/CLIPINF/00002.clpi b/tests/fixtures/disc23/CLIPINF/00002.clpi
new file mode 100644
index 0000000..edf057c
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc23/CLIPINF/00003.clpi b/tests/fixtures/disc23/CLIPINF/00003.clpi
new file mode 100644
index 0000000..d8b02f2
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc23/CLIPINF/00004.clpi b/tests/fixtures/disc23/CLIPINF/00004.clpi
new file mode 100644
index 0000000..0fa2e9b
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc23/CLIPINF/00006.clpi b/tests/fixtures/disc23/CLIPINF/00006.clpi
new file mode 100644
index 0000000..0c831c0
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc23/CLIPINF/00007.clpi b/tests/fixtures/disc23/CLIPINF/00007.clpi
new file mode 100644
index 0000000..139b374
Binary files /dev/null and b/tests/fixtures/disc23/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc23/META/DL/bdmt_eng.xml b/tests/fixtures/disc23/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..ad90bee
--- /dev/null
+++ b/tests/fixtures/disc23/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 23
+
+
diff --git a/tests/fixtures/disc23/MovieObject.bdmv b/tests/fixtures/disc23/MovieObject.bdmv
new file mode 100644
index 0000000..f9fc9fc
Binary files /dev/null and b/tests/fixtures/disc23/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc23/PLAYLIST/00000.mpls b/tests/fixtures/disc23/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..cbf16f4
Binary files /dev/null and b/tests/fixtures/disc23/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc23/PLAYLIST/00001.mpls b/tests/fixtures/disc23/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..7576fcd
Binary files /dev/null and b/tests/fixtures/disc23/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc23/PLAYLIST/00002.mpls b/tests/fixtures/disc23/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..06b1fd8
Binary files /dev/null and b/tests/fixtures/disc23/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc23/ics_menu.bin b/tests/fixtures/disc23/ics_menu.bin
new file mode 100644
index 0000000..db968b6
Binary files /dev/null and b/tests/fixtures/disc23/ics_menu.bin differ
diff --git a/tests/fixtures/disc23/index.bdmv b/tests/fixtures/disc23/index.bdmv
new file mode 100644
index 0000000..9ebd6bd
Binary files /dev/null and b/tests/fixtures/disc23/index.bdmv differ
diff --git a/tests/fixtures/disc24/CLIPINF/00000.clpi b/tests/fixtures/disc24/CLIPINF/00000.clpi
new file mode 100644
index 0000000..6906fa2
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00001.clpi b/tests/fixtures/disc24/CLIPINF/00001.clpi
new file mode 100644
index 0000000..c8fc749
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00002.clpi b/tests/fixtures/disc24/CLIPINF/00002.clpi
new file mode 100644
index 0000000..68449ff
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00003.clpi b/tests/fixtures/disc24/CLIPINF/00003.clpi
new file mode 100644
index 0000000..c1c4ba5
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00004.clpi b/tests/fixtures/disc24/CLIPINF/00004.clpi
new file mode 100644
index 0000000..319f0a8
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00005.clpi b/tests/fixtures/disc24/CLIPINF/00005.clpi
new file mode 100644
index 0000000..1c66af8
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00005.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00006.clpi b/tests/fixtures/disc24/CLIPINF/00006.clpi
new file mode 100644
index 0000000..9b92988
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00007.clpi b/tests/fixtures/disc24/CLIPINF/00007.clpi
new file mode 100644
index 0000000..76454f0
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00008.clpi b/tests/fixtures/disc24/CLIPINF/00008.clpi
new file mode 100644
index 0000000..a5c7a82
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00008.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00009.clpi b/tests/fixtures/disc24/CLIPINF/00009.clpi
new file mode 100644
index 0000000..2b2137d
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00009.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00010.clpi b/tests/fixtures/disc24/CLIPINF/00010.clpi
new file mode 100644
index 0000000..4d8eec7
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00010.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00011.clpi b/tests/fixtures/disc24/CLIPINF/00011.clpi
new file mode 100644
index 0000000..36f86db
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00011.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00012.clpi b/tests/fixtures/disc24/CLIPINF/00012.clpi
new file mode 100644
index 0000000..664104d
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00012.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00013.clpi b/tests/fixtures/disc24/CLIPINF/00013.clpi
new file mode 100644
index 0000000..8759207
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00013.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00014.clpi b/tests/fixtures/disc24/CLIPINF/00014.clpi
new file mode 100644
index 0000000..5c8d2ee
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00014.clpi differ
diff --git a/tests/fixtures/disc24/CLIPINF/00015.clpi b/tests/fixtures/disc24/CLIPINF/00015.clpi
new file mode 100644
index 0000000..a7afc5c
Binary files /dev/null and b/tests/fixtures/disc24/CLIPINF/00015.clpi differ
diff --git a/tests/fixtures/disc24/META/DL/bdmt_eng.xml b/tests/fixtures/disc24/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..54c01f1
--- /dev/null
+++ b/tests/fixtures/disc24/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 24
+
+
diff --git a/tests/fixtures/disc24/MovieObject.bdmv b/tests/fixtures/disc24/MovieObject.bdmv
new file mode 100644
index 0000000..33acbfa
Binary files /dev/null and b/tests/fixtures/disc24/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00000.mpls b/tests/fixtures/disc24/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..cbf16f4
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00001.mpls b/tests/fixtures/disc24/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..7576fcd
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00002.mpls b/tests/fixtures/disc24/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..e19fd51
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00003.mpls b/tests/fixtures/disc24/PLAYLIST/00003.mpls
new file mode 100644
index 0000000..1d3854a
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00003.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00004.mpls b/tests/fixtures/disc24/PLAYLIST/00004.mpls
new file mode 100644
index 0000000..1c62b80
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00004.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00005.mpls b/tests/fixtures/disc24/PLAYLIST/00005.mpls
new file mode 100644
index 0000000..c098212
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00005.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00006.mpls b/tests/fixtures/disc24/PLAYLIST/00006.mpls
new file mode 100644
index 0000000..11f5248
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00006.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00007.mpls b/tests/fixtures/disc24/PLAYLIST/00007.mpls
new file mode 100644
index 0000000..90cffb9
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00007.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00008.mpls b/tests/fixtures/disc24/PLAYLIST/00008.mpls
new file mode 100644
index 0000000..ce3db43
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00008.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00009.mpls b/tests/fixtures/disc24/PLAYLIST/00009.mpls
new file mode 100644
index 0000000..6184cae
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00009.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00010.mpls b/tests/fixtures/disc24/PLAYLIST/00010.mpls
new file mode 100644
index 0000000..9bc110a
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00010.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00011.mpls b/tests/fixtures/disc24/PLAYLIST/00011.mpls
new file mode 100644
index 0000000..785d957
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00011.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00012.mpls b/tests/fixtures/disc24/PLAYLIST/00012.mpls
new file mode 100644
index 0000000..eb05849
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00012.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00013.mpls b/tests/fixtures/disc24/PLAYLIST/00013.mpls
new file mode 100644
index 0000000..ce5310c
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00013.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00014.mpls b/tests/fixtures/disc24/PLAYLIST/00014.mpls
new file mode 100644
index 0000000..a36b9fa
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00014.mpls differ
diff --git a/tests/fixtures/disc24/PLAYLIST/00015.mpls b/tests/fixtures/disc24/PLAYLIST/00015.mpls
new file mode 100644
index 0000000..6f05241
Binary files /dev/null and b/tests/fixtures/disc24/PLAYLIST/00015.mpls differ
diff --git a/tests/fixtures/disc24/ics_menu.bin b/tests/fixtures/disc24/ics_menu.bin
new file mode 100644
index 0000000..7ac77d0
Binary files /dev/null and b/tests/fixtures/disc24/ics_menu.bin differ
diff --git a/tests/fixtures/disc24/index.bdmv b/tests/fixtures/disc24/index.bdmv
new file mode 100644
index 0000000..2730b8e
Binary files /dev/null and b/tests/fixtures/disc24/index.bdmv differ
diff --git a/tests/fixtures/disc25/CLIPINF/00000.clpi b/tests/fixtures/disc25/CLIPINF/00000.clpi
new file mode 100644
index 0000000..12b474d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00000.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00001.clpi b/tests/fixtures/disc25/CLIPINF/00001.clpi
new file mode 100644
index 0000000..a90358d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00001.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00002.clpi b/tests/fixtures/disc25/CLIPINF/00002.clpi
new file mode 100644
index 0000000..89b52c1
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00002.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00003.clpi b/tests/fixtures/disc25/CLIPINF/00003.clpi
new file mode 100644
index 0000000..4625220
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00003.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00004.clpi b/tests/fixtures/disc25/CLIPINF/00004.clpi
new file mode 100644
index 0000000..1898dda
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00004.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00005.clpi b/tests/fixtures/disc25/CLIPINF/00005.clpi
new file mode 100644
index 0000000..50041ef
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00005.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00006.clpi b/tests/fixtures/disc25/CLIPINF/00006.clpi
new file mode 100644
index 0000000..6d63c68
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00006.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00007.clpi b/tests/fixtures/disc25/CLIPINF/00007.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00007.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00008.clpi b/tests/fixtures/disc25/CLIPINF/00008.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00008.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00009.clpi b/tests/fixtures/disc25/CLIPINF/00009.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00009.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00010.clpi b/tests/fixtures/disc25/CLIPINF/00010.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00010.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00011.clpi b/tests/fixtures/disc25/CLIPINF/00011.clpi
new file mode 100644
index 0000000..5b70bc3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00011.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00012.clpi b/tests/fixtures/disc25/CLIPINF/00012.clpi
new file mode 100644
index 0000000..89ed28c
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00012.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00013.clpi b/tests/fixtures/disc25/CLIPINF/00013.clpi
new file mode 100644
index 0000000..5743f2e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00013.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00014.clpi b/tests/fixtures/disc25/CLIPINF/00014.clpi
new file mode 100644
index 0000000..e56b3f4
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00014.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00015.clpi b/tests/fixtures/disc25/CLIPINF/00015.clpi
new file mode 100644
index 0000000..fbd402d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00015.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00016.clpi b/tests/fixtures/disc25/CLIPINF/00016.clpi
new file mode 100644
index 0000000..2c0f587
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00016.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00017.clpi b/tests/fixtures/disc25/CLIPINF/00017.clpi
new file mode 100644
index 0000000..95e0816
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00017.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00018.clpi b/tests/fixtures/disc25/CLIPINF/00018.clpi
new file mode 100644
index 0000000..ceecfeb
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00018.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00019.clpi b/tests/fixtures/disc25/CLIPINF/00019.clpi
new file mode 100644
index 0000000..1514c97
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00019.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00020.clpi b/tests/fixtures/disc25/CLIPINF/00020.clpi
new file mode 100644
index 0000000..807ab6d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00020.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00021.clpi b/tests/fixtures/disc25/CLIPINF/00021.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00021.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00022.clpi b/tests/fixtures/disc25/CLIPINF/00022.clpi
new file mode 100644
index 0000000..cda1227
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00022.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00023.clpi b/tests/fixtures/disc25/CLIPINF/00023.clpi
new file mode 100644
index 0000000..42ada5e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00023.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00024.clpi b/tests/fixtures/disc25/CLIPINF/00024.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00024.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00025.clpi b/tests/fixtures/disc25/CLIPINF/00025.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00025.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00026.clpi b/tests/fixtures/disc25/CLIPINF/00026.clpi
new file mode 100644
index 0000000..902cb8e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00026.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00027.clpi b/tests/fixtures/disc25/CLIPINF/00027.clpi
new file mode 100644
index 0000000..963d2fd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00027.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00028.clpi b/tests/fixtures/disc25/CLIPINF/00028.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00028.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00029.clpi b/tests/fixtures/disc25/CLIPINF/00029.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00029.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00030.clpi b/tests/fixtures/disc25/CLIPINF/00030.clpi
new file mode 100644
index 0000000..807ab6d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00030.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00031.clpi b/tests/fixtures/disc25/CLIPINF/00031.clpi
new file mode 100644
index 0000000..1514c97
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00031.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00032.clpi b/tests/fixtures/disc25/CLIPINF/00032.clpi
new file mode 100644
index 0000000..4bd594e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00032.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00033.clpi b/tests/fixtures/disc25/CLIPINF/00033.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00033.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00034.clpi b/tests/fixtures/disc25/CLIPINF/00034.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00034.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00035.clpi b/tests/fixtures/disc25/CLIPINF/00035.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00035.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00036.clpi b/tests/fixtures/disc25/CLIPINF/00036.clpi
new file mode 100644
index 0000000..1982c1c
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00036.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00037.clpi b/tests/fixtures/disc25/CLIPINF/00037.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00037.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00038.clpi b/tests/fixtures/disc25/CLIPINF/00038.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00038.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00039.clpi b/tests/fixtures/disc25/CLIPINF/00039.clpi
new file mode 100644
index 0000000..963d2fd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00039.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00040.clpi b/tests/fixtures/disc25/CLIPINF/00040.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00040.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00041.clpi b/tests/fixtures/disc25/CLIPINF/00041.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00041.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00042.clpi b/tests/fixtures/disc25/CLIPINF/00042.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00042.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00043.clpi b/tests/fixtures/disc25/CLIPINF/00043.clpi
new file mode 100644
index 0000000..97c72c1
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00043.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00044.clpi b/tests/fixtures/disc25/CLIPINF/00044.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00044.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00045.clpi b/tests/fixtures/disc25/CLIPINF/00045.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00045.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00046.clpi b/tests/fixtures/disc25/CLIPINF/00046.clpi
new file mode 100644
index 0000000..42ada5e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00046.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00047.clpi b/tests/fixtures/disc25/CLIPINF/00047.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00047.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00048.clpi b/tests/fixtures/disc25/CLIPINF/00048.clpi
new file mode 100644
index 0000000..fc457ab
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00048.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00049.clpi b/tests/fixtures/disc25/CLIPINF/00049.clpi
new file mode 100644
index 0000000..4bd594e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00049.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00050.clpi b/tests/fixtures/disc25/CLIPINF/00050.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00050.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00051.clpi b/tests/fixtures/disc25/CLIPINF/00051.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00051.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00052.clpi b/tests/fixtures/disc25/CLIPINF/00052.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00052.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00053.clpi b/tests/fixtures/disc25/CLIPINF/00053.clpi
new file mode 100644
index 0000000..d49899f
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00053.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00054.clpi b/tests/fixtures/disc25/CLIPINF/00054.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00054.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00055.clpi b/tests/fixtures/disc25/CLIPINF/00055.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00055.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00056.clpi b/tests/fixtures/disc25/CLIPINF/00056.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00056.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00057.clpi b/tests/fixtures/disc25/CLIPINF/00057.clpi
new file mode 100644
index 0000000..807ab6d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00057.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00058.clpi b/tests/fixtures/disc25/CLIPINF/00058.clpi
new file mode 100644
index 0000000..cda1227
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00058.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00059.clpi b/tests/fixtures/disc25/CLIPINF/00059.clpi
new file mode 100644
index 0000000..1514c97
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00059.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00060.clpi b/tests/fixtures/disc25/CLIPINF/00060.clpi
new file mode 100644
index 0000000..d49899f
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00060.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00061.clpi b/tests/fixtures/disc25/CLIPINF/00061.clpi
new file mode 100644
index 0000000..6b033b3
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00061.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00062.clpi b/tests/fixtures/disc25/CLIPINF/00062.clpi
new file mode 100644
index 0000000..d49899f
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00062.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00063.clpi b/tests/fixtures/disc25/CLIPINF/00063.clpi
new file mode 100644
index 0000000..902cb8e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00063.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00064.clpi b/tests/fixtures/disc25/CLIPINF/00064.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00064.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00065.clpi b/tests/fixtures/disc25/CLIPINF/00065.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00065.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00066.clpi b/tests/fixtures/disc25/CLIPINF/00066.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00066.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00067.clpi b/tests/fixtures/disc25/CLIPINF/00067.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00067.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00068.clpi b/tests/fixtures/disc25/CLIPINF/00068.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00068.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00069.clpi b/tests/fixtures/disc25/CLIPINF/00069.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00069.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00070.clpi b/tests/fixtures/disc25/CLIPINF/00070.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00070.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00071.clpi b/tests/fixtures/disc25/CLIPINF/00071.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00071.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00072.clpi b/tests/fixtures/disc25/CLIPINF/00072.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00072.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00073.clpi b/tests/fixtures/disc25/CLIPINF/00073.clpi
new file mode 100644
index 0000000..97c72c1
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00073.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00074.clpi b/tests/fixtures/disc25/CLIPINF/00074.clpi
new file mode 100644
index 0000000..d130141
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00074.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00075.clpi b/tests/fixtures/disc25/CLIPINF/00075.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00075.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00076.clpi b/tests/fixtures/disc25/CLIPINF/00076.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00076.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00077.clpi b/tests/fixtures/disc25/CLIPINF/00077.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00077.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00078.clpi b/tests/fixtures/disc25/CLIPINF/00078.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00078.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00079.clpi b/tests/fixtures/disc25/CLIPINF/00079.clpi
new file mode 100644
index 0000000..1982c1c
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00079.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00080.clpi b/tests/fixtures/disc25/CLIPINF/00080.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00080.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00081.clpi b/tests/fixtures/disc25/CLIPINF/00081.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00081.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00082.clpi b/tests/fixtures/disc25/CLIPINF/00082.clpi
new file mode 100644
index 0000000..4bd594e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00082.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00083.clpi b/tests/fixtures/disc25/CLIPINF/00083.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00083.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00084.clpi b/tests/fixtures/disc25/CLIPINF/00084.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00084.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00085.clpi b/tests/fixtures/disc25/CLIPINF/00085.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00085.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00086.clpi b/tests/fixtures/disc25/CLIPINF/00086.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00086.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00087.clpi b/tests/fixtures/disc25/CLIPINF/00087.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00087.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00088.clpi b/tests/fixtures/disc25/CLIPINF/00088.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00088.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00089.clpi b/tests/fixtures/disc25/CLIPINF/00089.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00089.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00090.clpi b/tests/fixtures/disc25/CLIPINF/00090.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00090.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00091.clpi b/tests/fixtures/disc25/CLIPINF/00091.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00091.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00092.clpi b/tests/fixtures/disc25/CLIPINF/00092.clpi
new file mode 100644
index 0000000..807ab6d
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00092.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00093.clpi b/tests/fixtures/disc25/CLIPINF/00093.clpi
new file mode 100644
index 0000000..b1c4415
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00093.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00094.clpi b/tests/fixtures/disc25/CLIPINF/00094.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00094.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00095.clpi b/tests/fixtures/disc25/CLIPINF/00095.clpi
new file mode 100644
index 0000000..111ade7
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00095.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00096.clpi b/tests/fixtures/disc25/CLIPINF/00096.clpi
new file mode 100644
index 0000000..d3dc0a4
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00096.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00097.clpi b/tests/fixtures/disc25/CLIPINF/00097.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00097.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00098.clpi b/tests/fixtures/disc25/CLIPINF/00098.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00098.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00099.clpi b/tests/fixtures/disc25/CLIPINF/00099.clpi
new file mode 100644
index 0000000..cda1227
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00099.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00100.clpi b/tests/fixtures/disc25/CLIPINF/00100.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00100.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00101.clpi b/tests/fixtures/disc25/CLIPINF/00101.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00101.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00102.clpi b/tests/fixtures/disc25/CLIPINF/00102.clpi
new file mode 100644
index 0000000..d49899f
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00102.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00103.clpi b/tests/fixtures/disc25/CLIPINF/00103.clpi
new file mode 100644
index 0000000..902cb8e
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00103.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00104.clpi b/tests/fixtures/disc25/CLIPINF/00104.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00104.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00105.clpi b/tests/fixtures/disc25/CLIPINF/00105.clpi
new file mode 100644
index 0000000..97c72c1
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00105.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00106.clpi b/tests/fixtures/disc25/CLIPINF/00106.clpi
new file mode 100644
index 0000000..5171cbd
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00106.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00107.clpi b/tests/fixtures/disc25/CLIPINF/00107.clpi
new file mode 100644
index 0000000..e2bd391
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00107.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00108.clpi b/tests/fixtures/disc25/CLIPINF/00108.clpi
new file mode 100644
index 0000000..d130141
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00108.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00109.clpi b/tests/fixtures/disc25/CLIPINF/00109.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00109.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00110.clpi b/tests/fixtures/disc25/CLIPINF/00110.clpi
new file mode 100644
index 0000000..d130141
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00110.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00111.clpi b/tests/fixtures/disc25/CLIPINF/00111.clpi
new file mode 100644
index 0000000..3310360
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00111.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00112.clpi b/tests/fixtures/disc25/CLIPINF/00112.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00112.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00113.clpi b/tests/fixtures/disc25/CLIPINF/00113.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00113.clpi differ
diff --git a/tests/fixtures/disc25/CLIPINF/00114.clpi b/tests/fixtures/disc25/CLIPINF/00114.clpi
new file mode 100644
index 0000000..c9e9ddf
Binary files /dev/null and b/tests/fixtures/disc25/CLIPINF/00114.clpi differ
diff --git a/tests/fixtures/disc25/META/DL/bdmt_eng.xml b/tests/fixtures/disc25/META/DL/bdmt_eng.xml
new file mode 100644
index 0000000..16f2397
--- /dev/null
+++ b/tests/fixtures/disc25/META/DL/bdmt_eng.xml
@@ -0,0 +1,6 @@
+
+
+
+TEST DISC 25
+
+
diff --git a/tests/fixtures/disc25/MovieObject.bdmv b/tests/fixtures/disc25/MovieObject.bdmv
new file mode 100644
index 0000000..46f30df
Binary files /dev/null and b/tests/fixtures/disc25/MovieObject.bdmv differ
diff --git a/tests/fixtures/disc25/PLAYLIST/00000.mpls b/tests/fixtures/disc25/PLAYLIST/00000.mpls
new file mode 100644
index 0000000..9541ca8
Binary files /dev/null and b/tests/fixtures/disc25/PLAYLIST/00000.mpls differ
diff --git a/tests/fixtures/disc25/PLAYLIST/00001.mpls b/tests/fixtures/disc25/PLAYLIST/00001.mpls
new file mode 100644
index 0000000..92bc632
Binary files /dev/null and b/tests/fixtures/disc25/PLAYLIST/00001.mpls differ
diff --git a/tests/fixtures/disc25/PLAYLIST/00002.mpls b/tests/fixtures/disc25/PLAYLIST/00002.mpls
new file mode 100644
index 0000000..aa48c08
Binary files /dev/null and b/tests/fixtures/disc25/PLAYLIST/00002.mpls differ
diff --git a/tests/fixtures/disc25/PLAYLIST/00003.mpls b/tests/fixtures/disc25/PLAYLIST/00003.mpls
new file mode 100644
index 0000000..10c86eb
Binary files /dev/null and b/tests/fixtures/disc25/PLAYLIST/00003.mpls differ
diff --git a/tests/fixtures/disc25/ics_menu.bin b/tests/fixtures/disc25/ics_menu.bin
new file mode 100644
index 0000000..879f245
Binary files /dev/null and b/tests/fixtures/disc25/ics_menu.bin differ
diff --git a/tests/fixtures/disc25/index.bdmv b/tests/fixtures/disc25/index.bdmv
new file mode 100644
index 0000000..cee9035
Binary files /dev/null and b/tests/fixtures/disc25/index.bdmv differ
diff --git a/tests/test_disc22_scan.py b/tests/test_disc22_scan.py
new file mode 100644
index 0000000..2317c92
--- /dev/null
+++ b/tests/test_disc22_scan.py
@@ -0,0 +1,35 @@
+"""Integration tests for the disc22 fixture — 5-episode chapter-split compilation."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc22Episodes:
+ def test_episode_count(self, disc22_analysis: DiscAnalysis) -> None:
+ assert len(disc22_analysis.episodes) == 5
+
+ def test_episodes_are_ordered(self, disc22_analysis: DiscAnalysis) -> None:
+ assert [ep.episode for ep in disc22_analysis.episodes] == list(range(1, 6))
+
+ def test_all_from_same_playlist(self, disc22_analysis: DiscAnalysis) -> None:
+ assert all(ep.playlist == "00002.mpls" for ep in disc22_analysis.episodes)
+
+ def test_episode_durations(self, disc22_analysis: DiscAnalysis) -> None:
+ for ep in disc22_analysis.episodes:
+ dur_min = ep.duration_ms / 60000
+ assert 24 < dur_min < 32, f"ep{ep.episode} duration {dur_min:.1f}min out of range"
+
+
+class TestDisc22Specials:
+ def test_no_specials(self, disc22_analysis: DiscAnalysis) -> None:
+ assert len(disc22_analysis.special_features) == 0
+
+
+class TestDisc22Metadata:
+ def test_disc_title(self, disc22_analysis: DiscAnalysis) -> None:
+ assert disc22_analysis.disc_title == "TEST DISC 22"
diff --git a/tests/test_disc23_scan.py b/tests/test_disc23_scan.py
new file mode 100644
index 0000000..9924d8d
--- /dev/null
+++ b/tests/test_disc23_scan.py
@@ -0,0 +1,35 @@
+"""Integration tests for the disc23 fixture — 5-episode chapter-split compilation."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc23Episodes:
+ def test_episode_count(self, disc23_analysis: DiscAnalysis) -> None:
+ assert len(disc23_analysis.episodes) == 5
+
+ def test_episodes_are_ordered(self, disc23_analysis: DiscAnalysis) -> None:
+ assert [ep.episode for ep in disc23_analysis.episodes] == list(range(1, 6))
+
+ def test_all_from_same_playlist(self, disc23_analysis: DiscAnalysis) -> None:
+ assert all(ep.playlist == "00002.mpls" for ep in disc23_analysis.episodes)
+
+ def test_episode_durations(self, disc23_analysis: DiscAnalysis) -> None:
+ for ep in disc23_analysis.episodes:
+ dur_min = ep.duration_ms / 60000
+ assert 24 < dur_min < 32, f"ep{ep.episode} duration {dur_min:.1f}min out of range"
+
+
+class TestDisc23Specials:
+ def test_no_specials(self, disc23_analysis: DiscAnalysis) -> None:
+ assert len(disc23_analysis.special_features) == 0
+
+
+class TestDisc23Metadata:
+ def test_disc_title(self, disc23_analysis: DiscAnalysis) -> None:
+ assert disc23_analysis.disc_title == "TEST DISC 23"
diff --git a/tests/test_disc24_scan.py b/tests/test_disc24_scan.py
new file mode 100644
index 0000000..94c1b0f
--- /dev/null
+++ b/tests/test_disc24_scan.py
@@ -0,0 +1,49 @@
+"""Integration tests for the disc24 fixture — 3-episode compilation + commentary + extras."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc24Episodes:
+ def test_episode_count(self, disc24_analysis: DiscAnalysis) -> None:
+ assert len(disc24_analysis.episodes) == 3
+
+ def test_episodes_are_ordered(self, disc24_analysis: DiscAnalysis) -> None:
+ assert [ep.episode for ep in disc24_analysis.episodes] == [1, 2, 3]
+
+ def test_all_from_same_playlist(self, disc24_analysis: DiscAnalysis) -> None:
+ assert all(ep.playlist == "00002.mpls" for ep in disc24_analysis.episodes)
+
+ def test_episode_durations(self, disc24_analysis: DiscAnalysis) -> None:
+ for ep in disc24_analysis.episodes:
+ dur_min = ep.duration_ms / 60000
+ assert 25 < dur_min < 33, f"ep{ep.episode} duration {dur_min:.1f}min out of range"
+
+
+class TestDisc24Specials:
+ def test_special_count(self, disc24_analysis: DiscAnalysis) -> None:
+ assert len(disc24_analysis.special_features) == 8
+
+ def test_extra_count(self, disc24_analysis: DiscAnalysis) -> None:
+ extras = [sf for sf in disc24_analysis.special_features if sf.category == "extra"]
+ assert len(extras) == 1
+
+ def test_commentary_count(self, disc24_analysis: DiscAnalysis) -> None:
+ commentaries = [
+ sf for sf in disc24_analysis.special_features if sf.category == "commentary"
+ ]
+ assert len(commentaries) == 3
+
+ def test_creditless_ed_count(self, disc24_analysis: DiscAnalysis) -> None:
+ creds = [sf for sf in disc24_analysis.special_features if sf.category == "creditless_ed"]
+ assert len(creds) == 4
+
+
+class TestDisc24Metadata:
+ def test_disc_title(self, disc24_analysis: DiscAnalysis) -> None:
+ assert disc24_analysis.disc_title == "TEST DISC 24"
diff --git a/tests/test_disc25_scan.py b/tests/test_disc25_scan.py
new file mode 100644
index 0000000..b54378f
--- /dev/null
+++ b/tests/test_disc25_scan.py
@@ -0,0 +1,36 @@
+"""Integration tests for the disc25 fixture — special disc with OVA + digital archive."""
+
+from __future__ import annotations
+
+import pytest
+
+from bdpl.model import DiscAnalysis
+
+pytestmark = pytest.mark.integration
+
+
+class TestDisc25Episodes:
+ def test_episode_count(self, disc25_analysis: DiscAnalysis) -> None:
+ assert len(disc25_analysis.episodes) == 1
+
+ def test_episode_playlist(self, disc25_analysis: DiscAnalysis) -> None:
+ assert disc25_analysis.episodes[0].playlist == "00002.mpls"
+
+ def test_episode_duration(self, disc25_analysis: DiscAnalysis) -> None:
+ dur_min = disc25_analysis.episodes[0].duration_ms / 60000
+ assert 43 < dur_min < 45, f"OVA duration {dur_min:.1f}min, expected ~44min"
+
+
+class TestDisc25Specials:
+ def test_special_feature_count(self, disc25_analysis: DiscAnalysis) -> None:
+ assert len(disc25_analysis.special_features) == 1
+
+ def test_digital_archive(self, disc25_analysis: DiscAnalysis) -> None:
+ sf = disc25_analysis.special_features[0]
+ assert sf.category == "digital_archive"
+ assert sf.playlist == "00003.mpls"
+
+
+class TestDisc25Metadata:
+ def test_disc_title(self, disc25_analysis: DiscAnalysis) -> None:
+ assert disc25_analysis.disc_title == "TEST DISC 25"
diff --git a/tests/test_disc_matrix.py b/tests/test_disc_matrix.py
index 1a02ffe..3606d2d 100644
--- a/tests/test_disc_matrix.py
+++ b/tests/test_disc_matrix.py
@@ -32,6 +32,10 @@
("disc19_analysis", 1, ["00002.mpls"]),
("disc20_analysis", 1, ["00002.mpls"]),
("disc21_analysis", 1, ["00002.mpls"]),
+ ("disc22_analysis", 5, ["00002.mpls"] * 5),
+ ("disc23_analysis", 5, ["00002.mpls"] * 5),
+ ("disc24_analysis", 3, ["00002.mpls"] * 3),
+ ("disc25_analysis", 1, ["00002.mpls"]),
],
)
def test_disc_episode_expectation_matrix(
@@ -69,6 +73,10 @@ def test_disc_episode_expectation_matrix(
("disc19_analysis", 1, 1), # 1 digital archive (hint-backed)
("disc20_analysis", 1, 1), # 1 extra (trailer)
("disc21_analysis", 1, 1), # 1 digital archive
+ ("disc22_analysis", 0, 0), # chapter-split disc with no extras
+ ("disc23_analysis", 0, 0), # chapter-split disc with no extras
+ ("disc24_analysis", 8, 8), # 1 extra + 3 commentary + 4 creditless ED
+ ("disc25_analysis", 1, 1), # 1 digital archive
],
)
def test_disc_special_visibility_expectation_matrix(
@@ -110,6 +118,10 @@ def test_disc_special_visibility_expectation_matrix(
"disc19_analysis",
"disc20_analysis",
"disc21_analysis",
+ "disc22_analysis",
+ "disc23_analysis",
+ "disc24_analysis",
+ "disc25_analysis",
],
)
def test_disc_episode_segment_boundaries_matrix(
@@ -155,6 +167,10 @@ def test_disc_episode_segment_boundaries_matrix(
"disc19_analysis",
"disc20_analysis",
"disc21_analysis",
+ "disc22_analysis",
+ "disc23_analysis",
+ "disc24_analysis",
+ "disc25_analysis",
],
)
def test_disc_special_boundary_semantics_matrix(
@@ -207,6 +223,10 @@ def test_disc_special_boundary_semantics_matrix(
("disc19_analysis", 0),
("disc20_analysis", 0),
("disc21_analysis", 0),
+ ("disc22_analysis", 0),
+ ("disc23_analysis", 0),
+ ("disc24_analysis", 0),
+ ("disc25_analysis", 0),
],
)
def test_disc_special_chapter_split_expectation_matrix(
@@ -242,6 +262,10 @@ def test_disc_special_chapter_split_expectation_matrix(
("disc19_analysis", "TEST DISC 19"),
("disc20_analysis", "TEST DISC 20"),
("disc21_analysis", "TEST DISC 21"),
+ ("disc22_analysis", "TEST DISC 22"),
+ ("disc23_analysis", "TEST DISC 23"),
+ ("disc24_analysis", "TEST DISC 24"),
+ ("disc25_analysis", "TEST DISC 25"),
],
)
def test_disc_title_extraction_matrix(