Added tests for DOS 33 disk images; code still failing all tests, but making progress

This commit is contained in:
Rob McMullen 2017-02-22 12:11:56 -08:00
parent 4928a35700
commit 3157b13727
2 changed files with 72 additions and 35 deletions

View File

@ -57,14 +57,14 @@ class Dos33Dirent(object):
format = np.dtype([
('track', 'u1'),
('sector', 'u1'),
('flags', 'u1'),
('flag', 'u1'),
('name','S30'),
('num_sectors','<u2'),
])
def __init__(self, image, file_num=0, bytes=None):
self.file_num = file_num
self.flags = 0
self.file_type = 0
self.locked = False
self.deleted = False
self.track = 0
@ -79,8 +79,8 @@ class Dos33Dirent(object):
self.parse_raw_dirent(image, bytes)
def __str__(self):
flags = self.summary()
return "File #%-2d (%s) %03d %-30s %03d %03d" % (self.file_num, flags, self.num_sectors, self.filename, self.track, self.sector)
flag = self.summary()
return "File #%-2d (%s) %03d %-30s %03d %03d" % (self.file_num, flag, self.num_sectors, self.filename, self.track, self.sector)
type_map = {
0x0: "T",
@ -94,18 +94,25 @@ class Dos33Dirent(object):
}
def summary(self):
locked = "*" if self.flags else " "
f = self.flags & 0x7f
locked = "*" if self.locked else " "
try:
file_type = self.type_map[f]
file_type = self.type_map[self.file_type]
except KeyError:
file_type = "?"
flags = "%s%s" % (locked, file_type)
return flags
flag = "%s%s" % (locked, file_type)
return flag
@property
def verbose_info(self):
return self.summary
@property
def in_use(self):
return not self.deleted
@property
def flag(self):
return 0xff if self.deleted else self.file_type | (0x80 * int(self.locked))
def parse_raw_dirent(self, image, bytes):
if bytes is None:
@ -114,10 +121,12 @@ class Dos33Dirent(object):
self.track = values[0]
if self.track == 0xff:
self.deleted = True
self.track = bytes[0x20]
else:
self.deleted = False
self.sector = values[1]
self.flags = values[2]
self.file_type = values[2] & 0x7f
self.locked = values[2] & 0x80
self.filename = (bytes[3:0x20] - 0x80).tostring().rstrip()
self.num_sectors = int(values[4])
self.is_sane = self.sanity_check(image)
@ -125,12 +134,11 @@ class Dos33Dirent(object):
def encode_dirent(self):
data = np.zeros([self.format.itemsize], dtype=np.uint8)
values = data.view(dtype=self.format)[0]
flag = (1 * int(self.opened_output)) | (2 * int(self.dos_2)) | (4 * int(self.mydos)) | (0x10 * int(self.is_dir)) | (0x20 * int(self.locked)) | (0x40 * int(self.in_use)) | (0x80 * int(self.locked))
values[0] = flag
values[1] = self.num_sectors
values[2] = self.starting_sector
values[0] = self.track
values[1] = self.sector
values[2] = self.flag
values[3] = self.filename
values[4] = self.ext
values[4] = self.num_sectors
return data
def mark_deleted(self):
@ -215,8 +223,9 @@ class Dos33Dirent(object):
def set_values(self, filename, filetype, index):
self.filename = "%-30s" % filename[0:30]
self.flag = self.type_map.get(filetype, 0x04)
self.file_type = self.type_map.get(filetype, 0x04)
self.locked = False
self.deleted = False
class Dos33Header(AtrHeader):
@ -281,6 +290,14 @@ class Dos33DiskImage(DiskImageBase):
@property
def payload_bytes_per_sector(self):
return 256
@property
def vtoc_class(self):
return Dos33VTOC
@property
def directory_class(self):
return Dos33Directory
def get_boot_sector_info(self):
# based on logic from a2server
@ -326,7 +343,7 @@ class Dos33DiskImage(DiskImageBase):
self.total_sectors = int(values['num_tracks']) * int(values['sectors_per_track'])
self.dos_release = values['dos_release']
def get_directory(self):
def get_directory(self, directory=None):
sector = self.first_catalog
num = 0
files = []
@ -338,10 +355,14 @@ class Dos33DiskImage(DiskImageBase):
i = 0xb
while i < 256:
dirent = Dos33Dirent(self, num, values[i:i+0x23])
if not dirent.is_sane:
sector = 0
if dirent.flag == 0:
break
files.append(dirent)
if not dirent.is_sane:
self.all_sane = False
else:
files.append(dirent)
if directory is not None:
directory.set(num, dirent)
print dirent
i += 0x23
num += 1
@ -389,12 +410,14 @@ class Dos33DiskImage(DiskImageBase):
return segments
def get_next_directory_sector(self, sector):
if sector == -1:
sector = self.first_catalog
self.assert_valid_sector(sector)
print "reading catalog sector", sector
raw, _, _ = self.get_raw_bytes(sector)
next_sector = self.header.sector_from_track(raw[1], raw[2])
if next_sector == 0:
# need to figure out where the next sector should be
raise NoSpaceInDirectory("No space left in catalog")
def get_file_segment(self, dirent):
byte_order = []

View File

@ -2,15 +2,19 @@ import numpy as np
from mock import *
from atrcopy import SegmentData, AtariDosDiskImage, InvalidBinaryFile
from atrcopy import SegmentData, AtariDosDiskImage, Dos33DiskImage,InvalidBinaryFile
from atrcopy.errors import *
class TestAtariDosSDImage(object):
class BaseFilesystemModifyTest(object):
diskimage_type = None
sample_file = None
num_files_in_sample = 0
def setup(self):
data = np.fromfile("../test_data/dos_sd_test1.atr", dtype=np.uint8)
data = np.fromfile(self.sample_file, dtype=np.uint8)
rawdata = SegmentData(data)
self.image = AtariDosDiskImage(rawdata)
self.image = self.diskimage_type(rawdata)
def check_entries(self, entries, prefix="TEST", save=None):
orig_num_files = len(self.image.files)
@ -39,21 +43,21 @@ class TestAtariDosSDImage(object):
return filenames
def test_small(self):
assert len(self.image.files) == 5
assert len(self.image.files) == self.num_files_in_sample
data = np.asarray([0xff, 0xff, 0x00, 0x60, 0x01, 0x60, 1, 2], dtype=np.uint8)
self.image.write_file("TEST.XEX", None, data)
assert len(self.image.files) == 6
assert len(self.image.files) == self.num_files_in_sample + 1
data2 = self.image.find_file("TEST.XEX")
assert data.tostring() == data2
def test_50k(self):
assert len(self.image.files) == 5
assert len(self.image.files) == self.num_files_in_sample
data = np.arange(50*1024, dtype=np.uint8)
self.image.write_file("RAMP50K.BIN", None, data)
assert len(self.image.files) == 6
assert len(self.image.files) == self.num_files_in_sample + 1
data2 = self.image.find_file("RAMP50K.BIN")
assert data.tostring() == data2
@ -75,14 +79,14 @@ class TestAtariDosSDImage(object):
self.check_entries(entries, save="many_small.atr")
def test_big_failure(self):
assert len(self.image.files) == 5
assert len(self.image.files) == self.num_files_in_sample
data = np.arange(50*1024, dtype=np.uint8)
self.image.write_file("RAMP50K.BIN", None, data)
assert len(self.image.files) == 6
assert len(self.image.files) == self.num_files_in_sample + 1
with pytest.raises(NotEnoughSpaceOnDisk):
self.image.write_file("RAMP50K2.BIN", None, data)
assert len(self.image.files) == 6
assert len(self.image.files) == self.num_files_in_sample + 1
def test_delete(self):
entries1 = [
@ -104,15 +108,25 @@ class TestAtariDosSDImage(object):
]
filenames = self.check_entries(entries1, "FIRST")
assert len(self.image.files) == 16
assert len(self.image.files) == self.num_files_in_sample + 11
self.image.delete_file(filenames[2])
self.image.delete_file(filenames[5])
self.image.delete_file(filenames[0])
self.image.delete_file(filenames[8])
assert len(self.image.files) == 12
assert len(self.image.files) == self.num_files_in_sample + 7
filename = self.check_entries(entries2, "SECOND", save="test_delete.atr")
assert len(self.image.files) == 14
assert len(self.image.files) == self.num_files_in_sample + 9
# class TestAtariDosSDImage(BaseFilesystemModifyTest):
# diskimage_type = AtariDosDiskImage
# sample_file = "../test_data/dos_sd_test1.atr"
# num_files_in_sample
class TestDos33Image(BaseFilesystemModifyTest):
diskimage_type = Dos33DiskImage
sample_file = "../test_data/dos33_master.dsk"
num_files_in_sample = 19
if __name__ == "__main__":