import os, unittest
from datetime import datetime
from mgtdisklib import Disk, File, FileType

TESTDIR=os.path.join(os.path.split(__file__)[0], 'data')
TESTOUTPUTFILE=f'{TESTDIR}/__output__.file'

class FileTests(unittest.TestCase):
    def test_type_values(self):
        self.assertEqual(FileType.NONE, 0)
        self.assertEqual(FileType.ZX_BASIC, 1)
        self.assertEqual(FileType.ZX_DATA, 2)
        self.assertEqual(FileType.ZX_DATA_STR, 3)
        self.assertEqual(FileType.ZX_CODE, 4)
        self.assertEqual(FileType.ZX_SNP_48K, 5)
        self.assertEqual(FileType.ZX_MDRV, 6)
        self.assertEqual(FileType.ZX_SCREEN, 7)
        self.assertEqual(FileType.SPECIAL, 8)
        self.assertEqual(FileType.ZX_SNP_128K, 9)
        self.assertEqual(FileType.OPENTYPE, 10)
        self.assertEqual(FileType.ZX_EXECUTE, 11)
        self.assertEqual(FileType.UNIDOS_DIR, 12)
        self.assertEqual(FileType.UNIDOS_CREATE, 13)
        self.assertEqual(FileType.BASIC, 16)
        self.assertEqual(FileType.DATA, 17)
        self.assertEqual(FileType.DATA_STR, 18)
        self.assertEqual(FileType.CODE, 19)
        self.assertEqual(FileType.SCREEN, 20)
        self.assertEqual(FileType.DIR, 21)
        self.assertEqual(FileType.DRIVER_APP, 22)
        self.assertEqual(FileType.DRIVER_BOOT, 23)
        self.assertEqual(FileType.EDOS_NOMEN, 24)
        self.assertEqual(FileType.EDOS_SYSTEM, 25)
        self.assertEqual(FileType.EDOS_OVERLAY, 26)
        self.assertEqual(FileType.HDOS_DOS, 28)
        self.assertEqual(FileType.HDOS_DIR, 29)
        self.assertEqual(FileType.HDOS_DISK, 30)
        self.assertEqual(FileType.HDOS_TEMP, 31)

    def test_construct(self):
        file = File()
        self.assertEqual(file.type, FileType.NONE)

    def test_from_code_path(self):
        file = File.from_code_path(f'{TESTDIR}/samdos2')
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'samdos2')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 20)
        self.assertEqual(file.start, 32768)
        self.assertEqual(file.length, 10000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertIsNone(file.execute)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertTrue(file.is_bootable())

    def test_from_code_path_params(self):
        file = File.from_code_path(f'{TESTDIR}/samdos2', filename='altname', start=123456, execute=54321)
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'altname')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 20)
        self.assertEqual(file.start, 123456)
        self.assertEqual(file.length, 10000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.execute, 54321)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertTrue(file.is_bootable())

    def test_from_code_bytes(self):
        with open(f'{TESTDIR}/samdos2', 'rb') as f:
            file = File.from_code_bytes(f.read(), 'altname')
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'altname')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 20)
        self.assertEqual(file.start, 32768)
        self.assertEqual(file.length, 10000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertIsNone(file.execute)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertTrue(file.is_bootable())

    def test_from_code_bytes_params(self):
        with open(f'{TESTDIR}/samdos2', 'rb') as f:
            file = File.from_code_bytes(f.read(), 'altname', start=123456, execute=54321)

        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'altname')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 20)
        self.assertEqual(file.start, 123456)
        self.assertEqual(file.length, 10000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.execute, 54321)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertTrue(file.is_bootable())

    def test_from_path(self):
        file = File.from_path(f'{TESTDIR}/samdos2.file')
        with open(f'{TESTDIR}/samdos2', 'rb') as f:
            data = f.read()

        self.assertEqual(len(file.data), 10200)
        self.assertEqual(file.data[9:9+10000], data)
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'samdos2')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 20)
        self.assertEqual(file.start_track, 4)
        self.assertEqual(file.start_sector, 1)
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.start, 491529)
        self.assertEqual(file.length, 10000)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertTrue(file.is_bootable())

    def test_from_dir(self):
        with open(f'{TESTDIR}/samdos2.file', 'rb') as f:
            data = f.read()
        file = File.from_dir(data[:256])
        file.data = data[256:]

        self.assertEqual(file.entry, data[:256])
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'samdos2')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 20)
        self.assertEqual(file.start_track, 4)
        self.assertEqual(file.start_sector, 1)
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.start, 491529)
        self.assertEqual(file.length, 10000)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertTrue(file.is_bootable())

    def test_save(self):
        file = File.from_code_path(f'{TESTDIR}/samdos2', start=491529)
        file.save(TESTOUTPUTFILE)

        with open(f'{TESTDIR}/samdos2.file', 'rb') as f:
            data_golden = f.read()
        with open(TESTOUTPUTFILE, 'rb') as f:
            data = f.read()
        os.remove(TESTOUTPUTFILE)

        self.assertEqual(data, data_golden)

    def test_unpack_triple(self):
        self.assertEqual(File.unpack_triple(b'\x00\x00\x00'), (0x00, 0x0000))
        self.assertEqual(File.unpack_triple(b'\x00\x00\xff'), (0x00, 0x7f00))
        self.assertEqual(File.unpack_triple(b'\x00\xff\x00'), (0x00, 0x00ff))
        self.assertEqual(File.unpack_triple(b'\x00\xff\xff'), (0x00, 0x7fff))
        self.assertEqual(File.unpack_triple(b'\xff\x00\x00'), (0x1f, 0x0000))
        self.assertEqual(File.unpack_triple(b'\xff\x00\xff'), (0x1f, 0x7f00))
        self.assertEqual(File.unpack_triple(b'\xff\xff\x00'), (0x1f, 0x00ff))
        self.assertEqual(File.unpack_triple(b'\xff\xff\xff'), (0x1f, 0x7fff))

    def test_triple_to_addr(self):
        self.assertEqual(File.triple_to_addr(b'\x5f\x00\x80'), 0x80000) # MasterDOS
        self.assertEqual(File.triple_to_addr(b'\x60\x00\x80'), 0x4000)
        self.assertEqual(File.triple_to_addr(b'\x61\x00\x80'), 0x8000)
        self.assertEqual(File.triple_to_addr(b'\x7d\x00\x80'), 0x78000)
        self.assertEqual(File.triple_to_addr(b'\x7e\x00\x80'), 0x7c000)
        self.assertEqual(File.triple_to_addr(b'\x7f\x00\x80'), 0x80000) # MasterDOS
        self.assertEqual(File.triple_to_addr(b'\x7f\xff\xbf'), 0x83fff) # MasterDOS

    def test_triple_to_len(self):
        self.assertEqual(File.triple_to_len(b'\x00\x00\x00'), 0)
        self.assertEqual(File.triple_to_len(b'\x00\x00\xff'), 0x7f00)
        self.assertEqual(File.triple_to_len(b'\x00\xff\x00'), 0x00ff)
        self.assertEqual(File.triple_to_len(b'\x00\xff\xff'), 0x7fff)
        self.assertEqual(File.triple_to_len(b'\xff\x00\x00'), 0x7c000)
        self.assertEqual(File.triple_to_len(b'\xff\x00\xff'), 0x83f00)
        self.assertEqual(File.triple_to_len(b'\xff\xff\x00'), 0x7c0ff)
        self.assertEqual(File.triple_to_len(b'\xff\xff\xff'), 0x83fff)

    def test_triple_to_exec(self):
        self.assertEqual(File.triple_to_exec(b'\x00\x00\x80'), 0)
        self.assertEqual(File.triple_to_exec(b'\x01\x00\x80'), 0x4000)
        self.assertEqual(File.triple_to_exec(b'\x02\x00\x80'), 0x8000)
        self.assertEqual(File.triple_to_exec(b'\x1e\x00\x80'), 0x78000)
        self.assertEqual(File.triple_to_exec(b'\x1f\x00\x80'), 0x7c000)
        self.assertEqual(File.triple_to_exec(b'\x20\x00\x80'), 0)
        self.assertEqual(File.triple_to_exec(b'\x20\xff\xbf'), 0x3fff)

    def test_triple_to_line(self):
        self.assertEqual(File.triple_to_line(b'\x00\x00\x00'), 0x0000)
        self.assertEqual(File.triple_to_line(b'\x00\x00\xff'), 0xff00)
        self.assertEqual(File.triple_to_line(b'\x00\xff\x00'), 0x00ff)
        self.assertEqual(File.triple_to_line(b'\x00\xff\xff'), 0xffff)
        self.assertEqual(File.triple_to_line(b'\xff\x00\x00'), None)
        self.assertEqual(File.triple_to_line(b'\xff\x00\xff'), None)
        self.assertEqual(File.triple_to_line(b'\xff\xff\x00'), None)
        self.assertEqual(File.triple_to_line(b'\xff\xff\xff'), None)
        self.assertEqual(File.triple_to_line(b'\x01\xff\xff'), 0xffff)
        self.assertEqual(File.triple_to_line(b'\x80\xff\xff'), 0xffff)

    def test_addr_to_triple(self):
        self.assertEqual(File.addr_to_triple(0x80000), b'\x1f\x00\x80') # MasterDOS
        self.assertEqual(File.addr_to_triple(0x4000), b'\x00\x00\x80')
        self.assertEqual(File.addr_to_triple(0x8000), b'\x01\x00\x80')
        self.assertEqual(File.addr_to_triple(0x78000), b'\x1d\x00\x80')
        self.assertEqual(File.addr_to_triple(0x7c000), b'\x1e\x00\x80')
        self.assertEqual(File.addr_to_triple(0x80000), b'\x1f\x00\x80') # MasterDOS
        self.assertEqual(File.addr_to_triple(0x83fff), b'\x1f\xff\xbf') # MasterDOS

    def test_len_to_triple(self):
        self.assertEqual(File.len_to_triple(0), b'\x00\x00\x00')
        self.assertEqual(File.len_to_triple(0x7f00), b'\x01\x00\x3f')
        self.assertEqual(File.len_to_triple(0x00ff), b'\x00\xff\x00')
        self.assertEqual(File.len_to_triple(0x7fff), b'\x01\xff\x3f')
        self.assertEqual(File.len_to_triple(0x7c000), b'\x1f\x00\x00')
        self.assertEqual(File.len_to_triple(0x7ffff), b'\x1f\xff\x3f')

    def test_exec_to_triple(self):
        self.assertEqual(File.exec_to_triple(0), b'\x00\x00\x80')
        self.assertEqual(File.exec_to_triple(0xff), b'\x00\xff\x80')
        self.assertEqual(File.exec_to_triple(0x100), b'\x00\x00\x81')
        self.assertEqual(File.exec_to_triple(0x4000), b'\x01\x00\x80')
        self.assertEqual(File.exec_to_triple(0x8000), b'\x02\x00\x80')
        self.assertEqual(File.exec_to_triple(0xffff), b'\x03\xff\xbf')
        self.assertEqual(File.exec_to_triple(0x10000), b'\x04\x00\x80')
        self.assertEqual(File.exec_to_triple(0x7c000), b'\x1f\x00\x80')
        self.assertEqual(File.exec_to_triple(0x7ffff), b'\x1f\xff\xbf')

    def test_line_to_triple(self):
        self.assertEqual(File.line_to_triple(0x0000), b'\x00\x00\x00')
        self.assertEqual(File.line_to_triple(0xff00), b'\x00\x00\xff')
        self.assertEqual(File.line_to_triple(0x00ff), b'\x00\xff\x00')
        self.assertEqual(File.line_to_triple(0xffff), b'\x00\xff\xff')
        self.assertEqual(File.line_to_triple(None), b'\xff\xff\xff')

    def test_is_contig_data_type(self):
        self.assertFalse(File.is_contig_data_type(FileType.NONE))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_BASIC))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_DATA))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_DATA_STR))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_CODE))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_SNP_48K))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_MDRV))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_SCREEN))
        self.assertTrue(File.is_contig_data_type(FileType.SPECIAL))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_SNP_128K))
        self.assertFalse(File.is_contig_data_type(FileType.OPENTYPE))
        self.assertFalse(File.is_contig_data_type(FileType.ZX_EXECUTE))
        self.assertTrue(File.is_contig_data_type(FileType.UNIDOS_DIR))
        self.assertFalse(File.is_contig_data_type(FileType.UNIDOS_CREATE))
        self.assertFalse(File.is_contig_data_type(FileType.BASIC))
        self.assertFalse(File.is_contig_data_type(FileType.DATA))
        self.assertFalse(File.is_contig_data_type(FileType.DATA_STR))
        self.assertFalse(File.is_contig_data_type(FileType.CODE))
        self.assertFalse(File.is_contig_data_type(FileType.SCREEN))
        self.assertFalse(File.is_contig_data_type(FileType.DIR))
        self.assertFalse(File.is_contig_data_type(FileType.DRIVER_APP))
        self.assertFalse(File.is_contig_data_type(FileType.DRIVER_BOOT))
        self.assertFalse(File.is_contig_data_type(FileType.EDOS_NOMEN))
        self.assertFalse(File.is_contig_data_type(FileType.EDOS_SYSTEM))
        self.assertFalse(File.is_contig_data_type(FileType.EDOS_OVERLAY))
        self.assertFalse(File.is_contig_data_type(FileType.HDOS_DOS))
        self.assertFalse(File.is_contig_data_type(FileType.HDOS_DIR))
        self.assertFalse(File.is_contig_data_type(FileType.HDOS_DISK))
        self.assertFalse(File.is_contig_data_type(FileType.HDOS_TEMP))

    def test_is_sam_file_type(self):
        self.assertFalse(File.is_sam_file_type(FileType.NONE))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_BASIC))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_DATA))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_DATA_STR))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_CODE))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_SNP_48K))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_MDRV))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_SCREEN))
        self.assertFalse(File.is_sam_file_type(FileType.SPECIAL))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_SNP_128K))
        self.assertFalse(File.is_sam_file_type(FileType.OPENTYPE))
        self.assertFalse(File.is_sam_file_type(FileType.ZX_EXECUTE))
        self.assertFalse(File.is_sam_file_type(FileType.UNIDOS_DIR))
        self.assertFalse(File.is_sam_file_type(FileType.UNIDOS_CREATE))
        self.assertTrue(File.is_sam_file_type(FileType.BASIC))
        self.assertTrue(File.is_sam_file_type(FileType.DATA))
        self.assertTrue(File.is_sam_file_type(FileType.DATA_STR))
        self.assertTrue(File.is_sam_file_type(FileType.CODE))
        self.assertTrue(File.is_sam_file_type(FileType.SCREEN))
        self.assertTrue(File.is_sam_file_type(FileType.DIR))
        self.assertTrue(File.is_sam_file_type(FileType.DRIVER_APP))
        self.assertTrue(File.is_sam_file_type(FileType.DRIVER_BOOT))
        self.assertTrue(File.is_sam_file_type(FileType.EDOS_NOMEN))
        self.assertTrue(File.is_sam_file_type(FileType.EDOS_SYSTEM))
        self.assertTrue(File.is_sam_file_type(FileType.EDOS_OVERLAY))
        self.assertTrue(File.is_sam_file_type(FileType.HDOS_DOS))
        self.assertTrue(File.is_sam_file_type(FileType.HDOS_DIR))
        self.assertTrue(File.is_sam_file_type(FileType.HDOS_DISK))
        self.assertTrue(File.is_sam_file_type(FileType.HDOS_TEMP))

    def test_type_zx_basic_vars(self):
        file = Disk.open(f'{TESTDIR}/zx_basic_vars.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_BASIC)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'basic_vars')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 23755)
        self.assertEqual(file.length, 78)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+2], b'\x00\x0a')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_basic_auto(self):
        file = Disk.open(f'{TESTDIR}/zx_basic_auto.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_BASIC)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'basic_auto')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 23755)
        self.assertEqual(file.length, 189)
        self.assertEqual(file.execute, 1234)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+2], b'\x00\x0a')
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_data(self):
        file = Disk.open(f'{TESTDIR}/zx_data.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_DATA)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'data_x_10')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 23874)
        self.assertEqual(file.length, 53)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+8], b'\x01\x0a\x00\x00\x00\x7b\x00\x00')
        self.assertEqual(file.data_var, 'x')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_data_str1(self):
        file = Disk.open(f'{TESTDIR}/zx_data_str1.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_DATA_STR)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'x$_5')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 23816)
        self.assertEqual(file.length, 8)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+8], b'\x01\x05\x00abcde')
        self.assertEqual(file.data_var, 'x$')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_data_str2(self):
        file = Disk.open(f'{TESTDIR}/zx_data_str2.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_DATA_STR)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'x$_5,10')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 23858)
        self.assertEqual(file.length, 55)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+25], b'\x02\x05\x00\x0a\x00hello     world     ')
        self.assertEqual(file.data_var, 'x$')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_code(self):
        file = Disk.open(f'{TESTDIR}/zx_code.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'code')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 47)
        self.assertEqual(file.start, 0x8000)
        self.assertEqual(file.length, 23456)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+4], b'\x3e\x02\xd3\xfe')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_code_auto(self):
        file = Disk.open(f'{TESTDIR}/zx_code_auto.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'code_auto')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 0x8000)
        self.assertEqual(file.length, 5)
        self.assertEqual(file.execute, 0x8000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+4], b'\x3e\x02\xd3\xfe')
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_snap_48k(self):
        file = Disk.open(f'{TESTDIR}/zx_snap_48k.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_SNP_48K)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'Snap A')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 97)
        self.assertEqual(file.length, 0xc000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[49151], 123)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.start)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_mdrv(self):
        # TODO?
        pass

    def test_type_zx_screen(self):
        file = Disk.open(f'{TESTDIR}/zx_screen.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_SCREEN)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'Snap A')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 14)
        self.assertEqual(file.start, 16384)
        self.assertEqual(file.length, 6912)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+0x17ff], 0x00)
        self.assertEqual(file.data[9+0x1800], 0x38)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_special(self):
        # TODO?
        pass

    def test_type_zx_snap_128k(self):
        file = Disk.open(f'{TESTDIR}/zx_snap_128k.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_SNP_128K)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'Snap A')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 258)
        self.assertEqual(file.length, 0x4000*8+1)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[0], 16)
        self.assertEqual([file.data[i*0x4000] for i in range(1,8)], list(range(16,16+7)))
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.start)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_opentype(self):
        file = Disk.open(f'{TESTDIR}/zx_opentype.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.OPENTYPE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'opentype')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 24)
        self.assertEqual(file.length, 26*10*47)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[:47], b'A0 the quick brown fox jumps over the lazy dog.')
        self.assertEqual(file.data[file.length-47:file.length], b'Z9 the quick brown fox jumps over the lazy dog.')
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.start)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_zx_execute(self):
        file = Disk.open(f'{TESTDIR}/zx_execute.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.ZX_EXECUTE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'execute')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.length, 510)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[:4], b'\x3e\x02\xd3\xfe')
        self.assertEqual(file.data[4:file.length-1], bytes(file.length-5))
        self.assertEqual(file.data[file.length-1], 0xc9)
        self.assertIsNone(file.start)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_basic(self):
        file = Disk.open(f'{TESTDIR}/basic_vars.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.BASIC)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'basic')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 2)
        self.assertEqual(file.length, 682)
        self.assertEqual(file.start, 23765)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+2], b'\x00\x0a')
        self.assertEqual(file.data[9+file.length-43:9+file.length], b'the quick brown fox jumps over the lazy dog')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_basic_auto(self):
        file = Disk.open(f'{TESTDIR}/basic_auto.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.BASIC)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'basic_auto')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 2)
        self.assertEqual(file.length, 625)
        self.assertEqual(file.start, 23765)
        self.assertEqual(file.execute, 12345)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+2], b'\x00\x0a')
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_data(self):
        file = Disk.open(f'{TESTDIR}/data.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.DATA)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'abc_10')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 24493)
        self.assertEqual(file.length, 67)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+1:9+1+3], b'abc')
        self.assertEqual(file.data_var, 'abc')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_data_str(self):
        file = Disk.open(f'{TESTDIR}/data_str.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.DATA_STR)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'abc$_5,10')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 24476)
        self.assertEqual(file.length, 69)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+1:9+1+4], b'abc$')
        self.assertEqual(file.data_var, 'abc$')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_data_str_1(self):
        file = Disk.open(f'{TESTDIR}/data_str1.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.DATA_STR)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'abc$')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 24412)
        self.assertEqual(file.length, 26)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+1:9+1+4], b'abc$')
        self.assertEqual(file.data_var, 'abc$')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_code(self):
        file = Disk.open(f'{TESTDIR}/code.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'code')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 0x8000)
        self.assertEqual(file.length, 5)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+5], b'\x3e\x02\xd3\xfe\xc9')
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_code(self):
        file = Disk.open(f'{TESTDIR}/code_auto.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.CODE)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'code_auto')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 0x8000)
        self.assertEqual(file.length, 5)
        self.assertEqual(file.execute, 0x8000)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+5], b'\x3e\x02\xd3\xfe\xc9')
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_screen_1(self):
        file = Disk.open(f'{TESTDIR}/screen_1.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.SCREEN)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'mode1')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 14)
        self.assertEqual(file.start, 507904)
        self.assertEqual(file.length, 6912+41)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+0x17ff], 0x00)
        self.assertEqual(file.data[9+0x1800], 0x38)
        self.assertEqual(file.screen_mode, 1)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertFalse(file.is_bootable())

    def test_type_screen_2(self):
        file = Disk.open(f'{TESTDIR}/screen_2.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.SCREEN)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'mode2')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 29)
        self.assertEqual(file.start, 507904)
        self.assertEqual(file.length, 14336+41)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+0x17ff], 0x00)
        self.assertEqual(file.data[9+0x1fff], 0x00)
        self.assertEqual(file.data[9+0x2000], 0x38)
        self.assertEqual(file.data[9+0x37ff], 0x38)
        self.assertEqual(file.data[9+0x3800], 0x00)
        self.assertEqual(file.screen_mode, 2)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertFalse(file.is_bootable())

    def test_type_screen_3(self):
        file = Disk.open(f'{TESTDIR}/screen_3.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.SCREEN)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'mode3')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 49)
        self.assertEqual(file.start, 507904)
        self.assertEqual(file.length, 24576+41)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+0], 0xff)
        self.assertEqual(file.data[9+0x5fff], 0xff)
        self.assertEqual(file.data[9+0x6000], 0x00)
        self.assertEqual(file.screen_mode, 3)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertFalse(file.is_bootable())

    def test_type_screen_4(self):
        file = Disk.open(f'{TESTDIR}/screen_4.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.SCREEN)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'mode4')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 49)
        self.assertEqual(file.start, 507904)
        self.assertEqual(file.length, 24576+41)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9+0], 0x77)
        self.assertEqual(file.data[9+0x5fff], 0x77)
        self.assertEqual(file.data[9+0x6000], 0x00)
        self.assertEqual(file.screen_mode, 4)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.time)
        self.assertIsNone(file.data_var)
        self.assertFalse(file.is_bootable())

    def test_type_screen_flash(self):
        file = Disk.open(f'{TESTDIR}/screen_flash.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.SCREEN)
        self.assertEqual(file.length, 6912+41)
        self.assertEqual(file.screen_mode, 1)

    def test_type_screen_line(self):
        file = Disk.open(f'{TESTDIR}/screen_line.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.SCREEN)
        self.assertEqual(file.length, 24576+549)
        self.assertEqual(file.screen_mode, 4)

    def test_type_dir(self):
        file = Disk.open(f'{TESTDIR}/dir.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.DIR)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'subdir')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 0)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(len(file.data), 0)
        self.assertEqual(file.time, datetime(2021, 7, 28, 16, 44))
        self.assertEqual(file.dir, 1)
        self.assertIsNone(file.execute)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_dir_file(self):
        file = Disk.open(f'{TESTDIR}/dir.mgt.gz').files[1]
        self.assertEqual(file.type, FileType.CODE)
        self.assertEqual(file.dir, 1)

    def test_type_driver_app(self):
        file = Disk.open(f'{TESTDIR}/driver_app.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.DRIVER_APP)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'driverapp')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 21)
        self.assertEqual(file.start, 0x8000)
        self.assertEqual(file.length, 10240)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+3], b'\xc3\x23\x0a')
        self.assertEqual(file.data[9+0xf0:9+0xf0+11], b'Alarm Clock')
        self.assertEqual(file.time, datetime(1993, 12, 5, 23, 48))
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

    def test_type_driver_boot(self):
        file = Disk.open(f'{TESTDIR}/driver_boot.mgt.gz').files[0]
        self.assertEqual(file.type, FileType.DRIVER_BOOT)
        self.assertFalse(file.hidden)
        self.assertFalse(file.protected)
        self.assertEqual(file.name, 'driverboot')
        self.assertEqual(file.name_raw, bytes(f'{file.name:10}', 'ascii'))
        self.assertEqual(file.sectors, 1)
        self.assertEqual(file.start, 32000)
        self.assertEqual(file.length, 500)
        self.assertEqual(len(file.data), file.sectors * File.data_bytes_per_sector(file.type))
        self.assertEqual(file.sector_map, File.contig_sector_map(file.sectors, file.start_track, file.start_sector))
        self.assertEqual(file.data[9:9+10], b'\x00bootstrap')
        self.assertEqual(file.time, datetime(1995, 4, 17, 16, 14))
        self.assertIsNone(file.execute)
        self.assertIsNone(file.dir)
        self.assertIsNone(file.data_var)
        self.assertIsNone(file.screen_mode)
        self.assertFalse(file.is_bootable())

if __name__ == '__main__':
    unittest.main()
