backing_mocks.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright 2022 Nick Brassel (@tzarc)
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "gtest/gtest.h"
  4. #include "gmock/gmock.h"
  5. #include "backing_mocks.hpp"
  6. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. // Backing Store Mock implementation
  8. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. void MockBackingStore::reset_instance() {
  10. for (auto&& e : backing_storage)
  11. e.reset();
  12. locked = true;
  13. backing_erasure_count = 0;
  14. backing_max_write_count = 0;
  15. backing_total_write_count = 0;
  16. backing_init_invoke_count = 0;
  17. backing_unlock_invoke_count = 0;
  18. backing_erase_invoke_count = 0;
  19. backing_write_invoke_count = 0;
  20. backing_lock_invoke_count = 0;
  21. init_success_callback = [](std::uint64_t) { return true; };
  22. erase_success_callback = [](std::uint64_t) { return true; };
  23. unlock_success_callback = [](std::uint64_t) { return true; };
  24. write_success_callback = [](std::uint64_t, std::uint32_t) { return true; };
  25. lock_success_callback = [](std::uint64_t) { return true; };
  26. write_log.clear();
  27. }
  28. bool MockBackingStore::init(void) {
  29. ++backing_init_invoke_count;
  30. if (init_success_callback) {
  31. return init_success_callback(backing_init_invoke_count);
  32. }
  33. return true;
  34. }
  35. bool MockBackingStore::unlock(void) {
  36. ++backing_unlock_invoke_count;
  37. EXPECT_TRUE(is_locked()) << "Attempted to unlock but was not locked";
  38. locked = false;
  39. if (unlock_success_callback) {
  40. return unlock_success_callback(backing_unlock_invoke_count);
  41. }
  42. return true;
  43. }
  44. bool MockBackingStore::erase(void) {
  45. ++backing_erase_invoke_count;
  46. // Erase each slot
  47. for (std::size_t i = 0; i < backing_storage.size(); ++i) {
  48. // Drop out of erase early with failure if we need to
  49. if (erase_success_callback && !erase_success_callback(backing_erase_invoke_count)) {
  50. append_log(true);
  51. return false;
  52. }
  53. backing_storage[i].erase();
  54. }
  55. // Keep track of the erase in the write log so that we can verify during tests
  56. append_log(true);
  57. ++backing_erasure_count;
  58. return true;
  59. }
  60. bool MockBackingStore::write(uint32_t address, backing_store_int_t value) {
  61. ++backing_write_invoke_count;
  62. // precondition: value's buffer size already matches BACKING_STORE_WRITE_SIZE
  63. EXPECT_TRUE(address % BACKING_STORE_WRITE_SIZE == 0) << "Supplied address was not aligned with the backing store integral size";
  64. EXPECT_TRUE(address + BACKING_STORE_WRITE_SIZE <= WEAR_LEVELING_BACKING_SIZE) << "Address would result of out-of-bounds access";
  65. EXPECT_FALSE(is_locked()) << "Write was attempted without being unlocked first";
  66. // Drop out of write early with failure if we need to
  67. if (write_success_callback && !write_success_callback(backing_write_invoke_count, address)) {
  68. return false;
  69. }
  70. // Write the complement as we're simulating flash memory -- 0xFF means 0x00
  71. std::size_t index = address / BACKING_STORE_WRITE_SIZE;
  72. backing_storage[index].set(~value);
  73. // Keep track of the write log so that we can verify during tests
  74. append_log(address, value);
  75. // Keep track of the total number of writes into the backing store
  76. ++backing_total_write_count;
  77. return true;
  78. }
  79. bool MockBackingStore::lock(void) {
  80. ++backing_lock_invoke_count;
  81. EXPECT_FALSE(is_locked()) << "Attempted to lock but was not unlocked";
  82. locked = true;
  83. if (lock_success_callback) {
  84. return lock_success_callback(backing_lock_invoke_count);
  85. }
  86. return true;
  87. }
  88. bool MockBackingStore::read(uint32_t address, backing_store_int_t& value) const {
  89. // precondition: value's buffer size already matches BACKING_STORE_WRITE_SIZE
  90. EXPECT_TRUE(address % BACKING_STORE_WRITE_SIZE == 0) << "Supplied address was not aligned with the backing store integral size";
  91. EXPECT_TRUE(address + BACKING_STORE_WRITE_SIZE <= WEAR_LEVELING_BACKING_SIZE) << "Address would result of out-of-bounds access";
  92. // Read and take the complement as we're simulating flash memory -- 0xFF means 0x00
  93. std::size_t index = address / BACKING_STORE_WRITE_SIZE;
  94. value = ~backing_storage[index].get();
  95. return true;
  96. }
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. // Backing Implementation
  99. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  100. extern "C" bool backing_store_init(void) {
  101. return MockBackingStore::Instance().init();
  102. }
  103. extern "C" bool backing_store_unlock(void) {
  104. return MockBackingStore::Instance().unlock();
  105. }
  106. extern "C" bool backing_store_erase(void) {
  107. return MockBackingStore::Instance().erase();
  108. }
  109. extern "C" bool backing_store_write(uint32_t address, backing_store_int_t value) {
  110. return MockBackingStore::Instance().write(address, value);
  111. }
  112. extern "C" bool backing_store_lock(void) {
  113. return MockBackingStore::Instance().lock();
  114. }
  115. extern "C" bool backing_store_read(uint32_t address, backing_store_int_t* value) {
  116. return MockBackingStore::Instance().read(address, *value);
  117. }