using Amphora; using System; using UnitTestSharp; using static Susurrus.UnitTests.TestSounds; namespace Susurrus.UnitTests { public class NullModuleTests : TestFixture { public static DecodedSound HalfSecondMono() { return new DecodedSound(Silence(22050 * 2), sampleRate: 44100, channelCount: 1, format: SampleFormat.Pcm16); } public static Sound AnySound() { return new NullModule().LoadSound(HalfSecondMono()); } public static StreamedSound LoadStreamed(NullModule module) { SoundLoad load = module.LoadStream(new ByteChunks(new ByteView(LoadFixture("Mono441Hz.ogg")))); return (StreamedSound)load.Result.Value; } public class CtorTests : TestFixture { public void ZeroVoices_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule(voiceCount: 0); } } public class IsSupportedTests : TestFixture { public void IsTrue() { CheckTrue(new NullModule().IsSupported); } } public class PriorityTests : TestFixture { public void StartsAtZero() { CheckEqual(0, new NullModule().Priority); } public void HoldsTheValueSet() { NullModule module = new NullModule(); module.Priority = 7; CheckEqual(7, module.Priority); } } public class LoadTests : TestFixture { public void DoesNothing() { new NullModule().Load(); } } public class UnloadTests : TestFixture { public void DoesNothingEvenWithoutALoad() { new NullModule().Unload(); } } public class LoadSoundTests : TestFixture { public void CarriesTheDurationAndChannelCount() { Sound sound = new NullModule().LoadSound(HalfSecondMono()); CheckEqual(TimeSpan.FromSeconds(0.5), sound.Duration); CheckEqual(1, sound.ChannelCount); } public void NullSound_Throws() { CheckThrow(typeof(ArgumentNullException)); new NullModule().LoadSound(null); } public void WavBytes_GiveADoneLoadOfTheSound() { SoundLoad load = new NullModule().LoadSound(new Amphora.ByteView(SoundDecoderTests.WavFile())); CheckTrue(load.IsDone); CheckEqual(1, load.Result.Value.ChannelCount); } public void OggBytes_GiveADoneLoadOfTheSound() { SoundLoad load = new NullModule().LoadSound(new Amphora.ByteView(LoadFixture("Mono441Hz.ogg"))); CheckTrue(load.IsDone); CheckEqual(1, load.Result.Value.ChannelCount); } public void BytesThatAreNotAudio_GiveADoneLoadThatFailed() { SoundLoad load = new NullModule().LoadSound(new Amphora.ByteView(SoundDecoderTests.NotAudio())); CheckTrue(load.IsDone); CheckEqual(SoundFailures.UnrecognizedFormat, load.Result.Kind); } public void ADefaultView_Throws() { CheckThrow(typeof(ArgumentException)); new NullModule().LoadSound(default(Amphora.ByteView)); } } public class LoadStreamTests : TestFixture { public void GivesAStreamedSoundWithTheFilesDurationAndChannels() { StreamedSound sound = LoadStreamed(new NullModule()); CheckEqual(sound.Stream.FrameCount * TimeSpan.TicksPerSecond / 44100, sound.Duration.Ticks); CheckEqual(1, sound.ChannelCount); } public void ABrokenFile_FailsAsOpeningItDoes() { SoundLoad load = new NullModule().LoadStream(new ByteChunks(new ByteView(new byte[100]))); CheckTrue(load.IsDone); CheckEqual(SoundFailures.UnrecognizedFormat, load.Result.Status.Kind); } public void NullSource_Throws() { CheckThrow(typeof(ArgumentNullException)); new NullModule().LoadStream(null); } } public class PlayTests : TestFixture { public void AStreamedSoundThatIsAlreadyPlaying_GivesNoVoice() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Play(sound, volume: 1f); CheckTrue(module.Play(sound, volume: 1f).IsNone); } public void AStreamedSound_IsHeldWhilePlaying() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Play(sound, volume: 1f); CheckTrue(sound.IsHeld); } public void AStreamedSoundWhenEveryVoiceIsBusy_GivesNoVoiceAndStaysFree() { NullModule module = new NullModule(voiceCount: 1); module.Play(AnySound(), volume: 1f); StreamedSound sound = LoadStreamed(module); CheckTrue(module.Play(sound, volume: 1f).IsNone); CheckFalse(sound.IsHeld); } public void AStreamedSoundAfterItsVoiceEnded_PlaysAgain() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Play(sound, volume: 1f); module.Update(); CheckFalse(module.Play(sound, volume: 1f).IsNone); } public void ReturnsAVoiceThatIsPlaying() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), volume: 1f); CheckFalse(voice.IsNone); CheckTrue(module.IsPlaying(voice)); } public void GivesEachPlayItsOwnVoice() { NullModule module = new NullModule(); Sound sound = AnySound(); CheckNotEqual(module.Play(sound, 1f), module.Play(sound, 1f)); } public void WhenEveryVoiceIsBusy_ReturnsNone() { NullModule module = new NullModule(voiceCount: 2); Sound sound = AnySound(); module.Play(sound, 1f); module.Play(sound, 1f); CheckEqual(Voice.None, module.Play(sound, 1f)); } public void NullSound_Throws() { CheckThrow(typeof(ArgumentNullException)); new NullModule().Play(null, 1f); } public void NegativeVolume_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().Play(AnySound(), -1f); } public void PitchOutOfRange_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().Play(AnySound(), 1f, pitch: 0f); } public void PanOutOfRange_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().Play(AnySound(), 1f, pan: -2f); } public void ALoopPastTheEndOfTheSound_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().Play(AnySound(), 1f, loop: new Loop(TimeSpan.Zero, TimeSpan.FromSeconds(1))); } } public class LoopOfTests : TestFixture { public void IsTheLoopTheVoiceWasGiven() { NullModule module = new NullModule(); Loop loop = new Loop(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.4)); Voice voice = module.Play(AnySound(), 1f, loop: loop); CheckEqual(TimeSpan.FromSeconds(0.1), module.LoopOf(voice).Start); CheckEqual(TimeSpan.FromSeconds(0.4), module.LoopOf(voice).End.Value); } public void ByDefault_IsNone() { NullModule module = new NullModule(); CheckFalse(module.LoopOf(module.Play(AnySound(), 1f)).IsLooping); } public void ForAVoiceThatEnded_IsNone() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f, loop: Loop.Whole); module.Stop(voice); CheckFalse(module.LoopOf(voice).IsLooping); } } public class StopTests : TestFixture { public void AStreamedSoundsVoice_FreesTheSoundToPlayAgain() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Stop(module.Play(sound, volume: 1f)); CheckFalse(sound.IsHeld); } public void AStoppedStreamedVoice_DoesNotFreeTheSoundForTheVoiceThatReplacedIt() { NullModule module = new NullModule(voiceCount: 1); StreamedSound sound = LoadStreamed(module); Voice stopped = module.Play(sound, volume: 1f); module.Stop(stopped); module.Play(sound, volume: 1f); module.Stop(stopped); CheckTrue(sound.IsHeld); } public void EndsThePlay() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Stop(voice); CheckFalse(module.IsPlaying(voice)); } public void FreesTheVoiceForAnotherPlay() { NullModule module = new NullModule(voiceCount: 1); Sound sound = AnySound(); module.Stop(module.Play(sound, 1f)); CheckFalse(module.Play(sound, 1f).IsNone); } public void AStoppedVoice_DoesNotStopTheOneThatReusedItsSlot() { NullModule module = new NullModule(voiceCount: 1); Sound sound = AnySound(); Voice stopped = module.Play(sound, 1f); module.Stop(stopped); Voice current = module.Play(sound, 1f); module.Stop(stopped); CheckTrue(module.IsPlaying(current)); } public void None_DoesNothing() { new NullModule().Stop(Voice.None); } } public class SetVolumeTests : TestFixture { public void KeepsTheVoicePlaying() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetVolume(voice, 0.25f); CheckTrue(module.IsPlaying(voice)); } public void OnAFinishedVoice_DoesNothing() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Stop(voice); module.SetVolume(voice, 0.25f); } public void NegativeVolume_Throws() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); CheckThrow(typeof(ArgumentOutOfRangeException)); module.SetVolume(voice, -1f); } public void NegativeVolumeOnAFinishedVoice_StillThrows() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().SetVolume(Voice.None, -1f); } } public class SetPitchTests : TestFixture { public void ChangesThePitchOfAPlayingVoice() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPitch(voice, 2f); CheckEqual(2f, module.PitchOf(voice)); CheckTrue(module.IsPlaying(voice)); } public void OnAFinishedVoice_DoesNothing() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Stop(voice); module.SetPitch(voice, 2f); CheckEqual(1f, module.PitchOf(voice)); } public void APitchOutOfRange_Throws() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); CheckThrow(typeof(ArgumentOutOfRangeException)); module.SetPitch(voice, 2000f); } public void APitchOutOfRangeOnAFinishedVoice_StillThrows() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().SetPitch(Voice.None, 0f); } } public class SetPanTests : TestFixture { public void MovesAPlayingVoice() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPan(voice, -0.5f); CheckEqual(-0.5f, module.PanOf(voice)); CheckTrue(module.IsPlaying(voice)); } public void OnAFinishedVoice_DoesNothing() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Stop(voice); module.SetPan(voice, 0.5f); CheckEqual(0f, module.PanOf(voice)); } public void APanOutOfRange_Throws() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); CheckThrow(typeof(ArgumentOutOfRangeException)); module.SetPan(voice, 1.5f); } public void APanOutOfRangeOnAFinishedVoice_StillThrows() { CheckThrow(typeof(ArgumentOutOfRangeException)); new NullModule().SetPan(Voice.None, float.NaN); } } public class SetPausedTests : TestFixture { public void PausesAPlayingVoiceThatStaysPlaying() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPaused(voice, true); CheckTrue(module.PausedOf(voice)); CheckTrue(module.IsPlaying(voice)); } public void ResumesAPausedVoice() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPaused(voice, true); module.SetPaused(voice, false); CheckFalse(module.PausedOf(voice)); } public void OnAFinishedVoice_DoesNothing() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Stop(voice); module.SetPaused(voice, true); CheckFalse(module.PausedOf(voice)); } public void Update_LeavesAPausedVoicePlaying() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPaused(voice, true); module.Update(); CheckTrue(module.IsPlaying(voice)); } public void Update_EndsAVoiceOnceItIsResumed() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPaused(voice, true); module.Update(); module.SetPaused(voice, false); module.Update(); CheckFalse(module.IsPlaying(voice)); } public void Stop_EndsAPausedVoice() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPaused(voice, true); module.Stop(voice); CheckFalse(module.IsPlaying(voice)); } } public class PausedOfTests : TestFixture { public void IsFalseForAVoiceThatWasNeverPaused() { NullModule module = new NullModule(); CheckFalse(module.PausedOf(module.Play(AnySound(), 1f))); } public void IsFalseForNoVoice() { CheckFalse(new NullModule().PausedOf(Voice.None)); } public void ASlotReusedByAnotherPlay_StartsNotPaused() { NullModule module = new NullModule(voiceCount: 1); Voice first = module.Play(AnySound(), 1f); module.SetPaused(first, true); module.Finish(first); CheckFalse(module.PausedOf(module.Play(AnySound(), 1f))); } } public class PitchOfTests : TestFixture { public void IsThePitchThePlayStartedWith() { NullModule module = new NullModule(); CheckEqual(0.5f, module.PitchOf(module.Play(AnySound(), 1f, pitch: 0.5f))); } public void IsNaturalWhenPlayIsGivenNoPitch() { NullModule module = new NullModule(); CheckEqual(1f, module.PitchOf(module.Play(AnySound(), 1f))); } public void IsNaturalOnceTheVoiceEnded() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f, pitch: 4f); module.Finish(voice); CheckEqual(1f, module.PitchOf(voice)); } public void IsNaturalForNoVoice() { CheckEqual(1f, new NullModule().PitchOf(Voice.None)); } public void ASlotReusedByAnotherPlay_TakesTheNewPitch() { NullModule module = new NullModule(voiceCount: 1); module.Finish(module.Play(AnySound(), 1f, pitch: 4f)); CheckEqual(0.25f, module.PitchOf(module.Play(AnySound(), 1f, pitch: 0.25f))); } } public class PanOfTests : TestFixture { public void IsThePanThePlayStartedWith() { NullModule module = new NullModule(); CheckEqual(0.75f, module.PanOf(module.Play(AnySound(), 1f, pan: 0.75f))); } public void IsTheCenterWhenPlayIsGivenNoPan() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.SetPan(voice, 1f); module.Finish(voice); CheckEqual(0f, module.PanOf(module.Play(AnySound(), 1f))); } public void IsTheCenterOnceTheVoiceEnded() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f, pan: -1f); module.Finish(voice); CheckEqual(0f, module.PanOf(voice)); } public void IsTheCenterForNoVoice() { CheckEqual(0f, new NullModule().PanOf(Voice.None)); } } public class IsPlayingTests : TestFixture { public void None_IsNotPlaying() { CheckFalse(new NullModule().IsPlaying(Voice.None)); } } public class UpdateTests : TestFixture { public void FreesAStreamedSoundWhoseVoiceEnds() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Play(sound, volume: 1f); module.Update(); CheckFalse(sound.IsHeld); } public void KeepsAStreamedSoundHeldWhileItsVoiceLoops() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Play(sound, volume: 1f, loop: Loop.Whole); module.Update(); CheckTrue(sound.IsHeld); } public void FinishesEveryVoice() { NullModule module = new NullModule(); Sound sound = AnySound(); Voice first = module.Play(sound, 1f); Voice second = module.Play(sound, 1f); module.Update(); CheckFalse(module.IsPlaying(first)); CheckFalse(module.IsPlaying(second)); } public void LeavesALoopingVoicePlaying() { NullModule module = new NullModule(); Sound sound = AnySound(); Voice looping = module.Play(sound, 1f, loop: Loop.Whole); Voice once = module.Play(sound, 1f); module.Update(); CheckTrue(module.IsPlaying(looping)); CheckFalse(module.IsPlaying(once)); } public void ALoopingVoiceEndsWhenStopped() { NullModule module = new NullModule(); Voice looping = module.Play(AnySound(), 1f, loop: Loop.Whole); module.Stop(looping); module.Update(); CheckFalse(module.IsPlaying(looping)); } public void FreesTheVoicesForNewPlays() { NullModule module = new NullModule(voiceCount: 2); Sound sound = AnySound(); module.Play(sound, 1f); module.Play(sound, 1f); module.Update(); CheckFalse(module.Play(sound, 1f).IsNone); CheckFalse(module.Play(sound, 1f).IsNone); } public void WithNothingPlaying_DoesNothing() { new NullModule().Update(); } public void WithEndsVoicesOnUpdateOff_LeavesVoicesPlaying() { NullModule module = new NullModule { EndsVoicesOnUpdate = false }; Voice voice = module.Play(AnySound(), 1f); module.Update(); CheckTrue(module.IsPlaying(voice)); } } public class EndsVoicesOnUpdateTests : TestFixture { public void IsOnByDefault() { CheckTrue(new NullModule().EndsVoicesOnUpdate); } } public class FinishTests : TestFixture { public void FreesAStreamedSoundToPlayAgain() { NullModule module = new NullModule(); StreamedSound sound = LoadStreamed(module); module.Finish(module.Play(sound, volume: 1f)); CheckFalse(sound.IsHeld); } public void EndsTheVoice() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Finish(voice); CheckFalse(module.IsPlaying(voice)); } public void AVoiceAlreadyEnded_DoesNothing() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Finish(voice); module.Finish(voice); CheckFalse(module.IsPlaying(voice)); } } public class VolumeOfTests : TestFixture { public void IsTheVolumeThePlayStartedAt() { NullModule module = new NullModule(); CheckEqual(0.5f, module.VolumeOf(module.Play(AnySound(), 0.5f))); } public void IsTheLatestSetVolume() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 0.5f); module.SetVolume(voice, 2f); CheckEqual(2f, module.VolumeOf(voice)); } public void IsZeroOnceTheVoiceEnded() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 0.5f); module.Finish(voice); CheckEqual(0f, module.VolumeOf(voice)); } public void IsZeroForNoVoice() { CheckEqual(0f, new NullModule().VolumeOf(Voice.None)); } public void DoesNotCarryOverToAReusedSlot() { NullModule module = new NullModule(voiceCount: 1); Voice first = module.Play(AnySound(), 0.5f); module.Finish(first); Voice second = module.Play(AnySound(), 0.25f); CheckEqual(0f, module.VolumeOf(first)); CheckEqual(0.25f, module.VolumeOf(second)); } } public class SoundOfTests : TestFixture { public void IsTheSoundThePlayStartedWith() { NullModule module = new NullModule(); Sound sound = AnySound(); Check(sound == module.SoundOf(module.Play(sound, 1f))); } public void IsNullOnceTheVoiceEnded() { NullModule module = new NullModule(); Voice voice = module.Play(AnySound(), 1f); module.Finish(voice); CheckNull(module.SoundOf(voice)); } public void IsNullForNoVoice() { CheckNull(new NullModule().SoundOf(Voice.None)); } } } }