305 lines
7.9 KiB
C#
305 lines
7.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using AMWD.Common.Packing.Ar;
|
|
|
|
namespace AMWD.Common.Tests.Packing.Ar
|
|
{
|
|
[TestClass]
|
|
public class ArWriterTest
|
|
{
|
|
private readonly DateTime _fixedDateTime = new(2023, 03, 01, 10, 20, 30, 0, DateTimeKind.Utc);
|
|
|
|
private readonly Dictionary<string, string> _files = [];
|
|
|
|
private MemoryStream _outStream;
|
|
|
|
[TestInitialize]
|
|
public void Initialize()
|
|
{
|
|
_files.Clear();
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
var (filePath, content) = GenerateTestFile();
|
|
_files.Add(filePath, content);
|
|
}
|
|
|
|
_outStream = new MemoryStream();
|
|
}
|
|
|
|
[TestCleanup]
|
|
public void Cleanup()
|
|
{
|
|
foreach (var kvp in _files)
|
|
File.Delete(kvp.Key);
|
|
|
|
_files.Clear();
|
|
|
|
_outStream.Dispose();
|
|
_outStream = null;
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldInitializeArchive()
|
|
{
|
|
// Arrange
|
|
byte[] initBytes = new byte[8];
|
|
|
|
// Act
|
|
_ = new ArWriter(_outStream);
|
|
|
|
_outStream.Seek(0, SeekOrigin.Begin);
|
|
|
|
// Assert
|
|
Assert.AreEqual(initBytes.Length, _outStream.Length);
|
|
|
|
_outStream.Read(initBytes, 0, initBytes.Length);
|
|
CollectionAssert.AreEqual(Encoding.ASCII.GetBytes("!<arch>\n"), initBytes);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldWriteOneFile()
|
|
{
|
|
// Arrange
|
|
var firstFileKvp = _files.First();
|
|
byte[] headerBytes = new byte[60];
|
|
byte[] contentBytes = new byte[14];
|
|
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
writer.WriteFile(firstFileKvp.Key, 123, 456);
|
|
|
|
_outStream.Seek(8, SeekOrigin.Begin); // set behind init bytes
|
|
|
|
// Assert
|
|
Assert.AreEqual(8 + headerBytes.Length + contentBytes.Length, _outStream.Length);
|
|
|
|
_outStream.Read(headerBytes, 0, headerBytes.Length);
|
|
_outStream.Read(contentBytes, 0, contentBytes.Length);
|
|
|
|
string header = Encoding.ASCII.GetString(headerBytes);
|
|
string content = Encoding.UTF8.GetString(contentBytes);
|
|
|
|
Assert.AreEqual($"{Path.GetFileName(firstFileKvp.Key),-16}1677666030 123 456 100644 14 `\n", header);
|
|
Assert.AreEqual(firstFileKvp.Value, content);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldWriteMultipleFiles()
|
|
{
|
|
// Arrange
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
foreach (var kvp in _files)
|
|
writer.WriteFile(kvp.Key, 123, 456);
|
|
|
|
_outStream.Seek(8, SeekOrigin.Begin);
|
|
|
|
// Assert
|
|
Assert.AreEqual(8 + 3 * 60 + 3 * 14, _outStream.Length);
|
|
|
|
foreach (var kvp in _files)
|
|
{
|
|
byte[] headerBytes = new byte[60];
|
|
byte[] contentBytes = new byte[14];
|
|
|
|
_outStream.Read(headerBytes, 0, headerBytes.Length);
|
|
_outStream.Read(contentBytes, 0, contentBytes.Length);
|
|
|
|
string header = Encoding.ASCII.GetString(headerBytes);
|
|
string content = Encoding.UTF8.GetString(contentBytes);
|
|
|
|
Assert.AreEqual($"{Path.GetFileName(kvp.Key),-16}1677666030 123 456 100644 14 `\n", header);
|
|
Assert.AreEqual(kvp.Value, content);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldPadToEven()
|
|
{
|
|
// Arrange
|
|
var (filePath, fileContent) = GenerateTestFile(13);
|
|
|
|
try
|
|
{
|
|
byte[] headerBytes = new byte[60];
|
|
byte[] contentBytes = new byte[14];
|
|
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
writer.WriteFile(filePath, 123, 456);
|
|
|
|
_outStream.Seek(8, SeekOrigin.Begin);
|
|
|
|
// Assert
|
|
Assert.AreEqual(8 + headerBytes.Length + contentBytes.Length, _outStream.Length);
|
|
|
|
_outStream.Read(headerBytes, 0, headerBytes.Length);
|
|
_outStream.Read(contentBytes, 0, contentBytes.Length);
|
|
|
|
string header = Encoding.ASCII.GetString(headerBytes);
|
|
string content = Encoding.UTF8.GetString(contentBytes);
|
|
|
|
Assert.AreEqual($"{Path.GetFileName(filePath),-16}1677666030 123 456 100644 13 `\n", header);
|
|
Assert.AreEqual(fileContent + "\n", content);
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(filePath);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
[ExpectedException(typeof(ArgumentException))]
|
|
public void ShouldFailOnFileNameTooLong()
|
|
{
|
|
// Arrange
|
|
var (filePath, _) = GenerateTestFile();
|
|
try
|
|
{
|
|
string path = Path.GetDirectoryName(filePath);
|
|
string fileName = Path.GetFileName(filePath);
|
|
fileName = fileName.PadLeft(20, 'a');
|
|
|
|
File.Move(filePath, Path.Combine(path, fileName));
|
|
filePath = Path.Combine(path, fileName);
|
|
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
writer.WriteFile(filePath, 123, 456);
|
|
|
|
// Assert - Exception
|
|
Assert.Fail();
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(filePath);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldWriteEmptyOnNegativeUserId()
|
|
{
|
|
// Arrange
|
|
var firstFileKvp = _files.First();
|
|
byte[] headerBytes = new byte[60];
|
|
byte[] contentBytes = new byte[14];
|
|
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
writer.WriteFile(firstFileKvp.Key, -123, 456);
|
|
|
|
_outStream.Seek(8, SeekOrigin.Begin);
|
|
|
|
// Assert
|
|
Assert.AreEqual(8 + headerBytes.Length + contentBytes.Length, _outStream.Length);
|
|
|
|
_outStream.Read(headerBytes, 0, headerBytes.Length);
|
|
_outStream.Read(contentBytes, 0, contentBytes.Length);
|
|
|
|
string header = Encoding.ASCII.GetString(headerBytes);
|
|
string content = Encoding.UTF8.GetString(contentBytes);
|
|
|
|
Assert.AreEqual($"{Path.GetFileName(firstFileKvp.Key),-16}1677666030 456 100644 14 `\n", header);
|
|
Assert.AreEqual(firstFileKvp.Value, content);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldWriteEmptyOnNegativeGroupId()
|
|
{
|
|
// Arrange
|
|
var firstFileKvp = _files.First();
|
|
byte[] headerBytes = new byte[60];
|
|
byte[] contentBytes = new byte[14];
|
|
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
writer.WriteFile(firstFileKvp.Key, 123, -456);
|
|
|
|
_outStream.Seek(8, SeekOrigin.Begin);
|
|
|
|
// Assert
|
|
Assert.AreEqual(8 + headerBytes.Length + contentBytes.Length, _outStream.Length);
|
|
|
|
_outStream.Read(headerBytes, 0, headerBytes.Length);
|
|
_outStream.Read(contentBytes, 0, contentBytes.Length);
|
|
|
|
string header = Encoding.ASCII.GetString(headerBytes);
|
|
string content = Encoding.UTF8.GetString(contentBytes);
|
|
|
|
Assert.AreEqual($"{Path.GetFileName(firstFileKvp.Key),-16}1677666030 123 100644 14 `\n", header);
|
|
Assert.AreEqual(firstFileKvp.Value, content);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldWriteEmptyOnNegativeMode()
|
|
{
|
|
// Arrange
|
|
var firstFileKvp = _files.First();
|
|
byte[] headerBytes = new byte[60];
|
|
byte[] contentBytes = new byte[14];
|
|
|
|
var writer = new ArWriter(_outStream);
|
|
|
|
// Act
|
|
writer.WriteFile(firstFileKvp.Key, 123, 456, -1);
|
|
|
|
_outStream.Seek(8, SeekOrigin.Begin);
|
|
|
|
// Assert
|
|
Assert.AreEqual(8 + headerBytes.Length + contentBytes.Length, _outStream.Length);
|
|
|
|
_outStream.Read(headerBytes, 0, headerBytes.Length);
|
|
_outStream.Read(contentBytes, 0, contentBytes.Length);
|
|
|
|
string header = Encoding.ASCII.GetString(headerBytes);
|
|
string content = Encoding.UTF8.GetString(contentBytes);
|
|
|
|
Assert.AreEqual($"{Path.GetFileName(firstFileKvp.Key),-16}1677666030 123 456 14 `\n", header);
|
|
Assert.AreEqual(firstFileKvp.Value, content);
|
|
}
|
|
|
|
[TestMethod]
|
|
[ExpectedException(typeof(ArgumentException))]
|
|
public void ShouldFailOnNonWritableStream()
|
|
{
|
|
// Arrange
|
|
using var testStream = new NonWriteStream();
|
|
|
|
// Act
|
|
_ = new ArWriter(testStream);
|
|
|
|
// Assert - ArgumentException
|
|
Assert.Fail();
|
|
}
|
|
|
|
private (string filePath, string content) GenerateTestFile(int length = 14)
|
|
{
|
|
string filePath = Path.GetTempFileName();
|
|
string text = CryptographyHelper.GetRandomString(length);
|
|
|
|
File.WriteAllText(filePath, text);
|
|
File.SetLastWriteTimeUtc(filePath, _fixedDateTime);
|
|
return (filePath, text);
|
|
}
|
|
|
|
private class NonWriteStream : MemoryStream
|
|
{
|
|
public NonWriteStream()
|
|
: base()
|
|
{ }
|
|
|
|
public override bool CanWrite => false;
|
|
}
|
|
}
|
|
}
|