Fix HierarchicalRomFileTable not working and add tests

This commit is contained in:
Alex Barney 2019-02-22 14:09:35 -06:00
parent 01b14c6476
commit 5e321b7601
2 changed files with 207 additions and 1 deletions

View file

@ -207,6 +207,8 @@ namespace LibHac.IO.RomFs
path = PathTools.Normalize(path); path = PathTools.Normalize(path);
ReadOnlySpan<byte> pathBytes = GetUtf8Bytes(path); ReadOnlySpan<byte> pathBytes = GetUtf8Bytes(path);
if(path == "/") throw new ArgumentException("Path cannot be empty");
CreateFileRecursiveInternal(pathBytes, ref fileInfo); CreateFileRecursiveInternal(pathBytes, ref fileInfo);
} }
@ -347,7 +349,7 @@ namespace LibHac.IO.RomFs
{ {
ref FileRomEntry entry = ref FileTable.AddOrGet(ref key, out int offset, out bool alreadyExists, out _); ref FileRomEntry entry = ref FileTable.AddOrGet(ref key, out int offset, out bool alreadyExists, out _);
entry.Info = fileInfo; entry.Info = fileInfo;
if (alreadyExists) entry.NextSibling = -1; if (!alreadyExists) entry.NextSibling = -1;
ref DirectoryRomEntry parent = ref DirectoryTable.GetValueReference(prevOffset); ref DirectoryRomEntry parent = ref DirectoryTable.GetValueReference(prevOffset);

View file

@ -0,0 +1,204 @@
using System;
using LibHac.IO.RomFs;
using Xunit;
namespace LibHac.Tests
{
public class RomFsTests
{
[Fact]
public void SimpleAddAndRead()
{
const string path = "/a/b";
var table = new HierarchicalRomFileTable();
var item = new RomFileInfo { Length = 1, Offset = 1 };
table.AddFile(path, ref item);
bool success = table.TryOpenFile(path, out RomFileInfo readItem);
Assert.True(success, "Table read failed");
Assert.Equal(item, readItem);
}
[Fact]
public void UpdateExistingFile()
{
const string path = "/a/b";
var table = new HierarchicalRomFileTable();
var originalItem = new RomFileInfo { Length = 1, Offset = 1 };
var newItem = new RomFileInfo { Length = 1, Offset = 1 };
table.AddFile(path, ref originalItem);
table.AddFile(path, ref newItem);
bool success = table.TryOpenFile(path, out RomFileInfo readItem);
Assert.True(success, "Table read failed");
Assert.Equal(newItem, readItem);
}
[Fact]
public void AddingDirectory()
{
var table = new HierarchicalRomFileTable();
var expectedPosition = new FindPosition { NextDirectory = -1, NextFile = -1 };
table.AddDirectory("/dir");
bool success = table.TryOpenDirectory("/dir", out FindPosition position);
Assert.True(success, "Opening directory failed");
Assert.Equal(expectedPosition, position);
}
[Fact]
public void AddingEmptyPathThrows()
{
var table = new HierarchicalRomFileTable();
var item = new RomFileInfo();
Assert.Throws<ArgumentException>(() => table.AddFile("", ref item));
}
[Fact]
public void OpeningNonexistentFileFails()
{
var table = new HierarchicalRomFileTable();
bool success = table.TryOpenFile("/foo", out _);
Assert.False(success);
}
[Fact]
public void OpeningNonexistentDirectoryFails()
{
var table = new HierarchicalRomFileTable();
bool success = table.TryOpenDirectory("/foo", out _);
Assert.False(success);
}
[Fact]
public void OpeningFileAsDirectoryFails()
{
var table = new HierarchicalRomFileTable();
var fileInfo = new RomFileInfo();
table.AddFile("/file", ref fileInfo);
bool success = table.TryOpenDirectory("/file", out _);
Assert.False(success);
}
[Fact]
public void OpeningDirectoryAsFileFails()
{
var table = new HierarchicalRomFileTable();
table.AddDirectory("/dir");
bool success = table.TryOpenFile("/dir", out _);
Assert.False(success);
}
[Fact]
public void ChildFileIteration()
{
const int fileCount = 10;
var table = new HierarchicalRomFileTable();
for (int i = 0; i < fileCount; i++)
{
var item = new RomFileInfo { Length = i, Offset = i };
table.AddFile($"/a/{i}", ref item);
}
bool openDirSuccess = table.TryOpenDirectory("/a", out FindPosition position);
Assert.True(openDirSuccess, "Error opening directory");
for (int i = 0; i < fileCount; i++)
{
var expectedItem = new RomFileInfo { Length = i, Offset = i };
string expectedName = i.ToString();
bool success = table.FindNextFile(ref position, out RomFileInfo actualItem, out string actualName);
Assert.True(success, $"Failed reading file {i}");
Assert.Equal(expectedItem, actualItem);
Assert.Equal(expectedName, actualName);
}
bool endOfFilesSuccess = table.FindNextFile(ref position, out _, out _);
Assert.False(endOfFilesSuccess, "Table returned more files than it should");
}
[Fact]
public void ChildFileIterationPeek()
{
var table = new HierarchicalRomFileTable();
var itemA = new RomFileInfo { Length = 1, Offset = 1 };
var itemB = new RomFileInfo { Length = 2, Offset = 2 };
table.AddFile("/a/a", ref itemA);
table.AddFile("/a/b", ref itemB);
table.TryOpenDirectory("/a", out FindPosition position);
table.TryOpenFile(position.NextFile, out RomFileInfo peekItemA);
Assert.Equal(itemA, peekItemA);
table.FindNextFile(ref position, out RomFileInfo iterateItemA, out _);
Assert.Equal(itemA, iterateItemA);
table.TryOpenFile(position.NextFile, out RomFileInfo peekItemB);
Assert.Equal(itemB, peekItemB);
table.FindNextFile(ref position, out RomFileInfo iterateItemB, out _);
Assert.Equal(itemB, iterateItemB);
}
[Fact]
public void AddingCousinFiles()
{
var table = new HierarchicalRomFileTable();
var itemB1 = new RomFileInfo { Length = 1, Offset = 1 };
var itemB2 = new RomFileInfo { Length = 2, Offset = 2 };
var itemB3 = new RomFileInfo { Length = 3, Offset = 3 };
table.AddFile("/a/b1/c", ref itemB1);
table.AddFile("/a/b2/c", ref itemB2);
table.AddFile("/a/b3/c", ref itemB3);
table.TryOpenFile("/a/b1/c", out RomFileInfo actualItemB1);
table.TryOpenFile("/a/b2/c", out RomFileInfo actualItemB2);
table.TryOpenFile("/a/b3/c", out RomFileInfo actualItemB3);
Assert.Equal(itemB1, actualItemB1);
Assert.Equal(itemB2, actualItemB2);
Assert.Equal(itemB3, actualItemB3);
}
[Fact]
public void AddingSiblingFiles()
{
var table = new HierarchicalRomFileTable();
var itemC1 = new RomFileInfo { Length = 1, Offset = 1 };
var itemC2 = new RomFileInfo { Length = 2, Offset = 2 };
var itemC3 = new RomFileInfo { Length = 3, Offset = 3 };
table.AddFile("/a/b/c1", ref itemC1);
table.AddFile("/a/b/c2", ref itemC2);
table.AddFile("/a/b/c3", ref itemC3);
table.TryOpenFile("/a/b/c1", out RomFileInfo actualItemC1);
table.TryOpenFile("/a/b/c2", out RomFileInfo actualItemC2);
table.TryOpenFile("/a/b/c3", out RomFileInfo actualItemC3);
Assert.Equal(itemC1, actualItemC1);
Assert.Equal(itemC2, actualItemC2);
Assert.Equal(itemC3, actualItemC3);
}
}
}