Micro template library A library for building device drivers
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.
 
 
 
 

258 lignes
7.7 KiB

  1. /*!
  2. * \file test_ostream_dev.cpp
  3. *
  4. * Copyright (C) 2018 Christos Choutouridis
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as
  8. * published by the Free Software Foundation, either version 3
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <gtest/gtest.h>
  20. #include <utl/dev/ostream_dev.h>
  21. #include <array>
  22. namespace test_ostream_dev {
  23. using namespace utl;
  24. // Device base data types
  25. // MUST be DefaultConstructible, Copyable
  26. using test_data_t = uint8_t;
  27. // Test data
  28. static const size_t SIZE = 10;
  29. test_data_t Idata = 42;
  30. test_data_t& IdataR = Idata;
  31. test_data_t&& IdataRR = 0xAA;
  32. test_data_t Ibuffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  33. // ostream device implementer (Mocks)
  34. class Ostream_dev_impl : public ostream_dev<Ostream_dev_impl, test_data_t> {
  35. friend ostream_dev<Ostream_dev_impl, test_data_t>;
  36. public:
  37. // virtual device
  38. static constexpr size_t N =SIZE;
  39. std::array<test_data_t, N> v {}; // more than one so we can remember N-1 previous values
  40. size_t c {0};
  41. protected:
  42. // ostream_dev requirements
  43. size_t put_ (const test_data_t& data) {
  44. v[c++] = data;
  45. if (c >= N)
  46. c = 0;
  47. return 1;
  48. }
  49. size_t put_ (const test_data_t* data, size_t n) {
  50. for (size_t i=0 ; i<n && i<N; ++i) {
  51. v[i] = data[i];
  52. }
  53. return n;
  54. }
  55. public:
  56. test_data_t& getLastV () { return (c) ? v[c-1] : v[N-1]; }
  57. };
  58. // virtual ostream device
  59. class Ostream_vdev_impl : public ostream_dev<virtual_tag, test_data_t> {
  60. public:
  61. // virtual device
  62. static constexpr size_t N =SIZE;
  63. std::array<test_data_t, N> v {};
  64. size_t c {0};
  65. protected:
  66. // ostream_dev requirements
  67. size_t put_ (const test_data_t& data) {
  68. v[c++] = data;
  69. if (c >= N)
  70. c = 0;
  71. return 1;
  72. }
  73. size_t put_ (const test_data_t* data, size_t n) {
  74. for (size_t i=0 ; i<n && i<N; ++i) {
  75. v[i] = data[i];
  76. }
  77. return n;
  78. }
  79. public:
  80. test_data_t& getLastV () { return (c) ? v[c-1] : v[N-1]; }
  81. };
  82. // fixtures
  83. class Tostream_Idev : public ::testing::Test {
  84. protected:
  85. // zero initialized device
  86. Ostream_dev_impl osIdev {};
  87. };
  88. class Tostream_Vdev : public ::testing::Test {
  89. protected:
  90. // zero initialized devices
  91. std::array<Ostream_vdev_impl, 5> osVdev {};
  92. ostream_dev<virtual_tag, test_data_t> *basePointer = nullptr;
  93. };
  94. //ToDo: Must add Concept test for ostream_dev
  95. // TEST_F(Tostream_Idev, TestConcept) {
  96. // EXPECT_EQ(true, Ostream_dev<osIdev>);
  97. // }
  98. TEST_F(Tostream_Idev, Construction) {
  99. EXPECT_LT(0UL, sizeof(osIdev));
  100. }
  101. TEST_F (Tostream_Idev, Api) {
  102. EXPECT_EQ(1UL, osIdev.put(Idata)); // single write from var
  103. EXPECT_EQ(Idata, osIdev.getLastV ());
  104. EXPECT_EQ(1UL, osIdev.put(IdataR));// single write from lvalue ref
  105. EXPECT_EQ(IdataR, osIdev.getLastV ());
  106. EXPECT_EQ(1UL, osIdev.put(IdataRR));// single write from rvalue ref
  107. EXPECT_EQ(IdataRR, osIdev.getLastV ());
  108. EXPECT_EQ(1UL, osIdev.put(42));// single write from rvalue
  109. EXPECT_EQ(42U, osIdev.getLastV ());
  110. EXPECT_EQ(7U, osIdev.put(Ibuffer, 7)); // batch write some data
  111. for (size_t i =0 ; i<7 ; ++i) {
  112. EXPECT_EQ(Ibuffer[i], osIdev.v[i]);
  113. }
  114. EXPECT_EQ(0, osIdev.v[7]);
  115. EXPECT_EQ(SIZE, osIdev.put(Ibuffer, SIZE)); // batch write all data
  116. for (size_t i =0 ; i<SIZE ; ++i) {
  117. EXPECT_EQ(Ibuffer[i], osIdev.v[i]);
  118. }
  119. }
  120. TEST_F (Tostream_Idev, streamOperator) {
  121. struct Blop {
  122. test_data_t x, y, z;
  123. };
  124. osIdev << Idata; // single write from var
  125. EXPECT_EQ(Idata, osIdev.getLastV ());
  126. osIdev << IdataR;// single write from lvalue ref
  127. EXPECT_EQ(IdataR, osIdev.getLastV ());
  128. osIdev << IdataRR;// single write from rvalue ref
  129. EXPECT_EQ(IdataRR, osIdev.getLastV ());
  130. osIdev << (test_data_t)42; // single write from rvalue
  131. EXPECT_EQ(42U, osIdev.getLastV ());
  132. // stream a blop of data (should use put(T*, N) version)
  133. Blop blop {1, 1, 42};
  134. osIdev << blop;
  135. EXPECT_EQ(1U, osIdev.v[0]);
  136. EXPECT_EQ(1U, osIdev.v[1]);
  137. EXPECT_EQ(42U, osIdev.v[2]);
  138. const Blop cblop {2, 2, 42};
  139. osIdev << cblop;
  140. EXPECT_EQ(2U, osIdev.v[0]);
  141. EXPECT_EQ(2U, osIdev.v[1]);
  142. EXPECT_EQ(42U, osIdev.v[2]);
  143. }
  144. TEST_F (Tostream_Idev, Iterator1) {
  145. // default constructible
  146. Ostream_dev_impl::iterator def_it;
  147. EXPECT_EQ (0, *(int32_t*)&def_it); // not dereferencable
  148. // output iterator requirements
  149. // https://en.cppreference.com/w/cpp/named_req/OutputIterator
  150. auto it = osIdev.begin();
  151. auto it2(it);
  152. EXPECT_EQ (*(int32_t*)&it, *(int32_t*)&it2);
  153. it2 = it;
  154. EXPECT_EQ (*(int32_t*)&it, *(int32_t*)&it2);
  155. def_it = it;
  156. EXPECT_EQ (*(int32_t*)&it, *(int32_t*)&def_it);
  157. ++it, it++;
  158. *it = Idata;
  159. EXPECT_EQ (Idata, osIdev.getLastV ());
  160. *it = IdataR;
  161. EXPECT_EQ (IdataR, osIdev.getLastV ());
  162. *it = IdataRR;
  163. EXPECT_EQ (IdataRR, osIdev.getLastV ());
  164. *it++ = Idata;
  165. EXPECT_EQ (Idata, osIdev.getLastV ());
  166. }
  167. TEST_F (Tostream_Idev, Iterator2) {
  168. auto it = osIdev.begin();
  169. std::fill_n(it, SIZE, Idata);
  170. for (size_t i=0 ;i<SIZE ; ++i) {
  171. EXPECT_EQ (Idata, osIdev.v[i]);
  172. }
  173. }
  174. TEST_F (Tostream_Vdev, virtualApi) {
  175. // loop to virtual devices and use them via base pointer
  176. for (auto& dev : osVdev) {
  177. basePointer = &dev;
  178. basePointer->put(Idata);
  179. EXPECT_EQ(Idata, dev.v[0]);
  180. EXPECT_EQ(SIZE, basePointer->put(Ibuffer, SIZE)); // batch write all data
  181. for (size_t i =0 ; i<SIZE ; ++i) {
  182. EXPECT_EQ(Ibuffer[i], dev.v[i]);
  183. }
  184. }
  185. }
  186. TEST_F (Tostream_Vdev, virtualStream) {
  187. struct Blop {
  188. test_data_t x, y, z;
  189. };
  190. Blop blop {1, 1, 42};
  191. const Blop cblop {2, 2, 42};
  192. // loop to virtual devices and use them via base pointer
  193. for (auto& dev : osVdev) {
  194. basePointer = &dev;
  195. *basePointer << IdataR;
  196. EXPECT_EQ(IdataR, dev.v[0]);
  197. *basePointer << blop;
  198. EXPECT_EQ(1U, dev.v[0]);
  199. EXPECT_EQ(1U, dev.v[1]);
  200. EXPECT_EQ(42U, dev.v[2]);
  201. *basePointer << cblop;
  202. EXPECT_EQ(2U, dev.v[0]);
  203. EXPECT_EQ(2U, dev.v[1]);
  204. EXPECT_EQ(42U, dev.v[2]);
  205. }
  206. }
  207. TEST_F (Tostream_Vdev, virtualIterator) {
  208. // loop to virtual devices and use them via base pointer
  209. for (auto& dev : osVdev) {
  210. basePointer = &dev;
  211. auto it = *basePointer->begin();
  212. std::fill_n(it, SIZE, Idata);
  213. for (size_t i=0 ;i<SIZE ; ++i) {
  214. EXPECT_EQ (Idata, dev.v[i]);
  215. }
  216. }
  217. }
  218. }