Permalink
Browse files

Initial commit of unfinished mp3 integrity checker

  • Loading branch information...
0 parents commit 0517e7714b3d0f50764412e08f8d31ab6b432424 @brson committed Jan 6, 2010
Showing with 1,734,735 additions and 0 deletions.
  1. +13 −0 Slush.Test/Crc16Test.cs
  2. +59 −0 Slush.Test/DomainObjects.Mp3.Test/JunkRegionTest.cs
  3. +13 −0 Slush.Test/DomainObjects.Mp3.Test/LameHeaderRulesTest.cs
  4. +13 −0 Slush.Test/DomainObjects.Mp3.Test/LameHeaderTest.cs
  5. +397 −0 Slush.Test/DomainObjects.Mp3.Test/Mp3FrameHeaderRulesTest.cs
  6. +283 −0 Slush.Test/DomainObjects.Mp3.Test/Mp3FrameHeaderTest.cs
  7. +213 −0 Slush.Test/DomainObjects.Mp3.Test/Mp3FrameTest.cs
  8. +125 −0 Slush.Test/DomainObjects.Mp3.Test/Mp3StreamBuilder.cs
  9. +56 −0 Slush.Test/DomainObjects.Mp3.Test/Mp3StreamReaderTest.File.cs
  10. +559 −0 Slush.Test/DomainObjects.Mp3.Test/Mp3StreamReaderTest.cs
  11. +187 −0 Slush.Test/EventWeaverTest.cs
  12. +13 −0 Slush.Test/Mp3ValidatorTest.cs
  13. +26 −0 Slush.Test/PrereqAttribute.cs
  14. +35 −0 Slush.Test/Properties/AssemblyInfo.cs
  15. +13 −0 Slush.Test/Services.Mp3.Test/LameHeaderServiceTest.cs
  16. +209 −0 Slush.Test/Services.Mp3.Test/Mp3CrawlerServiceTest.cs
  17. +136 −0 Slush.Test/Services.Test/StreamProcessServiceTest.cs
  18. +125 −0 Slush.Test/Slush.Test.csproj
  19. +13 −0 Slush.Test/UtilTest.cs
  20. +13 −0 Slush.Test/ValidationFailureTest.cs
  21. +13 −0 Slush.Test/Validators.Mp3.Test/AverageBitrateValidatorTest.cs
  22. +13 −0 Slush.Test/Validators.Mp3.Test/BrokenFrameValidatorTest.cs
  23. +13 −0 Slush.Test/Validators.Mp3.Test/FrameCrcValidatorTest.cs
  24. +13 −0 Slush.Test/Validators.Mp3.Test/JunkDataValidatorTest.cs
  25. +13 −0 Slush.Test/Validators.Mp3.Test/LameHeaderPresentValidatorTest.cs
  26. +13 −0 Slush.Test/Validators.Mp3.Test/LameInfoCrcValidatorTest.cs
  27. +13 −0 Slush.Test/Validators.Mp3.Test/LameMusicCrcValidatorTest.cs
  28. +14 −0 Slush.Test/Validators.Test/ValidationFailureCollectorServiceTest.cs
  29. +182 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1.readme.txt
  30. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1.tar.gz
  31. +182 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/README.txt
  32. +7,056 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl1.mpg
  33. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl1.pcm
  34. +5,120 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl2.mpg
  35. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl2.pcm
  36. +4,704 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl3.mpg
  37. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl3.pcm
  38. +588 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl4.mpg
  39. +32,768 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl4.pcm
  40. +5,488 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl5.mpg
  41. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl5.pcm
  42. +5,121 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl6.mpg
  43. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl6.pcm
  44. +6,583 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl7.mpg
  45. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl7.pcm
  46. +5,120 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl8.mpg
  47. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer1/fl8.pcm
  48. +189 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2.readme.txt
  49. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2.tar.gz
  50. +189 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/README.txt
  51. +42,336 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl10.mpg
  52. +131,072 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl10.pcm
  53. +30,720 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl11.mpg
  54. +131,072 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl11.pcm
  55. +28,224 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl12.mpg
  56. +131,072 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl12.pcm
  57. +7,056 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl13.mpg
  58. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl13.pcm
  59. +18,432 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl14.mpg
  60. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl14.pcm
  61. +18,432 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl15.mpg
  62. +65,536 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl15.pcm
  63. +48,384 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl16.mpg
  64. +163,840 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer2/fl16.pcm
  65. +22 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3.readme.txt
  66. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3.tar.gz
  67. +22 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/README.txt
  68. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/compl.bit
  69. +248,832 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/compl.hex
  70. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/he_32khz.bit
  71. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/he_44khz.bit
  72. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/he_48khz.bit
  73. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/he_free.bit
  74. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/he_mode.bit
  75. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/hecommon.bit
  76. +725 −0 Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/l3compl.txt
  77. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/l3dec
  78. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/l3dec.exe
  79. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/si.bit
  80. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/si_block.bit
  81. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/si_huff.bit
  82. BIN Slush.Test/s022691_ISO_IEC_11172-4_1995_Compliance_Testing/layer3/sin1k0db.bit
  83. +26 −0 Slush.sln
  84. +55 −0 Slush/App/Slush.cs
  85. +82 −0 Slush/Crc16.cs
  86. +21 −0 Slush/DomainObjects.Mp3/IMp3StreamRegion.cs
  87. +71 −0 Slush/DomainObjects.Mp3/JunkRegion.cs
  88. +70 −0 Slush/DomainObjects.Mp3/LameHeader.cs
  89. +35 −0 Slush/DomainObjects.Mp3/LameHeaderRules.cs
  90. +147 −0 Slush/DomainObjects.Mp3/Mp3Frame.cs
  91. +395 −0 Slush/DomainObjects.Mp3/Mp3FrameHeader.cs
  92. +346 −0 Slush/DomainObjects.Mp3/Mp3FrameHeaderRules.cs
  93. +765 −0 Slush/DomainObjects.Mp3/Mp3StreamReader.cs
  94. +264 −0 Slush/EventWeaver.cs
  95. +11 −0 Slush/IValidator.cs
  96. +52 −0 Slush/Mp3Validator.cs
  97. +33 −0 Slush/Properties/AssemblyInfo.cs
  98. +72 −0 Slush/Services.Mp3/LameHeaderService.cs
  99. +187 −0 Slush/Services.Mp3/Mp3CrawlerService.cs
  100. +140 −0 Slush/Services/StreamProcessService.cs
  101. +121 −0 Slush/Slush.csproj
  102. +4 −0 Slush/TODO.txt
  103. +41 −0 Slush/UnexpectedException.cs
  104. +26 −0 Slush/Util.cs
  105. +59 −0 Slush/ValidationFailure.cs
  106. +11 −0 Slush/Validators.Mp3/AverageBitrateValidator.cs
  107. +26 −0 Slush/Validators.Mp3/BrokenFrameValidator.cs
  108. +11 −0 Slush/Validators.Mp3/FrameCrcValidator.cs
  109. +11 −0 Slush/Validators.Mp3/JunkDataValidator.cs
  110. +25 −0 Slush/Validators.Mp3/LameHeaderPresentValidator.cs
  111. +31 −0 Slush/Validators.Mp3/LameInfoCrcValidator.cs
  112. +63 −0 Slush/Validators.Mp3/LameMusicCrcValidator.cs
  113. +37 −0 Slush/Validators/ValidationFailureCollectorService.cs
13 Slush.Test/Crc16Test.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+
+namespace Slush.Test
+{
+ [TestFixture]
+ public class Crc16Test
+ {
+ }
+}
59 Slush.Test/DomainObjects.Mp3.Test/JunkRegionTest.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using NUnit.Framework;
+using Slush.DomainObjects.Mp3;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public class JunkRegionTest
+ {
+ #region Tests
+
+ /// <summary>
+ /// Argument of constructor may not be null
+ /// </summary>
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException),
+ ExpectedMessage="Argument may not be null",
+ MatchType=MessageMatch.Contains)]
+ public void Constructor_NullTest()
+ {
+ new JunkRegion(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException),
+ ExpectedMessage="Length must be greater than 0",
+ MatchType=MessageMatch.Contains)]
+ public void Constructor_0LengthTest()
+ {
+ byte[] b = new byte[0];
+ new JunkRegion(b);
+ }
+
+ [Test]
+ public void Constructor_CopyInputTest()
+ {
+ byte[] b = new byte[] { 1, 1 };
+ JunkRegion jr = new JunkRegion(b);
+ b[1] = 2;
+ Assert.AreEqual(1, jr.Bytes[1]);
+ }
+
+ [Test]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void Bytes_NotWritableTest()
+ {
+ JunkRegion jr = new JunkRegion(new byte[10]);
+ IList<byte> bytes = jr.Bytes;
+ Assert.AreEqual(10, bytes.Count);
+ // Modify junk region data
+ bytes[9] = 0xFF;
+ }
+
+ #endregion
+ }
+}
13 Slush.Test/DomainObjects.Mp3.Test/LameHeaderRulesTest.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public class LameHeaderRulesTest
+ {
+ }
+}
13 Slush.Test/DomainObjects.Mp3.Test/LameHeaderTest.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public class LameHeaderTest
+ {
+ }
+}
397 Slush.Test/DomainObjects.Mp3.Test/Mp3FrameHeaderRulesTest.cs
@@ -0,0 +1,397 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
+using Slush.DomainObjects.Mp3;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public class Mp3FrameHeaderRulesTest
+ {
+ #region Data
+
+ private static readonly byte[][] TEST_HEADER =
+ {
+ // Frame sync
+ // | Version
+ // | | Layer
+ // | | | CRC
+ // | | | | Bitrate index
+ // | | | | | Samplerate index
+ // | | | | | | Padding bit
+ // | | | | | | | Private bit
+ // | | | | | | | | Channel mode
+ // | | | | | | | | | Mode extension
+ // | | | | | | | | | | Copyright
+ // | | | | | | | | | | | Original
+ // | | | | | | | | | | | | Emphasis
+ // | | | | | | | | | | | | |
+ // 11111111 / 111 11 01 0 / 1001 00 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFA, 0x90, 0x00 }, // V1L3, 128/44, Stereo, CRC0
+ // 11111011 / 111 10 00 1 / 1111 00 0 0 / 01 00 0 0 01
+ new byte[] { 0xFB, 0xF1, 0xF0, 0x41 }, // Bad frame sync, V2LR, CRC1, invalid bitrate
+ // 11111011 / 111 00 10 1 / 0000 00 0 0 / 10 00 0 0 10
+ new byte[] { 0xFB, 0xE5, 0x00, 0x82 }, // Bad frame sync, V2.5L2, free bitrate, 11025 samplerate
+ // 11111011 / 111 01 11 1 / 1001 00 1 1 / 11 00 0 1 11
+ new byte[] { 0xFB, 0xEF, 0x93, 0xC7 }, // Bad frame sync, VRL1, bitrate, padding, private
+ // 11111011 / 111 10 00 1 / 1001 11 0 0 / 00 00 1 0 00
+ new byte[] { 0xFF, 0xF1, 0x9C, 0x08 }, // V2LR, bitrate, samplerate reserved
+ // 11111011 / 111 10 10 1 / 0100 00 0 0 / 10 00 1 0 00
+ new byte[] { 0xFF, 0xF5, 0x4C, 0x88 }, // L2, 32kbps, dual channel
+ // 11111011 / 111 10 00 1 / 1101 00 0 0 / 01 00 0 0 01
+ new byte[] { 0xFB, 0xF1, 0xD0, 0x41 }, // Bad frame sync, V2LR, CRC1, valid bitrate
+ // 11111111 / 111 11 01 0 / 1111 00 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFA, 0xF0, 0x00 }, // V1L3, 128/44, Stereo, CRC0, invalid bitrate
+ // 11111111 / 111 11 01 0 / 1001 11 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFA, 0x9C, 0x00 }, // V1L3, 128/44, Stereo, CRC0, samplerate res
+
+ // 11111111 / 111 00 11 1 / 1001 00 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xE7, 0x90, 0x00 }, // V25L1, 144/11025, no padding
+ // 11111111 / 111 00 11 1 / 0001 01 1 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xE7, 0x16, 0x00 }, // V25L1, 32/12000, padding
+ // 11111111 / 111 10 10 1 / 1101 10 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xF5, 0xD8, 0x00 }, // V2L2, 144/16000, no padding
+ // 11111111 / 111 10 10 1 / 0011 01 1 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xF5, 0x36, 0x00 }, // V2L2, 24/24000, padding
+ // 11111111 / 111 11 01 1 / 1000 10 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFB, 0x88, 0x00 }, // V1L3, 112/32000, no padding
+ // 11111111 / 111 11 01 1 / 0100 01 1 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFB, 0x46, 0x00 }, // V1L3, 56/48000, padding
+ // 11111111 / 111 11 01 0 / 0100 01 1 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFA, 0x46, 0x00 }, // V1L3, 56/48000, padding, Use CRC
+ };
+
+ // indexes into TEST_HEADER
+ private static readonly int THIDX_SMOKE = 0;
+ private static readonly int THIDX_BR_128 = 0;
+ private static readonly int THIDX_BR_INVALID = 1;
+ private static readonly int THIDX_BR_FREE = 2;
+ private static readonly int THIDX_BR_VR = 3;
+ private static readonly int THIDX_BR_LR = 4;
+ private static readonly int THIDX_SR_RESERVED = 4;
+ private static readonly int THIDX_SR00_V25 = 2;
+ private static readonly int THIDX_LEN_OK = 0;
+ private static readonly int THIDX_LEN_LR = 6;
+ private static readonly int THIDX_LEN_BR_INVALID = 7;
+ private static readonly int THIDX_LEN_BR_FREE = 2;
+ private static readonly int THIDX_LEN_SR_RESERVED = 8;
+ private static readonly int THIDX_LEN_VR = 3;
+ private static readonly int THIDX_LEN_V25L1_NO_PADDING = 9; // 628
+ private static readonly int THIDX_LEN_V25L1_PADDING = 10; // 136
+ private static readonly int THIDX_LEN_V2L2_NO_PADDING = 11; // 1300
+ private static readonly int THIDX_LEN_V2L2_PADDING = 12; // 149
+ private static readonly int THIDX_LEN_V1L3_NO_PADDING = 13; // 508
+ private static readonly int THIDX_LEN_V1L3_PADDING = 14; // 173
+ private static readonly int THIDX_LEN_WITH_CRC = 15; // 175
+
+ #endregion
+
+
+ #region Private Members
+
+ private Mp3FrameHeader h;
+
+ #endregion
+
+
+ #region Tests
+
+ [Test]
+ public void CalculateBitrate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_128]);
+ Assert.That(Mp3FrameHeaderRules.CalculateBitrate(h), Is.EqualTo(128000));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CalculateBitrate_NullTest()
+ {
+ Mp3FrameHeaderRules.CalculateBitrate(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame has a free bitrate")]
+ public void CalculateBitrate_HasFreeTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_FREE]);
+ Mp3FrameHeaderRules.CalculateBitrate(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame has an invalid bitrate")]
+ public void CalculateBitrate_HasInvalidTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_INVALID]);
+ Mp3FrameHeaderRules.CalculateBitrate(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame does not specify a version")]
+ public void CalculateBitrate_ReservedVersionTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_VR]);
+ Mp3FrameHeaderRules.CalculateBitrate(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame does not specify a layer")]
+ public void CalculateBitrate_ReservedLayerTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_LR]);
+ Mp3FrameHeaderRules.CalculateBitrate(h);
+ }
+
+ [Test]
+ public void CanCalculateBitrate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_128]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateBitrate(h), Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_FREE]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateBitrate(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_INVALID]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateBitrate(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_VR]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateBitrate(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_LR]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateBitrate(h), Is.False);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CanCalculateBitrate_NullTest()
+ {
+ Mp3FrameHeaderRules.CanCalculateBitrate(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame has a reserved samplerate")]
+ public void CalculateSamplerate_HasReservedTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SR_RESERVED]);
+ Mp3FrameHeaderRules.CalculateSamplerate(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame has a reserved version")]
+ public void CalculateSamplerate_ReservedVersionTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_VR]);
+ Mp3FrameHeaderRules.CalculateSamplerate(h);
+ }
+
+ [Test]
+ public void CalculateSamplerate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(Mp3FrameHeaderRules.CalculateSamplerate(h), Is.EqualTo(44100));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SR00_V25]);
+ Assert.That(Mp3FrameHeaderRules.CalculateSamplerate(h), Is.EqualTo(11025));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CalculateSamplerate_NullTest()
+ {
+ Mp3FrameHeaderRules.CalculateSamplerate(null);
+ }
+
+ [Test]
+ public void CanCalculateSamplerate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SR_RESERVED]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateSamplerate(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_VR]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateSamplerate(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateSamplerate(h), Is.True);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CanCalculateSamplerate_NullTest()
+ {
+ Mp3FrameHeaderRules.CanCalculateSamplerate(null);
+ }
+
+ // Frame length depends on version, layer, bitrate, samplerate
+ [Test]
+ public void CanCalculateFrameLength_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_OK]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateFrameLength(h), Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_LR]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateFrameLength(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_BR_INVALID]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateFrameLength(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_BR_FREE]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateFrameLength(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_SR_RESERVED]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateFrameLength(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_VR]);
+ Assert.That(Mp3FrameHeaderRules.CanCalculateFrameLength(h), Is.False);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CanCalculateFrameLength_NullTest()
+ {
+ Mp3FrameHeaderRules.CalculateFrameLength(null);
+ }
+
+ [Test]
+ public void CalculateFrameLength_Test()
+ {
+ // V25, Layer 1, no padding
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V25L1_NO_PADDING]);
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(624));
+ // V25, Layer 1, padding
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V25L1_PADDING]);
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(132));
+ // V2, Layer 2, no padding
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V2L2_NO_PADDING]);
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(1296));
+ // V2, Layer 2, padding
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V2L2_PADDING]);
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(145));
+ // V1, Layer 3, no padding
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V1L3_NO_PADDING]);
+ Assert.AreEqual(112000, Mp3FrameHeaderRules.CalculateBitrate(h));
+ Assert.AreEqual(32000, Mp3FrameHeaderRules.CalculateSamplerate(h));
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(504));
+ // V1, Layer 3, padding
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V1L3_PADDING]);
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(169));
+ // Add a CRC
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_WITH_CRC]);
+ Assert.That(Mp3FrameHeaderRules.CalculateFrameLength(h), Is.EqualTo(171));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CalculateFrameLength_NullTest()
+ {
+ Mp3FrameHeaderRules.CalculateFrameLength(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "Cannot calculate bitrate")]
+ public void CalculateFrameLength_NoBitrateTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_BR_FREE]);
+ Mp3FrameHeaderRules.CalculateFrameLength(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "Cannot calculate samplerate")]
+ public void CalculateFrameLength_NoSamplerateTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_SR_RESERVED]);
+ Mp3FrameHeaderRules.CalculateFrameLength(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame has a reserved layer")]
+ public void CalculateFrameLength_ReservedLayerTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[4]);
+ Mp3FrameHeaderRules.CalculateFrameLength(h);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame has a reserved version")]
+ public void CalculateFrameLength_ReservedVersionTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[3]);
+ Mp3FrameHeaderRules.CalculateFrameLength(h);
+ }
+
+ [Test]
+ public void HasInvalidBitrateForChannelMode_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[0]);
+ Assert.That(Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[1]);
+ Assert.That(Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[2]);
+ Assert.That(Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[3]);
+ Assert.That(Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[4]);
+ Assert.That(Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[5]);
+ Assert.That(Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(h), Is.True);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void HasInvalidBitrateForChannelMode_NullTest()
+ {
+ Mp3FrameHeaderRules.HasInvalidBitrateForChannelMode(null);
+ }
+
+ [Test]
+ public void IsValid_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[0]);
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[1]);
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[2]);
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[3]);
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[4]);
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[5]);
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.False);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void IsValid_NullTest()
+ {
+ Mp3FrameHeaderRules.IsValid(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CalculatePayloadLength_NullTest()
+ {
+ Mp3FrameHeaderRules.CalculatePayloadLength(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void CalculatePayloadLength_CantCalculateTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_BR_FREE]);
+ Mp3FrameHeaderRules.CalculatePayloadLength(h);
+ }
+
+ [Test]
+ public void CalculatePayloadLength_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_V1L3_PADDING]);
+ Assert.That(Mp3FrameHeaderRules.CalculatePayloadLength(h), Is.EqualTo(169 - 4));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LEN_WITH_CRC]);
+ Assert.That(Mp3FrameHeaderRules.CalculatePayloadLength(h), Is.EqualTo(171 - 6));
+ }
+
+
+ #endregion
+ }
+}
283 Slush.Test/DomainObjects.Mp3.Test/Mp3FrameHeaderTest.cs
@@ -0,0 +1,283 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
+using Slush.DomainObjects.Mp3;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public class Mp3FrameHeaderTest
+ {
+ #region Data
+
+ private static readonly byte[][] TEST_HEADER =
+ {
+ // Frame sync
+ // | Version
+ // | | Layer
+ // | | | CRC
+ // | | | | Bitrate index
+ // | | | | | Samplerate index
+ // | | | | | | Padding bit
+ // | | | | | | | Private bit
+ // | | | | | | | | Channel mode
+ // | | | | | | | | | Mode extension
+ // | | | | | | | | | | Copyright
+ // | | | | | | | | | | | Original
+ // | | | | | | | | | | | | Emphasis
+ // | | | | | | | | | | | | |
+ // 11111111 / 111 11 01 0 / 1001 00 0 0 / 00 00 0 0 00
+ new byte[] { 0xFF, 0xFA, 0x90, 0x00 }, // V1L3, 128/44, Stereo, CRC0
+ // 11111011 / 111 10 00 1 / 1111 00 0 0 / 01 00 0 0 01
+ new byte[] { 0xFB, 0xF1, 0xF0, 0x41 }, // Bad frame sync, V2LR, CRC1, invalid bitrate
+ // 11111011 / 111 00 10 1 / 0000 00 0 0 / 10 00 0 0 10
+ new byte[] { 0xFB, 0xE5, 0x00, 0x82 }, // Bad frame sync, V2.5L2, free bitrate, 11025 samplerate
+ // 11111011 / 111 01 11 1 / 1001 00 1 1 / 11 00 0 1 11
+ new byte[] { 0xFB, 0xEF, 0x93, 0xC7 }, // Bad frame sync, VRL1, bitrate, padding, private
+ // 11111011 / 111 10 00 1 / 1001 11 0 0 / 00 00 1 0 00
+ new byte[] { 0xFF, 0xF1, 0x9C, 0x08 }, // V2LR, bitrate, samplerate reserved
+ // 11111011 / 111 10 10 1 / 0100 00 0 0 / 10 00 1 0 00
+ new byte[] { 0xFF, 0xF5, 0x4C, 0x88 }, // L2, 32kbps, dual channel
+ };
+
+ // indexes into TEST_HEADER
+ private static readonly int THIDX_SMOKE = 0;
+ private static readonly int THIDX_BAD_FRAME_SYNC = 1;
+ private static readonly int THIDX_V1 = 0;
+ private static readonly int THIDX_V2 = 1;
+ private static readonly int THIDX_V25 = 2;
+ private static readonly int THIDX_VR = 3;
+ private static readonly int THIDX_LR = 1;
+ private static readonly int THIDX_L3 = 0;
+ private static readonly int THIDX_L2 = 2;
+ private static readonly int THIDX_L1 = 3;
+ private static readonly int THIDX_CRC0 = 0; // has CRC
+ private static readonly int THIDX_CRC1 = 1; // doesn't have CRC
+ private static readonly int THIDX_BR_INVALID = 1;
+ private static readonly int THIDX_BR_FREE = 2;
+ private static readonly int THIDX_SR_RESERVED = 4;
+ private static readonly int THIDX_SR00_V25 = 2;
+ private static readonly int THIDX_PADDING = 3;
+ private static readonly int THIDX_PRIVATE = 3;
+ private static readonly int THIDX_CM_STEREO = 0;
+ private static readonly int THIDX_CM_JS = 1;
+ private static readonly int THIDX_CM_DUAL = 2;
+ private static readonly int THIDX_CM_MONO = 3;
+ private static readonly int THIDX_COPY = 4;
+ private static readonly int THIDX_ORIG = 3;
+ private static readonly int THIDX_EM_NONE = 0;
+ private static readonly int THIDX_EM_50 = 1;
+ private static readonly int THIDX_EM_R = 2;
+ private static readonly int THIDX_EM_C = 3;
+
+ #endregion
+
+
+ #region Private Members
+
+ private Mp3FrameHeader h;
+
+ #endregion
+
+
+ #region Tests
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException),
+ ExpectedMessage = "Frame header must not be null",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_NullTest()
+ {
+ new Mp3FrameHeader(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentOutOfRangeException),
+ ExpectedMessage = "Frame header must be 4 bytes long",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_ShortTest()
+ {
+ new Mp3FrameHeader(new byte[3]);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentOutOfRangeException),
+ ExpectedMessage = "Frame header must be 4 bytes long",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_LongTest()
+ {
+ new Mp3FrameHeader(new byte[5]);
+ }
+
+ /// <summary>
+ /// The constructor should make a copy of the incoming list
+ /// </summary>
+ [Test]
+ public void Constructor_CopyTest()
+ {
+ byte[] b = {0xFF, 0xFF, 0, 0};
+ h = new Mp3FrameHeader(b);
+ b[0] = 0;
+ b[1] = 0;
+ Assert.That(h.HasFrameSync, Is.True);
+ }
+
+ [Test]
+ public void SmokeTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(h.HasFrameSync, Is.True);
+ Assert.That(h.Version, Is.EqualTo(MpegVersion.V1));
+ Assert.That(h.Layer, Is.EqualTo(MpegLayer.Layer3));
+ Assert.That(h.HasCRC, Is.True);
+ Assert.That(Mp3FrameHeaderRules.CalculateBitrate(h), Is.EqualTo(128000));
+ Assert.That(h.HasFreeBitrate, Is.False);
+ Assert.That(h.HasInvalidBitrate, Is.False);
+ Assert.That(Mp3FrameHeaderRules.CalculateSamplerate(h), Is.EqualTo(44100));
+ Assert.That(h.HasReservedSamplerate, Is.False);
+ Assert.That(h.HasPadding, Is.False);
+ Assert.That(h.HasPrivateFlag, Is.False);
+ Assert.That(h.ChannelMode, Is.EqualTo(MpegChannelMode.Stereo));
+ Assert.That(h.HasCopyright, Is.False);
+ Assert.That(h.HasOriginal, Is.False);
+ Assert.That(h.Emphasis, Is.EqualTo(MpegEmphasis.None));
+ Assert.That(Mp3FrameHeaderRules.IsValid(h), Is.True);
+ }
+
+ [Test]
+ public void HasFrameSync_FalseTest()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BAD_FRAME_SYNC]);
+ Assert.That(h.HasFrameSync, Is.False);
+ }
+
+ [Test]
+ public void Version_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_V1]);
+ Assert.That(h.Version, Is.EqualTo(MpegVersion.V1));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_V2]);
+ Assert.That(h.Version, Is.EqualTo(MpegVersion.V2));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_V25]);
+ Assert.That(h.Version, Is.EqualTo(MpegVersion.V25));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_VR]);
+ Assert.That(h.Version, Is.EqualTo(MpegVersion.Reserved));
+ }
+
+ [Test]
+ public void Layer_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_LR]);
+ Assert.That(h.Layer, Is.EqualTo(MpegLayer.Reserved));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_L3]);
+ Assert.That(h.Layer, Is.EqualTo(MpegLayer.Layer3));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_L2]);
+ Assert.That(h.Layer, Is.EqualTo(MpegLayer.Layer2));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_L1]);
+ Assert.That(h.Layer, Is.EqualTo(MpegLayer.Layer1));
+ }
+
+ [Test]
+ public void HasCrc_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_CRC0]);
+ Assert.That(h.HasCRC, Is.True, "If the CRC bit is zero, the frame has a CRC");
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_CRC1]);
+ Assert.That(h.HasCRC, Is.False, "If the CRC bit is one, the frame has no CRC");
+ }
+
+ [Test]
+ public void HasFreeBitrate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_FREE]);
+ Assert.That(h.HasFreeBitrate, Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(h.HasFreeBitrate, Is.False);
+ }
+
+ [Test]
+ public void HasInvalidBitrate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_BR_INVALID]);
+ Assert.That(h.HasInvalidBitrate, Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(h.HasInvalidBitrate, Is.False);
+ }
+
+ [Test]
+ public void HasReservedSamplerate_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SR_RESERVED]);
+ Assert.That(h.HasReservedSamplerate, Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SR00_V25]);
+ Assert.That(h.HasReservedSamplerate, Is.False);
+ }
+
+ [Test]
+ public void HasPadding_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_PADDING]);
+ Assert.That(h.HasPadding, Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(h.HasPadding, Is.False);
+ }
+
+ [Test]
+ public void HasPrivateFlag_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_PRIVATE]);
+ Assert.That(h.HasPrivateFlag, Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_SMOKE]);
+ Assert.That(h.HasPrivateFlag, Is.False);
+ }
+
+ [Test]
+ public void ChannelMode_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_CM_STEREO]);
+ Assert.That(h.ChannelMode, Is.EqualTo(MpegChannelMode.Stereo));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_CM_JS]);
+ Assert.That(h.ChannelMode, Is.EqualTo(MpegChannelMode.JointStereo));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_CM_DUAL]);
+ Assert.That(h.ChannelMode, Is.EqualTo(MpegChannelMode.DualChannel));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_CM_MONO]);
+ Assert.That(h.ChannelMode, Is.EqualTo(MpegChannelMode.SingleChannel));
+ }
+
+ [Test]
+ public void HasCopyright_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_COPY]);
+ Assert.That(h.HasCopyright, Is.True);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_ORIG]);
+ Assert.That(h.HasCopyright, Is.False);
+ }
+
+ [Test]
+ public void HasOriginal_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_COPY]);
+ Assert.That(h.HasOriginal, Is.False);
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_ORIG]);
+ Assert.That(h.HasOriginal, Is.True);
+ }
+
+ [Test]
+ public void Emphasis_Test()
+ {
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_EM_NONE]);
+ Assert.That(h.Emphasis, Is.EqualTo(MpegEmphasis.None));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_EM_50]);
+ Assert.That(h.Emphasis, Is.EqualTo(MpegEmphasis.Fifty15ms));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_EM_R]);
+ Assert.That(h.Emphasis, Is.EqualTo(MpegEmphasis.Reserved));
+ h = new Mp3FrameHeader(TEST_HEADER[THIDX_EM_C]);
+ Assert.That(h.Emphasis, Is.EqualTo(MpegEmphasis.CcitJ17));
+ }
+
+ #endregion
+ }
+}
213 Slush.Test/DomainObjects.Mp3.Test/Mp3FrameTest.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
+using Slush.DomainObjects.Mp3;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public class Mp3FrameTest
+ {
+ // 11111111 / 111 11 01 0 / 1001 00 0 0 / 00 00 0 0 00
+ // new byte[] { 0xFF, 0xFA, 0x90, 0x00 }, // V1L3, 128/44, Stereo, CRC0
+ // 11111011 / 111 10 00 1 / 1111 00 0 0 / 01 00 0 0 01
+ // new byte[] { 0xFB, 0xF1, 0xF0, 0x41 }, // Bad frame sync, V2LR, CRC1, invalid bitrate
+
+ private Mp3Frame f;
+
+ public static byte[] BuildFrame(
+ MpegVersion version,
+ MpegLayer layer,
+ bool hasCRC,
+ int frameSizeOffset,
+ int frameSize)
+ {
+ byte[] b = new byte[] { 0xFF, 0xE0, 0x90, 0x00 };
+
+ b[1] |= (byte) version;
+ b[1] |= (byte) layer;
+ if (!hasCRC)
+ {
+ b[1]++;
+ }
+
+ byte[] frameData;
+ Mp3FrameHeader h = new Mp3FrameHeader(b);
+ if (0 == frameSize)
+ {
+ frameData = new byte[Mp3FrameHeaderRules.CalculateFrameLength(h) + frameSizeOffset];
+ }
+ else
+ {
+ frameData = new byte[frameSize + frameSizeOffset];
+ }
+ try
+ {
+ Array.Copy(b, frameData, 4);
+ }
+ catch
+ {
+ }
+
+ return frameData;
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException),
+ ExpectedMessage="Frame data may not be null",
+ MatchType=MessageMatch.Contains)]
+ public void Constructor_NullTest()
+ {
+ new Mp3Frame(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException),
+ ExpectedMessage = "Invalid frame header",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_InvalidHeaderTest()
+ {
+ new Mp3Frame(BuildFrame(MpegVersion.Reserved, MpegLayer.Layer3, true, 0, 7));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException),
+ ExpectedMessage = "Data too long for frame",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_FrameTooLongTest()
+ {
+ new Mp3Frame(BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, +1, 0));
+ }
+
+ /// <summary>
+ /// Free bitrates should accept large frames
+ /// </summary>
+ [Test]
+ public void Constructor_FrameFreeTest()
+ {
+ byte[] data = BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, +1, 5000);
+ // set free bitrate
+ data[2] &= 0x0F;
+ f = new Mp3Frame(data);
+ Assert.That(f.Bytes.Count, Is.EqualTo(data.Length));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException),
+ ExpectedMessage = "Data too short for frame. Must be at least 4 bytes",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_FrameTooShortNoCRCTest()
+ {
+ new Mp3Frame(BuildFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 3));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException),
+ ExpectedMessage = "Data too short for frame. Must be at least 6 bytes with CRC",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_FrameTooShortCRCTest()
+ {
+ new Mp3Frame(BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 5));
+ }
+
+ [Test]
+ public void Constructor_CopyInputTest()
+ {
+ byte[] b = BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+ f = new Mp3Frame(b);
+ b[7] = 0xFF;
+ Assert.That(f.Bytes[7], Is.EqualTo(0x00));
+ }
+
+ [Test]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void Bytes_NotWritableTest()
+ {
+ byte[] frame = BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+ f = new Mp3Frame(frame);
+ IList<byte> bytes = f.Bytes;
+ // Modify data
+ bytes[0] = 0xFF;
+ }
+
+ [Test]
+ public void Bytes_Test()
+ {
+ byte[] bytes = BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+ Mp3Frame f = new Mp3Frame(bytes);
+ Assert.That(f.Bytes.Count, Is.EqualTo(bytes.Length));
+ }
+
+ [Test]
+ public void Header_Test()
+ {
+ byte[] bytes = BuildFrame(MpegVersion.V1, MpegLayer.Layer2, true, 0, 0);
+ byte[] header = new byte[4];
+ for (int i = 0; i < 4; i++) header[i] = bytes[i];
+ Mp3FrameHeader h1 = new Mp3FrameHeader(header);
+
+ f = new Mp3Frame(bytes);
+ Mp3FrameHeader h2 = f.Header;
+ Assert.That(h2.Version, Is.EqualTo(h1.Version));
+ Assert.That(h2.Layer, Is.EqualTo(h1.Layer));
+ Assert.That(h2.SamplerateIndex, Is.EqualTo(h1.SamplerateIndex));
+ }
+
+ [Test]
+ public void CalculatedFrameLength_Test()
+ {
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0));
+ Assert.That(f.CalculatedFrameLength,
+ Is.EqualTo(Mp3FrameHeaderRules.CalculateFrameLength(f.Header)));
+ }
+
+ [Test]
+ public void ActualFrameLength_Test()
+ {
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 50));
+ Assert.That(f.ActualFrameLength, Is.EqualTo(50));
+ }
+
+ [Test]
+ public void IsTruncated_Test()
+ {
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, true, -1, 0));
+ Assert.That(f.IsTruncated, Is.True);
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0));
+ Assert.That(f.IsTruncated, Is.False);
+ }
+
+ [Test]
+ public void HasCRC_Test()
+ {
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0));
+ Assert.That(f.HasCRC, Is.True);
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, false, 0, 0));
+ Assert.That(f.HasCRC, Is.False);
+ }
+
+ [Test]
+ public void CRC_Test()
+ {
+ byte[] b = BuildFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+ // set the crc
+ b[4] = 0xAA;
+ b[5] = 0xBB;
+ f = new Mp3Frame(b);
+ Assert.That(f.CRC, Is.EqualTo(new byte[] { 0xAA, 0xBB }));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "This frame does not have a CRC")]
+ public void CRC_NoHasCRCTest()
+ {
+ f = new Mp3Frame(BuildFrame(MpegVersion.V25, MpegLayer.Layer1, false, 0, 0));
+ IList<byte> b = f.CRC;
+ }
+ }
+}
125 Slush.Test/DomainObjects.Mp3.Test/Mp3StreamBuilder.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ internal class Mp3StreamBuilder
+ {
+ private IList<IMp3StreamRegion> regions = new List<IMp3StreamRegion>();
+
+ private Random random = null;
+
+ public void Add(IMp3StreamRegion r)
+ {
+ regions.Add(r);
+ }
+
+ public byte[] BuildFrame(
+ MpegVersion version,
+ MpegLayer layer,
+ bool hasCRC,
+ int frameSizeOffset,
+ int frameSize)
+ {
+ byte[] buf = Slush.DomainObjects.Mp3.Test.Mp3FrameTest.BuildFrame(
+ version,
+ layer,
+ hasCRC,
+ frameSizeOffset,
+ frameSize);
+
+ if (UseRandom)
+ {
+ for (int i = 6; i < buf.Length; i++)
+ {
+ buf[i] = (byte)random.Next();
+ }
+ }
+ return buf;
+ }
+
+ public void AddFrame()
+ {
+ AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+ }
+
+ public void AddFrame(
+ MpegVersion version,
+ MpegLayer layer,
+ bool hasCRC,
+ int frameSizeOffset,
+ int frameSize)
+ {
+ Add(new Mp3Frame(BuildFrame(
+ version,
+ layer,
+ hasCRC,
+ frameSizeOffset,
+ frameSize)));
+ }
+
+ public void AddFreeFrame(
+ MpegVersion version,
+ MpegLayer layer,
+ bool hasCRC,
+ int frameSizeOffset,
+ int frameSize)
+ {
+ byte[] buf = BuildFrame(
+ version,
+ layer,
+ hasCRC,
+ frameSizeOffset,
+ frameSize);
+
+ buf[2] &= 0x0F;
+
+ Add(new Mp3Frame(buf));
+ }
+
+ public void AddJunk(int length)
+ {
+ byte[] buf = new byte[length];
+
+ for (int i = 0; i < buf.Length; i++)
+ {
+ buf[i] = (byte)(
+ UseRandom ?
+ random.Next()
+ : 0);
+ }
+
+ Add(new JunkRegion(buf));
+ }
+
+ public Stream BuildStream()
+ {
+ MemoryStream stream = new MemoryStream();
+
+ foreach (IMp3StreamRegion r in regions)
+ {
+ byte[] buf = new byte[r.Bytes.Count];
+ r.Bytes.CopyTo(buf, 0);
+ stream.Write(buf, 0, buf.Length);
+ }
+ stream.Seek(0, SeekOrigin.Begin);
+ return stream;
+ }
+
+ public bool UseRandom
+ {
+ get
+ {
+ return random != null;
+ }
+ set
+ {
+ random = value ?
+ new Random(0xABCD)
+ : null;
+ }
+ }
+ }
+}
56 Slush.Test/DomainObjects.Mp3.Test/Mp3StreamReaderTest.File.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.Extensions;
+using NUnit.Framework.SyntaxHelpers;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ public partial class Mp3StreamReaderTest
+ {
+ private string testDir = @"..\s022691_ISO_IEC_11172-4_1995_Compliance_Testing\layer3\";
+
+ [Row("compl.bit" , 217)]
+ [Row("he_32khz.bit", 150)]
+ [Row("he_44khz.bit", 410)]
+ [Row("he_48khz.bit", 150)]
+ [Row("he_free.bit" , -1)]
+ [Row("he_mode.bit" , 128)]
+ [Row("hecommon.bit", 30)]
+ [Row("si.bit" , 118)]
+ [Row("si_block.bit", 64)]
+ [Row("si_huff.bit" , 75)]
+ [Row("sin1k0db.bit", 318)]
+ [RowTest]
+ public void FileTest(string fileName, int numFrames)
+ {
+ Assert.That(File.Exists(fileName));
+ Mp3StreamReader reader =
+ new Mp3StreamReader
+ (
+ new BufferedStream
+ (
+ new FileStream
+ (
+ fileName,
+ FileMode.Open,
+ FileAccess.Read
+ )
+ )
+ );
+
+ int frameCount = 0;
+
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (region is Mp3Frame)
+ {
+ frameCount++;
+ }
+ }
+ Assert.That(frameCount, Is.EqualTo(numFrames));
+ }
+ }
+}
559 Slush.Test/DomainObjects.Mp3.Test/Mp3StreamReaderTest.cs
@@ -0,0 +1,559 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
+using NUnit.Framework.Extensions;
+using Slush.DomainObjects.Mp3;
+
+namespace Slush.DomainObjects.Mp3.Test
+{
+ [TestFixture]
+ public partial class Mp3StreamReaderTest
+ {
+ #region Members
+
+ protected Mp3StreamReader reader;
+ private Mp3StreamBuilder builder;
+
+ #endregion
+
+
+ #region Private Types
+
+ private class WriteOnlyMemoryStream : MemoryStream
+ {
+ public override bool CanRead
+ {
+ get
+ {
+ return false;
+ }
+ }
+ }
+
+ #endregion
+
+
+ #region Abstract Factory Method
+
+ private Mp3StreamReader CreateReader(Stream stream)
+ {
+ return new Mp3StreamReader(stream);
+ }
+
+ #endregion
+
+
+ #region Housekeeping
+
+ [SetUp]
+ public void SetUp()
+ {
+ builder = new Mp3StreamBuilder();
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void Constructor_NullTest()
+ {
+ CreateReader(null);
+ }
+
+ #endregion
+
+
+ #region Tests
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException),
+ ExpectedMessage = "Stream must be readable",
+ MatchType = MessageMatch.Contains)]
+ public void Constructor_StreamNotReadableTest()
+ {
+ CreateReader(new WriteOnlyMemoryStream());
+ }
+
+ [Test]
+ public void GetEnumerator_FreeBitrateTest()
+ {
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 20);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 30);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 40);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 50);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 60);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ Assert.That(region.Bytes.Count, Is.EqualTo(count * 10 + 20));
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(5));
+ }
+
+ [Test]
+ public void GetEnumerator_FreeBitrateJunkBeforeTest()
+ {
+ builder.AddJunk(20);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 30);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 40);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 50);
+ builder.AddFreeFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 60);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (count == 0)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ }
+ Assert.That(region.Bytes.Count, Is.EqualTo(count * 10 + 20));
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(5));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "Cannot enumerate more than once")]
+ public void GetEnumerator_NotReentrantTest()
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (count == 1) break;
+ count++;
+ }
+
+ object o = reader.GetEnumerator().MoveNext();
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException),
+ ExpectedMessage = "Cannot enumerate more than once")]
+ public void GetEnumerator_NotReEnumerableTest()
+ {
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ count++;
+ }
+
+ reader.GetEnumerator().MoveNext();
+ }
+
+ [Test]
+ public void GetEnumerator_AsIEnumerableTest()
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in (System.Collections.IEnumerable) reader)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(3));
+ }
+
+ /// <summary>
+ /// Tests that the bytes returned as regions are
+ /// identical to the bytes in the stream
+ /// </summary>
+ [Test]
+ public void GetEnumerator_IdenticalStreamTest()
+ {
+ Random r = new Random(0x1234);
+ builder.UseRandom = true;
+
+ const int NUM_REGIONS = 1000;
+ for (int regionCount = 0; regionCount < NUM_REGIONS; regionCount++)
+ {
+ if (r.Next() % 2 == 0)
+ {
+ builder.AddJunk(r.Next() % 50 + 1);
+ }
+ else
+ {
+ if (r.Next() % 2 == 0)
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer2, true, 0, 0);
+ }
+ else
+ {
+ builder.AddFrame(MpegVersion.V2, MpegLayer.Layer1, false, - (r.Next() % 10), 0);
+ }
+ }
+ }
+
+ byte[] streamCopy;
+ {
+ MemoryStream stream = (MemoryStream) builder.BuildStream();
+ streamCopy = stream.ToArray();
+ reader = CreateReader(stream);
+ }
+
+ int copyIndex = 0;
+ foreach (IMp3StreamRegion region in reader)
+ {
+ foreach (byte b in region.Bytes)
+ {
+ Assert.That(b, Is.EqualTo(streamCopy[copyIndex]));
+
+ copyIndex++;
+ }
+ }
+
+ }
+
+ [Test]
+ [Ignore]
+ public void GetEnumerator_LongJunkTest()
+ {
+ }
+
+ [Test]
+ [Ignore]
+ public void GetEnumerator_LongFreeFrameTest()
+ {
+ }
+
+ [Test]
+ [Ignore]
+ public void TODO()
+ {
+ // run NCover to find more codepaths to test
+ }
+ #endregion
+
+
+ #region Parameterized Tests
+
+ [Row(true)]
+ [Row(false)]
+ [RowTest]
+ public void GetEnumerator_SmokeTest(bool useCrc)
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, useCrc, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, useCrc, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, useCrc, 0, 0);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(3));
+ }
+
+ [Row(1)]
+ [Row(2)]
+ [Row(3)]
+ [Row(4)]
+ [Row(5)]
+ [RowTest]
+ public void GetEnumerator_JunkBeforeStreamTest(int junkCount)
+ {
+ builder.AddJunk(junkCount);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (count == 0)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ }
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(3));
+ }
+
+ [Row(1)]
+ [Row(2)]
+ [Row(3)]
+ [Row(4)]
+ [Row(5)]
+ [RowTest]
+ public void GetEnumerator_JunkMiddleStreamTest(int junkCount)
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0); // junk
+ builder.AddJunk(junkCount);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0); // frame
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0); // frame
+ builder.AddJunk(junkCount); // junk
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0); // frame
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0); // frame
+ builder.AddJunk(junkCount); // junk
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (count == 0 || count == 3 || count == 6)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ }
+ count++;
+ }
+ // TODO: should the last frame be counted or not?
+ Assert.That(count, Is.EqualTo(7));
+ }
+
+ [Row(1)]
+ [Row(2)]
+ [Row(3)]
+ [Row(4)]
+ [Row(5)]
+ [RowTest]
+ public void GetEnumerator_JunkEndEstablishedStreamTest(int junkCount)
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddJunk(junkCount);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (count == 2)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ }
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(3));
+ }
+
+ [Row(1)]
+ [Row(2)]
+ [Row(3)]
+ [Row(4)]
+ [Row(5)]
+ [RowTest]
+ public void GetEnumerator_JunkEndNonEstablishedStreamTest(int junkCount)
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ builder.AddJunk(junkCount);
+
+ int count = 0;
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(JunkRegion)));
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(1));
+ }
+
+ [Row(0, 04, false)][Row(0, 05, false)][Row(0, 08, false)][Row(0, 09, false)]
+ [Row(0, 06, true)] [Row(0, 07, true)] [Row(0, 10, true)] [Row(0, 11, true)]
+ [Row(1, 04, false)][Row(1, 05, false)][Row(1, 08, false)][Row(1, 09, false)]
+ [Row(1, 06, true)] [Row(1, 07, true)] [Row(1, 10, true)] [Row(1, 11, true)]
+ [Row(2, 04, false)][Row(2, 05, false)][Row(2, 08, false)][Row(2, 09, false)]
+ [Row(2, 06, true)] [Row(2, 07, true)] [Row(2, 10, true)] [Row(2, 11, true)]
+ [Row(3, 04, false)][Row(3, 05, false)][Row(3, 08, false)][Row(3, 09, false)]
+ [Row(3, 06, true)] [Row(3, 07, true)] [Row(3, 10, true)] [Row(3, 11, true)]
+ [Row(4, 04, false)][Row(4, 05, false)][Row(4, 08, false)][Row(4, 09, false)]
+ [Row(4, 06, true)] [Row(4, 07, true)] [Row(4, 10, true)] [Row(4, 11, true)]
+ [RowTest]
+ public void GetEnumerator_TruncatedFrameTest(
+ int truncatedIndex, int truncatedFrameLength, bool useCrc)
+ {
+ const int NUM_FRAMES = 5;
+
+ // Row sanity test
+ Assert.That(truncatedIndex, Is.LessThan(NUM_FRAMES));
+ for (int frameNumber = 0; frameNumber < NUM_FRAMES; frameNumber++)
+ {
+ if (frameNumber != truncatedIndex)
+ {
+ this.builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, false, 0, 0);
+ }
+ else
+ {
+ this.builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, useCrc, 0, truncatedFrameLength);
+ }
+ }
+
+
+ int count = 0;
+ this.reader = CreateReader(this.builder.BuildStream());
+ foreach (IMp3StreamRegion region in this.reader)
+ {
+ if (count == truncatedIndex && count == 0)
+ {
+ // truncated frame at beginning of stream shouldn't be identified
+ Assert.That(region, Is.InstanceOfType(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.InstanceOfType(typeof(Mp3Frame)));
+ }
+ if (count == truncatedIndex)
+ {
+ Assert.That(region.Bytes.Count, Is.EqualTo(truncatedFrameLength));
+ }
+ count++;
+ }
+ Assert.That(count, Is.EqualTo(NUM_FRAMES));
+ }
+
+
+ // Rows for GetEnumerator_TruncatedFrameAfterJunkTest
+ [Row(0, 04, 1, false)][Row(0, 05, 1, false)][Row(0, 08, 1, false)][Row(0, 09, 1, false)]
+ [Row(0, 06, 1, true)] [Row(0, 07, 1, true)] [Row(0, 10, 1, true)] [Row(0, 11, 1, true)]
+ [Row(1, 04, 1, false)][Row(1, 05, 1, false)][Row(1, 08, 1, false)][Row(1, 09, 1, false)]
+ [Row(1, 06, 1, true)] [Row(1, 07, 1, true)] [Row(1, 10, 1, true)] [Row(1, 11, 1, true)]
+ [Row(2, 04, 1, false)][Row(2, 05, 1, false)][Row(2, 08, 1, false)][Row(2, 09, 1, false)]
+ [Row(2, 06, 1, true)] [Row(2, 07, 1, true)] [Row(2, 10, 1, true)] [Row(2, 11, 1, true)]
+ [Row(3, 04, 1, false)][Row(3, 05, 1, false)][Row(3, 08, 1, false)][Row(3, 09, 1, false)]
+ [Row(3, 06, 1, true)] [Row(3, 07, 1, true)] [Row(3, 10, 1, true)] [Row(3, 11, 1, true)]
+ [Row(4, 04, 1, false)][Row(4, 05, 1, false)][Row(4, 08, 1, false)][Row(4, 09, 1, false)]
+ [Row(4, 06, 1, true)] [Row(4, 07, 1, true)] [Row(4, 10, 1, true)] [Row(4, 11, 1, true)]
+
+ [Row(0, 04, 4, false)][Row(0, 05, 4, false)][Row(0, 08, 4, false)][Row(0, 09, 4, false)]
+ [Row(0, 06, 4, true)] [Row(0, 07, 4, true)] [Row(0, 10, 4, true)] [Row(0, 11, 4, true)]
+ [Row(1, 04, 4, false)][Row(1, 05, 4, false)][Row(1, 08, 4, false)][Row(1, 09, 4, false)]
+ [Row(1, 06, 4, true)] [Row(1, 07, 4, true)] [Row(1, 10, 4, true)] [Row(1, 11, 4, true)]
+ [Row(2, 04, 4, false)][Row(2, 05, 4, false)][Row(2, 08, 4, false)][Row(2, 09, 4, false)]
+ [Row(2, 06, 4, true)] [Row(2, 07, 4, true)] [Row(2, 10, 4, true)] [Row(2, 11, 4, true)]
+ [Row(3, 04, 4, false)][Row(3, 05, 4, false)][Row(3, 08, 4, false)][Row(3, 09, 4, false)]
+ [Row(3, 06, 4, true)] [Row(3, 07, 4, true)] [Row(3, 10, 4, true)] [Row(3, 11, 4, true)]
+ [Row(4, 04, 4, false)][Row(4, 05, 4, false)][Row(4, 08, 4, false)][Row(4, 09, 4, false)]
+ [Row(4, 06, 4, true)] [Row(4, 07, 4, true)] [Row(4, 10, 4, true)] [Row(4, 11, 4, true)]
+
+ [Row(0, 04, 5, false)][Row(0, 05, 5, false)][Row(0, 08, 5, false)][Row(0, 09, 5, false)]
+ [Row(0, 06, 5, true)] [Row(0, 07, 5, true)] [Row(0, 10, 5, true)] [Row(0, 11, 5, true)]
+ [Row(1, 04, 5, false)][Row(1, 05, 5, false)][Row(1, 08, 5, false)][Row(1, 09, 5, false)]
+ [Row(1, 06, 5, true)] [Row(1, 07, 5, true)] [Row(1, 10, 5, true)] [Row(1, 11, 5, true)]
+ [Row(2, 04, 5, false)][Row(2, 05, 5, false)][Row(2, 08, 5, false)][Row(2, 09, 5, false)]
+ [Row(2, 06, 5, true)] [Row(2, 07, 5, true)] [Row(2, 10, 5, true)] [Row(2, 11, 5, true)]
+ [Row(3, 04, 5, false)][Row(3, 05, 5, false)][Row(3, 08, 5, false)][Row(3, 09, 5, false)]
+ [Row(3, 06, 5, true)] [Row(3, 07, 5, true)] [Row(3, 10, 5, true)] [Row(3, 11, 5, true)]
+ [Row(4, 04, 5, false)][Row(4, 05, 5, false)][Row(4, 08, 5, false)][Row(4, 09, 5, false)]
+ [Row(4, 06, 5, true)] [Row(4, 07, 5, true)] [Row(4, 10, 5, true)] [Row(4, 11, 5, true)]
+
+ [RowTest]
+ public void GetEnumerator_TruncatedFrameAfterJunkTest(
+ int truncatedIndex, int truncatedFrameLength, int junkLength, bool useCrc)
+ {
+ const int NUM_FRAMES = 5;
+
+ // Row sanity test
+ Assert.That(truncatedIndex, Is.LessThan(NUM_FRAMES));
+ for (int frameNumber = 0; frameNumber < NUM_FRAMES; frameNumber++)
+ {
+ if (frameNumber != truncatedIndex)
+ {
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, true, 0, 0);
+ }
+ else
+ {
+ builder.AddJunk(junkLength);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer3, useCrc, 0, truncatedFrameLength);
+ }
+ }
+
+ int count = 0;
+
+ reader = CreateReader(builder.BuildStream());
+ foreach (IMp3StreamRegion region in reader)
+ {
+ if (truncatedIndex == 1)
+ {
+ // first frame, junk, and truncated frame are all one junk region
+ if (count == 0)
+ {
+ Assert.That(region, Is.TypeOf(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.TypeOf(typeof(Mp3Frame)));
+ }
+ }
+ else if (truncatedIndex == NUM_FRAMES - 2) // second to last
+ {
+ // junk, truncated frame, and last frame are all one junk region
+ if (count == NUM_FRAMES - 2)
+ {
+ Assert.That(region, Is.TypeOf(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.TypeOf(typeof(Mp3Frame)));
+ }
+ }
+ else
+ {
+ // junk and truncated frame are both junk
+ if (count == truncatedIndex)
+ {
+ Assert.That(region, Is.TypeOf(typeof(JunkRegion)));
+ }
+ else
+ {
+ Assert.That(region, Is.TypeOf(typeof(Mp3Frame)));
+ }
+ }
+
+ count++;
+ }
+
+ if (truncatedIndex == 1
+ || truncatedIndex == NUM_FRAMES - 2)
+ {
+ Assert.That(count, Is.EqualTo(NUM_FRAMES - 1));
+ }
+ else
+ {
+ Assert.That(count, Is.EqualTo(NUM_FRAMES));
+ }
+
+ }
+
+ [Test]
+ public void GetEnumerator_Id3Tag()
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
187 Slush.Test/EventWeaverTest.cs
@@ -0,0 +1,187 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using Slush;
+
+namespace Slush.Test
+{
+ [TestFixture]
+ public class EventWeaverTest
+ {
+ #region Private Delegates
+
+ delegate void TestEventHandler1(int i);
+ delegate void TestEventHandler2(string s);
+
+ #endregion
+
+
+ #region Private Types
+
+ class Service1
+ {
+ public event EventHandler Event;
+
+ public void Trigger()
+ {
+ if (null != Event) Event(this, null);
+ }
+ }
+
+ class Service2
+ {
+ public int EventCount = 0;
+
+ public void EventHandler(object o, EventArgs e)
+ {
+ ++EventCount;
+ }
+ }
+
+ class Service3
+ {
+ public int EventCount = 0;
+
+ public event TestEventHandler1 Event1;
+ public event TestEventHandler2 Event2;
+
+ public void EventHandler(object o, EventArgs e)
+ {
+ ++EventCount;
+
+ if (null != Event1) Event1(0);
+ if (null != Event2) Event2(null);
+ }
+ }
+
+ class Service4
+ {
+ public int Event1Count = 0;
+ public int Event2Count = 0;
+
+ public void Event1Handler(int i)
+ {
+ ++Event1Count;
+ }
+
+ public void Event2Handler(string s)
+ {
+ ++Event2Count;
+ }
+ }
+
+ #endregion
+
+
+ #region Members
+
+ private EventWeaver ew;
+
+ #endregion
+
+
+ #region Housekeeping
+
+ [SetUp]
+ public void SetUp()
+ {
+ ew = new EventWeaver();
+ }
+
+ #endregion
+
+
+ #region Tests
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void Add_NullTest()
+ {
+ ew.Add(null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void Add_AlreadyExistsTest()
+ {
+ Int16 i = new Int16();
+ try
+ {
+ ew.Add(i);
+ }
+ catch
+ {
+ Assert.Fail();
+ }
+ ew.Add(i);
+ }
+
+ [Test]
+ public void Add_WeaveTest1()
+ {
+ Service1 s1 = new Service1();
+ Service2 s2 = new Service2();
+
+ ew.Add(s1);
+ ew.Add(s2);
+
+ s1.Trigger();
+ Assert.AreEqual(1, s2.EventCount);
+ }
+
+ [Test]
+ public void Add_WeaveTest2()
+ {
+ Service1 s1 = new Service1();
+ Service2 s2 = new Service2();
+
+ // Add in wrong order won't weave
+ ew.Add(s2);
+ ew.Add(s1);
+
+ s1.Trigger();
+ Assert.AreEqual(0, s2.EventCount);
+ }
+
+ [Test]
+ public void Add_WeaveTest3()
+ {
+ Service1 s1 = new Service1();
+ Service3 s3 = new Service3();
+ Service4 s4 = new Service4();
+
+ ew.Add(s1);
+ ew.Add(s3);
+ ew.Add(s4);
+
+ s1.Trigger();
+
+ Assert.AreEqual(1, s3.EventCount);
+ Assert.AreEqual(1, s4.Event1Count);
+ Assert.AreEqual(1, s4.Event2Count);
+ }
+
+ [Test]
+ public void Add_WeaveDelegateTest()
+ {
+ int called = 0;
+
+ Service1 s1 = new Service1();
+
+ ew.Add(s1);
+ ew.Add(
+ new EventHandler(delegate(object o, EventArgs e)
+ {
+ ++called;
+ }
+ ));
+
+ s1.Trigger();
+
+ Assert.AreEqual(1, called);
+ }
+
+ #endregion
+ }
+}
13 Slush.Test/Mp3ValidatorTest.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+
+namespace Slush.Test
+{
+ [TestFixture]
+ public class Mp3ValidatorTest
+ {
+ }
+}
26 Slush.Test/PrereqAttribute.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Slush
+{
+ [AttributeUsage(AttributeTargets.Method,AllowMultiple=true)]
+ public class PrereqAttribute : Attribute
+ {
+ private string name;
+
+ public PrereqAttribute(string name)
+ {
+ this.name = name;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return name;
+ }
+ }
+
+ }
+}
35 Slush.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SlushTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SlushTest")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("97ef81da-96b2-4df8-ab16-e45fd533383a")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
13 Slush.Test/Services.Mp3.Test/LameHeaderServiceTest.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+
+namespace Slush.Services.Mp3.Test
+{
+ [TestFixture]
+ public class LameHeaderServiceTest
+ {
+ }
+}
209 Slush.Test/Services.Mp3.Test/Mp3CrawlerServiceTest.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
+using Slush.DomainObjects.Mp3;
+using Slush.Services.Mp3;
+using Slush.DomainObjects.Mp3.Test;
+
+namespace Slush.Services.Mp3.Test
+{
+ [TestFixture]
+ public class Mp3CrawlerServiceTest
+ {
+ #region Private Members
+
+ private Mp3CrawlerService crawler = null;
+ private Mp3StreamBuilder builder = null;
+
+ #endregion
+
+
+ #region Housekeeping
+
+ [SetUp]
+ public void SetUp()
+ {
+ crawler = new Mp3CrawlerService();
+ builder = new Mp3StreamBuilder();
+ }
+
+ #endregion
+
+
+ #region Tests
+
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldNotFindAnyRegions_IfArgumentIsNull()
+ {
+ crawler.OnFoundJunkRegion +=
+ delegate(FoundJunkRegionEventArgs e)
+ {
+ Assert.Fail();
+ };
+ crawler.OnFoundMp3Frame +=
+ delegate(FoundMp3FrameEventArgs e)
+ {
+ Assert.Fail();
+ };
+ crawler.BeginStreamProcessEventHandler(null);
+ }
+
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldNotThrow_IfArgumentIsNull()
+ {
+ crawler.BeginStreamProcessEventHandler(null);
+ }
+
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldNotThrow_IfOnFoundJunkRegionIsNull()
+ {
+ builder.AddJunk(10);
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(
+ builder.BuildStream()));
+ }
+
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldNotThrow_IfOnFoundMp3FrameIsNull()
+ {
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddFrame(MpegVersion.V1, MpegLayer.Layer1, true, 0, 0);
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(
+ builder.BuildStream()));
+ }
+
+ // Stream correctness is tested by Mp3StreamReaderTest
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldEnumerateAllRegions()
+ {
+ Type[] regionOrder =
+ {
+ typeof ( Mp3Frame ),
+ typeof ( Mp3Frame ),
+ typeof ( Mp3Frame ),
+ typeof ( JunkRegion ),
+ typeof ( Mp3Frame ),
+ typeof ( Mp3Frame )
+ };
+
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddJunk(100);
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+
+ int regionTypeIndex = 0;
+ crawler.OnFoundJunkRegion +=
+ delegate(FoundJunkRegionEventArgs e)
+ {
+ Assert.That(regionOrder[regionTypeIndex++], Is.EqualTo(typeof(JunkRegion)));
+ };
+ crawler.OnFoundMp3Frame +=
+ delegate(FoundMp3FrameEventArgs e)
+ {
+ Assert.That(regionOrder[regionTypeIndex++], Is.EqualTo(typeof(Mp3Frame)));
+ };
+
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(builder.BuildStream()));
+ Assert.That(regionTypeIndex, Is.EqualTo(regionOrder.Length));
+ }
+
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldContinue_IfOnFoundJunkRegionThrows()
+ {
+ crawler.OnFoundJunkRegion +=
+ delegate(FoundJunkRegionEventArgs e)
+ {
+ throw new Exception();
+ };
+ bool called = false;
+ crawler.OnFoundMp3Frame +=
+ delegate(FoundMp3FrameEventArgs e)
+ {
+ called = true;
+ };
+
+ builder.AddJunk(10);
+ builder.AddFrame();
+ builder.AddFrame();
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(builder.BuildStream()));
+ Assert.That(called, Is.True);
+ }
+
+ [Test]
+ public void BeginStreamProcessEventHandler_ShouldContinue_IfOnFoundMp3FrameThrows()
+ {
+ crawler.OnFoundMp3Frame +=
+ delegate(FoundMp3FrameEventArgs e)
+ {
+ throw new Exception();
+ };
+ bool called = false;
+ crawler.OnFoundJunkRegion +=
+ delegate(FoundJunkRegionEventArgs e)
+ {
+ called = true;
+ };
+
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddJunk(200);
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(builder.BuildStream()));
+ Assert.That(called, Is.True);
+ }
+
+ [Test]
+ public void OnFoundJunkRegion_ShouldBeCalledWithANonNullArgument()
+ {
+ crawler.OnFoundJunkRegion +=
+ delegate(FoundJunkRegionEventArgs e)
+ {
+ Assert.That(e, Is.Not.Null);
+ };
+
+ builder.AddJunk(10);
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(builder.BuildStream()));
+ }
+
+ [Test]
+ public void OnFoundMp3Frame_ShouldBeCalledWithANonNullArgument()
+ {
+ crawler.OnFoundMp3Frame +=
+ delegate(FoundMp3FrameEventArgs e)
+ {
+ Assert.That(e, Is.Not.Null);
+ };
+
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ builder.AddFrame(MpegVersion.V25, MpegLayer.Layer1, true, 0, 0);
+ crawler.BeginStreamProcessEventHandler(
+ new BeginStreamProcessEventArgs(builder.BuildStream()));
+ }
+
+ public void Handler(IFoundMp3StreamRegionEventArgs e)
+ {
+ }
+
+ [Test]
+ public void OnFoundMp3StreamRegion_Test()
+ {
+ // Just want to make sure that contravariance makes
+ // it possible for a single handler to handle both
+ // these events
+ crawler.OnFoundMp3Frame += Handler;
+ crawler.OnFoundJunkRegion += Handler;
+ }
+
+ #endregion
+ }
+}
136 Slush.Test/Services.Test/StreamProcessServiceTest.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
+using Slush.Services;
+
+namespace Slush.Services.Test
+{
+ [TestFixture]
+ public class StreamProcessServiceTest
+ {
+ #region Tests
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void Constructor_NullTest()
+ {
+ StreamProcessService p = new StreamProcessService(null);
+ }
+
+ [Test]
+ public void Begin_EventsTest()
+ {
+ StreamProcessService p = new StreamProcessService(Stream.Null);
+
+ int count = 0;
+
+ p.OnBeginStreamProcess +=
+ delegate(BeginStreamProcessEventArgs e)
+ {
+ count++;
+ };
+
+ p.OnEndStreamProcess +=
+ delegate(EndStreamProcessEventArgs e)
+ {
+ Assert.AreEqual(1, count++);
+ };
+
+ p.Begin();
+ Assert.AreEqual(2, count);
+ }
+