NameNormalization.cpp (5914B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "TestCommon.h" 5 #include <winget/NameNormalization.h> 6 7 using namespace std::string_view_literals; 8 using namespace AppInstaller::Utility; 9 10 11 // This skipped test case can be used to update the test file. 12 // It writes back to the output content location, so you must manually 13 // copy the file(s) back to the git managed location to update. 14 TEST_CASE("NameNorm_Update_Database_Initial", "[.]") 15 { 16 std::ifstream namesStream(TestCommon::TestDataFile("InputNames.txt").GetPath()); 17 REQUIRE(namesStream); 18 std::ifstream publishersStream(TestCommon::TestDataFile("InputPublishers.txt").GetPath()); 19 REQUIRE(publishersStream); 20 std::ofstream resultsStream(TestCommon::TestDataFile("NormalizationInitialIdsUpdate.txt").GetPath(), std::ofstream::out | std::ofstream::trunc | std::ofstream::binary); 21 REQUIRE(resultsStream); 22 23 // Far larger than any one value; hopefully 24 char name[4096]{}; 25 char publisher[4096]{}; 26 27 NameNormalizer normer(NormalizationVersion::Initial); 28 29 for (;;) 30 { 31 namesStream.getline(name, ARRAYSIZE(name)); 32 publishersStream.getline(publisher, ARRAYSIZE(publisher)); 33 34 if (namesStream || publishersStream) 35 { 36 REQUIRE(namesStream); 37 REQUIRE(publishersStream); 38 39 INFO("Name[" << name << "], Publisher[" << publisher << "]"); 40 41 auto normalized = normer.Normalize(name, publisher); 42 43 std::string normalizedId = normalized.Publisher(); 44 normalizedId += '.'; 45 normalizedId += normalized.Name(); 46 47 resultsStream << normalizedId << std::endl; 48 REQUIRE(resultsStream); 49 } 50 else 51 { 52 break; 53 } 54 } 55 } 56 57 // If this test is failing, either changes to winget code or the ICU binaries have caused it. 58 // This will impact the functionality of the PreIndexedPackageSource, as it is the primary 59 // mechanism used to cross reference packages installed outside of winget with those in the 60 // source. 61 TEST_CASE("NameNorm_Database_Initial", "[name_norm]") 62 { 63 std::ifstream namesStream(TestCommon::TestDataFile("InputNames.txt").GetPath()); 64 REQUIRE(namesStream); 65 std::ifstream publishersStream(TestCommon::TestDataFile("InputPublishers.txt").GetPath()); 66 REQUIRE(publishersStream); 67 std::ifstream resultsStream(TestCommon::TestDataFile("NormalizationInitialIds.txt").GetPath()); 68 REQUIRE(resultsStream); 69 70 // Far larger than any one value; hopefully 71 char name[4096]{}; 72 char publisher[4096]{}; 73 char expectedId[4096]{}; 74 75 NameNormalizer normer(NormalizationVersion::Initial); 76 77 for (;;) 78 { 79 namesStream.getline(name, ARRAYSIZE(name)); 80 publishersStream.getline(publisher, ARRAYSIZE(publisher)); 81 resultsStream.getline(expectedId, ARRAYSIZE(expectedId)); 82 83 if (namesStream || publishersStream || resultsStream) 84 { 85 REQUIRE(namesStream); 86 REQUIRE(publishersStream); 87 REQUIRE(resultsStream); 88 89 INFO("Name[" << name << "], Publisher[" << publisher << "]"); 90 91 auto normalized = normer.Normalize(name, publisher); 92 93 std::string normalizedId = normalized.Publisher(); 94 normalizedId += '.'; 95 normalizedId += normalized.Name(); 96 97 REQUIRE(expectedId == normalizedId); 98 } 99 else 100 { 101 break; 102 } 103 } 104 } 105 106 TEST_CASE("NameNorm_Architecture", "[name_norm]") 107 { 108 NameNormalizer normer(NormalizationVersion::Initial); 109 110 REQUIRE(normer.Normalize("Name", {}).Architecture() == Architecture::Unknown); 111 REQUIRE(normer.Normalize("Name x86", {}).Architecture() == Architecture::X86); 112 REQUIRE(normer.Normalize("Name x86_64", {}).Architecture() == Architecture::X64); 113 REQUIRE(normer.Normalize("Name (64 bit)", {}).Architecture() == Architecture::X64); 114 REQUIRE(normer.Normalize("Name 32/64 bit", {}).Architecture() == Architecture::Unknown); 115 REQUIRE(normer.Normalize("Fox86", {}).Architecture() == Architecture::Unknown); 116 } 117 118 TEST_CASE("NameNorm_Locale", "[name_norm]") 119 { 120 NameNormalizer normer(NormalizationVersion::Initial); 121 122 REQUIRE(normer.Normalize("Name", {}).Locale() == ""); 123 REQUIRE(normer.Normalize("Name en-US", {}).Locale() == "en-us"); 124 REQUIRE(normer.Normalize("Name (es-mx)", {}).Locale() == "es-mx"); 125 REQUIRE(normer.Normalize("Names-mx", {}).Locale() == ""); 126 } 127 128 TEST_CASE("NameNorm_KBNumbers", "[name_norm]") 129 { 130 NameNormalizer normer(NormalizationVersion::Initial); 131 132 REQUIRE(normer.Normalize("Fix for (KB42)", {}).Name() == "FixforKB42"); 133 } 134 135 TEST_CASE("NameNorm_Initial_PreserveWhitespace", "[name_norm]") 136 { 137 NameNormalizer normer(NormalizationVersion::InitialPreserveWhiteSpace); 138 139 REQUIRE(normer.NormalizeName("Some Name").Name() == "Some Name"); 140 REQUIRE(normer.NormalizePublisher("Some Publisher Corp") == "Some Publisher"); 141 } 142 143 TEST_CASE("NameNorm_GetNormalizedName_GetNormalizedFields", "[name_norm]") 144 { 145 NameNormalizer normer(NormalizationVersion::Initial); 146 147 auto normalizedName = normer.NormalizeName("Name(X64)"); 148 REQUIRE(normalizedName.GetNormalizedName(NormalizationField::None) == "Name"); 149 REQUIRE(normalizedName.GetNormalizedName(NormalizationField::Architecture) == "Name(X64)"); 150 REQUIRE(normalizedName.GetNormalizedFields() == NormalizationField::Architecture); 151 152 auto normalizedName2 = normer.NormalizeName("Name"); 153 REQUIRE(normalizedName2.GetNormalizedName(NormalizationField::None) == "Name"); 154 REQUIRE(normalizedName2.GetNormalizedName(NormalizationField::Architecture) == "Name"); 155 REQUIRE(normalizedName2.GetNormalizedFields() == NormalizationField::None); 156 }