Merge pull request #315 from davidgiven/tests

Overhaul the tests.
This commit is contained in:
David Given
2021-08-01 19:37:15 +02:00
committed by GitHub
25 changed files with 298 additions and 124 deletions

View File

@@ -8,33 +8,6 @@
#include "arch/brother/brother.pb.h"
#include "lib/encoders/encoders.pb.h"
FlagGroup brotherEncoderFlags;
static DoubleFlag clockRateUs(
{ "--clock-rate" },
"Encoded data clock rate (microseconds).",
3.83);
static DoubleFlag postIndexGapMs(
{ "--post-index-gap" },
"Post-index gap before first sector header (milliseconds).",
1.0);
static DoubleFlag sectorSpacingMs(
{ "--sector-spacing" },
"Time between successive sector headers (milliseconds).",
16.2);
static DoubleFlag postHeaderSpacingMs(
{ "--post-header-spacing" },
"Time between a sector's header and data records (milliseconds).",
0.69);
static StringFlag sectorSkew(
{ "--sector-skew" },
"Order in which to write sectors.",
"05a3816b4927");
static int encode_header_gcr(uint16_t word)
{
switch (word)
@@ -193,18 +166,18 @@ public:
break;
}
int bitsPerRevolution = 200000.0 / clockRateUs;
const std::string& skew = sectorSkew.get();
int bitsPerRevolution = 200000.0 / _config.clock_rate_us();
const std::string& skew = _config.sector_skew();
std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;
for (int sectorCount=0; sectorCount<BROTHER_SECTORS_PER_TRACK; sectorCount++)
{
int sectorId = charToInt(skew.at(sectorCount));
double headerMs = postIndexGapMs + sectorCount*sectorSpacingMs;
unsigned headerCursor = headerMs*1e3 / clockRateUs;
double dataMs = headerMs + postHeaderSpacingMs;
unsigned dataCursor = dataMs*1e3 / clockRateUs;
double headerMs = _config.post_index_gap_ms() + sectorCount*_config.sector_spacing_ms();
unsigned headerCursor = headerMs*1e3 / _config.clock_rate_us();
double dataMs = headerMs + _config.post_header_spacing_ms();
unsigned dataCursor = dataMs*1e3 / _config.clock_rate_us();
const auto& sectorData = image.get(logicalTrack, 0, sectorId);
@@ -222,7 +195,7 @@ public:
// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
fluxmap->appendBits(bits, clockRateUs*1e3);
fluxmap->appendBits(bits, _config.clock_rate_us()*1e3);
return fluxmap;
}

View File

@@ -174,9 +174,9 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::s
write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
write_bits(bits, cursor, MAC_SECTOR_RECORD, 3*8);
uint8_t encodedTrack = sector->physicalHead & 0x3f;
uint8_t encodedTrack = sector->logicalTrack & 0x3f;
uint8_t encodedSector = sector->logicalSector;
uint8_t encodedSide = encode_side(sector->physicalCylinder, sector->logicalSide);
uint8_t encodedSide = encode_side(sector->logicalTrack, sector->logicalSide);
uint8_t formatByte = MAC_FORMAT_BYTE;
uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
@@ -240,7 +240,7 @@ public:
fillBitmapTo(bits, cursor, _config.post_index_gap_us() / clockRateUs, { true, false });
lastBit = false;
for (const auto& sector : collectSectors(physicalTrack, physicalSide, image))
for (const auto& sector : sectors)
write_sector(bits, cursor, sector);
if (cursor >= bits.size())

View File

@@ -131,11 +131,10 @@ public:
int bitsPerRevolution = 100000;
double clockRateUs = 4.00;
if ((physicalTrack < 0) || (physicalTrack >= 35))
if ((physicalTrack < 0) || (physicalTrack >= 35) || sectors.empty())
return std::unique_ptr<Fluxmap>();
const auto& sector = image.get(physicalTrack, physicalSide, 0);
const auto& sector = *sectors.begin();
if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) {
bitsPerRevolution /= 2; // FM
} else {
@@ -145,11 +144,8 @@ public:
std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;
for (int sectorId = 0; sectorId < 10; sectorId++)
{
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
for (const auto& sectorData : sectors)
write_sector(bits, cursor, sectorData);
}
if (cursor > bits.size())
Error() << "track data overrun";

View File

@@ -11,6 +11,7 @@ class DecoderProto;
class EncoderProto;
extern std::unique_ptr<AbstractDecoder> createTids990Decoder(const DecoderProto& config);
extern std::unique_ptr<AbstractEncoder> createTids990Encoder(const EncoderProto& config);
#endif

View File

@@ -23,6 +23,7 @@ std::unique_ptr<AbstractEncoder> AbstractEncoder::create(const EncoderProto& con
{ EncoderProto::kIbm, createIbmEncoder },
{ EncoderProto::kMacintosh, createMacintoshEncoder },
{ EncoderProto::kNorthstar, createNorthstarEncoder },
{ EncoderProto::kTids990, createTids990Encoder },
};
auto encoder = encoders.find(config.format_case());

View File

@@ -183,9 +183,13 @@ void FlagGroup::parseFlagsWithConfigFiles(int argc, const char* argv[],
parseFlags(argc, argv,
[&](const auto& filename) {
const auto& it = configFiles.find(filename);
std::string data;
if (it != configFiles.end())
data = it->second;
{
ConfigProto newConfig;
if (!newConfig.ParseFromString(it->second))
Error() << "couldn't load built-in config proto";
config.MergeFrom(newConfig);
}
else
{
std::ifstream f(filename, std::ios::out);
@@ -194,13 +198,10 @@ void FlagGroup::parseFlagsWithConfigFiles(int argc, const char* argv[],
std::ostringstream ss;
ss << f.rdbuf();
data = ss.str();
}
ConfigProto newConfig;
if (!newConfig.ParseFromString(data))
Error() << "couldn't load config proto";
config.MergeFrom(newConfig);
if (!google::protobuf::TextFormat::MergeFromString(ss.str(), &config))
Error() << "couldn't load external config proto";
}
return true;
}

View File

@@ -69,3 +69,20 @@ ImageReader::ImageReader(const ImageReaderProto& config):
_config(config)
{}
void getTrackFormat(const ImgInputOutputProto& config,
ImgInputOutputProto::TrackdataProto& trackdata, unsigned track, unsigned side)
{
trackdata.Clear();
for (const ImgInputOutputProto::TrackdataProto& f : config.trackdata())
{
if (f.has_track() && f.has_up_to_track() && ((track < f.track()) || (track > f.up_to_track())))
continue;
if (f.has_track() && !f.has_up_to_track() && (track != f.track()))
continue;
if (f.has_side() && (f.side() != side))
continue;
trackdata.MergeFrom(f);
}
}

View File

@@ -3,17 +3,19 @@ syntax = "proto2";
import "lib/common.proto";
message ImgInputOutputProto {
// NEXT: 6
message TrackdataProto {
optional int32 track = 1 [(help) = "if present, this format only applies to this track"];
optional int32 side = 2 [(help) = "if present, this format only applies to this side"];
optional int32 track = 1 [(help) = "if present, this format only applies to this track"];
optional int32 up_to_track = 5 [(help) = "if present, forms a range with track"];
optional int32 side = 2 [(help) = "if present, this format only applies to this side"];
optional int32 sector_size = 3 [default=512, (help) = "number of bytes per sector"];
optional int32 sectors = 4 [(help) = "number of sectors in this track"];
optional int32 sectors = 4 [(help) = "number of sectors in this track"];
}
repeated TrackdataProto trackdata = 4 [(help) = "per-track format information (repeatable)"];
optional int32 tracks = 5 [default=80, (help) = "number of tracks in image"];
optional int32 sides = 6 [default=2, (help) = "number of sides in image"];
optional int32 tracks = 5 [default=0, (help) = "number of tracks in image"];
optional int32 sides = 6 [default=0, (help) = "number of sides in image"];
optional int32 physical_offset = 7 [default=0, (help) = "logical:physical track offset"];
optional int32 physical_step = 8 [default=1, (help) = "logical:physical track step"];
}

View File

@@ -0,0 +1,8 @@
#ifndef IMAGEREADERIMPL_H
#define IMAGEREADERIMPL_H
extern void getTrackFormat(const ImgInputOutputProto& config,
ImgInputOutputProto::TrackdataProto& trackdata, unsigned track, unsigned side);
#endif

View File

@@ -4,6 +4,7 @@
#include "imagereader/imagereader.h"
#include "image.h"
#include "lib/config.pb.h"
#include "imagereader/imagereaderimpl.h"
#include "fmt/format.h"
#include <algorithm>
#include <iostream>
@@ -22,6 +23,9 @@ public:
if (!inputFile.is_open())
Error() << "cannot open input file";
if (!_config.img().tracks() || !_config.img().sides())
Error() << "IMG: bad configuration; did you remember to set the tracks, sides and trackdata fields?";
Image image;
int trackCount = 0;
for (int track = 0; track < _config.img().tracks(); track++)
@@ -33,7 +37,7 @@ public:
for (int side = 0; side < _config.img().sides(); side++)
{
ImgInputOutputProto::TrackdataProto trackdata;
getTrackFormat(trackdata, track, side);
getTrackFormat(_config.img(), trackdata, track, side);
for (int sectorId = 0; sectorId < trackdata.sectors(); sectorId++)
{
@@ -55,26 +59,11 @@ public:
image.calculateSize();
const Geometry& geometry = image.getGeometry();
std::cout << fmt::format("reading {} tracks, {} sides, {} kB total\n",
std::cout << fmt::format("IMG: read {} tracks, {} sides, {} kB total\n",
geometry.numTracks, geometry.numSides,
inputFile.tellg() / 1024);
return image;
}
private:
void getTrackFormat(ImgInputOutputProto::TrackdataProto& trackdata, unsigned track, unsigned side)
{
trackdata.Clear();
for (const ImgInputOutputProto::TrackdataProto& f : _config.img().trackdata())
{
if (f.has_track() && (f.track() != track))
continue;
if (f.has_side() && (f.side() != side))
continue;
trackdata.MergeFrom(f);
}
}
};
std::unique_ptr<ImageReader> ImageReader::createImgImageReader(

View File

@@ -4,6 +4,7 @@
#include "imagewriter/imagewriter.h"
#include "image.h"
#include "lib/config.pb.h"
#include "imagereader/imagereaderimpl.h"
#include "fmt/format.h"
#include <algorithm>
#include <iostream>
@@ -32,7 +33,7 @@ public:
for (int side = 0; side < sides; side++)
{
ImgInputOutputProto::TrackdataProto trackdata;
getTrackFormat(trackdata, track, side);
getTrackFormat(_config.img(), trackdata, track, side);
int numSectors = trackdata.has_sectors() ? trackdata.sectors() : geometry.numSectors;
int sectorSize = trackdata.has_sector_size() ? trackdata.sector_size() : geometry.sectorSize;
@@ -48,25 +49,10 @@ public:
}
}
std::cout << fmt::format("wrote {} tracks, {} sides, {} kB total\n",
std::cout << fmt::format("IMG: wrote {} tracks, {} sides, {} kB total\n",
tracks, sides,
outputFile.tellp() / 1024);
}
private:
void getTrackFormat(ImgInputOutputProto::TrackdataProto& trackdata, unsigned track, unsigned side)
{
trackdata.Clear();
for (const ImgInputOutputProto::TrackdataProto& f : _config.img().trackdata())
{
if (f.has_track() && (f.track() != track))
continue;
if (f.has_side() && (f.side() != side))
continue;
trackdata.MergeFrom(f);
}
}
};
std::unique_ptr<ImageWriter> ImageWriter::createImgImageWriter(

View File

@@ -162,6 +162,11 @@ void setProtoFieldFromString(ProtoField& protoField, const std::string& value)
setRange((RangeProto*)reflection->MutableMessage(message, field), value);
break;
}
if (field->containing_oneof() && value.empty())
{
reflection->MutableMessage(message, field);
break;
}
/* fall through */
default:
Error() << "can't set this config value type";

View File

@@ -35,6 +35,10 @@ rule test
command = \$in && touch \$out
description = TEST \$in
rule encodedecode
command = sh scripts/encodedecodetest.sh \$format \$configs > \$out
description = ENCODEDECODE \$format
rule strip
command = cp -f \$in \$out && $STRIP \$out
description = STRIP \$in
@@ -255,6 +259,16 @@ runtest() {
echo build $OBJDIR/$prog.stamp : test $OBJDIR/$prog-debug$EXTENSION
}
encodedecodetest() {
local format
format=$1
shift
echo "build $OBJDIR/$format.encodedecode.stamp : encodedecode | fluxengine$EXTENSION scripts/encodedecodetest.sh $*"
echo " format=$format"
echo " configs=$*"
}
buildlibrary libagg.a \
-Idep/agg/include \
dep/stb/stb_image_write.c \
@@ -408,9 +422,9 @@ FORMATS="\
mac800 \
micropolis \
mx \
northstar87 \
northstar175 \
northstar350 \
northstar87 \
tids990 \
victor9k \
zilogmcz \
@@ -492,5 +506,28 @@ runtest proto-test -I$OBJDIR/proto \
tests/proto.cc \
$OBJDIR/proto/tests/testproto.cc
encodedecodetest amiga
encodedecodetest atarist360
encodedecodetest atarist370
encodedecodetest atarist400
encodedecodetest atarist410
encodedecodetest atarist720
encodedecodetest atarist740
encodedecodetest atarist800
encodedecodetest atarist820
encodedecodetest brother120
encodedecodetest brother240
encodedecodetest ibm1200_525
encodedecodetest ibm1440
encodedecodetest ibm180_525
encodedecodetest ibm360_525
encodedecodetest ibm720
encodedecodetest ibm720_525
encodedecodetest tids990
encodedecodetest commodore1581
encodedecodetest commodore1541 scripts/commodore1541_test.textpb
encodedecodetest mac400 scripts/mac400_test.textpb
encodedecodetest mac800 scripts/mac800_test.textpb
# vim: sw=4 ts=4 et

View File

@@ -0,0 +1,8 @@
image_reader {
d64 {}
}
image_writer {
d64 {}
}

33
scripts/encodedecodetest.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/sh
set -e
if [ $(uname) != "Linux" ]; then
echo "Skipping test as not on Linux"
exit 0
fi
tmp=/tmp/$$
srcfile=$tmp.src.img
fluxfile=$tmp.flux
destfile=$tmp.dest.img
format=$1
shift
trap "rm -f $srcfile $fluxfile $destfile" EXIT
dd if=/dev/urandom of=$srcfile bs=1M count=2 2>1
./fluxengine write $format -i $srcfile -d $fluxfile "$@"
./fluxengine read $format -s $fluxfile -o $destfile "$@"
if [ ! -s $destfile ]; then
echo "Zero length output file!" >&2
exit 1
fi
truncate $srcfile -r $destfile
if ! cmp $srcfile $destfile; then
echo "Comparison failed!" >&2
exit 1
fi
exit 0

View File

@@ -0,0 +1,70 @@
image_reader {
img {
tracks: 80
sides: 1
trackdata {
sector_size: 524
}
trackdata {
track: 0
up_to_track: 15
sectors: 12
}
trackdata {
track: 16
up_to_track: 31
sectors: 11
}
trackdata {
track: 32
up_to_track: 47
sectors: 10
}
trackdata {
track: 48
up_to_track: 63
sectors: 9
}
trackdata {
track: 64
up_to_track: 79
sectors: 8
}
}
}
image_writer {
img {
tracks: 80
sides: 1
trackdata {
sector_size: 524
}
trackdata {
track: 0
up_to_track: 15
sectors: 12
}
trackdata {
track: 16
up_to_track: 31
sectors: 11
}
trackdata {
track: 32
up_to_track: 47
sectors: 10
}
trackdata {
track: 48
up_to_track: 63
sectors: 9
}
trackdata {
track: 64
up_to_track: 79
sectors: 8
}
}
}

View File

@@ -0,0 +1,70 @@
image_reader {
img {
tracks: 80
sides: 2
trackdata {
sector_size: 524
}
trackdata {
track: 0
up_to_track: 15
sectors: 12
}
trackdata {
track: 16
up_to_track: 31
sectors: 11
}
trackdata {
track: 32
up_to_track: 47
sectors: 10
}
trackdata {
track: 48
up_to_track: 63
sectors: 9
}
trackdata {
track: 64
up_to_track: 79
sectors: 8
}
}
}
image_writer {
img {
tracks: 80
sides: 2
trackdata {
sector_size: 524
}
trackdata {
track: 0
up_to_track: 15
sectors: 12
}
trackdata {
track: 16
up_to_track: 31
sectors: 11
}
trackdata {
track: 32
up_to_track: 47
sectors: 10
}
trackdata {
track: 48
up_to_track: 63
sectors: 9
}
trackdata {
track: 64
up_to_track: 79
sectors: 8
}
}
}

View File

@@ -27,15 +27,13 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "012345678"
swap_sides: true
sector_size: 512
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "012345678"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "0123456789"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "0123456789"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "012345678"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "012345678"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "0123456789"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {

View File

@@ -27,15 +27,12 @@ encoder {
gap2: 22
gap3: 34
sector_skew: "0123456789"
swap_sides: true
}
}
}
decoder {
ibm {
swap_sides: false
}
ibm {}
}
cylinders {