Skip to content

Commit 839cb7c

Browse files
committed
Improve test coverage to 80%+ for all formats
Add comprehensive tests for previously low-coverage format classes: - AsfTag (49% → 100%): Render tests, setter tests, MusicBrainz IDs, ReplayGain, edge cases, result type equality - AsfFile (63% → 97%): File I/O tests, dispose tests, result types - WavPackFile (64% → 88%): Custom sample rate parsing, multi-channel metadata, EnsureApeTag/RemoveApeTag, Render, SaveToFile error paths - OggVorbisFile (76% → 85%): Render with originalData, field tests - MusepackFile (79% → 87%): Dispose tests, result type equality Overall coverage: 90.2% line, 77.5% branch
1 parent 323d4b6 commit 839cb7c

6 files changed

Lines changed: 1561 additions & 0 deletions

File tree

tests/TagLibSharp2.Tests/Asf/AsfFileTests.cs

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
33

44
using TagLibSharp2.Asf;
5+
using TagLibSharp2.Tests.Core;
56

67
namespace TagLibSharp2.Tests.Asf;
78

@@ -192,4 +193,270 @@ public void Parse_UnicodeArtist_Preserved ()
192193
Assert.IsTrue (result.IsSuccess);
193194
Assert.AreEqual ("Café Français", result.Value.Tag.Artist);
194195
}
196+
197+
// ═══════════════════════════════════════════════════════════════
198+
// File I/O Tests
199+
// ═══════════════════════════════════════════════════════════════
200+
201+
[TestMethod]
202+
public void ReadFromFile_ValidFile_ReturnsSuccess ()
203+
{
204+
var data = AsfTestBuilder.CreateMinimalWma (title: "File Test");
205+
var mockFs = new MockFileSystem ();
206+
mockFs.AddFile ("/test.wma", data);
207+
208+
var result = AsfFile.ReadFromFile ("/test.wma", mockFs);
209+
210+
Assert.IsTrue (result.IsSuccess, result.Error);
211+
Assert.AreEqual ("File Test", result.Value.Title);
212+
}
213+
214+
[TestMethod]
215+
public void ReadFromFile_SetsSourcePath ()
216+
{
217+
var data = AsfTestBuilder.CreateMinimalWma ();
218+
var mockFs = new MockFileSystem ();
219+
mockFs.AddFile ("/music/song.wma", data);
220+
221+
var result = AsfFile.ReadFromFile ("/music/song.wma", mockFs);
222+
223+
Assert.IsTrue (result.IsSuccess);
224+
Assert.AreEqual ("/music/song.wma", result.Value.SourcePath);
225+
}
226+
227+
[TestMethod]
228+
public void ReadFromFile_FileNotFound_ReturnsFailure ()
229+
{
230+
var mockFs = new MockFileSystem ();
231+
232+
var result = AsfFile.ReadFromFile ("/nonexistent.wma", mockFs);
233+
234+
Assert.IsFalse (result.IsSuccess);
235+
Assert.IsNotNull (result.Error);
236+
}
237+
238+
[TestMethod]
239+
public async Task ReadFromFileAsync_ValidFile_ReturnsSuccess ()
240+
{
241+
var data = AsfTestBuilder.CreateMinimalWma (title: "Async Test");
242+
var mockFs = new MockFileSystem ();
243+
mockFs.AddFile ("/test.wma", data);
244+
245+
var result = await AsfFile.ReadFromFileAsync ("/test.wma", mockFs);
246+
247+
Assert.IsTrue (result.IsSuccess, result.Error);
248+
Assert.AreEqual ("Async Test", result.Value.Title);
249+
}
250+
251+
[TestMethod]
252+
public async Task ReadFromFileAsync_SetsSourcePath ()
253+
{
254+
var data = AsfTestBuilder.CreateMinimalWma ();
255+
var mockFs = new MockFileSystem ();
256+
mockFs.AddFile ("/music/async.wma", data);
257+
258+
var result = await AsfFile.ReadFromFileAsync ("/music/async.wma", mockFs);
259+
260+
Assert.IsTrue (result.IsSuccess);
261+
Assert.AreEqual ("/music/async.wma", result.Value.SourcePath);
262+
}
263+
264+
[TestMethod]
265+
public async Task ReadFromFileAsync_FileNotFound_ReturnsFailure ()
266+
{
267+
var mockFs = new MockFileSystem ();
268+
269+
var result = await AsfFile.ReadFromFileAsync ("/nonexistent.wma", mockFs);
270+
271+
Assert.IsFalse (result.IsSuccess);
272+
Assert.IsNotNull (result.Error);
273+
}
274+
275+
// ═══════════════════════════════════════════════════════════════
276+
// Convenience Property Setter Tests
277+
// ═══════════════════════════════════════════════════════════════
278+
279+
[TestMethod]
280+
public void Title_Set_UpdatesTag ()
281+
{
282+
var data = AsfTestBuilder.CreateMinimalWma ();
283+
var result = AsfFile.Read (data);
284+
Assert.IsTrue (result.IsSuccess);
285+
286+
result.Value.Title = "New Title";
287+
288+
Assert.AreEqual ("New Title", result.Value.Title);
289+
Assert.AreEqual ("New Title", result.Value.Tag.Title);
290+
}
291+
292+
[TestMethod]
293+
public void Artist_Set_UpdatesTag ()
294+
{
295+
var data = AsfTestBuilder.CreateMinimalWma ();
296+
var result = AsfFile.Read (data);
297+
Assert.IsTrue (result.IsSuccess);
298+
299+
result.Value.Artist = "New Artist";
300+
301+
Assert.AreEqual ("New Artist", result.Value.Artist);
302+
Assert.AreEqual ("New Artist", result.Value.Tag.Artist);
303+
}
304+
305+
[TestMethod]
306+
public void Album_Get_DelegatesToTag ()
307+
{
308+
var data = AsfTestBuilder.CreateMinimalWmaWithExtended (album: "Test Album");
309+
var result = AsfFile.Read (data);
310+
311+
Assert.IsTrue (result.IsSuccess);
312+
Assert.AreEqual ("Test Album", result.Value.Album);
313+
}
314+
315+
[TestMethod]
316+
public void Album_Set_UpdatesTag ()
317+
{
318+
var data = AsfTestBuilder.CreateMinimalWma ();
319+
var result = AsfFile.Read (data);
320+
Assert.IsTrue (result.IsSuccess);
321+
322+
result.Value.Album = "New Album";
323+
324+
Assert.AreEqual ("New Album", result.Value.Album);
325+
Assert.AreEqual ("New Album", result.Value.Tag.Album);
326+
}
327+
328+
// ═══════════════════════════════════════════════════════════════
329+
// Dispose Tests
330+
// ═══════════════════════════════════════════════════════════════
331+
332+
[TestMethod]
333+
public void Dispose_ClearsSourcePath ()
334+
{
335+
var data = AsfTestBuilder.CreateMinimalWma ();
336+
var mockFs = new MockFileSystem ();
337+
mockFs.AddFile ("/test.wma", data);
338+
339+
var result = AsfFile.ReadFromFile ("/test.wma", mockFs);
340+
Assert.IsTrue (result.IsSuccess);
341+
Assert.IsNotNull (result.Value.SourcePath);
342+
343+
result.Value.Dispose ();
344+
345+
Assert.IsNull (result.Value.SourcePath);
346+
}
347+
348+
[TestMethod]
349+
public void Dispose_CalledTwice_DoesNotThrow ()
350+
{
351+
var data = AsfTestBuilder.CreateMinimalWma ();
352+
var result = AsfFile.Read (data);
353+
Assert.IsTrue (result.IsSuccess);
354+
355+
result.Value.Dispose ();
356+
result.Value.Dispose (); // Should not throw
357+
}
358+
359+
// ═══════════════════════════════════════════════════════════════
360+
// Result Type Tests
361+
// ═══════════════════════════════════════════════════════════════
362+
363+
[TestMethod]
364+
public void AsfFileReadResult_Success_IsSuccessTrue ()
365+
{
366+
var data = AsfTestBuilder.CreateMinimalWma ();
367+
var result = AsfFile.Read (data);
368+
369+
Assert.IsTrue (result.IsSuccess);
370+
Assert.IsNull (result.Error);
371+
}
372+
373+
[TestMethod]
374+
public void AsfFileReadResult_Failure_IsSuccessFalse ()
375+
{
376+
var result = AsfFile.Read ([]);
377+
378+
Assert.IsFalse (result.IsSuccess);
379+
Assert.IsNotNull (result.Error);
380+
}
381+
382+
[TestMethod]
383+
public void AsfFileReadResult_Equals_SameError_ReturnsTrue ()
384+
{
385+
var result1 = AsfFile.Read ([]);
386+
var result2 = AsfFile.Read ([]);
387+
388+
Assert.IsTrue (result1.Equals (result2));
389+
Assert.IsTrue (result1 == result2);
390+
}
391+
392+
[TestMethod]
393+
public void AsfFileReadResult_Equals_DifferentError_ReturnsFalse ()
394+
{
395+
// Empty array produces "Data too short for ASF header"
396+
var result1 = AsfFile.Read ([]);
397+
398+
// 30+ bytes with invalid GUID produces "Invalid ASF header: not an ASF file"
399+
var invalidGuidData = new byte[30];
400+
var result2 = AsfFile.Read (invalidGuidData);
401+
402+
// Different error messages should not be equal
403+
Assert.AreNotEqual (result1.Error, result2.Error);
404+
Assert.IsFalse (result1.Equals (result2));
405+
Assert.IsTrue (result1 != result2);
406+
}
407+
408+
[TestMethod]
409+
public void AsfFileReadResult_Equals_Object_ReturnsCorrectly ()
410+
{
411+
var result1 = AsfFile.Read ([]);
412+
var result2 = AsfFile.Read ([]);
413+
object boxed = result2;
414+
415+
Assert.IsTrue (result1.Equals (boxed));
416+
Assert.IsFalse (result1.Equals ("not a result"));
417+
Assert.IsFalse (result1.Equals (null));
418+
}
419+
420+
[TestMethod]
421+
public void AsfFileReadResult_GetHashCode_SameError_SameHash ()
422+
{
423+
var result1 = AsfFile.Read ([]);
424+
var result2 = AsfFile.Read ([]);
425+
426+
Assert.AreEqual (result1.GetHashCode (), result2.GetHashCode ());
427+
}
428+
429+
// ═══════════════════════════════════════════════════════════════
430+
// Edge Case Tests
431+
// ═══════════════════════════════════════════════════════════════
432+
433+
[TestMethod]
434+
public void Read_ChildObjectSizeTooLarge_ReturnsPartialParse ()
435+
{
436+
// Create file where child object claims to be larger than remaining data
437+
var data = AsfTestBuilder.CreateMinimalWma ();
438+
// Truncate to create inconsistent state - still parses what it can
439+
var truncated = data[..^50];
440+
441+
var result = AsfFile.Read (truncated);
442+
443+
// Should still succeed with what it could parse
444+
Assert.IsTrue (result.IsSuccess || result.Error!.Contains ("size"));
445+
}
446+
447+
[TestMethod]
448+
public void Read_HeaderSizeExceedsData_ReturnsFailure ()
449+
{
450+
// Create header claiming larger size than available
451+
var data = new byte[50];
452+
var headerGuid = AsfGuids.HeaderObject.Render ().ToArray ();
453+
Array.Copy (headerGuid, data, 16);
454+
// Write header size as very large number
455+
BitConverter.TryWriteBytes (data.AsSpan (16), 99999UL);
456+
457+
var result = AsfFile.Read (data);
458+
459+
Assert.IsFalse (result.IsSuccess);
460+
Assert.Contains ("size", result.Error!.ToLowerInvariant ());
461+
}
195462
}

0 commit comments

Comments
 (0)