squad_reference_scope_test.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Linux regression harness for the package-reference resolver. All identities are synthetic.
  2. // Include the implementation to exercise its private resolver without widening the public API.
  3. #include <cassert>
  4. #include <iostream>
  5. #include <openssl/sha.h>
  6. #include "../Sunrise/src/client/content/activity/activity_sdk_squad_graph_edges.cpp"
  7. namespace sunrise::middleware::crypto::sha256 {
  8. bool hash(std::span<const std::byte> input, Digest& output) noexcept {
  9. return SHA256(reinterpret_cast<const unsigned char*>(input.data()),
  10. input.size(),
  11. reinterpret_cast<unsigned char*>(output.data()))
  12. != nullptr;
  13. }
  14. } // namespace sunrise::middleware::crypto::sha256
  15. namespace squad = sunrise::client::content::activity::sdk_generation::squad_inventory;
  16. namespace topology = sunrise::client::content::activity::sdk_generation::topology_inventory;
  17. namespace detail = squad::detail;
  18. namespace tables = sunrise::middleware::content::packages::tables;
  19. struct Fixture {
  20. topology::Snapshot topology;
  21. squad::GraphSnapshot graph;
  22. std::unordered_map<detail::TargetKey, std::vector<std::uint32_t>, detail::TargetKeyHash>
  23. targets;
  24. std::unordered_map<std::uint32_t, std::uint32_t> rules;
  25. std::vector<std::vector<std::uint32_t>> scenarios{{0}, {1}};
  26. Fixture() {
  27. topology.objects.resize(2);
  28. topology.slots.resize(3);
  29. topology.slots[0].objectIndex = 0;
  30. topology.slots[0].slotType = 1;
  31. for (unsigned i = 1; i < 3; ++i) {
  32. topology.slots[i].objectIndex = i - 1;
  33. topology.slots[i].slotType = tables::kAuthoredSquadRuleSlotType;
  34. }
  35. graph.spawners.resize(1);
  36. graph.spawners[0].sourceDescriptorStatus = squad::SourceDescriptorStatus::exact;
  37. graph.spawners[0].sourceDescriptorRow = 0;
  38. graph.descriptors.resize(3);
  39. graph.descriptors[0].objectIndex = 0;
  40. graph.descriptors[0].slotIndex = 0;
  41. for (unsigned i = 1; i < 3; ++i) {
  42. auto& descriptor = graph.descriptors[i];
  43. descriptor.objectIndex = i - 1;
  44. descriptor.slotIndex = i;
  45. descriptor.configTag = 100 + i;
  46. descriptor.componentClass = tables::kAuthoredSquadRulePrimaryClass;
  47. rules.emplace(descriptor.configTag, i - 1);
  48. }
  49. targets[{123, tables::kAuthoredSquadRuleSlotType, 7}] = {1, 2};
  50. }
  51. squad::ReferenceResolutionStatus resolve(
  52. std::uint64_t raw = 123ULL
  53. | (static_cast<std::uint64_t>(tables::kAuthoredSquadRuleSlotType) << 32)
  54. | (7ULL << 48)) {
  55. std::map<detail::TargetGroup, detail::ExactTarget> exact;
  56. squad::ReferenceResolutionStatus status{};
  57. assert(detail::resolve_reference(
  58. topology, graph, 0, 0, raw, targets, rules, scenarios, exact, status));
  59. return status;
  60. }
  61. };
  62. int main() {
  63. using Status = squad::ReferenceResolutionStatus;
  64. {
  65. Fixture f;
  66. assert(f.resolve() == Status::exact);
  67. assert(f.graph.references[0].resolvedObjectRow == 0);
  68. assert(f.graph.referenceDescriptors.size() == 1);
  69. assert(f.graph.references[0].candidateDescriptors.count == 1);
  70. assert(f.graph.referenceDescriptors[0].resolvedTarget);
  71. }
  72. {
  73. Fixture f;
  74. f.graph.descriptors[2].componentClass = 0;
  75. assert(f.resolve()
  76. == Status::exact); // An unrelated scenario's wrong type cannot poison it.
  77. }
  78. {
  79. Fixture f;
  80. f.scenarios[1] = {0};
  81. assert(f.resolve() == Status::targetAmbiguous); // Keep real local ambiguity.
  82. }
  83. {
  84. Fixture f;
  85. f.scenarios[1] = {0};
  86. f.graph.descriptors[2].componentClass = 0;
  87. assert(f.resolve() == Status::targetDescriptorMismatch);
  88. }
  89. {
  90. Fixture f;
  91. f.targets.begin()->second = {2};
  92. assert(f.resolve() == Status::targetMissing); // No fallback to the arcade object.
  93. assert(f.graph.referenceDescriptors.empty());
  94. }
  95. {
  96. Fixture f;
  97. f.graph.spawners[0].sourceDescriptorStatus = squad::SourceDescriptorStatus::ambiguous;
  98. assert(f.resolve() == Status::sourceDescriptorAmbiguous);
  99. }
  100. {
  101. Fixture f;
  102. assert(f.resolve(~0ULL) == Status::invalidEncoding);
  103. }
  104. {
  105. Fixture f;
  106. f.scenarios[0] = {0, 2};
  107. f.scenarios[1] = {1, 2};
  108. assert(f.resolve()
  109. == Status::targetAmbiguous); // Shared objects retain overlapping contexts.
  110. }
  111. std::cout << "8 squad reference scope regressions passed\n";
  112. }