/* * Copyright 2004 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "rtc_base/memory/fifo_buffer.h" #include #include "test/gtest.h" namespace rtc { TEST(FifoBufferTest, TestAll) { rtc::AutoThread main_thread; const size_t kSize = 16; const uint8_t in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; uint8_t out[kSize * 2]; void* p; const void* q; size_t bytes; FifoBuffer buf(kSize); // Test assumptions about base state EXPECT_EQ(SS_OPEN, buf.GetState()); int error; EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); EXPECT_TRUE(nullptr != buf.GetWriteBuffer(&bytes)); EXPECT_EQ(kSize, bytes); buf.ConsumeWriteBuffer(0); // Try a full write EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error)); EXPECT_EQ(kSize, bytes); // Try a write that should block EXPECT_EQ(SR_BLOCK, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error)); // Try a full read EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); EXPECT_EQ(kSize, bytes); EXPECT_EQ(0, memcmp(in, out, kSize)); // Try a read that should block EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); // Try a too-big write EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize * 2), bytes, error)); EXPECT_EQ(bytes, kSize); // Try a too-big read EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize * 2), bytes, error)); EXPECT_EQ(kSize, bytes); EXPECT_EQ(0, memcmp(in, out, kSize)); // Try some small writes and reads EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); // Try wraparound reads and writes in the following pattern // WWWWWWWWWWWW.... 0123456789AB.... // RRRRRRRRXXXX.... ........89AB.... // WWWW....XXXXWWWW 4567....89AB0123 // XXXX....RRRRXXXX 4567........0123 // XXXXWWWWWWWWXXXX 4567012345670123 // RRRRXXXXXXXXRRRR ....01234567.... // ....RRRRRRRR.... ................ EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize * 3 / 4), bytes, error)); EXPECT_EQ(kSize * 3 / 4, bytes); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 4), bytes, error)); EXPECT_EQ(kSize / 4, bytes); EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4)); EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); // Use GetWriteBuffer to reset the read_position for the next tests buf.GetWriteBuffer(&bytes); buf.ConsumeWriteBuffer(0); // Try using GetReadData to do a full read EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error)); q = buf.GetReadData(&bytes); EXPECT_TRUE(nullptr != q); EXPECT_EQ(kSize, bytes); EXPECT_EQ(0, memcmp(q, in, kSize)); buf.ConsumeReadData(kSize); EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); // Try using GetReadData to do some small reads EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error)); q = buf.GetReadData(&bytes); EXPECT_TRUE(nullptr != q); EXPECT_EQ(kSize, bytes); EXPECT_EQ(0, memcmp(q, in, kSize / 2)); buf.ConsumeReadData(kSize / 2); q = buf.GetReadData(&bytes); EXPECT_TRUE(nullptr != q); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(q, in + kSize / 2, kSize / 2)); buf.ConsumeReadData(kSize / 2); EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); // Try using GetReadData in a wraparound case // WWWWWWWWWWWWWWWW 0123456789ABCDEF // RRRRRRRRRRRRXXXX ............CDEF // WWWWWWWW....XXXX 01234567....CDEF // ............RRRR 01234567........ // RRRRRRRR........ ................ EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error)); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize * 3 / 4), bytes, error)); EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); q = buf.GetReadData(&bytes); EXPECT_TRUE(nullptr != q); EXPECT_EQ(kSize / 4, bytes); EXPECT_EQ(0, memcmp(q, in + kSize * 3 / 4, kSize / 4)); buf.ConsumeReadData(kSize / 4); q = buf.GetReadData(&bytes); EXPECT_TRUE(nullptr != q); EXPECT_EQ(kSize / 2, bytes); EXPECT_EQ(0, memcmp(q, in, kSize / 2)); buf.ConsumeReadData(kSize / 2); // Use GetWriteBuffer to reset the read_position for the next tests buf.GetWriteBuffer(&bytes); buf.ConsumeWriteBuffer(0); // Try using GetWriteBuffer to do a full write p = buf.GetWriteBuffer(&bytes); EXPECT_TRUE(nullptr != p); EXPECT_EQ(kSize, bytes); memcpy(p, in, kSize); buf.ConsumeWriteBuffer(kSize); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); EXPECT_EQ(kSize, bytes); EXPECT_EQ(0, memcmp(in, out, kSize)); // Try using GetWriteBuffer to do some small writes p = buf.GetWriteBuffer(&bytes); EXPECT_TRUE(nullptr != p); EXPECT_EQ(kSize, bytes); memcpy(p, in, kSize / 2); buf.ConsumeWriteBuffer(kSize / 2); p = buf.GetWriteBuffer(&bytes); EXPECT_TRUE(nullptr != p); EXPECT_EQ(kSize / 2, bytes); memcpy(p, in + kSize / 2, kSize / 2); buf.ConsumeWriteBuffer(kSize / 2); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); EXPECT_EQ(kSize, bytes); EXPECT_EQ(0, memcmp(in, out, kSize)); // Try using GetWriteBuffer in a wraparound case // WWWWWWWWWWWW.... 0123456789AB.... // RRRRRRRRXXXX.... ........89AB.... // ........XXXXWWWW ........89AB0123 // WWWW....XXXXXXXX 4567....89AB0123 // RRRR....RRRRRRRR ................ EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize * 3 / 4), bytes, error)); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); p = buf.GetWriteBuffer(&bytes); EXPECT_TRUE(nullptr != p); EXPECT_EQ(kSize / 4, bytes); memcpy(p, in, kSize / 4); buf.ConsumeWriteBuffer(kSize / 4); p = buf.GetWriteBuffer(&bytes); EXPECT_TRUE(nullptr != p); EXPECT_EQ(kSize / 2, bytes); memcpy(p, in + kSize / 4, kSize / 4); buf.ConsumeWriteBuffer(kSize / 4); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize * 3 / 4), bytes, error)); EXPECT_EQ(kSize * 3 / 4, bytes); EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4)); EXPECT_EQ(0, memcmp(in, out + kSize / 4, kSize / 4)); // Check that the stream is now empty EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error)); // Write to the stream, close it, read the remaining bytes EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); buf.Close(); EXPECT_EQ(SS_CLOSED, buf.GetState()); EXPECT_EQ(SR_EOS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error)); EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); EXPECT_EQ(0, memcmp(in, out, kSize / 2)); EXPECT_EQ(SR_EOS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error)); } TEST(FifoBufferTest, FullBufferCheck) { rtc::AutoThread main_thread; FifoBuffer buff(10); buff.ConsumeWriteBuffer(10); size_t free; EXPECT_TRUE(buff.GetWriteBuffer(&free) != nullptr); EXPECT_EQ(0U, free); } } // namespace rtc