diff --git a/src/AppInstallerCLIE2ETests/AppInstallerCLIE2ETests.csproj b/src/AppInstallerCLIE2ETests/AppInstallerCLIE2ETests.csproj index 8a0520f5e1..45b393129c 100644 --- a/src/AppInstallerCLIE2ETests/AppInstallerCLIE2ETests.csproj +++ b/src/AppInstallerCLIE2ETests/AppInstallerCLIE2ETests.csproj @@ -43,6 +43,9 @@ False + + False + @@ -55,5 +58,6 @@ + diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/MergeSubmissionMismatch.json b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/MergeSubmissionMismatch.json new file mode 100644 index 0000000000..e9aa1b3dbe --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/MergeSubmissionMismatch.json @@ -0,0 +1,45 @@ +{ + "version": "1.0", + "metadatas": [ + { + "version": "1.0", + "productVersionMin": "1.0", + "productVersionMax": "1.0", + "metadata": [ + { + "installerHash": "ABCD", + "submissionIdentifier": "1", + "AppsAndFeaturesEntries": [ + { + "DisplayName": "Name", + "Publisher": "Publisher", + "DisplayVersion": "1.0", + "ProductCode": "{46210E3D-EBB3-43D4-B9BB-48A7DB0F9B93}", + "InstallerType": 3 + } + ] + } + ] + }, + { + "version": "1.0", + "productVersionMin": "1.0", + "productVersionMax": "1.0", + "metadata": [ + { + "installerHash": "EFGH", + "submissionIdentifier": "2", + "AppsAndFeaturesEntries": [ + { + "DisplayName": "Name", + "Publisher": "Publisher", + "DisplayVersion": "1.0", + "ProductCode": "{46210E3D-EBB3-43D4-B9BB-48A7DB0F9B93}", + "InstallerType": 3 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/MergeValid.json b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/MergeValid.json new file mode 100644 index 0000000000..100df54b38 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/MergeValid.json @@ -0,0 +1,45 @@ +{ + "version": "1.0", + "metadatas": [ + { + "version": "1.0", + "productVersionMin": "1.0", + "productVersionMax": "1.0", + "metadata": [ + { + "installerHash": "ABCD", + "submissionIdentifier": "1", + "AppsAndFeaturesEntries": [ + { + "DisplayName": "Name", + "Publisher": "Publisher", + "DisplayVersion": "1.0", + "ProductCode": "{46210E3D-EBB3-43D4-B9BB-48A7DB0F9B93}", + "InstallerType": 3 + } + ] + } + ] + }, + { + "version": "1.0", + "productVersionMin": "1.0", + "productVersionMax": "1.0", + "metadata": [ + { + "installerHash": "EFGH", + "submissionIdentifier": "1", + "AppsAndFeaturesEntries": [ + { + "DisplayName": "Name", + "Publisher": "Publisher", + "DisplayVersion": "1.0", + "ProductCode": "{46210E3D-EBB3-43D4-B9BB-48A7DB0F9B93}", + "InstallerType": 3 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/Minimal.json b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/Minimal.json new file mode 100644 index 0000000000..514d164a23 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/InstallerMetadata/Minimal.json @@ -0,0 +1,15 @@ +{ + "version": "1.0", + "supportedMetadataVersion": "1.0", + "submissionData": { + "submissionIdentifier": "1" + }, + "packageData": { + "installerHash": "ABCD", + "DefaultLocale": { + "PackageLocale": "en-us", + "PackageName": "Name", + "Publisher": "Publisher" + } + } +} diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Merged/WinGetUtilTest.Add.yaml b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Merged/WinGetUtilTest.Add.yaml new file mode 100644 index 0000000000..e9fcd7d8fb --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Merged/WinGetUtilTest.Add.yaml @@ -0,0 +1,16 @@ +Installers: +- Architecture: x86 + InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 + InstallerType: exe + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe +License: Test +ManifestType: merged +ManifestVersion: 1.1.0 +MinimumOSVersion: 10.0.0.0 +PackageIdentifier: AppInstallerTest.WinGetUtilTest +PackageLocale: en-US +PackageName: AppInstallerTest +PackageVersion: 1.0.0.0 +Publisher: AppInstallerTest +Tags: +- add diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Merged/WinGetUtilTest.Update.yaml b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Merged/WinGetUtilTest.Update.yaml new file mode 100644 index 0000000000..6c2307d4b0 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Merged/WinGetUtilTest.Update.yaml @@ -0,0 +1,16 @@ +Installers: +- Architecture: x86 + InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 + InstallerType: exe + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe +License: Test +ManifestType: merged +ManifestVersion: 1.1.0 +MinimumOSVersion: 10.0.0.0 +PackageIdentifier: AppInstallerTest.WinGetUtilTest +PackageLocale: en-US +PackageName: AppInstallerTest +PackageVersion: 1.0.0.0 +Publisher: AppInstallerTest +Tags: +- update diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.installer.yaml b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.installer.yaml new file mode 100644 index 0000000000..00a170f956 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.installer.yaml @@ -0,0 +1,10 @@ +PackageIdentifier: AppInstallerTest.WinGetUtilTest +PackageVersion: "1.0.0.0" +MinimumOSVersion: 10.0.0.0 +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: nullsoft + InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 +ManifestType: installer +ManifestVersion: 1.1.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.locale.en-US.yaml b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.locale.en-US.yaml new file mode 100644 index 0000000000..c18ef5894d --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.locale.en-US.yaml @@ -0,0 +1,9 @@ +PackageIdentifier: AppInstallerTest.WinGetUtilTest +PackageVersion: "1.0.0.0" +PackageLocale: en-US +Publisher: AppInstallerTest +License: Test +PackageName: AppInstallerTest +ShortDescription: WinGetUtilTest +ManifestType: defaultLocale +ManifestVersion: 1.1.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.yaml b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.yaml new file mode 100644 index 0000000000..c08fc757ae --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/WinGetUtil/Manifests/Unmerged/ValidateManifest/WinGetUtilTest.yaml @@ -0,0 +1,5 @@ +PackageIdentifier: AppInstallerTest.WinGetUtilTest +PackageVersion: "1.0.0.0" +DefaultLocale: en-US +ManifestType: version +ManifestVersion: 1.1.0 diff --git a/src/AppInstallerCLIE2ETests/TestIndexSetup.cs b/src/AppInstallerCLIE2ETests/TestIndexSetup.cs index 3964953125..db53f5fc95 100644 --- a/src/AppInstallerCLIE2ETests/TestIndexSetup.cs +++ b/src/AppInstallerCLIE2ETests/TestIndexSetup.cs @@ -71,7 +71,7 @@ private static void SetupSourcePackage() } // Generate Index.db file using IndexCreationTool.exe - RunCommand(Path.Combine(indexCreationToolPath, "IndexCreationTool.exe"), $"-d {TestCommon.StaticFileRootPath}", indexDestPath); + RunCommand(Path.Combine(indexCreationToolPath, "IndexCreationTool.exe"), $"-d {TestCommon.StaticFileRootPath} -i {ManifestsName}", indexDestPath); string packageDir = Path.Combine(TestCommon.StaticFileRootPath, PackageName); string indexPackageDestPath = Path.Combine(TestCommon.StaticFileRootPath, Constants.IndexPackage); diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilCompareVersions.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilCompareVersions.cs new file mode 100644 index 0000000000..84abc1825b --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilCompareVersions.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using NUnit.Framework; + + public class WinGetUtilCompareVersions + { + [Test] + // V1 = V2 + [TestCase("1.0.0.0", "1.0.0.0", 0)] + [TestCase("1.0.0", "1.0.0.0", 0)] + [TestCase("1.0", "1.0.0.0", 0)] + [TestCase("1", "1.0.0.0", 0)] + // V1 > V2 + [TestCase("1.0.0.1", "1.0.0.0", 1)] + [TestCase("1.0.1.0", "1.0.0.0", 1)] + [TestCase("1.1.0.0", "1.0.0.0", 1)] + [TestCase("2.0.0.0", "1.0.0.0", 1)] + // V1 < V2 + [TestCase("1.0.0.0", "1.0.0.1", -1)] + [TestCase("1.0.0.0", "1.0.1.0", -1)] + [TestCase("1.0.0.0", "1.1.0.0", -1)] + [TestCase("1.0.0.0", "2.0.0.0", -1)] + public void WinGetUtil_CompareVersions(string version1, string version2, int expectedResult) + { + // Compare versions + WinGetUtilWrapper.WinGetCompareVersions(version1, version2, out int result); + Assert.AreEqual(expectedResult, result); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilDownload.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilDownload.cs new file mode 100644 index 0000000000..d31a6073a1 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilDownload.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using System.IO; + using System.Linq; + using NUnit.Framework; + + public class WinGetUtilDownload + { + [Test] + public void WinGetUtil_Download() + { + uint hashSize = 32; + byte[] sha256Hash = new byte[hashSize]; + string installerUrl = @"https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe"; + string filePath = TestCommon.GetRandomTestFile(".exe"); + + // Download + WinGetUtilWrapper.WinGetDownload(installerUrl, filePath, sha256Hash, hashSize); + + Assert.True(File.Exists(filePath)); + Assert.False(sha256Hash.All(byteVal => byteVal == 0)); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilInstallerMetadataCollection.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilInstallerMetadataCollection.cs new file mode 100644 index 0000000000..d11c11128f --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilInstallerMetadataCollection.cs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using Newtonsoft.Json; + using NUnit.Framework; + using System; + using System.IO; + using System.Runtime.InteropServices; + + public class WinGetUtilInstallerMetadataCollection + { + [Test] + public void WinGetUtil_BeginCompleteInstallerMetadataCollection() + { + string logFilePath = TestCommon.GetRandomTestFile(".log"); + string inputJson = TestCommon.GetTestDataFile(@"WinGetUtil\InstallerMetadata\Minimal.json"); + string outputFilePath = TestCommon.GetRandomTestFile(".json"); + + WinGetUtilWrapper.WinGetBeginInstallerMetadataCollection( + inputJson, + logFilePath, + WinGetUtilWrapper.WinGetBeginInstallerMetadataCollectionOptions.WinGetBeginInstallerMetadataCollectionOption_InputIsFilePath, + out IntPtr collectionHandle); + + Assert.AreNotEqual(IntPtr.Zero, collectionHandle); + Assert.True(File.Exists(logFilePath)); + + WinGetUtilWrapper.WinGetCompleteInstallerMetadataCollection( + collectionHandle, + outputFilePath, + WinGetUtilWrapper.WinGetCompleteInstallerMetadataCollectionOptions.WinGetCompleteInstallerMetadataCollectionOption_None); + + string outputJson = File.ReadAllText(outputFilePath); + Assert.IsNotEmpty(JsonConvert.DeserializeObject(outputJson).ToString()); + } + + [Test] + public void WinGetUtil_MergeInstallerMetadata_Success() + { + string logFilePath = TestCommon.GetRandomTestFile(".log"); + string inputJsonPath = TestCommon.GetTestDataFile(@"WinGetUtil\InstallerMetadata\MergeValid.json"); + string inputJson = File.ReadAllText(inputJsonPath); + + WinGetUtilWrapper.WinGetMergeInstallerMetadata( + inputJson, + out string outputJson, + 0, + logFilePath, + WinGetUtilWrapper.WinGetMergeInstallerMetadataOptions.WinGetMergeInstallerMetadataOptions_None); + + Assert.True(File.Exists(logFilePath)); + Assert.IsNotEmpty(JsonConvert.DeserializeObject(outputJson).ToString()); + } + + [Test] + public void WinGetUtil_MergeInstallerMetadata_Fail_SubmissionMismatch() + { + string logFilePath = TestCommon.GetRandomTestFile(".log"); + string inputJsonPath = TestCommon.GetTestDataFile(@"WinGetUtil\InstallerMetadata\MergeSubmissionMismatch.json"); + string inputJson = File.ReadAllText(inputJsonPath); + + Assert.Throws(() => + { + WinGetUtilWrapper.WinGetMergeInstallerMetadata( + inputJson, + out string outputJson, + 0, + logFilePath, + WinGetUtilWrapper.WinGetMergeInstallerMetadataOptions.WinGetMergeInstallerMetadataOptions_None); + }); + + Assert.True(File.Exists(logFilePath)); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilLog.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilLog.cs new file mode 100644 index 0000000000..635f3a4af4 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilLog.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using System.IO; + using NUnit.Framework; + + public class WinGetUtilLog + { + [Test] + public void WinGetUtil_Logging() + { + string filePath = TestCommon.GetRandomTestFile(".log"); + + // Init logging + WinGetUtilWrapper.WinGetLoggingInit(filePath); + Assert.True(File.Exists(filePath)); + + // Terminate logging + WinGetUtilWrapper.WinGetLoggingTerm(filePath); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilManifest.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilManifest.cs new file mode 100644 index 0000000000..8dee02baaf --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilManifest.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using System; + using System.IO; + using NUnit.Framework; + + public class WinGetUtilManifest + { + private IntPtr indexHandle; + + [SetUp] + public void SetUp() + { + this.indexHandle = IntPtr.Zero; + var sqliteFile = TestCommon.GetRandomTestFile(".db"); + uint majorVersion = 1; + uint minorVersion = 2; + WinGetUtilWrapper.WinGetSQLiteIndexCreate(sqliteFile, majorVersion, minorVersion, out this.indexHandle); ; + } + + [TearDown] + public void TearDown() + { + WinGetUtilWrapper.WinGetSQLiteIndexClose(this.indexHandle); + } + + [Test] + [TestCase(WinGetUtilWrapper.CreateManifestOption.NoValidation)] + [TestCase(WinGetUtilWrapper.CreateManifestOption.SchemaAndSemanticValidation)] + public void WinGetUtil_ValidateManifest_Success(WinGetUtilWrapper.CreateManifestOption createManifestOption) + { + string manifestsDir = TestCommon.GetTestDataFile(@"WinGetUtil\Manifests\Unmerged\ValidateManifest"); + string mergedManifestPath = TestCommon.GetRandomTestFile(".yaml"); + + // Create manifest + WinGetUtilWrapper.WinGetCreateManifest( + manifestsDir, + out bool succeeded, + out IntPtr manifestHandle, + out string createFailureMessage, + mergedManifestPath, + createManifestOption); + + Assert.True(succeeded); + Assert.AreNotEqual(IntPtr.Zero, manifestHandle); + Assert.IsNull(createFailureMessage); + Assert.True(File.Exists(mergedManifestPath)); + + // Validate manifest + WinGetUtilWrapper.WinGetValidateManifestV3( + manifestHandle, + indexHandle, + out WinGetUtilWrapper.ValidateManifestResultCode resultCode, + out string validateFailureMessage, + WinGetUtilWrapper.ValidateManifestOptionV2.ArpVersionValidation, + WinGetUtilWrapper.ValidateManifestOperationType.Add); + + Assert.AreEqual(WinGetUtilWrapper.ValidateManifestResultCode.Success, resultCode); + Assert.IsEmpty(validateFailureMessage); + + // Close manifest + WinGetUtilWrapper.WinGetCloseManifest(manifestHandle); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilSQLiteIndex.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilSQLiteIndex.cs new file mode 100644 index 0000000000..652d04ad97 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilSQLiteIndex.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using System; + using System.IO; + using System.Runtime.InteropServices; + using NUnit.Framework; + + public class WinGetUtilSQLiteIndex + { + private string sqlitePath; + private readonly uint majorVersion = 1; + private readonly uint minorVersion = 2; + + // Manifest example 1 + private readonly string addManifestsFile_1 = TestCommon.GetTestDataFile(@"WinGetUtil\Manifests\Merged\WinGetUtilTest.Add.yaml"); + private readonly string updateManifestsFile_1 = TestCommon.GetTestDataFile(@"WinGetUtil\Manifests\Merged\WinGetUtilTest.Update.yaml"); + private readonly string relativePath_1 = @"manifests\a\AppInstallerTest\WinGetUtilTest\1.0.0.0\WinGetTest.yaml"; + + [SetUp] + public void SetUp() + { + this.sqlitePath = TestCommon.GetRandomTestFile(".sql"); + } + + [Test] + public void WinGetUtil_SQLiteIndex_AddManifest() + { + SQLiteIndex((indexHandle) => + { + // Add manifest + WinGetUtilWrapper.WinGetSQLiteIndexAddManifest(indexHandle, addManifestsFile_1, relativePath_1); + }); + } + + [Test] + public void WinGetUtil_SQLiteIndex_UpdateManifest_Success() + { + SQLiteIndex((indexHandle) => + { + // Add manifest + WinGetUtilWrapper.WinGetSQLiteIndexAddManifest(indexHandle, addManifestsFile_1, relativePath_1); + + // Update manifest + WinGetUtilWrapper.WinGetSQLiteIndexUpdateManifest(indexHandle, updateManifestsFile_1, relativePath_1, out bool indexModified); + Assert.True(indexModified); + }); + } + + [Test] + public void WinGetUtil_SQLiteIndex_UpdateManifest_Fail_NotFound() + { + SQLiteIndex((indexHandle) => + { + // Update non-existing manifest + Assert.Throws(() => + { + WinGetUtilWrapper.WinGetSQLiteIndexUpdateManifest(indexHandle, updateManifestsFile_1, relativePath_1, out bool indexModified); + }); + }); + } + + [Test] + public void WinGetUtil_SQLiteIndex_RemoveManifest_Success() + { + SQLiteIndex((indexHandle) => + { + // Add manifest + WinGetUtilWrapper.WinGetSQLiteIndexAddManifest(indexHandle, addManifestsFile_1, relativePath_1); + + // Remove manifest + WinGetUtilWrapper.WinGetSQLiteIndexRemoveManifest(indexHandle, addManifestsFile_1, relativePath_1); + }); + } + + [Test] + public void WinGetUtil_SQLiteIndex_RemoveManifest_Fail_NotFound() + { + SQLiteIndex((indexHandle) => + { + // Remove non-existing manifest + Assert.Throws(() => + { + WinGetUtilWrapper.WinGetSQLiteIndexRemoveManifest(indexHandle, addManifestsFile_1, relativePath_1); + }); + }); + } + + [Test] + public void WinGetUtil_SQLiteIndex_OpenClose() + { + SQLiteIndex((_) => + { + // Open + WinGetUtilWrapper.WinGetSQLiteIndexOpen(sqlitePath, out IntPtr indexHandle); + + // Add manifest + WinGetUtilWrapper.WinGetSQLiteIndexAddManifest(indexHandle, addManifestsFile_1, relativePath_1); + + // Close + WinGetUtilWrapper.WinGetSQLiteIndexClose(indexHandle); + }); + } + + [Test] + public void WinGetUtil_SQLiteIndex_CheckConsistency() + { + SQLiteIndex((indexHandle) => + { + // Add manifest + WinGetUtilWrapper.WinGetSQLiteIndexAddManifest(indexHandle, addManifestsFile_1, relativePath_1); + + // Prepare for packaging + WinGetUtilWrapper.WinGetSQLiteIndexPrepareForPackaging(indexHandle); + + // Check consistency + WinGetUtilWrapper.WinGetSQLiteIndexCheckConsistency(indexHandle, out bool succeeded); + Assert.True(succeeded); + }); + } + + /// + /// Create and close an sqlite index file. + /// + /// Function to execute. + private void SQLiteIndex(Action Execute) + { + // Create + WinGetUtilWrapper.WinGetSQLiteIndexCreate(sqlitePath, majorVersion, minorVersion, out IntPtr indexHandle); + Assert.True(File.Exists(sqlitePath)); + Assert.AreNotEqual(IntPtr.Zero, indexHandle); + + // Execute provided function + Execute(indexHandle); + + // Close + WinGetUtilWrapper.WinGetSQLiteIndexClose(indexHandle); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilWrapper.cs b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilWrapper.cs new file mode 100644 index 0000000000..a9a42749cf --- /dev/null +++ b/src/AppInstallerCLIE2ETests/WinGetUtil/WinGetUtilWrapper.cs @@ -0,0 +1,157 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace AppInstallerCLIE2ETests.WinGetUtil +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Wrapper class for WinGetUtil exports. + /// For more details about methods in this class visit WinGetUtil.h file. + /// + public class WinGetUtilWrapper + { + private const string DllName = @"WinGetUtil.dll"; + + [Flags] + public enum CreateManifestOption + { + NoValidation = 0, + SchemaValidation = 0x1, + SchemaAndSemanticValidation = 0x2, + ReturnErrorOnVerifiedPublisherFields = 0x1000, + } + + [Flags] + public enum ValidateManifestResultCode + { + Success = 0, + DependenciesValidationFailure = 0x1, + ArpVersionValidationFailure = 0x2, + InstallerValidationFailure = 0x4, + SingleManifestPackageHasDependencies = 0x10000, + MultiManifestPackageHasDependencies = 0x20000, + MissingManifestDependenciesNode = 0x40000, + NoSuitableMinVersionDependency = 0x80000, + FoundDependencyLoop = 0x100000, + InternalError = 0x1000, + } + + [Flags] + public enum ValidateManifestOptionV2 + { + None = 0, + DependenciesValidation = 0x1, + ArpVersionValidation = 0x2, + InstallerValidation = 0x4, + } + + public enum ValidateManifestOperationType + { + Add = 0, + Update = 1, + Delete = 2, + } + + public enum WinGetBeginInstallerMetadataCollectionOptions + { + WinGetBeginInstallerMetadataCollectionOption_None = 0, + WinGetBeginInstallerMetadataCollectionOption_InputIsFilePath = 0x1, + WinGetBeginInstallerMetadataCollectionOption_InputIsURI = 0x2, + }; + + public enum WinGetCompleteInstallerMetadataCollectionOptions + { + WinGetCompleteInstallerMetadataCollectionOption_None = 0, + WinGetCompleteInstallerMetadataCollectionOption_Abandon = 0x1, + }; + + public enum WinGetMergeInstallerMetadataOptions + { + WinGetMergeInstallerMetadataOptions_None = 0, + }; + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetCompareVersions(string version1, string version2, [MarshalAs(UnmanagedType.U4)] out int comparisonResult); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetDownload(string url, string filePath, [MarshalAs(UnmanagedType.LPArray)] byte[] sha26Hash, uint sha256HashLength); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetLoggingInit(string logPath); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetLoggingTerm(string logPath); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetCreateManifest( + string inputPath, + [MarshalAs(UnmanagedType.U1)] out bool succeeded, + out IntPtr manifestHandle, + [MarshalAs(UnmanagedType.BStr)] out string failureMessage, + string mergedManifestPath, + CreateManifestOption option); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetCloseManifest(IntPtr manifest); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetValidateManifestV3( + IntPtr manifestHandle, + IntPtr indexHandle, + out ValidateManifestResultCode result, + [MarshalAs(UnmanagedType.BStr)] out string failureMessage, + ValidateManifestOptionV2 option, + ValidateManifestOperationType operationType); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexCreate(string filePath, uint majorVersion, uint minorVersion, out IntPtr index); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexOpen(string filePath, out IntPtr index); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexClose(IntPtr index); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexAddManifest(IntPtr index, string manifestPath, string relativePath); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexUpdateManifest( + IntPtr index, + string manifestPath, + string relativePath, + [MarshalAs(UnmanagedType.U1)] out bool indexModified); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexRemoveManifest(IntPtr index, string manifestPath, string relativePath); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexPrepareForPackaging(IntPtr index); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetSQLiteIndexCheckConsistency(IntPtr index, [MarshalAs(UnmanagedType.U1)] out bool succeeded); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetBeginInstallerMetadataCollection( + string inputJSON, + string logFilePath, + WinGetBeginInstallerMetadataCollectionOptions options, + out IntPtr collectionHandle); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetCompleteInstallerMetadataCollection( + IntPtr collectionHandle, + string outputFilePath, + WinGetCompleteInstallerMetadataCollectionOptions options); + + [DllImport(DllName, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void WinGetMergeInstallerMetadata( + string inputJSON, + [MarshalAs(UnmanagedType.BStr)] out string outputJSON, + uint maximumOutputSizeInBytes, + string logFilePath, + WinGetMergeInstallerMetadataOptions options); + } +} diff --git a/src/IndexCreationTool/Program.cs b/src/IndexCreationTool/Program.cs index 17b5c86c19..4baef32d0a 100644 --- a/src/IndexCreationTool/Program.cs +++ b/src/IndexCreationTool/Program.cs @@ -4,8 +4,10 @@ namespace IndexCreationTool { using System; + using System.Collections.Generic; using System.Diagnostics; using System.IO; + using System.Linq; class Program { @@ -19,12 +21,19 @@ static void Main(string[] args) string appxManifestPath = string.Empty; string certPath = string.Empty; + // List of directories to include. By default, include all directories. + List includeDirList = new() { string.Empty }; + for (int i = 0; i < args.Length; i++) { if (args[i] == "-d" && ++i < args.Length) { rootDir = args[i]; } + else if (args[i] == "-i" && ++i < args.Length) + { + includeDirList = args[i].Split(",").ToList(); + } else if (args[i] == "-m" && ++i < args.Length) { appxManifestPath = args[i]; @@ -37,7 +46,7 @@ static void Main(string[] args) if (string.IsNullOrEmpty(rootDir)) { - Console.WriteLine("Usage: IndexCreationTool.exe -d [-m [-c ]]"); + Console.WriteLine("Usage: IndexCreationTool.exe -d [-i ] [-m [-c ]]"); return; } @@ -50,9 +59,13 @@ static void Main(string[] args) using (var indexHelper = WinGetUtilWrapper.Create(IndexName)) { - foreach (string file in Directory.EnumerateFiles(rootDir, "*.yaml", SearchOption.AllDirectories)) + foreach (string includeDir in includeDirList) { - indexHelper.AddManifest(file, Path.GetRelativePath(rootDir, file)); + var fullPath = Path.Combine(rootDir, includeDir); + foreach (string file in Directory.EnumerateFiles(fullPath, "*.yaml", SearchOption.AllDirectories)) + { + indexHelper.AddManifest(file, Path.GetRelativePath(rootDir, file)); + } } indexHelper.PrepareForPackaging(); }