/** * @file SignalRingBufferGTest.cpp * @brief Unit tests for the StreamHub SignalRingBuffer (ReadSince/ReadRange). * * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and * the Development of Fusion Energy ('Fusion for Energy'). * Licensed under the EUPL, Version 1.1 or - as soon they will be approved * by the European Commission - subsequent versions of the EUPL (the "Licence") * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl * * @warning Unless required by applicable law or agreed to in writing, * software distributed under the Licence is distributed on an "AS IS" * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the Licence permissions and limitations under the Licence. */ #include "SignalRingBuffer.h" #include using StreamHub::SignalRingBuffer; using MARTe::float64; using MARTe::uint32; using MARTe::uint64; TEST(SignalRingBufferGTest, TestAllocateZeroFails) { SignalRingBuffer rb; ASSERT_FALSE(rb.Allocate(0u)); } TEST(SignalRingBufferGTest, TestReadLastNInOrder) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(8u)); for (uint32 i = 0u; i < 5u; i++) { rb.Write(static_cast(i), static_cast(10u + i)); } float64 t[10], v[10]; ASSERT_EQ(5u, rb.Read(t, v, 10u)); for (uint32 i = 0u; i < 5u; i++) { EXPECT_DOUBLE_EQ(static_cast(i), t[i]); EXPECT_DOUBLE_EQ(static_cast(10u + i), v[i]); } } TEST(SignalRingBufferGTest, TestWrapOverwritesOldest) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(4u)); for (uint32 i = 0u; i < 6u; i++) { rb.Write(static_cast(i), static_cast(i)); } ASSERT_EQ(4u, rb.Count()); EXPECT_EQ(static_cast(6u), rb.TotalWritten()); float64 t[4], v[4]; ASSERT_EQ(4u, rb.Read(t, v, 4u)); /* Oldest two (t=0,1) were overwritten */ EXPECT_DOUBLE_EQ(2.0, t[0]); EXPECT_DOUBLE_EQ(5.0, t[3]); } TEST(SignalRingBufferGTest, TestReadRangeMiddle) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(16u)); for (uint32 i = 0u; i < 10u; i++) { rb.Write(static_cast(i), static_cast(i) * 2.0); } float64 t[16], v[16]; /* [2.5, 6.5] → t = 3,4,5,6 */ ASSERT_EQ(4u, rb.ReadRange(2.5, 6.5, t, v, 16u)); EXPECT_DOUBLE_EQ(3.0, t[0]); EXPECT_DOUBLE_EQ(6.0, t[3]); EXPECT_DOUBLE_EQ(12.0, v[3]); } TEST(SignalRingBufferGTest, TestReadRangeInclusiveBounds) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(16u)); for (uint32 i = 0u; i < 10u; i++) { rb.Write(static_cast(i), 0.0); } float64 t[16], v[16]; /* Bounds are inclusive on both sides */ ASSERT_EQ(5u, rb.ReadRange(2.0, 6.0, t, v, 16u)); EXPECT_DOUBLE_EQ(2.0, t[0]); EXPECT_DOUBLE_EQ(6.0, t[4]); } TEST(SignalRingBufferGTest, TestReadRangeAfterWrap) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(4u)); for (uint32 i = 0u; i < 6u; i++) { rb.Write(static_cast(i), static_cast(i)); } float64 t[4], v[4]; /* Whole range: only retained points t=2..5 */ ASSERT_EQ(4u, rb.ReadRange(0.0, 10.0, t, v, 4u)); EXPECT_DOUBLE_EQ(2.0, t[0]); EXPECT_DOUBLE_EQ(5.0, t[3]); /* Narrow range crossing the physical wrap point */ ASSERT_EQ(1u, rb.ReadRange(3.5, 4.5, t, v, 4u)); EXPECT_DOUBLE_EQ(4.0, t[0]); } TEST(SignalRingBufferGTest, TestReadRangeInvalid) { SignalRingBuffer rb; float64 t[4], v[4]; /* Unallocated */ EXPECT_EQ(0u, rb.ReadRange(0.0, 1.0, t, v, 4u)); ASSERT_TRUE(rb.Allocate(4u)); /* Empty */ EXPECT_EQ(0u, rb.ReadRange(0.0, 1.0, t, v, 4u)); rb.Write(1.0, 1.0); /* Inverted range */ EXPECT_EQ(0u, rb.ReadRange(2.0, 1.0, t, v, 4u)); /* Disjoint range */ EXPECT_EQ(0u, rb.ReadRange(5.0, 9.0, t, v, 4u)); } TEST(SignalRingBufferGTest, TestReadRangeMaxOutCap) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(16u)); for (uint32 i = 0u; i < 10u; i++) { rb.Write(static_cast(i), 0.0); } float64 t[3], v[3]; ASSERT_EQ(3u, rb.ReadRange(0.0, 9.0, t, v, 3u)); EXPECT_DOUBLE_EQ(0.0, t[0]); EXPECT_DOUBLE_EQ(2.0, t[2]); } TEST(SignalRingBufferGTest, TestReadSinceBasic) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(8u)); uint64 cursor = 0u; float64 t[8], v[8]; for (uint32 i = 0u; i < 3u; i++) { rb.Write(static_cast(i), static_cast(i)); } ASSERT_EQ(3u, rb.ReadSince(cursor, t, v, 8u)); EXPECT_EQ(static_cast(3u), cursor); EXPECT_DOUBLE_EQ(0.0, t[0]); EXPECT_DOUBLE_EQ(2.0, t[2]); /* Nothing new */ EXPECT_EQ(0u, rb.ReadSince(cursor, t, v, 8u)); /* Two more points: only the new ones are returned */ rb.Write(3.0, 3.0); rb.Write(4.0, 4.0); ASSERT_EQ(2u, rb.ReadSince(cursor, t, v, 8u)); EXPECT_DOUBLE_EQ(3.0, t[0]); EXPECT_DOUBLE_EQ(4.0, t[1]); EXPECT_EQ(static_cast(5u), cursor); } TEST(SignalRingBufferGTest, TestReadSinceOverrunClamps) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(4u)); uint64 cursor = 0u; float64 t[8], v[8]; for (uint32 i = 0u; i < 10u; i++) { rb.Write(static_cast(i), static_cast(i)); } /* 10 written, only 4 retained: clamp to oldest available (t=6..9) */ ASSERT_EQ(4u, rb.ReadSince(cursor, t, v, 8u)); EXPECT_DOUBLE_EQ(6.0, t[0]); EXPECT_DOUBLE_EQ(9.0, t[3]); EXPECT_EQ(static_cast(10u), cursor); } TEST(SignalRingBufferGTest, TestReadSinceMaxOutChunks) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(8u)); uint64 cursor = 0u; float64 t[8], v[8]; for (uint32 i = 0u; i < 5u; i++) { rb.Write(static_cast(i), static_cast(i)); } /* Consume in chunks of 2: cursor must advance only by what was read */ ASSERT_EQ(2u, rb.ReadSince(cursor, t, v, 2u)); EXPECT_DOUBLE_EQ(0.0, t[0]); EXPECT_DOUBLE_EQ(1.0, t[1]); ASSERT_EQ(2u, rb.ReadSince(cursor, t, v, 2u)); EXPECT_DOUBLE_EQ(2.0, t[0]); EXPECT_DOUBLE_EQ(3.0, t[1]); ASSERT_EQ(1u, rb.ReadSince(cursor, t, v, 2u)); EXPECT_DOUBLE_EQ(4.0, t[0]); EXPECT_EQ(static_cast(5u), cursor); } TEST(SignalRingBufferGTest, TestReadSinceAfterReallocate) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(8u)); uint64 cursor = 0u; float64 t[8], v[8]; for (uint32 i = 0u; i < 5u; i++) { rb.Write(static_cast(i), static_cast(i)); } ASSERT_EQ(5u, rb.ReadSince(cursor, t, v, 8u)); /* Re-Allocate resets totalWritten: a stale cursor must not underflow */ ASSERT_TRUE(rb.Allocate(8u)); EXPECT_EQ(0u, rb.ReadSince(cursor, t, v, 8u)); EXPECT_EQ(static_cast(0u), cursor); rb.Write(100.0, 1.0); ASSERT_EQ(1u, rb.ReadSince(cursor, t, v, 8u)); EXPECT_DOUBLE_EQ(100.0, t[0]); } TEST(SignalRingBufferGTest, TestClear) { SignalRingBuffer rb; ASSERT_TRUE(rb.Allocate(8u)); rb.Write(1.0, 1.0); rb.Write(2.0, 2.0); rb.Clear(); EXPECT_EQ(0u, rb.Count()); float64 t[8], v[8]; EXPECT_EQ(0u, rb.Read(t, v, 8u)); }