# -*- coding: utf-8 -*-

import pytest
import subprocess
import os
import sys
import struct

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))

import pycdlib

from test_common import *

def do_a_test(tmp_path, outfile, check_func):
    testout = tmp_path / 'writetest.iso'

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))
    check_func(iso, os.stat(str(outfile)).st_size)

    iso.write(str(testout))

    iso.close()

    # Now round-trip through write.
    iso2 = pycdlib.PyCdlib()
    iso2.open(str(testout))
    check_func(iso2, os.stat(str(outfile)).st_size)
    iso2.close()

def test_parse_invalid_file(tmp_path):
    iso = pycdlib.PyCdlib()
    with pytest.raises(TypeError):
        iso.open(None)

def test_parse_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'nofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_nofiles)

def test_parse_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_onefile)

def test_parse_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_onedir)

def test_parse_twofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    with open(os.path.join(str(indir), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_twofiles)

def test_parse_twodirs(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefileonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'bb'
    newdir.mkdir()
    newdir = indir / 'aa'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_twodirs)

def test_parse_onefileonedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefileonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_onefileonedir)

def test_parse_onefile_onedirwithfile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefileonedirwithfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(dir1), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_onefile_onedirwithfile)

def test_parse_tendirs(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'tendirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 10
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_tendirs)

def test_parse_dirs_overflow_ptr_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'manydirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 295
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_dirs_overflow_ptr_extent)

def test_parse_dirs_just_short_ptr_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'manydirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 293
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_dirs_just_short_ptr_extent)

def test_parse_twoextentfile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'bigfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    outstr = b''
    for j in range(0, 8):
        for i in range(0, 256):
            outstr += struct.pack('=B', i)
    outstr += struct.pack('=B', 0)
    with open(os.path.join(str(indir), 'bigfile'), 'wb') as outfp:
        outfp.write(outstr)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    testout = tmp_path / 'writetest.iso'

    do_a_test(tmp_path, outfile, check_twoextentfile)

def test_parse_twoleveldeepdir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twoleveldeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    subdir = dir1 / 'subdir1'
    subdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_twoleveldeepdir)

def test_parse_twoleveldeepfile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twoleveldeepfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    subdir1 = dir1 / 'subdir1'
    subdir1.mkdir()
    with open(os.path.join(str(subdir1), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_twoleveldeepfile)

def test_parse_joliet_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'joliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_nofiles)

def test_parse_joliet_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'joliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_onedir)

def test_parse_joliet_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_onefile)

def test_parse_joliet_onefileonedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_onefileonedir)

def test_parse_eltorito_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_nofiles)

def test_parse_eltorito_twofile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritotwofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    with open(os.path.join(str(indir), 'aa'), 'wb') as outfp:
        outfp.write(b'aa\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_twofile)

def test_parse_rr_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrnofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_nofiles)

def test_parse_rr_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rronefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_onefile)

def test_parse_rr_twofile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrtwofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    with open(os.path.join(str(indir), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_twofile)

def test_parse_rr_onefileonedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rronefileonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_onefileonedir)

def test_parse_rr_onefileonedirwithfile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rronefileonedirwithfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(dir1), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_onefileonedirwithfile)

def test_parse_rr_symlink(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrsymlink'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('foo', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_symlink)

def test_parse_rr_symlink2(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrsymlink2'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(dir1), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('dir1/foo', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_symlink2)

def test_parse_rr_symlink_dot(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrsymlinkdot'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('.', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_symlink_dot)

def test_parse_rr_symlink_dotdot(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrsymlinkdotdot'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('..', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_symlink_dotdot)

def test_parse_rr_symlink_broken(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrsymlinkbroken'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('foo', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_symlink_broken)

def test_parse_alternating_subdir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'alternating'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'bb'), 'wb') as outfp:
        outfp.write(b'bb\n')
    cc = newdir = indir / 'cc'
    newdir.mkdir()
    aa = newdir = indir / 'aa'
    newdir.mkdir()
    with open(os.path.join(str(indir), 'dd'), 'wb') as outfp:
        outfp.write(b'dd\n')
    with open(os.path.join(str(cc), 'sub2'), 'wb') as outfp:
        outfp.write(b'sub2\n')
    with open(os.path.join(str(aa), 'sub1'), 'wb') as outfp:
        outfp.write(b'sub1\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_alternating_subdir)

def test_parse_rr_verylongname(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrverylongname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'a'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'aa\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_verylongname)

def test_parse_rr_verylongname_joliet(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrverylongname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'a'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'aa\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_verylongname_joliet)

def test_parse_rr_manylongname(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrmanylongname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'a'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'aa\n')
    with open(os.path.join(str(indir), 'b'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'bb\n')
    with open(os.path.join(str(indir), 'c'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'cc\n')
    with open(os.path.join(str(indir), 'd'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'dd\n')
    with open(os.path.join(str(indir), 'e'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'ee\n')
    with open(os.path.join(str(indir), 'f'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'ff\n')
    with open(os.path.join(str(indir), 'g'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'gg\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_manylongname)

def test_parse_rr_manylongname2(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrmanylongname2'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'a'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'aa\n')
    with open(os.path.join(str(indir), 'b'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'bb\n')
    with open(os.path.join(str(indir), 'c'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'cc\n')
    with open(os.path.join(str(indir), 'd'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'dd\n')
    with open(os.path.join(str(indir), 'e'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'ee\n')
    with open(os.path.join(str(indir), 'f'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'ff\n')
    with open(os.path.join(str(indir), 'g'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'gg\n')
    with open(os.path.join(str(indir), 'h'*RR_MAX_FILENAME_LENGTH), 'wb') as outfp:
        outfp.write(b'hh\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_manylongname2)

def test_parse_joliet_and_rr_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietandrrnofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_rr_nofiles)

def test_parse_joliet_and_rr_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietandrronefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_rr_onefile)

def test_parse_joliet_and_rr_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietandrronedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_rr_onedir)

def test_parse_rr_and_eltorito_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrandeltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_and_eltorito_nofiles)

def test_parse_rr_and_eltorito_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrandeltoritoonefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_and_eltorito_onefile)

def test_parse_rr_and_eltorito_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrandeltoritoonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_and_eltorito_onedir)

def test_parse_joliet_and_eltorito_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietandeltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_eltorito_nofiles)

def test_parse_joliet_and_eltorito_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietandeltoritoonefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_eltorito_onefile)

def test_parse_joliet_and_eltorito_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietandeltoritoonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_eltorito_onedir)

@pytest.mark.skipif(find_executable('isohybrid') is None,
                    reason='syslinux not installed')
def test_parse_isohybrid(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isohybrid'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'isolinux.bin'), 'wb') as outfp:
        outfp.seek(0x40)
        outfp.write(b'\xfb\xc0\x78\x70')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'isolinux.bin', '-no-emul-boot',
                     '-boot-load-size', '4',
                     '-o', str(outfile), str(indir)])
    subprocess.call(['isohybrid', '-v', str(outfile)])

    do_a_test(tmp_path, outfile, check_isohybrid)

@pytest.mark.skipif(find_executable('isohybrid') is None,
                    reason='syslinux not installed')
def test_parse_isohybrid_uefi(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isohybriduefi'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'isolinux.bin'), 'wb') as outfp:
        outfp.seek(0x40)
        outfp.write(b'\xfb\xc0\x78\x70')
    with open(os.path.join(str(indir), 'efiboot.img'), 'wb') as outfp:
        outfp.write(b'a')
    retcode = subprocess.call(['genisoimage', '-v', '-v', '-no-pad',
                               '-c', 'boot.cat', '-b', 'isolinux.bin',
                               '-no-emul-boot', '-boot-load-size', '4',
                               '-boot-info-table', '-eltorito-alt-boot',
                               '-efi-boot', 'efiboot.img', '-no-emul-boot',
                               '-o', str(outfile), str(indir)])
    if retcode != 0:
        pytest.skip("This version of genisoimage doesn't support -efi-boot")

    subprocess.call(['isohybrid', '-u', '-v', str(outfile)])

    do_a_test(tmp_path, outfile, check_isohybrid_uefi)

@pytest.mark.skipif(find_executable('isohybrid') is None,
                    reason='syslinux not installed')
def test_parse_isohybrid_mac_uefi(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isohybridmacuefi'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'isolinux.bin'), 'wb') as outfp:
        outfp.seek(0x40)
        outfp.write(b'\xfb\xc0\x78\x70')
    with open(os.path.join(str(indir), 'efiboot.img'), 'wb') as outfp:
        outfp.write(b'a')
    with open(os.path.join(str(indir), 'macboot.img'), 'wb') as outfp:
        outfp.write(b'b')
    retcode = subprocess.call(['genisoimage', '-v', '-v', '-no-pad',
                               '-c', 'boot.cat', '-b', 'isolinux.bin',
                               '-no-emul-boot', '-boot-load-size', '4',
                               '-boot-info-table', '-eltorito-alt-boot',
                               '-efi-boot', 'efiboot.img', '-no-emul-boot',
                               '-eltorito-alt-boot', '-efi-boot', 'macboot.img',
                               '-no-emul-boot',
                               '-o', str(outfile), str(indir)])
    if retcode != 0:
        pytest.skip("This version of genisoimage doesn't support -efi-boot")

    subprocess.call(['isohybrid', '-u', '-m', '-v', str(outfile)])

    do_a_test(tmp_path, outfile, check_isohybrid_mac_uefi)

def test_parse_joliet_rr_and_eltorito_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietrrandeltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_rr_and_eltorito_nofiles)

def test_parse_joliet_rr_and_eltorito_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietrrandeltoritoonefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_rr_and_eltorito_onefile)

def test_parse_joliet_rr_and_eltorito_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietrrandeltoritoonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_rr_and_eltorito_onedir)

def test_parse_rr_deep_dir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrdeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7' / 'dir8'
    newdir.mkdir(parents=True)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_deep_dir)

def test_parse_rr_deep(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrdeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7' / 'dir8'
    newdir.mkdir(parents=True)
    with open(os.path.join(str(indir), 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', 'dir6', 'dir7', 'dir8', 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_deep)

def test_parse_rr_deep2(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrdeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7' / 'dir8' / 'dir9'
    newdir.mkdir(parents=True)
    with open(os.path.join(str(indir), 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', 'dir6', 'dir7', 'dir8', 'dir9', 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_deep2)

def test_parse_xa_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xa'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_xa_nofiles)

def test_parse_xa_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xa'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_xa_onefile)

def test_parse_xa_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xa'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_xa_onedir)

def test_parse_sevendeepdirs(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'sevendeepdirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 7
    x = indir
    for i in range(1, 1+numdirs):
        x = x / ('dir%d' % i)
        x.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_sevendeepdirs)

def test_parse_xa_joliet_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xajoliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_xa_joliet_nofiles)

def test_parse_xa_joliet_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xajolietonefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_xa_joliet_onefile)

def test_parse_xa_joliet_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xajolietonefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_xa_joliet_onedir)

def test_parse_iso_level4_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isolevel4nofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_isolevel4_nofiles)

def test_parse_iso_level4_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_isolevel4_onefile)

def test_parse_iso_level4_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isolevel4onedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_isolevel4_onedir)

def test_parse_iso_level4_eltorito(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isolevel4eltorito'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_isolevel4_eltorito)

def test_parse_everything(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'everything'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7' / 'dir8'
    newdir.mkdir(parents=True)
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    with open(os.path.join(str(indir), 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', 'dir6', 'dir7', 'dir8', 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('foo', 'sym')
    os.chdir(pwd)
    os.link(os.path.join(str(indir), 'foo'), os.path.join(str(indir), 'dir1', 'foo'))
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-rational-rock', '-xa', '-boot-info-table',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_everything)

def test_parse_rr_xa_nofiles(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xarrnofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_xa_nofiles)

def test_parse_rr_xa_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xarronefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_xa_onefile)

def test_parse_rr_xa_onedir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'xarronefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-xa', '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_xa_onedir)

def test_parse_rr_joliet_symlink(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrsymlinkbroken'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.symlink('foo', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_joliet_symlink)

def test_parse_rr_joliet_deep(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrjolietdeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7' / 'dir8'
    newdir.mkdir(parents=True)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_joliet_deep)

def test_parse_eltorito_multi_boot(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'multiboot'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    with open(os.path.join(str(indir), 'boot2'), 'wb') as outfp:
        outfp.write(b'boot2\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-b', 'boot', '-c', 'boot.cat', '-no-emul-boot',
                     '-eltorito-alt-boot', '-b', 'boot2', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_multi_boot)

def test_parse_eltorito_boot_table(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'boottable'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-b', 'boot', '-c', 'boot.cat', '-no-emul-boot',
                     '-boot-info-table', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_boot_info_table)

def test_parse_eltorito_boot_table_large(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'boottable'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot'*20)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-b', 'boot', '-c', 'boot.cat', '-no-emul-boot',
                     '-boot-info-table', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_boot_info_table_large)

def test_parse_hard_link(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'boottable'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    os.link(os.path.join(str(indir), 'foo'), os.path.join(str(indir), str(dir1), 'foo'))
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_hard_link)

def test_parse_open_twice(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'This object already has an ISO; either close it or create a new object')

    iso.close()

def test_parse_get_and_write_fp_not_initialized(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        iso.get_and_write_fp('/FOO.;1', open(os.path.join(str(tmp_path), 'bar'), 'w'))
    assert(str(excinfo.value) == 'This object is not initialized; call either open() or new() to create an ISO')

def test_parse_get_and_write_not_initialized(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        iso.get_and_write('/FOO.;1', 'foo')
    assert(str(excinfo.value) == 'This object is not initialized; call either open() or new() to create an ISO')

def test_parse_write_not_initialized(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        iso.write('out.iso')
    assert(str(excinfo.value) == 'This object is not initialized; call either open() or new() to create an ISO')

def test_parse_write_with_progress(tmp_path):
    test_parse_write_with_progress.num_progress_calls = 0
    test_parse_write_with_progress.done = 0
    def _progress(done, total):
        assert(total == 73728)
        test_parse_write_with_progress.num_progress_calls += 1
        test_parse_write_with_progress.done = done

    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))
    iso.write(str(tmp_path / 'writetest.iso'), progress_cb=_progress)

    assert(test_parse_write_with_progress.num_progress_calls == 14)
    assert(test_parse_write_with_progress.done == 73728)

    iso.close()

def test_parse_write_with_progress_three_arg(tmp_path):
    def _progress(done, total, opaque):
        assert(total == 73728)
        opaque['num_calls'] += 1
        opaque['done'] = done

    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))
    collect = {'num_calls': 0, 'done': 0}
    iso.write(str(tmp_path / 'writetest.iso'), progress_cb=_progress, progress_opaque=collect)

    assert(collect['num_calls'] == 14)
    assert(collect['done'] == 73728)

    iso.close()

def test_parse_get_entry(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))

    fooentry = iso.get_entry('/FOO.;1')
    assert(len(fooentry.children) == 0)
    assert(fooentry.isdir == False)
    assert(fooentry.is_root == False)
    assert(fooentry.file_ident == b'FOO.;1')
    assert(fooentry.dr_len == 40)
    assert(fooentry.extent_location() == 24)
    assert(fooentry.file_flags == 0)
    assert(fooentry.get_data_length() == 4)

    iso.close()

def test_parse_get_entry_not_initialized(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        fooentry = iso.get_entry('/FOO.;1')
    assert(str(excinfo.value) == 'This object is not initialized; call either open() or new() to create an ISO')

def test_parse_list_dir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(dir1), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))

    for children in iso.list_dir('/DIR1'):
        pass

    iso.close()

def test_parse_list_dir_not_initialized(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(dir1), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        for children in iso.list_dir('/DIR1'):
            pass
    assert(str(excinfo.value) == 'This object is not initialized; call either open() or new() to create an ISO')

def test_parse_list_dir_not_dir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'twofile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()

    iso.open(str(outfile))

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        for children in iso.list_dir('/FOO.;1'):
            pass
    assert(str(excinfo.value) == 'Record is not a directory!')

    iso.close()

def test_parse_get_and_write(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'f\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))

    foofile = os.path.join(str(indir), 'foo')
    iso.get_and_write('/foo', foofile)

    iso.close()

    with open(foofile, 'r') as infp:
        assert(infp.read() == 'f\n')

def test_parse_open_fp_twice(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()

    iso.open(str(outfile))

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        with open(str(outfile), 'rb') as infp:
            iso.open_fp(infp)
    assert(str(excinfo.value) == 'This object already has an ISO; either close it or create a new object')

def test_parse_open_invalid_vd(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Valid ISO9660 filesystems must have at least one PVD')

def test_parse_same_dirname_different_parent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'samedirnamedifferentparent'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    dir2 = newdir = indir / 'dir2'
    newdir.mkdir()
    boot1 = dir1 / 'boot'
    boot2 = dir2 / 'boot'
    boot1.mkdir()
    boot2.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-rational-rock',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_same_dirname_different_parent)

def test_parse_joliet_iso_level_4(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietisolevel4'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir1 = newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_isolevel4)

def test_parse_eltorito_nofiles_hide(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-hide', 'boot.cat',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_nofiles_hide)

def test_parse_eltorito_nofiles_hide_joliet(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-hide', 'boot.cat', '-hide-joliet', 'boot.cat',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_eltorito_nofiles_hide)

def test_parse_eltorito_nofiles_hide_joliet_only(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-hide-joliet', 'boot.cat',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_eltorito_nofiles_hide_only)

def test_parse_eltorito_nofiles_hide_iso_only_joliet(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-J', '-hide', 'boot.cat',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_and_eltorito_nofiles_hide_iso_only)

def test_parse_hard_link_reshuffle(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'boottable'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    os.link(os.path.join(str(indir), 'foo'), os.path.join(str(indir), 'bar'))
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_hard_link_reshuffle)

def test_parse_open_invalid_pvd_ident(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+5)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Valid ISO9660 filesystems must have at least one PVD')

def test_parse_open_invalid_pvd_version(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+6)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid volume descriptor version 2')

def test_parse_open_invalid_pvd_unused1(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+7)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'PVD flags field is not zero')

def test_parse_open_invalid_pvd_unused2(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+72)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'data in 2nd unused field not zero')

def test_parse_open_invalid_pvd_unused4(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+882)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'data in 2nd unused field not zero')

def test_parse_open_invalid_pvd_unused5(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the last
    # byte of the PVD.  According to Ecma-119 this is invalid, but we have
    # seen ISOs in the wild where there is something other than 0 here, so
    # we allow it.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)-1)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    iso.open(str(outfile))
    iso.close()

def test_parse_invalid_pvd_space_size_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+84)
        fp.write(b'\x00\x00\x00\x00')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian space size disagree')

def test_parse_invalid_pvd_set_size_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+122)
        fp.write(b'\x00\x44')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian set size disagree')

def test_parse_invalid_pvd_seqnum_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+126)
        fp.write(b'\x00\x44')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian seqnum disagree')

def test_parse_invalid_pvd_lb_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+130)
        fp.write(b'\x00\x01')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian logical block size disagree')

def test_parse_invalid_pvd_ptr_size_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((16*2048)+136)
        fp.write(b'\x00\x01\x00\x00')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian path table size disagree')

def test_parse_open_invalid_vdst_ident(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+5)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Valid ISO9660 filesystems must have at least one Volume Descriptor Set Terminator')

def test_parse_open_invalid_vdst_version(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+6)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid VDST version')

def test_parse_invalid_br_ident(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+5)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    # The error is a bit odd, but correct; since we can't identify the record,
    # we have to assume it is the end of volume descriptors (there is no other
    # definitive marker).  We don't find out that this was a problem until we
    # see that we didn't parse the VDST.
    assert(str(excinfo.value) == 'Valid ISO9660 filesystems must have at least one Volume Descriptor Set Terminator')

def test_parse_invalid_br_version(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+6)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid boot record version')

def test_parse_open_invalid_svd_ident(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+5)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    # The error is a bit odd, but correct; since we can't identify the record,
    # we have to assume it is the end of volume descriptors (there is no other
    # definitive marker).  We don't find out that this was a problem until we
    # see that we didn't parse the VDST.
    assert(str(excinfo.value) == 'Valid ISO9660 filesystems must have at least one Volume Descriptor Set Terminator')

def test_parse_open_invalid_svd_version(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+6)
        fp.write(b'\x03')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid volume descriptor version 3')

def test_parse_open_invalid_svd_unused1(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+72)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'data in 2nd unused field not zero')

def test_parse_open_invalid_svd_file_structure_version(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+881)
        fp.write(b'\x03')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'File structure version expected to be 1')

def test_parse_open_invalid_svd_unused2(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+882)
        fp.write(b'\x02')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'data in 2nd unused field not zero')

def test_parse_invalid_svd_space_size_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+84)
        fp.write(b'\x00\x00\x00\x00')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian space size disagree')

def test_parse_invalid_svd_set_size_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+122)
        fp.write(b'\x00\x44')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian set size disagree')

def test_parse_invalid_svd_seqnum_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+126)
        fp.write(b'\x00\x44')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian seqnum disagree')

def test_parse_invalid_svd_lb_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+130)
        fp.write(b'\x00\x01')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian logical block size disagree')

def test_parse_invalid_svd_ptr_size_le_be_mismatch(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte.  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek((17*2048)+136)
        fp.write(b'\x00\x01\x00\x00')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian path table size disagree')

def test_parse_iso_too_small(tmp_path):
    indir = tmp_path / 'isotoosmall'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(outfile, 'wb') as outfp:
        outfp.write(b'\x00'*16*2048)

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Failed to read entire volume descriptor')

def test_parse_eltorito_boot_table_odd(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'boottable'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boo'*27)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-b', 'boot', '-c', 'boot.cat', '-no-emul-boot',
                     '-boot-info-table', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_boot_info_table_large_odd)

def test_parse_joliet_large_directory(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietlargedirectory'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    for i in range(1, 50):
        newdir = indir / ('dir' + str(i))
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_large_directory)

def test_parse_zero_byte_file(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'zerobytefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        pass
    with open(os.path.join(str(indir), 'bar'), 'wb') as outfp:
        outfp.write(b'bar\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_zero_byte_file)

def test_parse_dirrecord_too_short(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'tooshort'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    with open(outfile, 'a+b') as editfp:
        os.ftruncate(editfp.fileno(), 47104)

    iso = pycdlib.PyCdlib()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid directory record')

def test_parse_eltorito_hide_boot(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritohideboot'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-hide', 'boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_hide_boot)

def test_parse_get_entry_joliet(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'getentryjoliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J',
                     '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))

    fooentry = iso.get_entry('/foo', joliet=True)
    assert(len(fooentry.children) == 0)
    assert(fooentry.isdir == False)
    assert(fooentry.is_root == False)
    assert(fooentry.file_ident == 'foo'.encode('utf-16_be'))
    assert(fooentry.dr_len == 40)
    assert(fooentry.extent_location() == 30)
    assert(fooentry.file_flags == 0)
    assert(fooentry.get_data_length() == 4)

    iso.close()

def test_parse_dirrecord_nonzero_pad(tmp_path):
    indir = tmp_path / 'dirrecordnonzeropad'
    indir.mkdir()
    outfile = str(indir) + '.iso'

    for d in range(0, 53):
        newdir = indir / ('dir%d' % d)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    with open(outfile, 'r+b') as changefp:
        changefp.seek(24*2048 - 1)
        changefp.write(b'\xff')

    iso = pycdlib.PyCdlib()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid padding on ISO')

def test_parse_open_invalid_eltorito_header_id(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the El Torito
    # header ID (extent 25).  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048 + 0)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'El Torito Validation entry header ID not 1')

def test_parse_open_invalid_eltorito_platform_id(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the El Torito
    # header ID (extent 25).  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048 + 1)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'El Torito Validation entry platform ID not valid')

def test_parse_open_invalid_eltorito_first_key_byte(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the El Torito
    # header ID (extent 25).  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048 + 0x1e)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'El Torito Validation entry first keybyte not 0x55')

def test_parse_open_invalid_eltorito_second_key_byte(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the El Torito
    # header ID (extent 25).  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048 + 0x1f)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'El Torito Validation entry second keybyte not 0xaa')

def test_parse_open_invalid_eltorito_csum(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'modifyinplaceisolevel4onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the El Torito
    # header ID (extent 25).  This should be enough to make an invalid ISO.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048 + 0x1c)
        fp.write(b'\x00')
        fp.write(b'\x00')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'El Torito Validation entry checksum not correct')

def test_parse_hidden_file(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'aaaaaaaa'), 'wb') as outfp:
        outfp.write(b'aa\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-hidden', 'aaaaaaaa', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_hidden_file)

def test_parse_hidden_dir(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-hidden', 'dir1', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_hidden_dir)

def test_parse_eltorito_bad_boot_indicator(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we have the ISO, perturb the initial entry
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048+32)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid El Torito initial entry boot indicator')

def test_parse_eltorito_bad_boot_media(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we have the ISO, perturb the initial entry
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048+33)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Invalid El Torito boot media type')

def test_parse_eltorito_bad_unused(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    # Now that we have the ISO, perturb the initial entry
    with open(str(outfile), 'r+b') as fp:
        fp.seek(25*2048+37)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'El Torito unused field must be 0')

def test_parse_eltorito_hd_emul(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'\x00'*446 + b'\x00\x01\x01\x00\x02\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00'*16 + b'\x00'*16 + b'\x00'*16 + b'\x55' + b'\xaa')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-hard-disk-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_hd_emul)

def test_parse_eltorito_hd_emul_not_bootable(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'\x00'*446 + b'\x00\x01\x01\x00\x02\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00'*16 + b'\x00'*16 + b'\x00'*16 + b'\x55' + b'\xaa')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-hard-disk-boot', '-no-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_hd_emul_not_bootable)

def test_parse_eltorito_floppy12(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'\x00'*(2400*512))
    # If you don't pass -hard-disk-boot or -no-emul-boot to genisoimage,
    # it assumes floppy.
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_floppy12)

def test_parse_eltorito_floppy144(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'\x00'*(2880*512))
    # If you don't pass -hard-disk-boot or -no-emul-boot to genisoimage,
    # it assumes floppy.
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_floppy144)

def test_parse_eltorito_floppy288(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'\x00'*(5760*512))
    # If you don't pass -hard-disk-boot or -no-emul-boot to genisoimage,
    # it assumes floppy.
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_floppy288)

def test_parse_ptr_le_and_be_disagree(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte of the Big Endian PTR.  This should make open_fp() fail.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(21*2048)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Little-endian and big-endian path table records do not agree')

def test_parse_joliet_ptr_le_and_be_disagree(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-iso-level', '1', '-no-pad', '-J',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and perturb the first
    # byte of the Joliet Big Endian PTR.  This should make open_fp() fail.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(24*2048)
        fp.write(b'\xF4')

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        iso.open(str(outfile))
    assert(str(excinfo.value) == 'Joliet little-endian and big-endian path table records do not agree')

def test_parse_add_file_with_semicolon(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'FOO;1'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-relaxed-filenames', '-o', str(outfile), str(indir)])

    # Now open up the ISO with pycdlib and check some things out.
    iso = pycdlib.PyCdlib()

    iso.open(str(outfile))

    do_a_test(tmp_path, outfile, check_onefile_with_semicolon)

    iso.close()

def test_parse_bad_eltorito_ident(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+') as outfp:
        # Change the EL TORITO SPECIFICATION string to be something else
        outfp.seek(17*2048+7)
        outfp.write('Z')

    do_a_test(tmp_path, outfile, check_bad_eltorito_ident)

def test_parse_duplicate_rrmoved_name(tmp_path):
    iso = pycdlib.PyCdlib()
    iso.new(rock_ridge='1.09')

    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    fdir = indir / 'A' / 'B' / 'C' / 'D' / 'E' / 'F'
    fdir.mkdir(parents=True)
    newdir = fdir / 'G' / '1'
    newdir.mkdir(parents=True)
    newdir = fdir / 'H' / '1'
    newdir.mkdir(parents=True)
    with open(os.path.join(str(indir), 'A', 'B', 'C', 'D', 'E', 'F', 'G', '1', 'first'), 'wb') as outfp:
        outfp.write(b'first\n')
    with open(os.path.join(str(indir), 'A', 'B', 'C', 'D', 'E', 'F', 'H', '1', 'second'), 'wb') as outfp:
        outfp.write(b'second\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_two_dirs_same_level)

def test_parse_eltorito_rr_verylongname(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrverylongname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'a'*RR_MAX_FILENAME_LENGTH, '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_rr_verylongname)

@pytest.mark.skipif(find_executable('isohybrid') is None,
                    reason='syslinux not installed')
def test_parse_isohybrid_file_before(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'isohybrid'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'isolinux.bin'), 'wb') as outfp:
        outfp.seek(0x40)
        outfp.write(b'\xfb\xc0\x78\x70')
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'isolinux.bin', '-no-emul-boot',
                     '-boot-load-size', '4',
                     '-o', str(outfile), str(indir)])
    subprocess.call(['isohybrid', '-v', str(outfile)])

    do_a_test(tmp_path, outfile, check_isohybrid_file_before)

def test_parse_eltorito_rr_joliet_verylongname(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrjolietverylongname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'a'*RR_MAX_FILENAME_LENGTH, '-b', 'boot', '-no-emul-boot',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_rr_joliet_verylongname)

def test_parse_joliet_dirs_overflow_ptr_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietmanydirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 216
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_dirs_overflow_ptr_extent)

def test_parse_joliet_dirs_just_short_ptr_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietjustshortdirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 215
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_dirs_just_short_ptr_extent)

def test_parse_joliet_dirs_add_ptr_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietjustshortdirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 295
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_dirs_add_ptr_extent)

def test_parse_joliet_dirs_rm_ptr_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietjustshortdirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 293
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_dirs_rm_ptr_extent)

def test_parse_long_directory_name(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'longdirectoryname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'directory1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '3', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_long_directory_name)

def test_parse_long_file_name(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'longdirectoryname'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foobarbaz1'), 'wb') as outfp:
        outfp.write(b'foobarbaz1\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '3', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_long_file_name)

def test_parse_overflow_root_dir_record(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'overflowrootdirrecord'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    for letter in ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o'):
        with open(os.path.join(str(indir), letter*20), 'wb') as outfp:
            outfp.write(b'\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_overflow_root_dir_record)

def test_parse_duplicate_deep_dir(tmp_path):
    indir = tmp_path / 'duplicatedeepdir'
    indir.mkdir()
    outfile = str(indir)+'.iso'

    get = indir / 'books' / 'lkhg' / 'HyperNews' / 'get'
    get.mkdir(parents=True)
    newdir = get / 'fs' / 'fs' / '1'
    newdir.mkdir(parents=True)
    khg = get / 'khg'
    khg.mkdir()
    newdir = khg / '1'
    newdir.mkdir(parents=True)
    newdir = khg / '117' / '1' / '1' / '1' / '1'
    newdir.mkdir(parents=True)
    newdir = khg / '35' / '1' / '1'
    newdir.mkdir(parents=True)

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_duplicate_deep_dir)

def test_parse_no_joliet_name(tmp_path):
    indir = tmp_path / 'nojolietname'
    indir.mkdir()
    outfile = str(indir)+'.iso'

    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-hide-joliet', 'foo', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_onefile_joliet_no_file)

def test_parse_joliet_isolevel4_nofiles(tmp_path):
    indir = tmp_path / 'jolietisolevel4nofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-J', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_isolevel4_nofiles)

def test_parse_deep_rr_symlink(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'sevendeepdirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    dir7 = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7'
    dir7.mkdir(parents=True)
    pwd = os.getcwd()
    os.chdir(str(dir7))
    os.symlink('/usr/share/foo', 'sym')
    os.chdir(pwd)
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_deep_rr_symlink)

def test_parse_rr_deep_weird_layout(tmp_path):
    indir = tmp_path / 'rrdeepweird'
    indir.mkdir()
    outfile = str(indir) + '.iso'
    absimp = indir / 'astroid' / 'astroid' / 'tests' / 'testdata' / 'python3' / 'data' / 'absimp'
    absimp.mkdir(parents=True)
    sidepackage = absimp / 'sidepackage'
    sidepackage.mkdir()
    with open(os.path.join(str(absimp), 'string.py'), 'wb') as outfp:
        outfp.write(b'from __future__ import absolute_import, print_functino\nimport string\nprint(string)\n')
    with open(os.path.join(str(sidepackage), '__init__.py'), 'wb') as outfp:
        outfp.write(b'"""a side package with nothing in it\n"""\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_deep_weird_layout)

def test_parse_rr_long_dir_name(tmp_path):
    indir = tmp_path / 'rrlongdirname'
    indir.mkdir()
    outfile = str(indir) + '.iso'
    newdir = indir / ('a'*RR_MAX_FILENAME_LENGTH)
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_long_dir_name)

def test_parse_rr_hidden_relocated(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrdeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7' / 'dir8' / 'dir9'
    newdir.mkdir(parents=True)
    with open(os.path.join(str(indir), 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', 'dir6', 'dir7', 'dir8', 'dir9', 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-rational-rock', '-hide-rr-moved', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_rr_relocated_hidden)

def test_parse_open_fp_not_binary(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'rrdeep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        with open(str(outfile), 'r') as infp:
            iso.open_fp(infp)
    assert(str(excinfo.value) == "The file to open must be in binary mode (add 'b' to the open flags)")

def test_parse_open_too_small_pvd(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'toosmallpvd'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and shrink the volume
    # size to be too small.  PyCdlib should fix it at open time.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048+0x50)
        fp.write(b'\x16\x00\x00\x00\x00\x00\x00\x16')

    do_a_test(tmp_path, outfile, check_onefile)

def test_parse_open_too_small_joliet(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'toosmalljoliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-J',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and shrink the volume
    # size to be too small.  PyCdlib should fix it at open time.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048+0x50)
        fp.write(b'\x16\x00\x00\x00\x00\x00\x00\x16')

    do_a_test(tmp_path, outfile, check_joliet_onefile)

def test_parse_open_too_small_isolevel4(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'toosmallisolevel4'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '4',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and shrink the volume
    # size to be too small.  PyCdlib should fix it at open time.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048+0x50)
        fp.write(b'\x16\x00\x00\x00\x00\x00\x00\x16')

    do_a_test(tmp_path, outfile, check_isolevel4_onefile)

def test_parse_open_larger_than_iso(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'largerthaniso'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    # Now that we've made a valid ISO, we open it up and make the file too
    # large.  PyCdlib should fix it at open time.
    with open(str(outfile), 'r+b') as fp:
        fp.seek(23*2048+0x4e)
        fp.write(b'\x01\x08\x00\x00\x00\x00\x08\x01')

    do_a_test(tmp_path, outfile, check_onefile_toolong)

def test_parse_pvd_zero_datetime(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'zerodatetimeiso'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048 + 813)
        fp.write(b'\x00'*17)

    do_a_test(tmp_path, outfile, check_pvd_zero_datetime)

def test_parse_pvd_zero_digit_datetime(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'zerodatetimeiso'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048 + 813)
        fp.write(b'0'*17)

    do_a_test(tmp_path, outfile, check_pvd_zero_datetime)

def test_parse_pvd_zero_digit_datetime_zero_tz(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'zerodatetimeiso'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048 + 813)
        fp.write(b'0'*16)
        fp.write(b'\x00')

    do_a_test(tmp_path, outfile, check_pvd_zero_datetime)

def test_parse_pvd_invalid_year(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'zerodatetimeiso'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048 + 813)
        fp.write(b'0'*4)

    do_a_test(tmp_path, outfile, check_pvd_zero_datetime)

def test_parse_bad_root_dir_ident(tmp_path):
    indir = tmp_path / 'badrootdirident'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048 + 156 + 33)
        fp.write(b'\x01')

    do_a_test(tmp_path, outfile, check_nofiles)

def test_parse_bad_file_structure_version(tmp_path):
    indir = tmp_path / 'badfilestructureversion'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-o', str(outfile), str(indir)])

    with open(str(outfile), 'r+b') as fp:
        fp.seek(16*2048 + 881)
        fp.write(b'\x02')

    do_a_test(tmp_path, outfile, check_nofiles)

def test_parse_get_file_from_iso_not_initialized(tmp_path):
    iso = pycdlib.PyCdlib()

    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidInput) as excinfo:
        iso.get_file_from_iso('junk')
    assert(str(excinfo.value) == 'This object is not initialized; call either open() or new() to create an ISO')

def test_parse_get_file_from_iso(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'onefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    iso = pycdlib.PyCdlib()
    iso.open(str(outfile))

    foofile = os.path.join(str(indir), 'foo')
    iso.get_file_from_iso(foofile, iso_path='/FOO.;1')

    iso.close()

    with open(foofile, 'r') as infp:
        assert(infp.read() == 'foo\n')

def test_parse_joliet_encoded_system_identifier(tmp_path):
    indir = tmp_path / 'jolietsysident'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'user-data'), 'wb') as outfp:
        outfp.write(b'''\
#cloud-config
password: password
chpasswd: { expire: False }
ssh_pwauth: True
''')

    with open(os.path.join(str(indir), 'meta-data'), 'wb') as outfp:
        outfp.write(b'''\
local-hostname: cloudimg
''')

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '4',
                     '-J', '-rational-rock', '-sysid', 'LINUX', '-volid', 'cidata',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_ident_encoding)

def test_parse_joliet_hidden_iso_file(tmp_path):
    indir = tmp_path / 'joliethiddeniso'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-J', '-hide', 'foo',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_hidden_iso_file)

def test_parse_udf_nofiles(tmp_path):
    indir = tmp_path / 'udfnofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_nofiles)

def test_parse_udf_onedir(tmp_path):
    indir = tmp_path / 'udfonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_onedir)

def test_parse_udf_twodirs(tmp_path):
    indir = tmp_path / 'udftwodirs'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    newdir = indir / 'dir2'
    newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_twodirs)

def test_parse_udf_subdir(tmp_path):
    indir = tmp_path / 'udfsubdir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'subdir1'
    newdir.mkdir(parents=True)
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_subdir)

def test_parse_udf_subdir_odd(tmp_path):
    indir = tmp_path / 'udfsubdir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'subdi1'
    newdir.mkdir(parents=True)
    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_subdir_odd)

def test_parse_udf_onefile(tmp_path):
    indir = tmp_path / 'udfonefile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_onefile)

def test_parse_udf_onefileonedir(tmp_path):
    indir = tmp_path / 'udfonefileonedir'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1'
    newdir.mkdir()
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_onefileonedir)

def test_parse_udf_dir_spillover(tmp_path):
    indir = tmp_path / 'udfdirspillover'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    for i in range(ord('a'), ord('v')):
        dirname = indir / (chr(i) * 64)
        dirname.mkdir()

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_dir_spillover)

def test_parse_udf_dir_oneshort(tmp_path):
    indir = tmp_path / 'udfdironeshort'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    for i in range(ord('a'), ord('u')):
        dirname = indir / (chr(i) * 64)
        dirname.mkdir()

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_dir_oneshort)

def test_parse_udf_iso_hidden(tmp_path):
    indir = tmp_path / 'udfisohidden'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-hide', 'foo', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_iso_hidden)

@pytest.mark.slow
def test_parse_udf_very_large(tmp_path):
    indir = tmp_path / 'udfverylarge'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    largefile = os.path.join(str(indir), 'foo')
    with open(largefile, 'wb') as outfp:
        outfp.truncate(1073739776+1)

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_very_large)

def test_parse_joliet_udf_nofiles(tmp_path):
    indir = tmp_path / 'jolietudfnofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-J', '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_joliet_udf_nofiles)

def test_parse_udf_dir_exactly2048(tmp_path):
    indir = tmp_path / 'udfdirspillover'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / ('a' * 248)
    newdir.mkdir()
    newdir = indir / ('b' * 248)
    newdir.mkdir()
    newdir = indir / ('c' * 248)
    newdir.mkdir()
    newdir = indir / ('d' * 248)
    newdir.mkdir()
    newdir = indir / ('e' * 248)
    newdir.mkdir()
    newdir = indir / ('f' * 248)
    newdir.mkdir()
    newdir = indir / ('g' * 240)
    newdir.mkdir()

    subprocess.call(['genisoimage', '-v', '-v', '-no-pad', '-iso-level', '1',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_dir_exactly2048)

def test_parse_udf_overflow_dir_extent(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'udfoverflow'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    numdirs = 46
    for i in range(1, 1+numdirs):
        newdir = indir / ('dir%d' % i)
        newdir.mkdir()
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_overflow_dir_extent)

def test_parse_multi_hard_link(tmp_path):
    indir = tmp_path / 'jolietudfnofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'

    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    pwd = os.getcwd()
    os.chdir(str(indir))
    os.link('foo', 'bar')
    os.link('bar', 'baz')
    os.chdir(pwd)

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-cache-inodes', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_multi_hard_link)

def test_parse_udf_joliet_onefile(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'jolietfile'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-J', '-udf', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_udf_joliet_onefile)

def test_parse_zero_byte_hard_link(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'boottable'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'foo'), 'wb') as outfp:
        pass
    os.link(os.path.join(str(indir), 'foo'), os.path.join(str(indir), 'bar'))
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_zero_byte_hard_link)

def test_parse_unicode_name(tmp_path):
    indir = tmp_path / 'unicode'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'föo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name)

def test_parse_unicode_name_isolevel4(tmp_path):
    indir = tmp_path / 'unicodeisolevel4'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'föo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_isolevel4)

def test_parse_unicode_name_joliet(tmp_path):
    indir = tmp_path / 'unicodejoliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'föo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-J',
                     '-no-pad', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_joliet)

def test_parse_unicode_name_udf(tmp_path):
    indir = tmp_path / 'unicodeudf'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'föo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-udf',
                     '-no-pad', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_udf)

def test_parse_unicode_name_two_byte(tmp_path):
    indir = tmp_path / 'unicode'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'fᴔo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_two_byte)

def test_parse_unicode_name_two_byte(tmp_path):
    indir = tmp_path / 'unicode'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'fᴔo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_two_byte)

def test_parse_unicode_name_two_byte_isolevel4(tmp_path):
    indir = tmp_path / 'unicodeisolevel4'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'fᴔo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_two_byte_isolevel4)

def test_parse_unicode_name_two_byte_joliet(tmp_path):
    indir = tmp_path / 'unicodetwobytejoliet'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'fᴔo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-J',
                     '-no-pad', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_two_byte_joliet)

def test_parse_unicode_name_two_byte_udf(tmp_path):
    indir = tmp_path / 'unicodeudftwobyte'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'fᴔo'), 'wb') as outfp:
        outfp.write(b'foo\n')

    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-udf',
                     '-no-pad', '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_unicode_name_two_byte_udf)

def test_parse_eltorito_get_bootcat(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritogetbootcat'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-b', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_get_bootcat)

def test_parse_eltorito_uefi(tmp_path):
    # First set things up, and generate the ISO with genisoimage.
    indir = tmp_path / 'eltoritonofiles'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    with open(os.path.join(str(indir), 'boot'), 'wb') as outfp:
        outfp.write(b'boot\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '1', '-no-pad',
                     '-c', 'boot.cat', '-e', 'boot', '-no-emul-boot',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_eltorito_uefi)

def test_parse_isolevel4_deep_directory(tmp_path):
    indir = tmp_path / 'isolevel4deep'
    indir.mkdir()
    outfile = str(indir)+'.iso'
    newdir = indir / 'dir1' / 'dir2' / 'dir3' / 'dir4' / 'dir5' / 'dir6' / 'dir7'
    newdir.mkdir(parents=True)
    with open(os.path.join(str(indir), 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', 'dir6', 'dir7', 'foo'), 'wb') as outfp:
        outfp.write(b'foo\n')
    subprocess.call(['genisoimage', '-v', '-v', '-iso-level', '4', '-no-pad',
                     '-o', str(outfile), str(indir)])

    do_a_test(tmp_path, outfile, check_isolevel4_deep_directory)
