/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * Copyright 2012-2020 Couchbase, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include "ringbuffer.h" class Ringbuffer : public ::testing::Test { protected: // Helper function used for debugging ;) void dump_buffer(ringbuffer_t *ring) { const char *begin = (const char *)ringbuffer_get_start(ring); const char *end = begin + ringbuffer_get_size(ring); const char *rd = (const char *)ringbuffer_get_read_head(ring); const char *wr = (const char *)ringbuffer_get_write_head(ring); const char *cur; /* write head */ fprintf(stderr, " "); for (cur = begin; cur < end; cur++) { if (cur == wr) { fprintf(stderr, "w"); } else { fprintf(stderr, " "); } } fprintf(stderr, "\n"); /* the buffer contents */ fprintf(stderr, "|"); for (cur = begin; cur < end; cur++) { fprintf(stderr, "%c", *cur ? *cur : '-'); } fprintf(stderr, "|\n"); /* the read head */ fprintf(stderr, " "); for (cur = begin; cur < end; cur++) { if (cur == rd) { fprintf(stderr, "r"); } else { fprintf(stderr, " "); } } fprintf(stderr, "\n"); } }; TEST_F(Ringbuffer, basicTests) { ringbuffer_t ring; char buffer[1024]; int ii; EXPECT_NE(0, ringbuffer_initialize(&ring, 16)); EXPECT_EQ(0, ringbuffer_read(&ring, buffer, 1)); EXPECT_EQ(16, ringbuffer_write(&ring, "01234567891234567", 17)); for (ii = 0; ii < 2; ++ii) { memset(buffer, 0, sizeof(buffer)); EXPECT_EQ(16, ringbuffer_peek(&ring, buffer, 16)); EXPECT_EQ(0, memcmp(buffer, "01234567891234567", 16)); memset(buffer, 0, sizeof(buffer)); EXPECT_EQ(10, ringbuffer_peek_at(&ring, 6, buffer, 10)); EXPECT_EQ(0, memcmp(buffer, "67891234567", 10)); } EXPECT_EQ(16, ringbuffer_read(&ring, buffer, 16)); EXPECT_EQ(0, ringbuffer_read(&ring, buffer, 1)); EXPECT_EQ(16, ringbuffer_write(&ring, "01234567891234567", 17)); EXPECT_EQ(8, ringbuffer_read(&ring, buffer, 8)); EXPECT_NE(0, ringbuffer_ensure_capacity(&ring, 9)); EXPECT_EQ(32, ring.size); EXPECT_EQ(ring.root, ring.read_head); EXPECT_EQ(8, ringbuffer_read(&ring, buffer, 9)); EXPECT_EQ(0, memcmp(buffer, "89123456", 8)); ringbuffer_destruct(&ring); // wrapped_buffer_test(); // my_regression_1_test(); } TEST_F(Ringbuffer, wrappedBufferTest) { ringbuffer_t ring; char buffer[128]; EXPECT_NE(0, ringbuffer_initialize(&ring, 10)); memset(ringbuffer_get_start(&ring), 0, 10); /* w * |----------| * r */ /* put 8 chars into the buffer */ EXPECT_EQ(8, ringbuffer_write(&ring, "01234567", 8)); /* w * |01234567--| * r */ /* consume first 5 chars */ EXPECT_EQ(5, ringbuffer_read(&ring, buffer, 5)); EXPECT_EQ(0, memcmp(buffer, "01234", 5)); /* w * |-----567--| * r */ EXPECT_EQ(0, ringbuffer_is_continous(&ring, RINGBUFFER_WRITE, 5)); EXPECT_NE(0, ringbuffer_is_continous(&ring, RINGBUFFER_WRITE, 2)); /* wrapped write: write 5 more chars */ EXPECT_EQ(5, ringbuffer_write(&ring, "abcde", 5)); /* w * |cde--567ab| * r */ EXPECT_EQ(0, ringbuffer_is_continous(&ring, RINGBUFFER_READ, 7)); EXPECT_NE(0, ringbuffer_is_continous(&ring, RINGBUFFER_READ, 2)); /* wrapped read: read 6 chars */ EXPECT_EQ(6, ringbuffer_read(&ring, buffer, 6)); EXPECT_EQ(0, memcmp(buffer, "567abc", 6)); /* w * |-de-------| * r */ ringbuffer_destruct(&ring); } // This is a crash I noticed while I was debugging the tap code TEST_F(Ringbuffer, regression1) { ringbuffer_t ring; struct lcb_iovec_st iov[2]; ring.root = (char *)0x477a80; ring.read_head = (char *)0x47b0a3; ring.write_head = (char *)0x47b555; ring.size = 16384; ring.nbytes = 1202; ringbuffer_get_iov(&ring, RINGBUFFER_WRITE, iov); // up to the end EXPECT_EQ(ring.write_head, iov[0].iov_base); EXPECT_EQ(1323, iov[0].iov_len); // then from the beginning EXPECT_EQ(ring.root, iov[1].iov_base); EXPECT_EQ(13859, iov[1].iov_len); } TEST_F(Ringbuffer, replace) { ringbuffer_t rb; EXPECT_EQ(1, ringbuffer_initialize(&rb, 16)); EXPECT_TRUE(memset(rb.root, 0, rb.size) != NULL); EXPECT_EQ(8, ringbuffer_write(&rb, "01234567", 8)); EXPECT_EQ(0, memcmp(rb.root, "01234567\0\0\0\0\0\0\0\0", rb.size)); /* w * |01234567--------| * r */ EXPECT_EQ(2, ringbuffer_update(&rb, RINGBUFFER_READ, "ab", 2)); EXPECT_EQ(8, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "ab234567\0\0\0\0\0\0\0\0", rb.size)); /* w * |ab234567--------| * r */ EXPECT_EQ(2, ringbuffer_update(&rb, RINGBUFFER_WRITE, "cd", 2)); EXPECT_EQ(8, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "ab2345cd\0\0\0\0\0\0\0\0", rb.size)); /* w * |ab2345cd--------| * r */ ringbuffer_consumed(&rb, 3); EXPECT_EQ(5, rb.nbytes); EXPECT_EQ(rb.root + 3, rb.read_head); /* w * |ab2345cd--------| * r */ EXPECT_EQ(5, ringbuffer_update(&rb, RINGBUFFER_READ, "efghij", 6)); EXPECT_EQ(5, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "ab2efghi\0\0\0\0\0\0\0\0", rb.size)); /* w * |ab2efghi--------| * r */ EXPECT_EQ(5, ringbuffer_update(&rb, RINGBUFFER_WRITE, "klmnop", 6)); EXPECT_EQ(5, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "ab2klmno\0\0\0\0\0\0\0\0", rb.size)); /* w * |ab2klmno--------| * r */ EXPECT_EQ(10, ringbuffer_write(&rb, "0123456789", 10)); EXPECT_EQ(15, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "892klmno01234567", rb.size)); /* w * |892klmno01234567| * r */ EXPECT_EQ(10, ringbuffer_update(&rb, RINGBUFFER_WRITE, "abcdefghij", 10)); EXPECT_EQ(15, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "ij2klmnoabcdefgh", rb.size)); /* w * |ij2klmnoabcdefgh| * r */ ringbuffer_consumed(&rb, 6); EXPECT_EQ(9, rb.nbytes); EXPECT_EQ(rb.root + 9, rb.read_head); /* w * |ij2klmnoabcdefgh| * r */ EXPECT_EQ(8, ringbuffer_update(&rb, RINGBUFFER_READ, "12345678", 8)); EXPECT_EQ(9, rb.nbytes); EXPECT_EQ(0, memcmp(rb.root, "8j2klmnoa1234567", rb.size)); /* w * |8j2klmnoa1234567| * r */ ringbuffer_destruct(&rb); } TEST_F(Ringbuffer, memcpy) { char buffer[1024]; ringbuffer_t src, dst; EXPECT_EQ(1, ringbuffer_initialize(&src, 16)); EXPECT_EQ(8, ringbuffer_write(&src, "01234567", 8)); EXPECT_EQ(1, ringbuffer_initialize(&dst, 16)); EXPECT_EQ(0, ringbuffer_memcpy(&dst, &src, 4)); EXPECT_EQ(4, dst.nbytes); EXPECT_EQ(4, ringbuffer_read(&dst, buffer, 4)); EXPECT_EQ(0, memcmp(buffer, "0123", 4)); ringbuffer_destruct(&src); ringbuffer_destruct(&dst); }