|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /*!
- * \file test_ostream_dev.cpp
- *
- * Copyright (C) 2018 Christos Choutouridis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include <gtest/gtest.h>
- #include <utl/dev/ostream_dev.h>
- #include <array>
-
- namespace test_ostream_dev {
- using namespace utl;
-
- // Device base data types
- // MUST be DefaultConstructible, Copyable
- using test_data_t = uint8_t;
-
- // Test data
- static const size_t SIZE = 10;
-
- test_data_t Idata = 42;
- test_data_t& IdataR = Idata;
- test_data_t&& IdataRR = 0xAA;
- test_data_t Ibuffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
- // ostream device implementer (Mocks)
- class Ostream_dev_impl : public ostream_dev<Ostream_dev_impl, test_data_t> {
- friend ostream_dev<Ostream_dev_impl, test_data_t>;
- public:
- // virtual device
- static constexpr size_t N =SIZE;
- std::array<test_data_t, N> v {}; // more than one so we can remember N-1 previous values
- size_t c {0};
-
- protected:
- // ostream_dev requirements
- size_t put_ (const test_data_t& data) {
- v[c++] = data;
- if (c >= N)
- c = 0;
- return 1;
- }
- size_t put_ (const test_data_t* data, size_t n) {
- for (size_t i=0 ; i<n && i<N; ++i) {
- v[i] = data[i];
- }
- return n;
- }
- public:
- test_data_t& getLastV () { return (c) ? v[c-1] : v[N-1]; }
- };
- // virtual ostream device
- class Ostream_vdev_impl : public ostream_dev<virtual_tag, test_data_t> {
- public:
- // virtual device
- static constexpr size_t N =SIZE;
- std::array<test_data_t, N> v {};
- size_t c {0};
-
- protected:
- // ostream_dev requirements
- size_t put_ (const test_data_t& data) {
- v[c++] = data;
- if (c >= N)
- c = 0;
- return 1;
- }
- size_t put_ (const test_data_t* data, size_t n) {
- for (size_t i=0 ; i<n && i<N; ++i) {
- v[i] = data[i];
- }
- return n;
- }
- public:
- test_data_t& getLastV () { return (c) ? v[c-1] : v[N-1]; }
- };
-
- // fixtures
- class Tostream_Idev : public ::testing::Test {
- protected:
- // zero initialized device
- Ostream_dev_impl osIdev {};
- };
- class Tostream_Vdev : public ::testing::Test {
- protected:
- // zero initialized devices
- std::array<Ostream_vdev_impl, 5> osVdev {};
- ostream_dev<virtual_tag, test_data_t> *basePointer = nullptr;
- };
-
- //ToDo: Must add Concept test for ostream_dev
- // TEST_F(Tostream_Idev, TestConcept) {
- // EXPECT_EQ(true, Ostream_dev<osIdev>);
- // }
-
- TEST_F(Tostream_Idev, Construction) {
- EXPECT_LT(0UL, sizeof(osIdev));
- }
-
- TEST_F (Tostream_Idev, Api) {
- EXPECT_EQ(1UL, osIdev.put(Idata)); // single write from var
- EXPECT_EQ(Idata, osIdev.getLastV ());
-
- EXPECT_EQ(1UL, osIdev.put(IdataR));// single write from lvalue ref
- EXPECT_EQ(IdataR, osIdev.getLastV ());
-
- EXPECT_EQ(1UL, osIdev.put(IdataRR));// single write from rvalue ref
- EXPECT_EQ(IdataRR, osIdev.getLastV ());
-
- EXPECT_EQ(1UL, osIdev.put(42));// single write from rvalue
- EXPECT_EQ(42U, osIdev.getLastV ());
-
- EXPECT_EQ(7U, osIdev.put(Ibuffer, 7)); // batch write some data
- for (size_t i =0 ; i<7 ; ++i) {
- EXPECT_EQ(Ibuffer[i], osIdev.v[i]);
- }
- EXPECT_EQ(0, osIdev.v[7]);
-
- EXPECT_EQ(SIZE, osIdev.put(Ibuffer, SIZE)); // batch write all data
- for (size_t i =0 ; i<SIZE ; ++i) {
- EXPECT_EQ(Ibuffer[i], osIdev.v[i]);
- }
- }
-
- TEST_F (Tostream_Idev, streamOperator) {
- struct Blop {
- test_data_t x, y, z;
- };
-
- osIdev << Idata; // single write from var
- EXPECT_EQ(Idata, osIdev.getLastV ());
-
- osIdev << IdataR;// single write from lvalue ref
- EXPECT_EQ(IdataR, osIdev.getLastV ());
-
- osIdev << IdataRR;// single write from rvalue ref
- EXPECT_EQ(IdataRR, osIdev.getLastV ());
-
- osIdev << (test_data_t)42; // single write from rvalue
- EXPECT_EQ(42U, osIdev.getLastV ());
-
- // stream a blop of data (should use put(T*, N) version)
- Blop blop {1, 1, 42};
- osIdev << blop;
- EXPECT_EQ(1U, osIdev.v[0]);
- EXPECT_EQ(1U, osIdev.v[1]);
- EXPECT_EQ(42U, osIdev.v[2]);
-
- const Blop cblop {2, 2, 42};
- osIdev << cblop;
- EXPECT_EQ(2U, osIdev.v[0]);
- EXPECT_EQ(2U, osIdev.v[1]);
- EXPECT_EQ(42U, osIdev.v[2]);
- }
-
- TEST_F (Tostream_Idev, Iterator1) {
- // default constructible
- Ostream_dev_impl::iterator def_it;
- EXPECT_EQ (0, *(int32_t*)&def_it); // not dereferencable
-
- // output iterator requirements
- // https://en.cppreference.com/w/cpp/named_req/OutputIterator
- auto it = osIdev.begin();
- auto it2(it);
- EXPECT_EQ (*(int32_t*)&it, *(int32_t*)&it2);
-
- it2 = it;
- EXPECT_EQ (*(int32_t*)&it, *(int32_t*)&it2);
- def_it = it;
- EXPECT_EQ (*(int32_t*)&it, *(int32_t*)&def_it);
- ++it, it++;
-
- *it = Idata;
- EXPECT_EQ (Idata, osIdev.getLastV ());
- *it = IdataR;
- EXPECT_EQ (IdataR, osIdev.getLastV ());
- *it = IdataRR;
- EXPECT_EQ (IdataRR, osIdev.getLastV ());
-
- *it++ = Idata;
- EXPECT_EQ (Idata, osIdev.getLastV ());
-
- }
-
- TEST_F (Tostream_Idev, Iterator2) {
- auto it = osIdev.begin();
-
- std::fill_n(it, SIZE, Idata);
- for (size_t i=0 ;i<SIZE ; ++i) {
- EXPECT_EQ (Idata, osIdev.v[i]);
- }
- }
-
- TEST_F (Tostream_Vdev, virtualApi) {
- // loop to virtual devices and use them via base pointer
- for (auto& dev : osVdev) {
- basePointer = &dev;
- basePointer->put(Idata);
- EXPECT_EQ(Idata, dev.v[0]);
-
- EXPECT_EQ(SIZE, basePointer->put(Ibuffer, SIZE)); // batch write all data
- for (size_t i =0 ; i<SIZE ; ++i) {
- EXPECT_EQ(Ibuffer[i], dev.v[i]);
- }
- }
- }
-
- TEST_F (Tostream_Vdev, virtualStream) {
- struct Blop {
- test_data_t x, y, z;
- };
- Blop blop {1, 1, 42};
- const Blop cblop {2, 2, 42};
-
- // loop to virtual devices and use them via base pointer
- for (auto& dev : osVdev) {
- basePointer = &dev;
- *basePointer << IdataR;
- EXPECT_EQ(IdataR, dev.v[0]);
-
- *basePointer << blop;
- EXPECT_EQ(1U, dev.v[0]);
- EXPECT_EQ(1U, dev.v[1]);
- EXPECT_EQ(42U, dev.v[2]);
-
- *basePointer << cblop;
- EXPECT_EQ(2U, dev.v[0]);
- EXPECT_EQ(2U, dev.v[1]);
- EXPECT_EQ(42U, dev.v[2]);
- }
- }
-
- TEST_F (Tostream_Vdev, virtualIterator) {
- // loop to virtual devices and use them via base pointer
- for (auto& dev : osVdev) {
- basePointer = &dev;
- auto it = *basePointer->begin();
- std::fill_n(it, SIZE, Idata);
- for (size_t i=0 ;i<SIZE ; ++i) {
- EXPECT_EQ (Idata, dev.v[i]);
- }
- }
- }
- }
|