opcode406_item_state_regression_tests.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #include <array>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <cstdio>
  5. #include <span>
  6. #include "middleware/web_service/messages/opcode406.h"
  7. extern int failures;
  8. namespace {
  9. namespace opcode406 = sunrise::middleware::web_service::messages::opcode406;
  10. void expect(bool value, const char* label) noexcept {
  11. if (!value) {
  12. std::fprintf(stderr, "FAIL %s\n", label);
  13. ++failures;
  14. }
  15. }
  16. void write_bits(std::span<std::byte> output,
  17. std::size_t& position,
  18. std::uint64_t value,
  19. std::uint8_t width) noexcept {
  20. for (std::uint8_t index = 0; index < width; ++index) {
  21. const unsigned shift = static_cast<unsigned>(width - index - 1);
  22. const auto bit = static_cast<unsigned>((value >> shift) & 1U);
  23. const std::size_t byteIndex = position / 8;
  24. const unsigned byteShift = static_cast<unsigned>(7 - (position % 8));
  25. output[byteIndex] |= std::byte{static_cast<unsigned char>(bit << byteShift)};
  26. ++position;
  27. }
  28. }
  29. std::array<std::byte, 15> payload(std::uint32_t flags) noexcept {
  30. std::array<std::byte, 15> output{};
  31. std::size_t position = 0;
  32. write_bits(output, position, 1, 1);
  33. write_bits(output, position, 0x1234U, 64);
  34. write_bits(output, position, 1, 1);
  35. write_bits(output, position, 42, 15);
  36. write_bits(output, position, 0x80000000ULL + flags, 32);
  37. write_bits(output, position, 0, 7);
  38. return output;
  39. }
  40. } // namespace
  41. void test_opcode406_item_state() noexcept {
  42. for (std::uint32_t flags = 0; flags <= 7; ++flags) {
  43. const auto bytes = payload(flags);
  44. const sunrise::middleware::web_service::Message message{opcode406::kOpcode, 1, bytes};
  45. opcode406::Request request{};
  46. expect(opcode406::parse_request(message, request),
  47. "opcode 406 accepts known item-state bits");
  48. expect(request.instanceSoid == 0x1234U && request.definitionIndex == 42
  49. && request.flags == flags,
  50. "opcode 406 preserves known item-state bits");
  51. }
  52. const auto bytes = payload(8);
  53. const sunrise::middleware::web_service::Message message{opcode406::kOpcode, 1, bytes};
  54. opcode406::Request request{};
  55. expect(!opcode406::parse_request(message, request),
  56. "opcode 406 rejects unknown item-state bits");
  57. const auto maximumBytes = payload(0x7FFFFFFFU);
  58. const sunrise::middleware::web_service::Message maximumMessage{
  59. opcode406::kOpcode, 1, maximumBytes};
  60. opcode406::Request maximumRequest{};
  61. expect(!opcode406::parse_request(maximumMessage, maximumRequest)
  62. && maximumRequest.flags == 0x7FFFFFFFU,
  63. "opcode 406 decodes the maximum biased value without overflow");
  64. }