diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 74b58bb..a6f3260 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -26,4 +26,23 @@ jobs: - name: Build run: dotnet build --no-restore - name: Test - run: dotnet test --no-build --verbosity normal + run: dotnet test --no-build --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage + - name: Code Coverage Report + uses: irongut/CodeCoverageSummary@v1.3.0 + with: + filename: coverage/**/coverage.cobertura.xml + badge: true + fail_below_min: true + format: markdown + hide_branch_rate: false + hide_complexity: true + indicators: true + output: both + thresholds: '33 66' + + - name: Add Coverage PR Comment + uses: marocchino/sticky-pull-request-comment@v2 + if: github.event_name == 'pull_request' + with: + recreate: true + path: code-coverage-results.md diff --git a/Source/Tests/CoreTests/CoreTests.csproj b/Source/Tests/CoreTests/CoreTests.csproj index c8e85c4..3f67473 100644 --- a/Source/Tests/CoreTests/CoreTests.csproj +++ b/Source/Tests/CoreTests/CoreTests.csproj @@ -11,6 +11,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Source/Tests/CoreTests/LoggerTest.cs b/Source/Tests/CoreTests/LoggerTest.cs new file mode 100644 index 0000000..db1b383 --- /dev/null +++ b/Source/Tests/CoreTests/LoggerTest.cs @@ -0,0 +1,44 @@ +using skullOS.Core; +using skullOS.Core.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Moq; + +namespace CoreTests +{ + public class LoggerTest + { + ISkullLogger SkullLogger; + + public LoggerTest() + { + FileManager.CreateSkullDirectory(isTest: true); + SkullLogger = new SkullLogger(); + } + + [Fact] + public void CanCreateLogger() + { + Assert.NotNull(SkullLogger); + } + + [Fact] + public void LogIsLocatable() + { + Assert.Equal(It.IsAny(), SkullLogger.GetLogLocation()); + } + + [Fact] + public void CanAddToLog() + { + var logContentsBefore = File.ReadAllText(SkullLogger.GetLogLocation()); + SkullLogger.LogMessage("FooBar!"); + var logContentsAfter = File.ReadAllText(SkullLogger.GetLogLocation()); + + Assert.NotEqual(logContentsBefore, logContentsAfter); + } + } +} diff --git a/Source/Tests/CoreTests/LoggerTests.cs b/Source/Tests/CoreTests/LoggerTests.cs deleted file mode 100644 index fa084c4..0000000 --- a/Source/Tests/CoreTests/LoggerTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreTests -{ - internal class LoggerTests - { - } -} diff --git a/Source/Tests/ModuleTests/CameraTest.cs b/Source/Tests/ModuleTests/CameraTest.cs index d172138..86c0c00 100644 --- a/Source/Tests/ModuleTests/CameraTest.cs +++ b/Source/Tests/ModuleTests/CameraTest.cs @@ -40,5 +40,51 @@ public async void CanRecordVideo() await sut.RecordShortVideo(); Mock.Verify(camMock); } + + [Fact] + public void CreateThrowsException() + { + Camera sut = new Camera(camMock.Object, micMock.Object, speakerMock.Object, LedMock.Object, buzzerMock.Object, @"TestData/CameraSettings.txt"); + Assert.Throws(() => sut.Create()); + } + + [Fact] + public void ToStringReturnsName() + { + Camera sut = new Camera(camMock.Object, micMock.Object, speakerMock.Object, LedMock.Object, buzzerMock.Object, @"TestData/CameraSettings.txt"); + Assert.Equal("Camera", sut.ToString()); + } + + [Fact] + public void OnEnableSetsModeCorrectly() + { + Camera sut = new Camera(camMock.Object, micMock.Object, speakerMock.Object, LedMock.Object, buzzerMock.Object, @"TestData/CameraSettings.txt"); + sut.OnEnable(["ShortVideo"]); + Assert.Equal(CameraMode.ShortVideo, sut.CameraMode); + } + + [Fact] + public void OnActionExecutesCorrectlyWithPicture() + { + camMock.Setup(camera => camera.TakePictureAsync(It.IsAny())).Returns(Task.FromResult("Pass")).Verifiable(); + Camera sut = new Camera(camMock.Object, micMock.Object, speakerMock.Object, LedMock.Object, buzzerMock.Object, @"TestData/CameraSettings.txt"); + + sut.CameraMode = CameraMode.Image; + sut.OnAction(It.IsAny(), It.IsAny()); + + Mock.Verify(camMock); + } + [Fact] + public void OnActionExecutesCorrectlyWithShortVideo() + { + camMock.Setup(camera => + camera.RecordShortVideoAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult("Pass")).Verifiable(); + Camera sut = new Camera(camMock.Object, micMock.Object, speakerMock.Object, LedMock.Object, buzzerMock.Object, @"TestData/CameraSettings.txt"); + + sut.CameraMode= CameraMode.ShortVideo; + sut.OnAction(It.IsAny(), It.IsAny()); + + Mock.Verify(camMock); + } } } diff --git a/Source/Tests/ModuleTests/DownlinkTest.cs b/Source/Tests/ModuleTests/DownlinkTest.cs new file mode 100644 index 0000000..762ddf2 --- /dev/null +++ b/Source/Tests/ModuleTests/DownlinkTest.cs @@ -0,0 +1,46 @@ +using Moq; +using skullOS.Modules; +using skullOS.Modules.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ModuleTests +{ + public class DownlinkTest + { + Downlink Downlink; + + public DownlinkTest() + { + Downlink = new Downlink(); + } + + [Fact] + public void CreateThrowsException() + { + Assert.Throws(() => Downlink.Create()); + } + + [Fact] + public void OnActionThrowsException() + { + Assert.Throws(() => + Downlink.OnAction(It.IsAny(), It.IsAny())); + } + + [Fact] + public void OnEnableThrowsException() + { + Assert.Throws(() => Downlink.OnEnable(It.IsAny())); + } + + [Fact] + public void OnStringThrowsException() + { + Assert.Throws(() => Downlink.ToString()); + } + } +} diff --git a/Source/Tests/ModuleTests/QrCodeReaderTest.cs b/Source/Tests/ModuleTests/QrCodeReaderTest.cs new file mode 100644 index 0000000..89c1e43 --- /dev/null +++ b/Source/Tests/ModuleTests/QrCodeReaderTest.cs @@ -0,0 +1,46 @@ +using Moq; +using skullOS.Modules; +using skullOS.Modules.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ModuleTests +{ + public class QrCodeReaderTest + { + QrCodeReader codeReader; + + public QrCodeReaderTest() + { + codeReader = new QrCodeReader(); + } + + [Fact] + public void CreateThrowsException() + { + Assert.Throws(() => codeReader.Create()); + } + + [Fact] + public void OnActionThrowsException() + { + Assert.Throws(() => + codeReader.OnAction(It.IsAny(), It.IsAny())); + } + + [Fact] + public void OnEnableThrowsException() + { + Assert.Throws(() => codeReader.OnEnable(It.IsAny())); + } + + [Fact] + public void OnStringThrowsException() + { + Assert.Throws(() => codeReader.ToString()); + } + } +} diff --git a/Source/Tests/ModuleTests/UplinkTest.cs b/Source/Tests/ModuleTests/UplinkTest.cs new file mode 100644 index 0000000..daf81c5 --- /dev/null +++ b/Source/Tests/ModuleTests/UplinkTest.cs @@ -0,0 +1,46 @@ +using Moq; +using skullOS.Modules; +using skullOS.Modules.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ModuleTests +{ + public class UplinkTest + { + Uplink Uplink; + + public UplinkTest() + { + Uplink = new Uplink(); + } + + [Fact] + public void CreateThrowsException() + { + Assert.Throws(() => Uplink.Create()); + } + + [Fact] + public void OnActionThrowsException() + { + Assert.Throws(() => + Uplink.OnAction(It.IsAny(), It.IsAny())); + } + + [Fact] + public void OnEnableThrowsException() + { + Assert.Throws(() => Uplink.OnEnable(It.IsAny())); + } + + [Fact] + public void OnStringThrowsException() + { + Assert.Throws(() => Uplink.ToString()); + } + } +} diff --git a/Source/skullOS.Core/FileManager.cs b/Source/skullOS.Core/FileManager.cs index 8532aef..330c76b 100644 --- a/Source/skullOS.Core/FileManager.cs +++ b/Source/skullOS.Core/FileManager.cs @@ -61,7 +61,11 @@ public static void CreateSkullDirectory(bool usePersonalDir = true, bool isTest } } - + else + { + var testDir = Directory.CreateDirectory("/tmp"); + rootDirectoryPath = testDir.FullName; + } } } diff --git a/Source/skullOS.Core/Interfaces/ISkullLogger.cs b/Source/skullOS.Core/Interfaces/ISkullLogger.cs index c677ecf..39e9a21 100644 --- a/Source/skullOS.Core/Interfaces/ISkullLogger.cs +++ b/Source/skullOS.Core/Interfaces/ISkullLogger.cs @@ -2,6 +2,7 @@ { public interface ISkullLogger { + string GetLogLocation(); void LogMessage(string message); } } \ No newline at end of file diff --git a/Source/skullOS.Core/SkullLogger.cs b/Source/skullOS.Core/SkullLogger.cs index 902201d..b8f33f3 100644 --- a/Source/skullOS.Core/SkullLogger.cs +++ b/Source/skullOS.Core/SkullLogger.cs @@ -19,5 +19,10 @@ public void LogMessage(string message) #endif File.AppendAllText(filepath, DateTime.Now.ToShortTimeString() + ":" + message + "\n"); } + + public string GetLogLocation() + { + return filepath; + } } } diff --git a/Source/skullOS.Modules/Buzzer.cs b/Source/skullOS.Modules/Buzzer.cs index e475dd3..cd215d9 100644 --- a/Source/skullOS.Modules/Buzzer.cs +++ b/Source/skullOS.Modules/Buzzer.cs @@ -79,7 +79,7 @@ public override string ToString() /// 3rd party class for playing media via a buzzer /// Sourced from teh iot samples /// - public class MelodyPlayer : IMelodyPlayer + internal class MelodyPlayer : IMelodyPlayer { private readonly DeviceBuzzer _buzzer; private int _wholeNoteDurationInMilliseconds; @@ -391,17 +391,16 @@ public NoteElement(Note note, Octave octave, Duration duration) Note = note; Octave = octave; } - } - /// - /// A pause - /// - internal class PauseElement : MelodyElement - { - public PauseElement(Duration duration) : base(duration) + /// + /// A pause + /// Once there's a tune with a puase in, this can be made internal again + /// + internal class PauseElement(BuzzerStructures.Duration duration) : MelodyElement(duration) { - } } + + #endregion } diff --git a/Source/skullOS.Modules/Downlink.cs b/Source/skullOS.Modules/Downlink.cs index 0159c25..bb9ea36 100644 --- a/Source/skullOS.Modules/Downlink.cs +++ b/Source/skullOS.Modules/Downlink.cs @@ -1,4 +1,6 @@ -namespace skullOS.Modules +using skullOS.Modules.Exceptions; + +namespace skullOS.Modules { public class Downlink : Module, IDownlinkModule { @@ -9,12 +11,12 @@ public override void Create() public override void OnAction(object? sender, EventArgs e) { - throw new NotImplementedException(); + throw new OnActionException("Not yet implemented"); } public override void OnEnable(string[] args) { - throw new NotImplementedException(); + throw new OnEnableException("Not yet implemented"); } public override string ToString() { diff --git a/Source/skullOS.Modules/QrCodeReader.cs b/Source/skullOS.Modules/QrCodeReader.cs index d74d754..16b8835 100644 --- a/Source/skullOS.Modules/QrCodeReader.cs +++ b/Source/skullOS.Modules/QrCodeReader.cs @@ -1,4 +1,6 @@ -namespace skullOS.Modules +using skullOS.Modules.Exceptions; + +namespace skullOS.Modules { public class QrCodeReader : Module, IQrCodeReaderModule { @@ -9,12 +11,12 @@ public override void Create() public override void OnAction(object? sender, EventArgs e) { - throw new NotImplementedException(); + throw new OnActionException("Not yet implemented"); } public override void OnEnable(string[] args) { - throw new NotImplementedException(); + throw new OnEnableException("Not yet implemented"); } public override string ToString() { diff --git a/Source/skullOS.Modules/Uplink.cs b/Source/skullOS.Modules/Uplink.cs index 3640b45..bf48c8d 100644 --- a/Source/skullOS.Modules/Uplink.cs +++ b/Source/skullOS.Modules/Uplink.cs @@ -1,4 +1,5 @@ -using skullOS.Modules.Interfaces; +using skullOS.Modules.Exceptions; +using skullOS.Modules.Interfaces; namespace skullOS.Modules { @@ -11,12 +12,12 @@ public override void Create() public override void OnAction(object? sender, EventArgs e) { - throw new NotImplementedException(); + throw new OnActionException("Not yet implemented"); } public override void OnEnable(string[] args) { - throw new NotImplementedException(); + throw new OnEnableException("Not yet implemented"); } public override string ToString() {