#include <iostream>
#include <chrono>
#include <future>
#include <thread>
#include <condition_variable>
#include "gtest/gtest.h"
#define SRT_TEST_CIRCULAR_BUFFER
#include "api.h"
#include "common.h"
using namespace std;
struct Double
{
double d;
size_t instance;
static size_t sourceid;
Double(): d(0.0)
{
instance = ++sourceid;
IF_HEAVY_LOGGING(cerr << "(Double/" << instance << ": empty costruction)\n");
}
Double(double dd): d(dd)
{
instance = ++sourceid;
IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " init construction:" << dd << ")\n");
}
Double(const Double& dd): d(dd.d)
{
instance = ++sourceid;
IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " copy construction:" << dd.d << " object/" << dd.instance << ")\n");
}
operator double() { return d; }
~Double()
{
IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " destruction:" << d << ")\n");
}
void operator=(double dd)
{
IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " copy assignment:" << d << " -> " << dd << " value)\n");
d = dd;
}
void operator=(const Double& dd)
{
IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " copy assignment:" << d << " -> " << dd.d << " object/" << dd.instance << ")\n");
d = dd.d;
}
friend bool operator==(const Double& l, double r) { return l.d == r; }
friend bool operator==(double l, const Double r) { return l == r.d; }
bool operator == (const Double& r) { return d == r; }
};
size_t Double::sourceid = 0;
template <class Val> inline
void ShowCircularBuffer(const CircularBuffer<Val>& buf)
{
cerr << "SIZE: " << buf.size() << " FREE:" << buf.spaceleft() << " BEGIN:" << buf.m_xBegin << " END: " << buf.m_xEnd << endl;
for (int i = 0; i < buf.size(); ++i)
{
Double v;
if (buf.get(i, (v)))
cerr << "[" << i << "] = " << v << endl;
else
cerr << "[" << i << "] EMPTY!\n";
}
}
struct Add
{
Double v;
Add(const Double& vv): v(vv) {}
void operator()(Double& accessed, bool isnew)
{
if (isnew)
accessed = v;
else
accessed = Double(accessed.d + v.d);
}
};
TEST(CircularBuffer, Overall)
{
using namespace std;
CircularBuffer<Double> buf(7);
cerr << dec;
buf.push(11.2);
buf.push(12.3);
buf.push(13.4);
IF_HEAVY_LOGGING(cerr << "After adding 3 elements: size=" << buf.size() << " capacity=" << buf.capacity() << ":\n");
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
ASSERT_EQ(buf.size(), 3);
IF_HEAVY_LOGGING(cerr << "Adding element at position 5:\n");
EXPECT_TRUE(buf.set(5, 15.5));
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
ASSERT_EQ(buf.size(), 6);
IF_HEAVY_LOGGING(cerr << "Adding element at position 7 (should fail):\n");
EXPECT_FALSE(buf.set(7, 10.0));
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
ASSERT_EQ(buf.size(), 6);
IF_HEAVY_LOGGING(cerr << "Dropping first 2 elements:\n");
buf.drop(2);
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
ASSERT_EQ(buf.size(), 4);
IF_HEAVY_LOGGING(cerr << "Adding again element at position 6 (should roll):\n");
buf.set(6, 22.1);
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
IF_HEAVY_LOGGING(cerr << "Adding element at existing position 2 (overwrite):\n");
buf.set(2, 33.1);
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
IF_HEAVY_LOGGING(cerr << "Adding element at existing position 3 (no overwrite):\n");
buf.set(3, 44.4, false);
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
Double output;
EXPECT_TRUE(buf.get(0, (output)));
ASSERT_EQ(output, 13.4);
EXPECT_TRUE(buf.get(2, (output)));
ASSERT_EQ(output, 33.1);
EXPECT_TRUE(buf.get(3, (output)));
ASSERT_EQ(output, 15.5);
EXPECT_TRUE(buf.get(6, (output)));
ASSERT_EQ(output, 22.1);
IF_HEAVY_LOGGING(cerr << "Dropping first 4 positions:\n");
buf.drop(4);
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
EXPECT_TRUE(buf.get(2, (output))); ASSERT_EQ(output.d, 22.1);
IF_HEAVY_LOGGING(cerr << "Pushing 1 aslong there is capacity:\n");
int i = 0;
while (buf.push(1) != -1)
{
IF_HEAVY_LOGGING(cerr << "Pushed, begin=" << buf.m_xBegin << " end=" << buf.m_xEnd << endl);
++i;
}
IF_HEAVY_LOGGING(cerr << "Done " << i << " operations, buffer:\n");
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
IF_HEAVY_LOGGING(cerr << "Updating value at position 5:\n");
EXPECT_TRUE(buf.update(5, Add(3.33)));
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
EXPECT_TRUE(buf.get(5, (output)));
ASSERT_EQ(output, 4.33);
int offset = 9;
IF_HEAVY_LOGGING(cerr << "Forced adding at position 9 with dropping (capacity: " << buf.capacity() << "):\n");
int dropshift = offset - (buf.capacity() - 1); offset -= dropshift;
IF_HEAVY_LOGGING(cerr << "Need to drop: " << dropshift << " New offset:" << offset << endl);
ASSERT_GE(dropshift, 0);
if (dropshift > 0)
{
buf.drop(dropshift);
IF_HEAVY_LOGGING(cerr << "AFTER DROPPING:\n");
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
EXPECT_TRUE(buf.set(offset, 99.1, true));
ASSERT_EQ(buf.size() - 1 + dropshift, 9);
}
else
{
IF_HEAVY_LOGGING(cerr << "NEGATIVE DROP!\n");
}
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
int size = buf.size();
IF_HEAVY_LOGGING(cerr << "Dropping rest of the items (passing " << (size) << "):\n");
buf.drop(size);
EXPECT_TRUE(buf.empty());
IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
IF_HEAVY_LOGGING(cerr << "DONE.\n");
}