Micro template library A library for building device drivers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

258 lines
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. }