TestSource.cpp (15973B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "TestCommon.h" 5 #include "TestSource.h" 6 7 using namespace AppInstaller; 8 using namespace AppInstaller::Repository; 9 10 namespace TestCommon 11 { 12 namespace 13 { 14 size_t GetNextTestPackageId() 15 { 16 static std::atomic_size_t packageId(0); 17 return ++packageId; 18 } 19 20 TestSource* GetTestSourceFromWeakPtr(const std::weak_ptr<const ISource>& weakSource) 21 { 22 if (auto source = weakSource.lock()) 23 { 24 if (auto testSource = const_cast<ISource*>(source.get())->CastTo(TestSource::SourceType)) 25 { 26 return reinterpret_cast<TestSource*>(testSource); 27 } 28 } 29 30 return nullptr; 31 } 32 } 33 34 TestPackageVersion::TestPackageVersion(const Manifest& manifest, MetadataMap installationMetadata, std::weak_ptr<const ISource> source) : 35 VersionManifest(manifest), Metadata(std::move(installationMetadata)), Source(source) {} 36 37 TestPackageVersion::TestPackageVersion(const Manifest& manifest, std::weak_ptr<const ISource> source, bool hideSystemReferenceStrings) : 38 VersionManifest(manifest), Source(source), HideSystemReferenceStrings(hideSystemReferenceStrings) {} 39 40 TestPackageVersion::LocIndString TestPackageVersion::GetProperty(PackageVersionProperty property) const 41 { 42 switch (property) 43 { 44 case PackageVersionProperty::Id: 45 return LocIndString{ VersionManifest.Id }; 46 case PackageVersionProperty::Name: 47 return LocIndString{ VersionManifest.DefaultLocalization.Get<AppInstaller::Manifest::Localization::PackageName>() }; 48 case PackageVersionProperty::Version: 49 return LocIndString{ VersionManifest.Version }; 50 case PackageVersionProperty::Channel: 51 return LocIndString{ VersionManifest.Channel }; 52 case PackageVersionProperty::SourceIdentifier: 53 return LocIndString{ Source.lock()->GetIdentifier() }; 54 case PackageVersionProperty::Publisher: 55 return LocIndString{ VersionManifest.DefaultLocalization.Get<AppInstaller::Manifest::Localization::Publisher>() }; 56 case PackageVersionProperty::ArpMinVersion: 57 return LocIndString{ VersionManifest.GetArpVersionRange().IsEmpty() ? "" : VersionManifest.GetArpVersionRange().GetMinVersion().ToString() }; 58 case PackageVersionProperty::ArpMaxVersion: 59 return LocIndString{ VersionManifest.GetArpVersionRange().IsEmpty() ? "" : VersionManifest.GetArpVersionRange().GetMaxVersion().ToString() }; 60 default: 61 return {}; 62 } 63 } 64 65 std::vector<TestPackageVersion::LocIndString> TestPackageVersion::GetMultiProperty(PackageVersionMultiProperty property) const 66 { 67 std::vector<LocIndString> result; 68 69 switch (property) 70 { 71 case PackageVersionMultiProperty::PackageFamilyName: 72 if (!HideSystemReferenceStrings) 73 { 74 for (const auto& installer : VersionManifest.Installers) 75 { 76 AddIfHasValueAndNotPresent(installer.PackageFamilyName, result, true); 77 } 78 } 79 break; 80 case PackageVersionMultiProperty::ProductCode: 81 if (!HideSystemReferenceStrings) 82 { 83 for (const auto& installer : VersionManifest.Installers) 84 { 85 bool shouldFoldCaseForNonPortable = installer.EffectiveInstallerType() != AppInstaller::Manifest::InstallerTypeEnum::Portable; 86 AddIfHasValueAndNotPresent(installer.ProductCode, result, shouldFoldCaseForNonPortable); 87 } 88 } 89 break; 90 case PackageVersionMultiProperty::Name: 91 for (auto name : VersionManifest.GetPackageNames()) 92 { 93 result.emplace_back(std::move(name)); 94 } 95 break; 96 case PackageVersionMultiProperty::Publisher: 97 for (auto publisher : VersionManifest.GetPublishers()) 98 { 99 result.emplace_back(std::move(publisher)); 100 } 101 break; 102 case PackageVersionMultiProperty::Locale: 103 result.emplace_back(VersionManifest.DefaultLocalization.Locale); 104 for (const auto& loc : VersionManifest.Localizations) 105 { 106 result.emplace_back(loc.Locale); 107 } 108 break; 109 } 110 111 return result; 112 } 113 114 TestPackageVersion::Manifest TestPackageVersion::GetManifest() 115 { 116 if (auto source = GetTestSource()) 117 { 118 source->IncrementCountOfCallsRequiringManifestData(); 119 } 120 121 return VersionManifest; 122 } 123 124 Repository::Source TestPackageVersion::GetSource() const 125 { 126 return std::const_pointer_cast<TestPackageVersion::ISource>(Source.lock()); 127 } 128 129 TestPackageVersion::MetadataMap TestPackageVersion::GetMetadata() const 130 { 131 return Metadata; 132 } 133 134 void TestPackageVersion::AddIfHasValueAndNotPresent(const Utility::NormalizedString& value, std::vector<LocIndString>& target, bool folded) 135 { 136 if (!value.empty()) 137 { 138 std::string valueString = folded ? FoldCase(value) : value; 139 auto itr = std::find(target.begin(), target.end(), valueString); 140 if (itr == target.end()) 141 { 142 target.emplace_back(std::move(valueString)); 143 } 144 } 145 } 146 147 TestSource* TestPackageVersion::GetTestSource() const 148 { 149 return GetTestSourceFromWeakPtr(Source); 150 } 151 152 TestPackage::TestPackage(const std::vector<Manifest>& available, std::weak_ptr<const ISource> source, bool hideSystemReferenceStringsOnVersion) : 153 Source(source) 154 { 155 DefaultIsSameIdentity = GetNextTestPackageId(); 156 for (const auto& manifest : available) 157 { 158 Versions.emplace_back(TestPackageVersion::Make(manifest, source, hideSystemReferenceStringsOnVersion)); 159 } 160 } 161 162 TestPackage::TestPackage(const Manifest& installed, MetadataMap installationMetadata, std::weak_ptr<const ISource> source) : 163 Source(source) 164 { 165 DefaultIsSameIdentity = GetNextTestPackageId(); 166 Versions.emplace_back(TestPackageVersion::Make(installed, std::move(installationMetadata), source)); 167 } 168 169 TestPackage::LocIndString TestPackage::GetProperty(PackageProperty property) const 170 { 171 std::shared_ptr<IPackageVersion> truth; 172 173 if (!Versions.empty()) 174 { 175 truth = Versions[0]; 176 } 177 178 if (!truth) 179 { 180 THROW_HR(E_NOT_VALID_STATE); 181 } 182 183 switch (property) 184 { 185 case PackageProperty::Id: 186 return truth->GetProperty(PackageVersionProperty::Id); 187 case PackageProperty::Name: 188 return truth->GetProperty(PackageVersionProperty::Name); 189 default: 190 return {}; 191 } 192 } 193 194 std::vector<TestPackage::LocIndString> TestPackage::GetMultiProperty(PackageMultiProperty property) const 195 { 196 std::vector<LocIndString> result; 197 PackageVersionMultiProperty mappedProperty = PackageMultiPropertyToPackageVersionMultiProperty(property); 198 199 for (const auto& version : Versions) 200 { 201 for (auto&& string : version->GetMultiProperty(mappedProperty)) 202 { 203 auto itr = std::lower_bound(result.begin(), result.end(), string); 204 205 if (itr == result.end() || *itr != string) 206 { 207 result.emplace(itr, std::move(string)); 208 } 209 } 210 } 211 212 return result; 213 } 214 215 std::vector<PackageVersionKey> TestPackage::GetVersionKeys() const 216 { 217 if (auto source = GetTestSource()) 218 { 219 source->IncrementCountOfCallsRequiringVersionData(); 220 } 221 222 std::vector<PackageVersionKey> result; 223 for (const auto& version : Versions) 224 { 225 result.emplace_back(PackageVersionKey(version->GetSource().GetIdentifier(), version->GetProperty(PackageVersionProperty::Version).get(), version->GetProperty(PackageVersionProperty::Channel).get())); 226 } 227 return result; 228 } 229 230 std::shared_ptr<IPackageVersion> TestPackage::GetLatestVersion() const 231 { 232 if (Versions.empty()) 233 { 234 return {}; 235 } 236 237 return Versions[0]; 238 } 239 240 std::shared_ptr<IPackageVersion> TestPackage::GetVersion(const PackageVersionKey& versionKey) const 241 { 242 if (!versionKey.IsDefaultLatest()) 243 { 244 if (auto source = GetTestSource()) 245 { 246 source->IncrementCountOfCallsRequiringVersionData(); 247 } 248 } 249 250 for (const auto& version : Versions) 251 { 252 if ((versionKey.Version.empty() || versionKey.Version == version->GetProperty(PackageVersionProperty::Version).get()) && 253 (versionKey.Channel.empty() || versionKey.Channel == version->GetProperty(PackageVersionProperty::Channel).get())) 254 { 255 return version; 256 } 257 } 258 259 return {}; 260 } 261 262 Repository::Source TestPackage::GetSource() const 263 { 264 return std::const_pointer_cast<TestPackage::ISource>(Source.lock()); 265 } 266 267 bool TestPackage::IsSame(const IPackage* other) const 268 { 269 if (IsSameOverride) 270 { 271 return IsSameOverride(this, other); 272 } 273 274 const TestPackage* otherPackage = PackageCast<const TestPackage*>(other); 275 276 if (otherPackage && DefaultIsSameIdentity == otherPackage->DefaultIsSameIdentity) 277 { 278 return true; 279 } 280 281 return false; 282 } 283 284 const void* TestPackage::CastTo(IPackageType type) const 285 { 286 if (type == PackageType) 287 { 288 return this; 289 } 290 291 return nullptr; 292 } 293 294 TestSource* TestPackage::GetTestSource() const 295 { 296 return GetTestSourceFromWeakPtr(Source); 297 } 298 299 TestCompositePackage::TestCompositePackage(const std::vector<Manifest>& available, std::weak_ptr<const ISource> source, bool hideSystemReferenceStringsOnVersion) 300 { 301 if (!available.empty()) 302 { 303 Available.emplace_back(TestPackage::Make(available, source, hideSystemReferenceStringsOnVersion)); 304 } 305 } 306 307 TestCompositePackage::TestCompositePackage(const Manifest& installed, MetadataMap installationMetadata, const std::vector<Manifest>& available, std::weak_ptr<const ISource> source) : 308 Installed(TestPackage::Make(installed, std::move(installationMetadata), source)) 309 { 310 if (!available.empty()) 311 { 312 Available.emplace_back(TestPackage::Make(available, source)); 313 } 314 } 315 316 TestCompositePackage::LocIndString TestCompositePackage::GetProperty(PackageProperty property) const 317 { 318 std::shared_ptr<IPackage> truth; 319 320 if (!Available.empty()) 321 { 322 truth = Available[0]; 323 } 324 else 325 { 326 truth = Installed; 327 } 328 329 if (!truth) 330 { 331 THROW_HR(E_NOT_VALID_STATE); 332 } 333 334 switch (property) 335 { 336 case PackageProperty::Id: 337 return truth->GetProperty(PackageProperty::Id); 338 case PackageProperty::Name: 339 return truth->GetProperty(PackageProperty::Name); 340 default: 341 return {}; 342 } 343 } 344 345 std::shared_ptr<AppInstaller::Repository::IPackage> TestCompositePackage::GetInstalled() 346 { 347 return Installed; 348 } 349 350 std::vector<std::shared_ptr<AppInstaller::Repository::IPackage>> TestCompositePackage::GetAvailable() 351 { 352 return { Available.begin(), Available.end() }; 353 } 354 355 const SourceDetails& TestSource::GetDetails() const 356 { 357 return Details; 358 } 359 360 const std::string& TestSource::GetIdentifier() const 361 { 362 return Details.Identifier; 363 } 364 365 SourceInformation TestSource::GetInformation() const 366 { 367 return Information; 368 } 369 370 bool TestSource::QueryFeatureFlag(SourceFeatureFlag flag) const 371 { 372 return (QueryFeatureFlagFunction ? QueryFeatureFlagFunction(flag) : false); 373 } 374 375 SearchResult TestSource::Search(const SearchRequest& request) const 376 { 377 if (SearchFunction) 378 { 379 return SearchFunction(request); 380 } 381 else 382 { 383 return {}; 384 } 385 } 386 387 void* TestSource::CastTo(AppInstaller::Repository::ISourceType type) 388 { 389 if (type == SourceType) 390 { 391 return this; 392 } 393 394 return nullptr; 395 } 396 397 void TestSource::IncrementCountOfCallsRequiringVersionData() 398 { 399 ++CountOfCallsRequiringVersionData; 400 } 401 402 void TestSource::IncrementCountOfCallsRequiringManifestData() 403 { 404 ++CountOfCallsRequiringManifestData; 405 } 406 407 std::string_view TestSourceFactory::TypeName() const 408 { 409 return "*TestSource"sv; 410 } 411 412 std::shared_ptr<ISourceReference> TestSourceFactory::Create(const SourceDetails& details) 413 { 414 std::shared_ptr<TestSourceReference> result; 415 416 if (OnOpenWithCustomHeader) 417 { 418 result = std::make_shared<TestSourceReference>(details, OnOpenWithCustomHeader); 419 } 420 else 421 { 422 result = std::make_shared<TestSourceReference>(details, OnOpen); 423 } 424 425 result->ShouldUpdateBeforeOpenResult = ShouldUpdateBeforeOpenResult; 426 427 return result; 428 } 429 430 bool TestSourceFactory::Add(SourceDetails& details, IProgressCallback&) 431 { 432 if (OnAdd) 433 { 434 OnAdd(details); 435 } 436 return true; 437 } 438 439 bool TestSourceFactory::Update(const SourceDetails& details, IProgressCallback&) 440 { 441 if (OnUpdate) 442 { 443 OnUpdate(details); 444 } 445 return true; 446 } 447 448 bool TestSourceFactory::Remove(const SourceDetails& details, IProgressCallback&) 449 { 450 if (OnRemove) 451 { 452 OnRemove(details); 453 } 454 return true; 455 } 456 457 // Make copies of self when requested. 458 TestSourceFactory::operator std::function<std::unique_ptr<ISourceFactory>()>() 459 { 460 return [this]() { return std::make_unique<TestSourceFactory>(*this); }; 461 } 462 463 bool AddSource(const AppInstaller::Repository::SourceDetails& details, AppInstaller::IProgressCallback& progress) 464 { 465 Repository::Source source{ details.Name, details.Arg, details.Type, Repository::SourceTrustLevel::None, false }; 466 return source.Add(progress); 467 } 468 469 bool UpdateSource(std::string_view name, AppInstaller::IProgressCallback& progress) 470 { 471 Repository::Source source{ name }; 472 return source.Update(progress).empty(); 473 } 474 475 bool RemoveSource(std::string_view name, AppInstaller::IProgressCallback& progress) 476 { 477 Repository::Source source{ name }; 478 return source.Remove(progress); 479 } 480 481 std::vector<AppInstaller::Repository::SourceDetails> GetSources() 482 { 483 return Repository::Source::GetCurrentSources(); 484 } 485 486 AppInstaller::Repository::Source OpenSource(std::string_view name, AppInstaller::IProgressCallback& progress) 487 { 488 Repository::Source source{ name }; 489 source.Open(progress); 490 return source; 491 } 492 493 void DropSource(std::string_view name) 494 { 495 Source::DropSource(name); 496 } 497 }