FileEntityTests.cpp (30527B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 4 #include "../../../util/SFSExceptionMatcher.h" 5 #include "../../../util/TestHelper.h" 6 #include "ReportingHandler.h" 7 #include "entity/FileEntity.h" 8 #include "sfsclient/AppFile.h" 9 #include "sfsclient/File.h" 10 11 #include <catch2/catch_test_macros.hpp> 12 #include <nlohmann/json.hpp> 13 14 #define TEST(...) TEST_CASE("[FileEntityTests] " __VA_ARGS__) 15 16 using namespace SFS; 17 using namespace SFS::details; 18 using namespace SFS::test; 19 using json = nlohmann::json; 20 21 // GenericFileEntity constants 22 const std::string c_fileId = "fileId"; 23 const std::string c_url = "url"; 24 const uint64_t c_size = 123; 25 const std::string c_sha1 = "sha1"; 26 const std::string c_sha256 = "sha256"; 27 28 // AppFileEntity constants 29 const std::string c_fileMoniker = "fileMoniker"; 30 const std::string c_arch = "amd64"; 31 const std::string c_applicability = "app"; 32 ApplicabilityDetailsEntity c_appDetailsEntity{{c_arch}, {c_applicability}}; 33 34 TEST("Testing FileEntity::FromJson()") 35 { 36 ReportingHandler handler; 37 handler.SetLoggingCallback(LogCallbackToTest); 38 39 SECTION("Generic File Entity") 40 { 41 std::unique_ptr<FileEntity> entity; 42 SECTION("Correct") 43 { 44 const json fileEntity = {{"FileId", c_fileId}, 45 {"Url", c_url}, 46 {"SizeInBytes", c_size}, 47 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 48 49 REQUIRE_NOTHROW(entity = FileEntity::FromJson(fileEntity, handler)); 50 REQUIRE(entity != nullptr); 51 REQUIRE(entity->GetContentType() == ContentType::Generic); 52 REQUIRE(entity->fileId == c_fileId); 53 REQUIRE(entity->url == c_url); 54 REQUIRE(entity->sizeInBytes == c_size); 55 REQUIRE(entity->hashes.size() == 2); 56 REQUIRE(entity->hashes.at("Sha1") == c_sha1); 57 REQUIRE(entity->hashes.at("Sha256") == c_sha256); 58 } 59 60 SECTION("Missing fields") 61 { 62 SECTION("Missing FileId") 63 { 64 const json fileEntity = {{"Url", c_url}, 65 {"SizeInBytes", c_size}, 66 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 67 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 68 ServiceInvalidResponse, 69 "Missing File.FileId in response"); 70 } 71 72 SECTION("Missing Url") 73 { 74 const json fileEntity = {{"FileId", c_fileId}, 75 {"SizeInBytes", c_size}, 76 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 77 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 78 ServiceInvalidResponse, 79 "Missing File.Url in response"); 80 } 81 82 SECTION("Missing SizeInBytes") 83 { 84 const json fileEntity = {{"FileId", c_fileId}, 85 {"Url", c_url}, 86 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 87 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 88 ServiceInvalidResponse, 89 "Missing File.SizeInBytes in response"); 90 } 91 92 SECTION("Missing Hashes") 93 { 94 const json fileEntity = {{"FileId", c_fileId}, {"Url", c_url}, {"SizeInBytes", c_size}}; 95 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 96 ServiceInvalidResponse, 97 "Missing File.Hashes in response"); 98 } 99 } 100 101 SECTION("Wrong types") 102 { 103 SECTION("FileId") 104 { 105 const json fileEntity = {{"FileId", 1}, 106 {"Url", c_url}, 107 {"SizeInBytes", c_size}, 108 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 109 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 110 ServiceInvalidResponse, 111 "File.FileId is not a string"); 112 } 113 114 SECTION("Url") 115 { 116 const json fileEntity = {{"FileId", c_fileId}, 117 {"Url", 1}, 118 {"SizeInBytes", c_size}, 119 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 120 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 121 ServiceInvalidResponse, 122 "File.Url is not a string"); 123 } 124 125 SECTION("SizeInBytes") 126 { 127 const json fileEntity = {{"FileId", c_fileId}, 128 {"Url", c_url}, 129 {"SizeInBytes", "size"}, 130 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 131 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 132 ServiceInvalidResponse, 133 "File.SizeInBytes is not an unsigned number"); 134 } 135 136 SECTION("Hashes not an object") 137 { 138 const json fileEntity = {{"FileId", c_fileId}, {"Url", c_url}, {"SizeInBytes", c_size}, {"Hashes", 1}}; 139 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 140 ServiceInvalidResponse, 141 "File.Hashes is not an object"); 142 } 143 144 SECTION("Hashes.Sha1") 145 { 146 const json fileEntity = {{"FileId", c_fileId}, 147 {"Url", c_url}, 148 {"SizeInBytes", c_size}, 149 {"Hashes", {{"Sha1", 1}}}}; 150 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 151 ServiceInvalidResponse, 152 "File.Hashes object value is not a string"); 153 } 154 } 155 } 156 157 SECTION("App File Entity") 158 { 159 std::unique_ptr<FileEntity> entity; 160 const json applicabilityDetails = {{"Architectures", json::array({c_arch})}, 161 {"PlatformApplicabilityForPackage", json::array({c_applicability})}}; 162 163 SECTION("Correct") 164 { 165 const json fileEntity = {{"FileId", c_fileId}, 166 {"Url", c_url}, 167 {"SizeInBytes", c_size}, 168 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 169 {"FileMoniker", c_fileMoniker}, 170 {"ApplicabilityDetails", applicabilityDetails}}; 171 172 REQUIRE_NOTHROW(entity = FileEntity::FromJson(fileEntity, handler)); 173 REQUIRE(entity != nullptr); 174 REQUIRE(entity->GetContentType() == ContentType::App); 175 REQUIRE(entity->fileId == c_fileId); 176 REQUIRE(entity->url == c_url); 177 REQUIRE(entity->sizeInBytes == c_size); 178 REQUIRE(entity->hashes.size() == 2); 179 REQUIRE(entity->hashes.at("Sha1") == c_sha1); 180 REQUIRE(entity->hashes.at("Sha256") == c_sha256); 181 182 AppFileEntity* appEntity = dynamic_cast<AppFileEntity*>(entity.get()); 183 REQUIRE(appEntity->fileMoniker == c_fileMoniker); 184 REQUIRE(appEntity->applicabilityDetails.architectures.size() == 1); 185 REQUIRE(appEntity->applicabilityDetails.architectures[0] == c_arch); 186 REQUIRE(appEntity->applicabilityDetails.platformApplicabilityForPackage.size() == 1); 187 REQUIRE(appEntity->applicabilityDetails.platformApplicabilityForPackage[0] == c_applicability); 188 } 189 190 SECTION("Missing fields") 191 { 192 SECTION("Missing ApplicabilityDetails") 193 { 194 const json fileEntity = {{"FileId", c_fileId}, 195 {"Url", c_url}, 196 {"SizeInBytes", c_size}, 197 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 198 {"FileMoniker", c_fileMoniker}}; 199 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 200 ServiceInvalidResponse, 201 "Missing File.ApplicabilityDetails in response"); 202 } 203 204 SECTION("Missing ApplicabilityDetails.Architectures") 205 { 206 const json wrongApplicabilityDetails = { 207 {"PlatformApplicabilityForPackage", json::array({c_applicability})}}; 208 const json fileEntity = {{"FileId", c_fileId}, 209 {"Url", c_url}, 210 {"SizeInBytes", c_size}, 211 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 212 {"FileMoniker", c_fileMoniker}, 213 {"ApplicabilityDetails", wrongApplicabilityDetails}}; 214 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 215 ServiceInvalidResponse, 216 "Missing File.ApplicabilityDetails.Architectures in response"); 217 } 218 219 SECTION("Missing ApplicabilityDetails.PlatformApplicabilityForPackage") 220 { 221 const json wrongApplicabilityDetails = {{"Architectures", json::array({c_arch})}}; 222 const json fileEntity = {{"FileId", c_fileId}, 223 {"Url", c_url}, 224 {"SizeInBytes", c_size}, 225 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 226 {"FileMoniker", c_fileMoniker}, 227 {"ApplicabilityDetails", wrongApplicabilityDetails}}; 228 REQUIRE_THROWS_CODE_MSG( 229 FileEntity::FromJson(fileEntity, handler), 230 ServiceInvalidResponse, 231 "Missing File.ApplicabilityDetails.PlatformApplicabilityForPackage in response"); 232 } 233 } 234 235 SECTION("Wrong types") 236 { 237 SECTION("FileMoniker") 238 { 239 const json fileEntity = {{"FileId", c_fileId}, 240 {"Url", c_url}, 241 {"SizeInBytes", c_size}, 242 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 243 {"FileMoniker", 1}, 244 {"ApplicabilityDetails", applicabilityDetails}}; 245 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 246 ServiceInvalidResponse, 247 "File.FileMoniker is not a string"); 248 } 249 250 SECTION("ApplicabilityDetails") 251 { 252 SECTION("Not an object") 253 { 254 const json fileEntity = {{"FileId", c_fileId}, 255 {"Url", c_url}, 256 {"SizeInBytes", c_size}, 257 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 258 {"FileMoniker", c_fileMoniker}, 259 {"ApplicabilityDetails", c_fileId}}; 260 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 261 ServiceInvalidResponse, 262 "File.ApplicabilityDetails is not an object"); 263 } 264 265 SECTION("Architectures is not an array") 266 { 267 const json wrongApplicabilityDetails = { 268 {"Architectures", c_fileId}, 269 {"PlatformApplicabilityForPackage", json::array({c_applicability})}}; 270 const json fileEntity = {{"FileId", c_fileId}, 271 {"Url", c_url}, 272 {"SizeInBytes", c_size}, 273 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 274 {"FileMoniker", c_fileMoniker}, 275 {"ApplicabilityDetails", wrongApplicabilityDetails}}; 276 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 277 ServiceInvalidResponse, 278 "File.ApplicabilityDetails.Architectures is not an array"); 279 } 280 281 SECTION("Architectures array value is not a string") 282 { 283 const json wrongApplicabilityDetails = { 284 {"Architectures", json::array({1})}, 285 {"PlatformApplicabilityForPackage", json::array({c_applicability})}}; 286 const json fileEntity = {{"FileId", c_fileId}, 287 {"Url", c_url}, 288 {"SizeInBytes", c_size}, 289 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 290 {"FileMoniker", c_fileMoniker}, 291 {"ApplicabilityDetails", wrongApplicabilityDetails}}; 292 REQUIRE_THROWS_CODE_MSG(FileEntity::FromJson(fileEntity, handler), 293 ServiceInvalidResponse, 294 "File.ApplicabilityDetails.Architectures array value is not a string"); 295 } 296 297 SECTION("PlatformApplicabilityForPackage is not an array") 298 { 299 const json wrongApplicabilityDetails = {{"Architectures", json::array({c_arch})}, 300 {"PlatformApplicabilityForPackage", c_fileId}}; 301 const json fileEntity = {{"FileId", c_fileId}, 302 {"Url", c_url}, 303 {"SizeInBytes", c_size}, 304 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 305 {"FileMoniker", c_fileMoniker}, 306 {"ApplicabilityDetails", wrongApplicabilityDetails}}; 307 REQUIRE_THROWS_CODE_MSG( 308 FileEntity::FromJson(fileEntity, handler), 309 ServiceInvalidResponse, 310 "File.ApplicabilityDetails.PlatformApplicabilityForPackage is not an array"); 311 } 312 313 SECTION("PlatformApplicabilityForPackage array value is not a string") 314 { 315 const json wrongApplicabilityDetails = {{"Architectures", json::array({c_arch})}, 316 {"PlatformApplicabilityForPackage", json::array({1})}}; 317 const json fileEntity = {{"FileId", c_fileId}, 318 {"Url", c_url}, 319 {"SizeInBytes", c_size}, 320 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 321 {"FileMoniker", c_fileMoniker}, 322 {"ApplicabilityDetails", wrongApplicabilityDetails}}; 323 REQUIRE_THROWS_CODE_MSG( 324 FileEntity::FromJson(fileEntity, handler), 325 ServiceInvalidResponse, 326 "File.ApplicabilityDetails.PlatformApplicabilityForPackage array value is not a string"); 327 } 328 } 329 } 330 } 331 } 332 333 TEST("Testing GenericFileEntity conversions") 334 { 335 ReportingHandler handler; 336 handler.SetLoggingCallback(LogCallbackToTest); 337 338 auto CheckFile = [&](const File& file) { 339 REQUIRE(file.GetFileId() == c_fileId); 340 REQUIRE(file.GetUrl() == c_url); 341 REQUIRE(file.GetSizeInBytes() == c_size); 342 REQUIRE(file.GetHashes().size() == 2); 343 REQUIRE(file.GetHashes().at(HashType::Sha1) == c_sha1); 344 REQUIRE(file.GetHashes().at(HashType::Sha256) == c_sha256); 345 }; 346 347 SECTION("GenericFileEntity::ToFile()") 348 { 349 SECTION("Success") 350 { 351 std::unique_ptr<FileEntity> entity = std::make_unique<GenericFileEntity>(); 352 entity->fileId = c_fileId; 353 entity->url = c_url; 354 entity->sizeInBytes = c_size; 355 entity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 356 357 auto file = GenericFileEntity::ToFile(std::move(*entity), handler); 358 CheckFile(*file); 359 } 360 361 SECTION("Wrong type") 362 { 363 std::unique_ptr<FileEntity> wrongEntity = std::make_unique<AppFileEntity>(); 364 wrongEntity->fileId = c_fileId; 365 wrongEntity->url = c_url; 366 wrongEntity->sizeInBytes = c_size; 367 wrongEntity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 368 369 REQUIRE_THROWS_CODE_MSG( 370 GenericFileEntity::ToFile(std::move(*wrongEntity), handler), 371 ServiceUnexpectedContentType, 372 R"(The service returned file "fileId" with content type [App] while the expected type was [Generic])"); 373 } 374 } 375 376 SECTION("GenericFileEntity::FileEntitiesToFileVector()") 377 { 378 SECTION("Success") 379 { 380 std::unique_ptr<FileEntity> entity = std::make_unique<GenericFileEntity>(); 381 entity->fileId = c_fileId; 382 entity->url = c_url; 383 entity->sizeInBytes = c_size; 384 entity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 385 386 FileEntities entities; 387 entities.push_back(std::move(entity)); 388 389 std::vector<File> files; 390 SECTION("1 file") 391 { 392 REQUIRE_NOTHROW(files = GenericFileEntity::FileEntitiesToFileVector(std::move(entities), handler)); 393 REQUIRE(files.size() == 1); 394 CheckFile(files[0]); 395 } 396 397 SECTION("2 files") 398 { 399 std::unique_ptr<FileEntity> entity2 = std::make_unique<GenericFileEntity>(); 400 entity2->fileId = c_fileId; 401 entity2->url = c_url; 402 entity2->sizeInBytes = c_size; 403 entity2->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 404 405 entities.push_back(std::move(entity2)); 406 REQUIRE_NOTHROW(files = GenericFileEntity::FileEntitiesToFileVector(std::move(entities), handler)); 407 REQUIRE(files.size() == 2); 408 CheckFile(files[0]); 409 CheckFile(files[1]); 410 } 411 } 412 413 SECTION("Wrong type, fails") 414 { 415 std::unique_ptr<FileEntity> wrongEntity = std::make_unique<AppFileEntity>(); 416 wrongEntity->fileId = c_fileId; 417 wrongEntity->url = c_url; 418 wrongEntity->sizeInBytes = c_size; 419 wrongEntity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 420 421 FileEntities wrongEntities; 422 wrongEntities.push_back(std::move(wrongEntity)); 423 REQUIRE_THROWS_CODE_MSG( 424 GenericFileEntity::FileEntitiesToFileVector(std::move(wrongEntities), handler), 425 ServiceUnexpectedContentType, 426 R"(The service returned file "fileId" with content type [App] while the expected type was [Generic])"); 427 } 428 } 429 } 430 431 TEST("Testing AppFileEntity conversions") 432 { 433 ReportingHandler handler; 434 handler.SetLoggingCallback(LogCallbackToTest); 435 436 auto CheckAppFile = [&](const AppFile& file) { 437 REQUIRE(file.GetFileId() == c_fileId); 438 REQUIRE(file.GetUrl() == c_url); 439 REQUIRE(file.GetSizeInBytes() == c_size); 440 REQUIRE(file.GetHashes().size() == 2); 441 REQUIRE(file.GetHashes().at(HashType::Sha1) == c_sha1); 442 REQUIRE(file.GetHashes().at(HashType::Sha256) == c_sha256); 443 REQUIRE(file.GetFileMoniker() == c_fileMoniker); 444 REQUIRE(file.GetApplicabilityDetails().GetArchitectures().size() == 1); 445 REQUIRE(file.GetApplicabilityDetails().GetArchitectures()[0] == Architecture::Amd64); 446 REQUIRE(file.GetApplicabilityDetails().GetPlatformApplicabilityForPackage().size() == 1); 447 REQUIRE(file.GetApplicabilityDetails().GetPlatformApplicabilityForPackage()[0] == c_applicability); 448 }; 449 450 SECTION("AppFileEntity::ToAppFile()") 451 { 452 SECTION("Success") 453 { 454 std::unique_ptr<FileEntity> entity = std::make_unique<AppFileEntity>(); 455 auto appEntity = dynamic_cast<AppFileEntity*>(entity.get()); 456 appEntity->fileId = c_fileId; 457 appEntity->url = c_url; 458 appEntity->sizeInBytes = c_size; 459 appEntity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 460 appEntity->fileMoniker = c_fileMoniker; 461 appEntity->applicabilityDetails = c_appDetailsEntity; 462 463 auto file = AppFileEntity::ToAppFile(std::move(*entity), handler); 464 CheckAppFile(*file); 465 } 466 467 SECTION("Wrong type") 468 { 469 std::unique_ptr<FileEntity> wrongEntity = std::make_unique<GenericFileEntity>(); 470 wrongEntity->fileId = c_fileId; 471 wrongEntity->url = c_url; 472 wrongEntity->sizeInBytes = c_size; 473 wrongEntity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 474 475 REQUIRE_THROWS_CODE_MSG( 476 AppFileEntity::ToAppFile(std::move(*wrongEntity), handler), 477 ServiceUnexpectedContentType, 478 R"(The service returned file "fileId" with content type [Generic] while the expected type was [App])"); 479 } 480 } 481 482 SECTION("Testing AppFileEntity::FileEntitiesToAppFileVector()") 483 { 484 SECTION("Success") 485 { 486 std::unique_ptr<FileEntity> entity = std::make_unique<AppFileEntity>(); 487 auto appEntity = dynamic_cast<AppFileEntity*>(entity.get()); 488 appEntity->fileId = c_fileId; 489 appEntity->url = c_url; 490 appEntity->sizeInBytes = c_size; 491 appEntity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 492 appEntity->fileMoniker = c_fileMoniker; 493 appEntity->applicabilityDetails = c_appDetailsEntity; 494 495 FileEntities entities; 496 entities.push_back(std::move(entity)); 497 498 std::vector<AppFile> files; 499 SECTION("1 file") 500 { 501 REQUIRE_NOTHROW(files = AppFileEntity::FileEntitiesToAppFileVector(std::move(entities), handler)); 502 REQUIRE(files.size() == 1); 503 CheckAppFile(files[0]); 504 } 505 506 SECTION("2 files") 507 { 508 std::unique_ptr<FileEntity> entity2 = std::make_unique<AppFileEntity>(); 509 auto appEntity2 = dynamic_cast<AppFileEntity*>(entity2.get()); 510 appEntity2->fileId = c_fileId; 511 appEntity2->url = c_url; 512 appEntity2->sizeInBytes = c_size; 513 appEntity2->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 514 appEntity2->fileMoniker = c_fileMoniker; 515 appEntity2->applicabilityDetails = c_appDetailsEntity; 516 517 entities.push_back(std::move(entity2)); 518 REQUIRE_NOTHROW(files = AppFileEntity::FileEntitiesToAppFileVector(std::move(entities), handler)); 519 REQUIRE(files.size() == 2); 520 CheckAppFile(files[0]); 521 CheckAppFile(files[1]); 522 } 523 } 524 525 SECTION("Wrong type, fails") 526 { 527 std::unique_ptr<FileEntity> wrongEntity = std::make_unique<GenericFileEntity>(); 528 wrongEntity->fileId = c_fileId; 529 wrongEntity->url = c_url; 530 wrongEntity->sizeInBytes = c_size; 531 wrongEntity->hashes = {{"Sha1", c_sha1}, {"Sha256", c_sha256}}; 532 533 FileEntities wrongEntities; 534 wrongEntities.push_back(std::move(wrongEntity)); 535 REQUIRE_THROWS_CODE_MSG( 536 AppFileEntity::FileEntitiesToAppFileVector(std::move(wrongEntities), handler), 537 ServiceUnexpectedContentType, 538 R"(The service returned file "fileId" with content type [Generic] while the expected type was [App])"); 539 } 540 } 541 } 542 543 TEST("Testing FileEntity::DownloadInfoResponseToFileEntities()") 544 { 545 ReportingHandler handler; 546 handler.SetLoggingCallback(LogCallbackToTest); 547 548 SECTION("GenericFileEntity") 549 { 550 auto CheckEntity = [&](const FileEntity& entity) { 551 REQUIRE(entity.GetContentType() == ContentType::Generic); 552 REQUIRE(entity.fileId == c_fileId); 553 REQUIRE(entity.url == c_url); 554 REQUIRE(entity.sizeInBytes == c_size); 555 REQUIRE(entity.hashes.size() == 2); 556 REQUIRE(entity.hashes.at("Sha1") == c_sha1); 557 REQUIRE(entity.hashes.at("Sha256") == c_sha256); 558 }; 559 560 SECTION("Correct") 561 { 562 const json fileJson = {{"FileId", c_fileId}, 563 {"Url", c_url}, 564 {"SizeInBytes", c_size}, 565 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}}; 566 567 SECTION("1 file") 568 { 569 const json downloadInfoResponse = json::array({fileJson}); 570 auto entities = FileEntity::DownloadInfoResponseToFileEntities(downloadInfoResponse, handler); 571 REQUIRE(entities.size() == 1); 572 REQUIRE(entities[0] != nullptr); 573 CheckEntity(*entities[0]); 574 } 575 576 SECTION("2 files") 577 { 578 const json downloadInfoResponse = json::array({fileJson, fileJson}); 579 auto entities = FileEntity::DownloadInfoResponseToFileEntities(downloadInfoResponse, handler); 580 REQUIRE(entities.size() == 2); 581 REQUIRE(entities[0] != nullptr); 582 CheckEntity(*entities[0]); 583 REQUIRE(entities[1] != nullptr); 584 CheckEntity(*entities[1]); 585 } 586 } 587 } 588 589 SECTION("AppFileEntity") 590 { 591 const json applicabilityDetails = {{"Architectures", json::array({c_arch})}, 592 {"PlatformApplicabilityForPackage", json::array({c_applicability})}}; 593 594 auto CheckEntity = [&](const AppFileEntity& entity) { 595 REQUIRE(entity.GetContentType() == ContentType::App); 596 REQUIRE(entity.fileId == c_fileId); 597 REQUIRE(entity.url == c_url); 598 REQUIRE(entity.sizeInBytes == c_size); 599 REQUIRE(entity.hashes.size() == 2); 600 REQUIRE(entity.hashes.at("Sha1") == c_sha1); 601 REQUIRE(entity.hashes.at("Sha256") == c_sha256); 602 REQUIRE(entity.fileMoniker == c_fileMoniker); 603 REQUIRE(entity.applicabilityDetails.architectures.size() == 1); 604 REQUIRE(entity.applicabilityDetails.architectures[0] == c_arch); 605 REQUIRE(entity.applicabilityDetails.platformApplicabilityForPackage.size() == 1); 606 REQUIRE(entity.applicabilityDetails.platformApplicabilityForPackage[0] == c_applicability); 607 }; 608 609 SECTION("Correct") 610 { 611 const json fileJson = {{"FileId", c_fileId}, 612 {"Url", c_url}, 613 {"SizeInBytes", c_size}, 614 {"Hashes", {{"Sha1", c_sha1}, {"Sha256", c_sha256}}}, 615 {"FileMoniker", c_fileMoniker}, 616 {"ApplicabilityDetails", applicabilityDetails}}; 617 618 SECTION("1 file") 619 { 620 const json downloadInfoResponse = json::array({fileJson}); 621 auto entities = FileEntity::DownloadInfoResponseToFileEntities(downloadInfoResponse, handler); 622 REQUIRE(entities.size() == 1); 623 REQUIRE(entities[0] != nullptr); 624 CheckEntity(dynamic_cast<AppFileEntity&>(*entities[0])); 625 } 626 627 SECTION("2 files") 628 { 629 const json downloadInfoResponse = json::array({fileJson, fileJson}); 630 auto entities = FileEntity::DownloadInfoResponseToFileEntities(downloadInfoResponse, handler); 631 REQUIRE(entities.size() == 2); 632 REQUIRE(entities[0] != nullptr); 633 CheckEntity(dynamic_cast<AppFileEntity&>(*entities[0])); 634 REQUIRE(entities[1] != nullptr); 635 CheckEntity(dynamic_cast<AppFileEntity&>(*entities[1])); 636 } 637 } 638 } 639 }