|
| 1 | +using System; |
1 | 2 | using System.IO; |
2 | 3 | using System.Text; |
3 | 4 | using NUnit.Framework; |
@@ -164,5 +165,145 @@ public void NormalizesSlashes() |
164 | 165 | Assert.That(file.FileName, Is.EqualTo("d")); |
165 | 166 | } |
166 | 167 | } |
| 168 | + |
| 169 | + [Test] |
| 170 | + public void WriteThrowsWhenIsDirVPK() |
| 171 | + { |
| 172 | + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "steamdb_test_dir.vpk"); |
| 173 | + |
| 174 | + using var package = new Package(); |
| 175 | + package.Read(path); |
| 176 | + |
| 177 | + using var output = new MemoryStream(); |
| 178 | + var ex = Assert.Throws<InvalidOperationException>(() => package.Write(output)); |
| 179 | + Assert.That(ex.Message, Is.EqualTo("This package was opened from a _dir.vpk, writing back is currently unsupported.")); |
| 180 | + } |
| 181 | + |
| 182 | + [Test] |
| 183 | + public void WriteThrowsOnNonSeekableStream() |
| 184 | + { |
| 185 | + using var package = new Package(); |
| 186 | + package.AddFile("test.txt", Encoding.UTF8.GetBytes("hello")); |
| 187 | + |
| 188 | + using var nonSeekable = new NonSeekableStream(); |
| 189 | + var ex = Assert.Throws<InvalidOperationException>(() => package.Write(nonSeekable)); |
| 190 | + Assert.That(ex.Message, Is.EqualTo("Stream must be seekable and readable.")); |
| 191 | + } |
| 192 | + |
| 193 | + [Test] |
| 194 | + public void AddFileThrowsOnNullFilePath() |
| 195 | + { |
| 196 | + using var package = new Package(); |
| 197 | + Assert.Throws<ArgumentNullException>(() => package.AddFile(null!, [])); |
| 198 | + } |
| 199 | + |
| 200 | + [Test] |
| 201 | + public void RemoveFileThrowsOnNullEntry() |
| 202 | + { |
| 203 | + using var package = new Package(); |
| 204 | + Assert.Throws<ArgumentNullException>(() => package.RemoveFile(null!)); |
| 205 | + } |
| 206 | + |
| 207 | + [Test] |
| 208 | + public void RemoveFileReturnsFalseOnEmptyPackage() |
| 209 | + { |
| 210 | + using var package = new Package(); |
| 211 | + var result = package.RemoveFile(new PackageEntry |
| 212 | + { |
| 213 | + FileName = "test", |
| 214 | + TypeName = "txt", |
| 215 | + DirectoryName = " ", |
| 216 | + }); |
| 217 | + Assert.That(result, Is.False); |
| 218 | + } |
| 219 | + |
| 220 | + [Test] |
| 221 | + public void WriteAndVerifyRoundTrip() |
| 222 | + { |
| 223 | + using var output = new MemoryStream(); |
| 224 | + |
| 225 | + using (var package = new Package()) |
| 226 | + { |
| 227 | + package.AddFile("hello.txt", Encoding.UTF8.GetBytes("world")); |
| 228 | + package.AddFile("folder/image.jpg", Encoding.UTF8.GetBytes("not really a jpg")); |
| 229 | + package.Write(output); |
| 230 | + } |
| 231 | + |
| 232 | + output.Position = 0; |
| 233 | + |
| 234 | + using var readBack = new Package(); |
| 235 | + readBack.SetFileName("test.vpk"); |
| 236 | + readBack.Read(output); |
| 237 | + |
| 238 | + using (Assert.EnterMultipleScope()) |
| 239 | + { |
| 240 | + Assert.That(readBack.Version, Is.EqualTo(2)); |
| 241 | + Assert.That(readBack.HeaderSize, Is.GreaterThan(0u)); |
| 242 | + Assert.That(readBack.TreeSize, Is.GreaterThan(0u)); |
| 243 | + Assert.That(readBack.FileDataSectionSize, Is.GreaterThan(0u)); |
| 244 | + Assert.That(readBack.OtherMD5SectionSize, Is.EqualTo(48u)); |
| 245 | + } |
| 246 | + |
| 247 | + Assert.DoesNotThrow(() => readBack.VerifyHashes()); |
| 248 | + } |
| 249 | + |
| 250 | + [Test] |
| 251 | + public void WriteToFile() |
| 252 | + { |
| 253 | + var tempFile = Path.GetTempFileName(); |
| 254 | + |
| 255 | + try |
| 256 | + { |
| 257 | + using (var package = new Package()) |
| 258 | + { |
| 259 | + package.AddFile("test.txt", Encoding.UTF8.GetBytes("hello from file")); |
| 260 | + package.Write(tempFile); |
| 261 | + } |
| 262 | + |
| 263 | + using var readBack = new Package(); |
| 264 | + readBack.Read(tempFile); |
| 265 | + readBack.VerifyHashes(); |
| 266 | + |
| 267 | + var entry = readBack.FindEntry("test.txt"); |
| 268 | + Assert.That(entry, Is.Not.Null); |
| 269 | + |
| 270 | + readBack.ReadEntry(entry, out var data); |
| 271 | + Assert.That(Encoding.UTF8.GetString(data), Is.EqualTo("hello from file")); |
| 272 | + } |
| 273 | + finally |
| 274 | + { |
| 275 | + File.Delete(tempFile); |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | + [Test] |
| 280 | + public void RemoveFileReturnsFalseForWrongType() |
| 281 | + { |
| 282 | + using var package = new Package(); |
| 283 | + package.AddFile("test.txt", []); |
| 284 | + |
| 285 | + var result = package.RemoveFile(new PackageEntry |
| 286 | + { |
| 287 | + FileName = "test", |
| 288 | + TypeName = "jpg", |
| 289 | + DirectoryName = " ", |
| 290 | + }); |
| 291 | + |
| 292 | + Assert.That(result, Is.False); |
| 293 | + } |
| 294 | + |
| 295 | + private sealed class NonSeekableStream : Stream |
| 296 | + { |
| 297 | + public override bool CanRead => true; |
| 298 | + public override bool CanSeek => false; |
| 299 | + public override bool CanWrite => true; |
| 300 | + public override long Length => 0; |
| 301 | + public override long Position { get => 0; set { } } |
| 302 | + public override void Flush() { } |
| 303 | + public override int Read(byte[] buffer, int offset, int count) => 0; |
| 304 | + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); |
| 305 | + public override void SetLength(long value) { } |
| 306 | + public override void Write(byte[] buffer, int offset, int count) { } |
| 307 | + } |
167 | 308 | } |
168 | 309 | } |
0 commit comments