diff --git a/src/c#/GeneralUpdate.sln b/src/c#/GeneralUpdate.sln index d4f9416b..84cdea36 100644 --- a/src/c#/GeneralUpdate.sln +++ b/src/c#/GeneralUpdate.sln @@ -31,56 +31,162 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionTest", "ExtensionT EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneralUpdate.Ext", "GeneralUpdate.Ext\GeneralUpdate.Ext.csproj", "{27028918-925E-45D4-BD72-199349B6E6AA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreTest", "..\..\tests\CoreTest\CoreTest.csproj", "{D8B45203-B939-4628-AC77-C477A4AC5F45}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|x64.ActiveCfg = Debug|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|x64.Build.0 = Debug|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|x86.ActiveCfg = Debug|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|x86.Build.0 = Debug|Any CPU {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|Any CPU.Build.0 = Release|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|x64.ActiveCfg = Release|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|x64.Build.0 = Release|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|x86.ActiveCfg = Release|Any CPU + {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|x86.Build.0 = Release|Any CPU {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|x64.ActiveCfg = Debug|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|x64.Build.0 = Debug|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|x86.ActiveCfg = Debug|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|x86.Build.0 = Debug|Any CPU {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|Any CPU.ActiveCfg = Release|Any CPU {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|Any CPU.Build.0 = Release|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|x64.ActiveCfg = Release|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|x64.Build.0 = Release|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|x86.ActiveCfg = Release|Any CPU + {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|x86.Build.0 = Release|Any CPU {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|x64.ActiveCfg = Debug|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|x64.Build.0 = Debug|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|x86.ActiveCfg = Debug|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|x86.Build.0 = Debug|Any CPU {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|Any CPU.ActiveCfg = Release|Any CPU {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|Any CPU.Build.0 = Release|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|x64.ActiveCfg = Release|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|x64.Build.0 = Release|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|x86.ActiveCfg = Release|Any CPU + {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|x86.Build.0 = Release|Any CPU {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|x64.ActiveCfg = Debug|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|x64.Build.0 = Debug|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|x86.ActiveCfg = Debug|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|x86.Build.0 = Debug|Any CPU {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|Any CPU.Build.0 = Release|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|x64.ActiveCfg = Release|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|x64.Build.0 = Release|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|x86.ActiveCfg = Release|Any CPU + {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|x86.Build.0 = Release|Any CPU {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|x64.Build.0 = Debug|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|x86.Build.0 = Debug|Any CPU {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|Any CPU.Build.0 = Release|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|x64.ActiveCfg = Release|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|x64.Build.0 = Release|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|x86.ActiveCfg = Release|Any CPU + {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|x86.Build.0 = Release|Any CPU {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|x64.ActiveCfg = Debug|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|x64.Build.0 = Debug|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|x86.ActiveCfg = Debug|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|x86.Build.0 = Debug|Any CPU {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|Any CPU.ActiveCfg = Release|Any CPU {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|Any CPU.Build.0 = Release|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|x64.ActiveCfg = Release|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|x64.Build.0 = Release|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|x86.ActiveCfg = Release|Any CPU + {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|x86.Build.0 = Release|Any CPU {49D0687D-1321-48E9-84C3-936B10532367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {49D0687D-1321-48E9-84C3-936B10532367}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Debug|x64.ActiveCfg = Debug|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Debug|x64.Build.0 = Debug|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Debug|x86.ActiveCfg = Debug|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Debug|x86.Build.0 = Debug|Any CPU {49D0687D-1321-48E9-84C3-936B10532367}.Release|Any CPU.ActiveCfg = Release|Any CPU {49D0687D-1321-48E9-84C3-936B10532367}.Release|Any CPU.Build.0 = Release|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Release|x64.ActiveCfg = Release|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Release|x64.Build.0 = Release|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Release|x86.ActiveCfg = Release|Any CPU + {49D0687D-1321-48E9-84C3-936B10532367}.Release|x86.Build.0 = Release|Any CPU {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|x64.ActiveCfg = Debug|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|x64.Build.0 = Debug|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|x86.ActiveCfg = Debug|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|x86.Build.0 = Debug|Any CPU {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|Any CPU.ActiveCfg = Release|Any CPU {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|Any CPU.Build.0 = Release|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|x64.ActiveCfg = Release|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|x64.Build.0 = Release|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|x86.ActiveCfg = Release|Any CPU + {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|x86.Build.0 = Release|Any CPU {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Debug|x64.ActiveCfg = Debug|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Debug|x64.Build.0 = Debug|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Debug|x86.Build.0 = Debug|Any CPU {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Release|Any CPU.Build.0 = Release|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Release|x64.ActiveCfg = Release|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Release|x64.Build.0 = Release|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Release|x86.ActiveCfg = Release|Any CPU + {7B8E164F-C2D8-4C5F-8E20-450FB56AEB34}.Release|x86.Build.0 = Release|Any CPU {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Debug|x64.ActiveCfg = Debug|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Debug|x64.Build.0 = Debug|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Debug|x86.ActiveCfg = Debug|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Debug|x86.Build.0 = Debug|Any CPU {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Release|Any CPU.ActiveCfg = Release|Any CPU {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Release|Any CPU.Build.0 = Release|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Release|x64.ActiveCfg = Release|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Release|x64.Build.0 = Release|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Release|x86.ActiveCfg = Release|Any CPU + {3FA78F9A-A942-4F7E-A30D-70DF42E8A83D}.Release|x86.Build.0 = Release|Any CPU {27028918-925E-45D4-BD72-199349B6E6AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {27028918-925E-45D4-BD72-199349B6E6AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Debug|x64.ActiveCfg = Debug|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Debug|x64.Build.0 = Debug|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Debug|x86.ActiveCfg = Debug|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Debug|x86.Build.0 = Debug|Any CPU {27028918-925E-45D4-BD72-199349B6E6AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {27028918-925E-45D4-BD72-199349B6E6AA}.Release|Any CPU.Build.0 = Release|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Release|x64.ActiveCfg = Release|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Release|x64.Build.0 = Release|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Release|x86.ActiveCfg = Release|Any CPU + {27028918-925E-45D4-BD72-199349B6E6AA}.Release|x86.Build.0 = Release|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Debug|x64.ActiveCfg = Debug|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Debug|x64.Build.0 = Debug|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Debug|x86.ActiveCfg = Debug|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Debug|x86.Build.0 = Debug|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Release|Any CPU.Build.0 = Release|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Release|x64.ActiveCfg = Release|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Release|x64.Build.0 = Release|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Release|x86.ActiveCfg = Release|Any CPU + {D8B45203-B939-4628-AC77-C477A4AC5F45}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/tests/CoreTest/Bootstrap/GeneralUpdateBootstrapTests.cs b/tests/CoreTest/Bootstrap/GeneralUpdateBootstrapTests.cs new file mode 100644 index 00000000..92481102 --- /dev/null +++ b/tests/CoreTest/Bootstrap/GeneralUpdateBootstrapTests.cs @@ -0,0 +1,210 @@ +using GeneralUpdate.Common.Download; +using GeneralUpdate.Common.Internal; +using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Core; +using Xunit; + +namespace CoreTest.Bootstrap +{ + /// + /// Contains test cases for the GeneralUpdateBootstrap class. + /// Tests the main orchestrator for platform-agnostic update process. + /// + public class GeneralUpdateBootstrapTests + { + /// + /// Tests that GeneralUpdateBootstrap can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var bootstrap = new GeneralUpdateBootstrap(); + + // Assert + Assert.NotNull(bootstrap); + } + + /// + /// Tests that SetConfig returns the bootstrap instance for chaining. + /// + [Fact] + public void SetConfig_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + var configInfo = new Configinfo + { + InstallPath = "/test/install", + MainAppName = "TestApp.exe", + UpdateUrl = "https://example.com/update", + ClientVersion = "1.0.0" + }; + + // Act + var result = bootstrap.SetConfig(configInfo); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that SetFieldMappings returns the bootstrap instance for chaining. + /// + [Fact] + public void SetFieldMappings_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + var fieldMappings = new Dictionary + { + { "field1", "value1" } + }; + + // Act + var result = bootstrap.SetFieldMappings(fieldMappings); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that SetCustomSkipOption returns the bootstrap instance for chaining. + /// + [Fact] + public void SetCustomSkipOption_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Func skipFunc = () => false; + + // Act + var result = bootstrap.SetCustomSkipOption(skipFunc); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that AddListenerMultiAllDownloadCompleted returns the bootstrap instance for chaining. + /// + [Fact] + public void AddListenerMultiAllDownloadCompleted_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Action callback = (sender, e) => { }; + + // Act + var result = bootstrap.AddListenerMultiAllDownloadCompleted(callback); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that AddListenerMultiDownloadCompleted returns the bootstrap instance for chaining. + /// + [Fact] + public void AddListenerMultiDownloadCompleted_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Action callback = (sender, e) => { }; + + // Act + var result = bootstrap.AddListenerMultiDownloadCompleted(callback); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that AddListenerMultiDownloadError returns the bootstrap instance for chaining. + /// + [Fact] + public void AddListenerMultiDownloadError_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Action callback = (sender, e) => { }; + + // Act + var result = bootstrap.AddListenerMultiDownloadError(callback); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that AddListenerMultiDownloadStatistics returns the bootstrap instance for chaining. + /// + [Fact] + public void AddListenerMultiDownloadStatistics_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Action callback = (sender, e) => { }; + + // Act + var result = bootstrap.AddListenerMultiDownloadStatistics(callback); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that AddListenerException returns the bootstrap instance for chaining. + /// + [Fact] + public void AddListenerException_ReturnsBootstrapInstance() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Action callback = (sender, e) => { }; + + // Act + var result = bootstrap.AddListenerException(callback); + + // Assert + Assert.Same(bootstrap, result); + } + + /// + /// Tests that null callback throws ArgumentNullException. + /// + [Fact] + public void AddListener_WithNullCallback_ThrowsArgumentNullException() + { + // Arrange + var bootstrap = new GeneralUpdateBootstrap(); + Action? callback = null; + + // Act & Assert + Assert.Throws(() => bootstrap.AddListenerException(callback!)); + } + + /// + /// Tests method chaining pattern for configuration. + /// + [Fact] + public void MethodChaining_ConfigureBootstrap_ReturnsCorrectInstance() + { + // Arrange & Act + var bootstrap = new GeneralUpdateBootstrap() + .SetConfig(new Configinfo + { + InstallPath = "/test/install", + MainAppName = "TestApp.exe", + UpdateUrl = "https://example.com/update", + ClientVersion = "1.0.0" + }) + .SetFieldMappings(new Dictionary { { "key", "value" } }) + .SetCustomSkipOption(() => false) + .AddListenerException((sender, e) => { }); + + // Assert + Assert.NotNull(bootstrap); + } + } +} diff --git a/tests/CoreTest/Bootstrap/GeneralUpdateOSSTests.cs b/tests/CoreTest/Bootstrap/GeneralUpdateOSSTests.cs new file mode 100644 index 00000000..e16ed050 --- /dev/null +++ b/tests/CoreTest/Bootstrap/GeneralUpdateOSSTests.cs @@ -0,0 +1,40 @@ +using GeneralUpdate.Core; +using Xunit; + +namespace CoreTest.Bootstrap +{ + /// + /// Contains test cases for the GeneralUpdateOSS class. + /// Tests OSS update functionality for cross-platform scenarios. + /// + public class GeneralUpdateOSSTests + { + /// + /// Tests that GeneralUpdateOSS is a sealed class. + /// + [Fact] + public void Class_IsSealed() + { + // Arrange + var type = typeof(GeneralUpdateOSS); + + // Assert + Assert.True(type.IsSealed); + } + + /// + /// Tests that Start method exists and is static. + /// + [Fact] + public void StartMethod_IsStatic() + { + // Arrange + var type = typeof(GeneralUpdateOSS); + var method = type.GetMethod("Start"); + + // Assert + Assert.NotNull(method); + Assert.True(method.IsStatic); + } + } +} diff --git a/tests/CoreTest/CoreTest.csproj b/tests/CoreTest/CoreTest.csproj new file mode 100644 index 00000000..4d31d3fc --- /dev/null +++ b/tests/CoreTest/CoreTest.csproj @@ -0,0 +1,26 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/CoreTest/Driver/DriverInfoTests.cs b/tests/CoreTest/Driver/DriverInfoTests.cs new file mode 100644 index 00000000..a45e8268 --- /dev/null +++ b/tests/CoreTest/Driver/DriverInfoTests.cs @@ -0,0 +1,60 @@ +using GeneralUpdate.Core.Driver; +using Xunit; + +namespace CoreTest.Driver +{ + /// + /// Contains test cases for the DriverInfo class. + /// Tests driver metadata storage. + /// + public class DriverInfoTests + { + /// + /// Tests that DriverInfo properties can be set and retrieved. + /// + [Fact] + public void Properties_CanBeSetAndRetrieved() + { + // Arrange + var driverInfo = new DriverInfo(); + + // Act + driverInfo.PublishedName = "oem1.inf"; + driverInfo.OriginalName = "mydriver.inf"; + driverInfo.Provider = "Microsoft"; + driverInfo.ClassName = "Display"; + driverInfo.ClassGUID = "{4d36e968-e325-11ce-bfc1-08002be10318}"; + driverInfo.Version = "1.0.0.0"; + driverInfo.Signer = "Microsoft Windows Hardware Compatibility Publisher"; + + // Assert + Assert.Equal("oem1.inf", driverInfo.PublishedName); + Assert.Equal("mydriver.inf", driverInfo.OriginalName); + Assert.Equal("Microsoft", driverInfo.Provider); + Assert.Equal("Display", driverInfo.ClassName); + Assert.Equal("{4d36e968-e325-11ce-bfc1-08002be10318}", driverInfo.ClassGUID); + Assert.Equal("1.0.0.0", driverInfo.Version); + Assert.Equal("Microsoft Windows Hardware Compatibility Publisher", driverInfo.Signer); + } + + /// + /// Tests that DriverInfo can be instantiated with default values. + /// + [Fact] + public void Constructor_CreatesInstanceWithDefaultValues() + { + // Act + var driverInfo = new DriverInfo(); + + // Assert + Assert.NotNull(driverInfo); + Assert.Null(driverInfo.PublishedName); + Assert.Null(driverInfo.OriginalName); + Assert.Null(driverInfo.Provider); + Assert.Null(driverInfo.ClassName); + Assert.Null(driverInfo.ClassGUID); + Assert.Null(driverInfo.Version); + Assert.Null(driverInfo.Signer); + } + } +} diff --git a/tests/CoreTest/Driver/DriverInformationTests.cs b/tests/CoreTest/Driver/DriverInformationTests.cs new file mode 100644 index 00000000..b5e92fc9 --- /dev/null +++ b/tests/CoreTest/Driver/DriverInformationTests.cs @@ -0,0 +1,132 @@ +using GeneralUpdate.Core.Driver; +using Xunit; + +namespace CoreTest.Driver +{ + /// + /// Contains test cases for the DriverInformation class. + /// Tests driver information builder pattern and validation. + /// + public class DriverInformationTests + { + /// + /// Tests that Builder can create a valid DriverInformation instance. + /// + [Fact] + public void Builder_WithAllRequiredFields_BuildsSuccessfully() + { + // Arrange + var builder = new DriverInformation.Builder(); + var fieldMappings = new Dictionary + { + { "field1", "value1" } + }; + + // Act + var information = builder + .SetDriverFileExtension(".inf") + .SetOutPutDirectory("/test/output") + .SetDriverDirectory("/test/drivers") + .SetFieldMappings(fieldMappings) + .Build(); + + // Assert + Assert.NotNull(information); + Assert.Equal(".inf", information.DriverFileExtension); + Assert.Equal("/test/output", information.OutPutDirectory); + Assert.Equal("/test/drivers", information.DriverDirectory); + Assert.Equal(fieldMappings, information.FieldMappings); + } + + /// + /// Tests that Builder throws ArgumentNullException when OutPutDirectory is not set. + /// + [Fact] + public void Builder_WithoutOutPutDirectory_ThrowsArgumentNullException() + { + // Arrange + var builder = new DriverInformation.Builder(); + + // Act & Assert + Assert.Throws(() => + builder + .SetDriverFileExtension(".inf") + .SetDriverDirectory("/test/drivers") + .Build()); + } + + /// + /// Tests that Builder throws ArgumentNullException when DriverFileExtension is not set. + /// + [Fact] + public void Builder_WithoutDriverFileExtension_ThrowsArgumentNullException() + { + // Arrange + var builder = new DriverInformation.Builder(); + + // Act & Assert + Assert.Throws(() => + builder + .SetOutPutDirectory("/test/output") + .SetDriverDirectory("/test/drivers") + .Build()); + } + + /// + /// Tests that Builder can set and retrieve all properties. + /// + [Fact] + public void Builder_SetAllProperties_ReturnsCorrectValues() + { + // Arrange + var builder = new DriverInformation.Builder(); + var fieldMappings = new Dictionary + { + { "key1", "val1" }, + { "key2", "val2" } + }; + + // Act + var information = builder + .SetDriverFileExtension(".sys") + .SetOutPutDirectory("/output/path") + .SetDriverDirectory("/driver/path") + .SetFieldMappings(fieldMappings) + .Build(); + + // Assert + Assert.Equal(".sys", information.DriverFileExtension); + Assert.Equal("/output/path", information.OutPutDirectory); + Assert.Equal("/driver/path", information.DriverDirectory); + Assert.Equal(2, information.FieldMappings.Count); + } + + /// + /// Tests that Drivers property can be set and retrieved. + /// + [Fact] + public void Drivers_CanBeSetAndRetrieved() + { + // Arrange + var builder = new DriverInformation.Builder(); + var drivers = new List + { + new DriverInfo { OriginalName = "driver1.inf", PublishedName = "oem1.inf" }, + new DriverInfo { OriginalName = "driver2.inf", PublishedName = "oem2.inf" } + }; + + // Act + var information = builder + .SetDriverFileExtension(".inf") + .SetOutPutDirectory("/test/output") + .SetDriverDirectory("/test/drivers") + .Build(); + + information.Drivers = drivers; + + // Assert + Assert.NotNull(information.Drivers); + Assert.Equal(2, information.Drivers.Count()); + } + } +} diff --git a/tests/CoreTest/Driver/DriverProcessorTests.cs b/tests/CoreTest/Driver/DriverProcessorTests.cs new file mode 100644 index 00000000..1c60b2fb --- /dev/null +++ b/tests/CoreTest/Driver/DriverProcessorTests.cs @@ -0,0 +1,100 @@ +using GeneralUpdate.Core.Driver; +using Moq; +using Xunit; + +namespace CoreTest.Driver +{ + /// + /// Contains test cases for the DriverProcessor class. + /// Tests driver command management and execution. + /// + public class DriverProcessorTests + { + /// + /// Tests that processor can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var processor = new DriverProcessor(); + + // Assert + Assert.NotNull(processor); + } + + /// + /// Tests that commands can be added to the processor. + /// + [Fact] + public void AddCommand_AddsCommandToProcessor() + { + // Arrange + var processor = new DriverProcessor(); + var mockCommand = new Mock(); + + // Act + processor.AddCommand(mockCommand.Object); + + // Assert - if no exception, command was added + } + + /// + /// Tests that ProcessCommands executes all added commands. + /// + [Fact] + public void ProcessCommands_ExecutesAllCommands() + { + // Arrange + var processor = new DriverProcessor(); + var mockCommand1 = new Mock(); + var mockCommand2 = new Mock(); + var mockCommand3 = new Mock(); + + processor.AddCommand(mockCommand1.Object); + processor.AddCommand(mockCommand2.Object); + processor.AddCommand(mockCommand3.Object); + + // Act + processor.ProcessCommands(); + + // Assert + mockCommand1.Verify(c => c.Execute(), Times.Once); + mockCommand2.Verify(c => c.Execute(), Times.Once); + mockCommand3.Verify(c => c.Execute(), Times.Once); + } + + /// + /// Tests that ProcessCommands with no commands does not throw. + /// + [Fact] + public void ProcessCommands_WithNoCommands_DoesNotThrow() + { + // Arrange + var processor = new DriverProcessor(); + + // Act & Assert - should not throw + processor.ProcessCommands(); + Assert.True(true); + } + + /// + /// Tests that ProcessCommands clears commands after execution. + /// + [Fact] + public void ProcessCommands_ClearsCommandsAfterExecution() + { + // Arrange + var processor = new DriverProcessor(); + var mockCommand = new Mock(); + processor.AddCommand(mockCommand.Object); + + // Act + processor.ProcessCommands(); + processor.ProcessCommands(); // Call again + + // Assert - Execute should only be called once (from first ProcessCommands) + mockCommand.Verify(c => c.Execute(), Times.Once); + } + } +} diff --git a/tests/CoreTest/Pipeline/CompressMiddlewareTests.cs b/tests/CoreTest/Pipeline/CompressMiddlewareTests.cs new file mode 100644 index 00000000..edaab62b --- /dev/null +++ b/tests/CoreTest/Pipeline/CompressMiddlewareTests.cs @@ -0,0 +1,61 @@ +using System.Text; +using GeneralUpdate.Common.Internal.Pipeline; +using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Core.Pipeline; +using Xunit; + +namespace CoreTest.Pipeline +{ + /// + /// Contains test cases for the CompressMiddleware class. + /// Tests decompression functionality for update packages. + /// + public class CompressMiddlewareTests + { + /// + /// Tests that InvokeAsync requires necessary context values. + /// + [Fact] + public async Task InvokeAsync_WithMissingContextValues_ThrowsException() + { + // Arrange + var middleware = new CompressMiddleware(); + var context = new PipelineContext(); + + // Act & Assert + await Assert.ThrowsAsync(() => middleware.InvokeAsync(context)); + } + + /// + /// Tests that context contains expected keys after setup. + /// + [Fact] + public void Context_CanStoreAndRetrieveValues() + { + // Arrange + var context = new PipelineContext(); + var format = Format.ZIP; + var sourcePath = "/test/source.zip"; + var patchPath = "/test/patch"; + var encoding = Encoding.UTF8; + var appPath = "/test/app"; + var patchEnabled = true; + + // Act + context.Add("Format", format); + context.Add("ZipFilePath", sourcePath); + context.Add("PatchPath", patchPath); + context.Add("Encoding", encoding); + context.Add("SourcePath", appPath); + context.Add("PatchEnabled", patchEnabled); + + // Assert + Assert.Equal(format, context.Get("Format")); + Assert.Equal(sourcePath, context.Get("ZipFilePath")); + Assert.Equal(patchPath, context.Get("PatchPath")); + Assert.Equal(encoding, context.Get("Encoding")); + Assert.Equal(appPath, context.Get("SourcePath")); + Assert.Equal(patchEnabled, context.Get("PatchEnabled")); + } + } +} diff --git a/tests/CoreTest/Pipeline/DriverMiddlewareTests.cs b/tests/CoreTest/Pipeline/DriverMiddlewareTests.cs new file mode 100644 index 00000000..39467ac7 --- /dev/null +++ b/tests/CoreTest/Pipeline/DriverMiddlewareTests.cs @@ -0,0 +1,98 @@ +using GeneralUpdate.Common.Internal.Pipeline; +using GeneralUpdate.Core.Pipeline; +using Xunit; + +namespace CoreTest.Pipeline +{ + /// + /// Contains test cases for the DriverMiddleware class. + /// Tests driver installation and management functionality. + /// + public class DriverMiddlewareTests + { + /// + /// Tests that DriverMiddleware can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var middleware = new DriverMiddleware(); + + // Assert + Assert.NotNull(middleware); + } + + /// + /// Tests that InvokeAsync returns early when DriverOutPut is missing. + /// + [Fact] + public async Task InvokeAsync_WithMissingDriverOutPut_ReturnsEarly() + { + // Arrange + var middleware = new DriverMiddleware(); + var context = new PipelineContext(); + + // Act - should return early without throwing + await middleware.InvokeAsync(context); + } + + /// + /// Tests that InvokeAsync returns early when PatchPath is missing. + /// + [Fact] + public async Task InvokeAsync_WithMissingPatchPath_ReturnsEarly() + { + // Arrange + var middleware = new DriverMiddleware(); + var context = new PipelineContext(); + context.Add("DriverOutPut", "/test/output"); + + // Act - should return early without throwing + await middleware.InvokeAsync(context); + } + + /// + /// Tests that InvokeAsync returns early when FieldMappings is missing. + /// + [Fact] + public async Task InvokeAsync_WithMissingFieldMappings_ReturnsEarly() + { + // Arrange + var middleware = new DriverMiddleware(); + var context = new PipelineContext(); + context.Add("DriverOutPut", "/test/output"); + context.Add("PatchPath", "/test/patch"); + + // Act - should return early without throwing + await middleware.InvokeAsync(context); + } + + /// + /// Tests that context can store driver-related values. + /// + [Fact] + public void Context_CanStoreDriverValues() + { + // Arrange + var context = new PipelineContext(); + var outPutPath = "/test/output"; + var patchPath = "/test/patch"; + var fieldMappings = new Dictionary + { + { "field1", "value1" }, + { "field2", "value2" } + }; + + // Act + context.Add("DriverOutPut", outPutPath); + context.Add("PatchPath", patchPath); + context.Add("FieldMappings", fieldMappings); + + // Assert + Assert.Equal(outPutPath, context.Get("DriverOutPut")); + Assert.Equal(patchPath, context.Get("PatchPath")); + Assert.Equal(fieldMappings, context.Get>("FieldMappings")); + } + } +} diff --git a/tests/CoreTest/Pipeline/HashMiddlewareTests.cs b/tests/CoreTest/Pipeline/HashMiddlewareTests.cs new file mode 100644 index 00000000..76a121c4 --- /dev/null +++ b/tests/CoreTest/Pipeline/HashMiddlewareTests.cs @@ -0,0 +1,120 @@ +using System.Security.Cryptography; +using GeneralUpdate.Common.Internal.Pipeline; +using GeneralUpdate.Core.Pipeline; +using Xunit; + +namespace CoreTest.Pipeline +{ + /// + /// Contains test cases for the HashMiddleware class. + /// Tests hash verification functionality for downloaded files. + /// + public class HashMiddlewareTests + { + /// + /// Tests that InvokeAsync throws CryptographicException when hash verification fails. + /// + [Fact] + public async Task InvokeAsync_WithInvalidHash_ThrowsCryptographicException() + { + // Arrange + var middleware = new HashMiddleware(); + var context = new PipelineContext(); + + // Create a temporary test file + var tempFile = Path.GetTempFileName(); + File.WriteAllText(tempFile, "test content"); + + try + { + context.Add("ZipFilePath", tempFile); + context.Add("Hash", "invalidhash123"); + + // Act & Assert + await Assert.ThrowsAsync(() => middleware.InvokeAsync(context)); + } + finally + { + // Cleanup + if (File.Exists(tempFile)) + File.Delete(tempFile); + } + } + + /// + /// Tests that InvokeAsync succeeds with valid hash. + /// + [Fact] + public async Task InvokeAsync_WithValidHash_Succeeds() + { + // Arrange + var middleware = new HashMiddleware(); + var context = new PipelineContext(); + + // Create a temporary test file + var tempFile = Path.GetTempFileName(); + File.WriteAllText(tempFile, "test content"); + + try + { + // Compute the actual SHA256 hash of the file + using (var sha256 = SHA256.Create()) + using (var stream = File.OpenRead(tempFile)) + { + var hashBytes = sha256.ComputeHash(stream); + var hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant(); + + context.Add("ZipFilePath", tempFile); + context.Add("Hash", hash); + + // Act - should not throw + await middleware.InvokeAsync(context); + } + } + finally + { + // Cleanup + if (File.Exists(tempFile)) + File.Delete(tempFile); + } + } + + /// + /// Tests that hash comparison is case-insensitive. + /// + [Fact] + public async Task InvokeAsync_WithUppercaseHash_Succeeds() + { + // Arrange + var middleware = new HashMiddleware(); + var context = new PipelineContext(); + + // Create a temporary test file + var tempFile = Path.GetTempFileName(); + File.WriteAllText(tempFile, "test content"); + + try + { + // Compute the actual SHA256 hash of the file in uppercase + using (var sha256 = SHA256.Create()) + using (var stream = File.OpenRead(tempFile)) + { + var hashBytes = sha256.ComputeHash(stream); + var hash = BitConverter.ToString(hashBytes).Replace("-", "").ToUpperInvariant(); + + context.Add("ZipFilePath", tempFile); + context.Add("Hash", hash); + + // Act - should not throw + await middleware.InvokeAsync(context); + } + } + finally + { + // Cleanup + if (File.Exists(tempFile)) + File.Delete(tempFile); + } + } + } +} diff --git a/tests/CoreTest/Pipeline/PatchMiddlewareTests.cs b/tests/CoreTest/Pipeline/PatchMiddlewareTests.cs new file mode 100644 index 00000000..3f162082 --- /dev/null +++ b/tests/CoreTest/Pipeline/PatchMiddlewareTests.cs @@ -0,0 +1,46 @@ +using GeneralUpdate.Common.Internal.Pipeline; +using GeneralUpdate.Core.Pipeline; +using Xunit; + +namespace CoreTest.Pipeline +{ + /// + /// Contains test cases for the PatchMiddleware class. + /// Tests binary patching functionality for incremental updates. + /// + public class PatchMiddlewareTests + { + /// + /// Tests that PatchMiddleware can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var middleware = new PatchMiddleware(); + + // Assert + Assert.NotNull(middleware); + } + + /// + /// Tests that context stores patch-related values correctly. + /// + [Fact] + public void Context_CanStorePatchPaths() + { + // Arrange + var context = new PipelineContext(); + var sourcePath = "/test/source"; + var targetPath = "/test/target"; + + // Act + context.Add("SourcePath", sourcePath); + context.Add("PatchPath", targetPath); + + // Assert + Assert.Equal(sourcePath, context.Get("SourcePath")); + Assert.Equal(targetPath, context.Get("PatchPath")); + } + } +} diff --git a/tests/CoreTest/Strategys/LinuxStrategyTests.cs b/tests/CoreTest/Strategys/LinuxStrategyTests.cs new file mode 100644 index 00000000..9a905d69 --- /dev/null +++ b/tests/CoreTest/Strategys/LinuxStrategyTests.cs @@ -0,0 +1,45 @@ +using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Core.Strategys; +using Xunit; + +namespace CoreTest.Strategys +{ + /// + /// Contains test cases for the LinuxStrategy class. + /// Tests Linux-specific update implementation. + /// + public class LinuxStrategyTests + { + /// + /// Tests that LinuxStrategy can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var strategy = new LinuxStrategy(); + + // Assert + Assert.NotNull(strategy); + } + + /// + /// Tests that Create method accepts GlobalConfigInfo. + /// + [Fact] + public void Create_WithValidConfig_DoesNotThrow() + { + // Arrange + var strategy = new LinuxStrategy(); + var config = new GlobalConfigInfo + { + InstallPath = "/test/install", + MainAppName = "TestApp", + TempPath = "/test/temp" + }; + + // Act & Assert - should not throw + strategy.Create(config); + } + } +} diff --git a/tests/CoreTest/Strategys/OSSStrategyTests.cs b/tests/CoreTest/Strategys/OSSStrategyTests.cs new file mode 100644 index 00000000..1f429d19 --- /dev/null +++ b/tests/CoreTest/Strategys/OSSStrategyTests.cs @@ -0,0 +1,45 @@ +using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Core.Strategys; +using Xunit; + +namespace CoreTest.Strategys +{ + /// + /// Contains test cases for the OSSStrategy class. + /// Tests OSS (Object Storage Service) update implementation. + /// + public class OSSStrategyTests + { + /// + /// Tests that OSSStrategy can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var strategy = new OSSStrategy(); + + // Assert + Assert.NotNull(strategy); + } + + /// + /// Tests that Create method accepts GlobalConfigInfoOSS. + /// + [Fact] + public void Create_WithValidConfig_DoesNotThrow() + { + // Arrange + var strategy = new OSSStrategy(); + var config = new GlobalConfigInfoOSS + { + AppName = "TestApp.exe", + VersionFileName = "versions.json", + Encoding = "utf-8" + }; + + // Act & Assert - should not throw + strategy.Create(config); + } + } +} diff --git a/tests/CoreTest/Strategys/WindowsStrategyTests.cs b/tests/CoreTest/Strategys/WindowsStrategyTests.cs new file mode 100644 index 00000000..254656bf --- /dev/null +++ b/tests/CoreTest/Strategys/WindowsStrategyTests.cs @@ -0,0 +1,45 @@ +using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Core.Strategys; +using Xunit; + +namespace CoreTest.Strategys +{ + /// + /// Contains test cases for the WindowsStrategy class. + /// Tests Windows-specific update implementation. + /// + public class WindowsStrategyTests + { + /// + /// Tests that WindowsStrategy can be instantiated. + /// + [Fact] + public void Constructor_CreatesInstance() + { + // Act + var strategy = new WindowsStrategy(); + + // Assert + Assert.NotNull(strategy); + } + + /// + /// Tests that Create method accepts GlobalConfigInfo. + /// + [Fact] + public void Create_WithValidConfig_DoesNotThrow() + { + // Arrange + var strategy = new WindowsStrategy(); + var config = new GlobalConfigInfo + { + InstallPath = "/test/install", + MainAppName = "TestApp.exe", + TempPath = "/test/temp" + }; + + // Act & Assert - should not throw + strategy.Create(config); + } + } +}