Add separated-value deserialization test

This commit is contained in:
Matt Nadareski
2023-07-14 13:20:11 -04:00
parent d973ad50d3
commit a32b1d7e6f
11 changed files with 263 additions and 1 deletions

View File

@@ -0,0 +1,9 @@
namespace SabreTools.Models.SeparatedValue
{
public class MetadataFile
{
public string[] Header { get; set; }
public Row[]? Row { get; set; }
}
}

View File

@@ -0,0 +1,66 @@
namespace SabreTools.Models.SeparatedValue
{
/// <summary>
/// Standardized variant of a row
/// </summary>
public class Row
{
/// <remarks>File Name</remarks>
public string FileName { get; set; }
/// <remarks>Internal Name</remarks>
public string InternalName { get; set; }
/// <remarks>Description</remarks>
public string Description { get; set; }
/// <remarks>Game Name</remarks>
public string GameName { get; set; }
/// <remarks>Game Description</remarks>
public string GameDescription { get; set; }
/// <remarks>Type</remarks>
public string Type { get; set; }
/// <remarks>Rom Name</remarks>
public string RomName { get; set; }
/// <remarks>Disk Name</remarks>
public string DiskName { get; set; }
/// <remarks>Size, Numeric</remarks>
public string Size { get; set; }
/// <remarks>CRC</remarks>
public string CRC { get; set; }
/// <remarks>MD5</remarks>
public string MD5 { get; set; }
/// <remarks>SHA1</remarks>
public string SHA1 { get; set; }
/// <remarks>SHA256</remarks>
public string SHA256 { get; set; }
/// <remarks>SHA384, Optional</remarks>
public string SHA384 { get; set; }
/// <remarks>SHA512, Optional</remarks>
public string SHA512 { get; set; }
/// <remarks>SpamSum, Optional</remarks>
public string SpamSum { get; set; }
/// <remarks>Nodump</remarks>
public string Nodump { get; set; }
#region DO NOT USE IN PRODUCTION
/// <remarks>Should be empty</remarks>
public string[]? ADDITIONAL_ELEMENTS { get; set; }
#endregion
}
}

View File

@@ -73,7 +73,7 @@ namespace SabreTools.Serialization
break; break;
// Parse the line into a row // Parse the line into a row
Row row = null; Row? row = null;
if (reader.Line.Count < HeaderWithRomnameCount) if (reader.Line.Count < HeaderWithRomnameCount)
{ {
row = new Row row = new Row

View File

@@ -0,0 +1,143 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SabreTools.IO.Readers;
using SabreTools.Models.SeparatedValue;
namespace SabreTools.Serialization
{
/// <summary>
/// Serializer for separated-value variants
/// </summary>
public class SeparatedValue
{
private const int HeaderWithoutExtendedHashesCount = 14;
private const int HeaderWithExtendedHashesCount = 17;
/// <summary>
/// Deserializes a separated-value variant to the defined type
/// </summary>
/// <param name="path">Path to the file to deserialize</param>
/// <param name="delim">Character delimiter between values</param>
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path, char delim)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, delim);
}
catch
{
// TODO: Handle logging the exception
return default;
}
}
/// <summary>
/// Deserializes a separated-value variant in a stream to the defined type
/// </summary>
/// <param name="stream">Stream to deserialize</param>
/// <param name="delim">Character delimiter between values</param>
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream, char delim)
{
try
{
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
{
Header = true,
Separator = delim,
VerifyFieldCount = false,
};
var dat = new MetadataFile();
// Read the header values first
if (!reader.ReadHeader())
return null;
dat.Header = reader.HeaderValues.ToArray();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
Row? row = null;
if (reader.Line.Count < HeaderWithExtendedHashesCount)
{
row = new Row
{
FileName = reader.Line[0],
InternalName = reader.Line[1],
Description = reader.Line[2],
GameName = reader.Line[3],
GameDescription = reader.Line[4],
Type = reader.Line[5],
RomName = reader.Line[6],
DiskName = reader.Line[7],
Size = reader.Line[8],
CRC = reader.Line[9],
MD5 = reader.Line[10],
SHA1 = reader.Line[11],
SHA256 = reader.Line[12],
Nodump = reader.Line[13],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithoutExtendedHashesCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutExtendedHashesCount).ToArray();
}
else
{
row = new Row
{
FileName = reader.Line[0],
InternalName = reader.Line[1],
Description = reader.Line[2],
GameName = reader.Line[3],
GameDescription = reader.Line[4],
Type = reader.Line[5],
RomName = reader.Line[6],
DiskName = reader.Line[7],
Size = reader.Line[8],
CRC = reader.Line[9],
MD5 = reader.Line[10],
SHA1 = reader.Line[11],
SHA256 = reader.Line[12],
SHA384 = reader.Line[13],
SHA512 = reader.Line[14],
SpamSum = reader.Line[15],
Nodump = reader.Line[16],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithExtendedHashesCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithExtendedHashesCount).ToArray();
}
rows.Add(row);
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
catch
{
// TODO: Handle logging the exception
return default;
}
}
}
}

View File

@@ -816,6 +816,32 @@ namespace SabreTools.Test.Parser
} }
} }
[Theory]
[InlineData("test-csv-files1.csv", ',', 2)]
[InlineData("test-csv-files2.csv", ',', 2)]
[InlineData("test-ssv-files1.ssv", ';', 2)]
[InlineData("test-ssv-files2.ssv", ';', 2)]
[InlineData("test-tsv-files2.tsv", '\t', 2)]
[InlineData("test-tsv-files1.tsv", '\t', 2)]
public void SeparatedValueDeserializeTest(string path, char delim, long count)
{
// Open the file for reading
string filename = System.IO.Path.Combine(Environment.CurrentDirectory, "TestData", path);
// Deserialize the file
var dat = Serialization.SeparatedValue.Deserialize(filename, delim);
// Validate the values
Assert.NotNull(dat);
Assert.Equal(count, dat.Row.Length);
// Validate we're not missing any attributes or elements
foreach (var rom in dat.Row ?? Array.Empty<Models.SeparatedValue.Row>())
{
Assert.Null(rom.ADDITIONAL_ELEMENTS);
}
}
[Theory] [Theory]
[InlineData("test-softwarelist-files1.xml", 4531)] [InlineData("test-softwarelist-files1.xml", 4531)]
[InlineData("test-softwarelist-files2.xml", 2797)] [InlineData("test-softwarelist-files2.xml", 2797)]

View File

@@ -0,0 +1,3 @@
File Name,Internal Name,Description,Game Name,Game Description,Type,Rom Name,Disk Name,Size,CRC,MD5,SHA1,SHA256,Nodump
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Rom,file.bin,,12345,0,d41d8cd98f00b204e9800998ecf8427e,da39a3ee5e6b4b0d3255bfef95601890afd80709,ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad,No
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Disk,,file.chd,,,,da39a3ee5e6b4b0d3255bfef95601890afd80709,,No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

View File

@@ -0,0 +1,3 @@
File Name,Internal Name,Description,Game Name,Game Description,Type,Rom Name,Disk Name,Size,CRC,MD5,SHA1,SHA256,SHA384,SHA512,SpamSum,Nodump
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Rom,file.bin,,12345,0,d41d8cd98f00b204e9800998ecf8427e,da39a3ee5e6b4b0d3255bfef95601890afd80709,ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad,cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7,ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f,QXX,No
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Disk,,file.chd,,,,da39a3ee5e6b4b0d3255bfef95601890afd80709,,,,,No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 SHA384 SHA512 SpamSum Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f QXX No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

View File

@@ -0,0 +1,3 @@
File Name;Internal Name;Description;Game Name;Game Description;Type;Rom Name;Disk Name;Size;CRC;MD5;SHA1;SHA256;Nodump
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Rom;file.bin;;12345;0;d41d8cd98f00b204e9800998ecf8427e;da39a3ee5e6b4b0d3255bfef95601890afd80709;ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad;No
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Disk;;file.chd;;;;da39a3ee5e6b4b0d3255bfef95601890afd80709;;No

View File

@@ -0,0 +1,3 @@
File Name;Internal Name;Description;Game Name;Game Description;Type;Rom Name;Disk Name;Size;CRC;MD5;SHA1;SHA256;SHA384;SHA512;SpamSum;Nodump
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Rom;file.bin;;12345;0;d41d8cd98f00b204e9800998ecf8427e;da39a3ee5e6b4b0d3255bfef95601890afd80709;ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad;cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7;ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f;QXX;No
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Disk;;file.chd;;;;da39a3ee5e6b4b0d3255bfef95601890afd80709;;;;;No

View File

@@ -0,0 +1,3 @@
File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 Nodump
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad No
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

View File

@@ -0,0 +1,3 @@
File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 SHA384 SHA512 SpamSum Nodump
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f QXX No
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 SHA384 SHA512 SpamSum Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f QXX No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No