Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

168 lignes
4.7 KiB

  1. #include <string>
  2. #include <gtest/gtest.h>
  3. #include <gmock/gmock.h>
  4. #include "mariadb_mock.h"
  5. ACTION(EscapeString)
  6. {
  7. char* dst = arg0;
  8. const char* src = arg1;
  9. unsigned long len = arg2;
  10. if (len <= 0)
  11. return 0;
  12. *(dst++) = 'X';
  13. for (unsigned long i = 0; i < len; ++i)
  14. *(dst++) = *(src++);
  15. *(dst++) = 'X';
  16. return len + 2;
  17. }
  18. struct result_data
  19. : public mariadb_mock_item
  20. {
  21. using row_type = std::vector<const char *>;
  22. using data_type = std::vector<row_type>;
  23. struct internal_data_t
  24. {
  25. std::vector<char*> data;
  26. std::vector<unsigned long> length;
  27. };
  28. using interal_data_vector = std::vector<internal_data_t>;
  29. bool is_stored;
  30. ssize_t affected_rows;
  31. data_type data;
  32. interal_data_vector internal_data;
  33. template<typename T_data>
  34. result_data(T_data&& p_data, bool p_is_stored, ssize_t p_affected_rows)
  35. : data (std::forward<T_data>(p_data))
  36. , is_stored (p_is_stored)
  37. , affected_rows (p_affected_rows)
  38. {
  39. internal_data.resize(data.size());
  40. for (size_t i = 0; i < data.size(); ++i)
  41. {
  42. auto& intern = internal_data.at(i);
  43. auto& d = data.at(i);
  44. intern.data.resize(d.size());
  45. intern.length.resize(d.size());
  46. for (size_t j = 0; j < d.size(); ++j)
  47. {
  48. auto& str = d.at(j);
  49. intern.data[j] = const_cast<char*>(str);
  50. intern.length[j] = static_cast<unsigned long>(str ? strlen(str) : 0);
  51. }
  52. }
  53. }
  54. };
  55. inline MYSQL_RES* next_result()
  56. {
  57. static MYSQL_RES* value = reinterpret_cast<MYSQL_RES*>(0x1000);
  58. return ++value;
  59. }
  60. inline const result_data::data_type& empty_result_data()
  61. {
  62. static const result_data::data_type value;
  63. return value;
  64. }
  65. template<typename T_data = decltype(empty_result_data())>
  66. inline decltype(auto) result_stored(T_data&& data = empty_result_data(), ssize_t affected_rows = -1)
  67. { return result_data(std::forward<T_data>(data), true, affected_rows); }
  68. template<typename T_data = decltype(empty_result_data())>
  69. inline decltype(auto) result_used(T_data&& data = empty_result_data(), ssize_t affected_rows = -1)
  70. { return result_data(std::forward<T_data>(data), false, affected_rows); }
  71. inline decltype(auto) result_affected_rows(ssize_t affected_rows)
  72. { return result_data(empty_result_data(), true, affected_rows); }
  73. template<typename T_mock, typename T_result>
  74. inline void expect_query(T_mock& mock, const std::string& query, T_result&& result)
  75. {
  76. EXPECT_CALL(
  77. mock,
  78. mysql_real_query(
  79. reinterpret_cast<MYSQL*>(0x1111),
  80. ::testing::StrEq(query),
  81. query.size()))
  82. .InSequence(mock.sequence);
  83. auto& res = mock.store(std::forward<T_result>(result));
  84. auto ptr = next_result();
  85. if (res.is_stored)
  86. {
  87. EXPECT_CALL(
  88. mock,
  89. mysql_store_result(reinterpret_cast<MYSQL*>(0x1111)))
  90. .InSequence(mock.sequence)
  91. .WillOnce(::testing::Return(ptr));
  92. }
  93. else
  94. {
  95. EXPECT_CALL(
  96. mock,
  97. mysql_use_result(reinterpret_cast<MYSQL*>(0x1111)))
  98. .InSequence(mock.sequence)
  99. .WillOnce(::testing::Return(ptr));
  100. }
  101. if (res.affected_rows >= 0)
  102. {
  103. EXPECT_CALL(
  104. mock,
  105. mysql_affected_rows(reinterpret_cast<MYSQL*>(0x1111)))
  106. .InSequence(mock.sequence)
  107. .WillOnce(::testing::Return(static_cast<unsigned long long>(res.affected_rows)));
  108. }
  109. if (!res.data.empty())
  110. {
  111. EXPECT_CALL(
  112. mock,
  113. mysql_num_fields(ptr))
  114. .Times(::testing::AnyNumber())
  115. .WillRepeatedly(::testing::Return(res.data.at(0).size()));
  116. }
  117. for (auto& x : res.internal_data)
  118. {
  119. EXPECT_CALL(
  120. mock,
  121. mysql_fetch_row(ptr))
  122. .InSequence(mock.sequence)
  123. .WillOnce(::testing::Return(x.data.data()));
  124. EXPECT_CALL(
  125. mock,
  126. mysql_fetch_lengths(ptr))
  127. .InSequence(mock.sequence)
  128. .WillOnce(::testing::Return(x.length.data()));
  129. }
  130. if (!res.is_stored)
  131. {
  132. EXPECT_CALL(
  133. mock,
  134. mysql_fetch_row(ptr))
  135. .InSequence(mock.sequence)
  136. .WillOnce(::testing::Return(nullptr));
  137. }
  138. EXPECT_CALL(
  139. mock,
  140. mysql_free_result(ptr))
  141. .InSequence(mock.sequence);
  142. }
  143. template<typename T_mock>
  144. inline void expect_query(T_mock& mock, const std::string& query)
  145. { expect_query(mock, query, result_stored()); }