1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 2012 Couchbase, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * pgstattuplenull9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 #include "config.h" 18 #include <gtest/gtest.h> 19 #include <libcouchbase/couchbase.h> 20 #include "ringbuffer.h" 21 22 class Ringbuffer : public ::testing::Test 23 { 24 protected: 25 // Helper function used for debugging ;) 26 void dump_buffer(ringbuffer_t *ring) { 27 const char *begin = (const char *)ringbuffer_get_start(ring); 28 const char *end = begin + ringbuffer_get_size(ring); 29 const char *rd = (const char *)ringbuffer_get_read_head(ring); 30 const char *wr = (const char *)ringbuffer_get_write_head(ring); 31 const char *cur; 32 33 /* write head */ 34 fprintf(stderr, " "); 35 for (cur = begin; cur < end; cur++) { 36 if (cur == wr) { 37 fprintf(stderr, "w"); 38 } else { 39 fprintf(stderr, " "); 40 } 41 } 42 fprintf(stderr, "\n"); 43 44 /* the buffer contents */ 45 fprintf(stderr, "|"); 46 for (cur = begin; cur < end; cur++) { 47 fprintf(stderr, "%c", *cur ? *cur : '-'); 48 } 49 fprintf(stderr, "|\n"); 50 51 /* the read head */ 52 fprintf(stderr, " "); 53 for (cur = begin; cur < end; cur++) { 54 if (cur == rd) { 55 fprintf(stderr, "r"); 56 } else { 57 fprintf(stderr, " "); 58 } 59 } 60 fprintf(stderr, "\n"); 61 } 62 }; 63 64 TEST_F(Ringbuffer, basicTests) 65 { 66 ringbuffer_t ring; 67 char buffer[1024]; 68 int ii; 69 70 EXPECT_NE(0, ringbuffer_initialize(&ring, 16)); 71 EXPECT_EQ(0, ringbuffer_read(&ring, buffer, 1)); 72 EXPECT_EQ(16, ringbuffer_write(&ring, "01234567891234567", 17)); 73 74 for (ii = 0; ii < 2; ++ii) { 75 memset(buffer, 0, sizeof(buffer)); 76 EXPECT_EQ(16, ringbuffer_peek(&ring, buffer, 16)); 77 EXPECT_EQ(0, memcmp(buffer, "01234567891234567", 16)); 78 memset(buffer, 0, sizeof(buffer)); 79 EXPECT_EQ(10, ringbuffer_peek_at(&ring, 6, buffer, 10)); 80 EXPECT_EQ(0, memcmp(buffer, "67891234567", 10)); 81 } 82 83 EXPECT_EQ(16, ringbuffer_read(&ring, buffer, 16)); 84 EXPECT_EQ(0, ringbuffer_read(&ring, buffer, 1)); 85 EXPECT_EQ(16, ringbuffer_write(&ring, "01234567891234567", 17)); 86 EXPECT_EQ(8, ringbuffer_read(&ring, buffer, 8)); 87 EXPECT_NE(0, ringbuffer_ensure_capacity(&ring, 9)); 88 EXPECT_EQ(32, ring.size); 89 EXPECT_EQ(ring.root, ring.read_head); 90 EXPECT_EQ(8, ringbuffer_read(&ring, buffer, 9)); 91 EXPECT_EQ(0, memcmp(buffer, "89123456", 8)); 92 93 ringbuffer_destruct(&ring); 94 95 // wrapped_buffer_test(); 96 // my_regression_1_test(); 97 98 } 99 100 TEST_F(Ringbuffer, wrappedBufferTest) 101 { 102 ringbuffer_t ring; 103 char buffer[128]; 104 105 EXPECT_NE(0, ringbuffer_initialize(&ring, 10)); 106 107 memset(ringbuffer_get_start(&ring), 0, 10); 108 /* w 109 * |----------| 110 * r 111 */ 112 113 /* put 8 chars into the buffer */ 114 EXPECT_EQ(8, ringbuffer_write(&ring, "01234567", 8)); 115 116 /* w 117 * |01234567--| 118 * r 119 */ 120 121 /* consume first 5 chars */ 122 EXPECT_EQ(5, ringbuffer_read(&ring, buffer, 5)); 123 EXPECT_EQ(0, memcmp(buffer, "01234", 5)); 124 125 /* w 126 * |-----567--| 127 * r 128 */ 129 EXPECT_EQ(0, ringbuffer_is_continous(&ring, RINGBUFFER_WRITE, 5)); 130 EXPECT_NE(0, ringbuffer_is_continous(&ring, RINGBUFFER_WRITE, 2)); 131 132 /* wrapped write: write 5 more chars */ 133 EXPECT_EQ(5, ringbuffer_write(&ring, "abcde", 5)); 134 135 /* w 136 * |cde--567ab| 137 * r 138 */ 139 140 EXPECT_EQ(0, ringbuffer_is_continous(&ring, RINGBUFFER_READ, 7)); 141 EXPECT_NE(0, ringbuffer_is_continous(&ring, RINGBUFFER_READ, 2)); 142 143 /* wrapped read: read 6 chars */ 144 EXPECT_EQ(6, ringbuffer_read(&ring, buffer, 6)); 145 EXPECT_EQ(0, memcmp(buffer, "567abc", 6)); 146 /* w 147 * |-de-------| 148 * r 149 */ 150 ringbuffer_destruct(&ring); 151 } 152 153 // This is a crash I noticed while I was debugging the tap code 154 TEST_F(Ringbuffer, regression1) 155 { 156 ringbuffer_t ring; 157 struct lcb_iovec_st iov[2]; 158 ring.root = (char *)0x477a80; 159 ring.read_head = (char *)0x47b0a3; 160 ring.write_head = (char *)0x47b555; 161 ring.size = 16384; 162 ring.nbytes = 1202; 163 164 ringbuffer_get_iov(&ring, RINGBUFFER_WRITE, iov); 165 // up to the end 166 EXPECT_EQ(ring.write_head, iov[0].iov_base); 167 EXPECT_EQ(1323, iov[0].iov_len); 168 169 // then from the beginning 170 EXPECT_EQ(ring.root, iov[1].iov_base); 171 EXPECT_EQ(13859, iov[1].iov_len); 172 } 173 174 TEST_F(Ringbuffer, replace) 175 { 176 ringbuffer_t rb; 177 178 EXPECT_EQ(1, ringbuffer_initialize(&rb, 16)); 179 EXPECT_TRUE(memset(rb.root, 0, rb.size) != NULL); 180 EXPECT_EQ(8, ringbuffer_write(&rb, "01234567", 8)); 181 EXPECT_EQ(0, memcmp(rb.root, "01234567\0\0\0\0\0\0\0\0", rb.size)); 182 /* w 183 * |01234567--------| 184 * r 185 */ 186 187 EXPECT_EQ(2, ringbuffer_update(&rb, RINGBUFFER_READ, "ab", 2)); 188 EXPECT_EQ(8, rb.nbytes); 189 EXPECT_EQ(0, memcmp(rb.root, "ab234567\0\0\0\0\0\0\0\0", rb.size)); 190 /* w 191 * |ab234567--------| 192 * r 193 */ 194 195 EXPECT_EQ(2, ringbuffer_update(&rb, RINGBUFFER_WRITE, "cd", 2)); 196 EXPECT_EQ(8, rb.nbytes); 197 EXPECT_EQ(0, memcmp(rb.root, "ab2345cd\0\0\0\0\0\0\0\0", rb.size)); 198 /* w 199 * |ab2345cd--------| 200 * r 201 */ 202 203 ringbuffer_consumed(&rb, 3); 204 EXPECT_EQ(5, rb.nbytes); 205 EXPECT_EQ(rb.root + 3, rb.read_head); 206 /* w 207 * |ab2345cd--------| 208 * r 209 */ 210 211 EXPECT_EQ(5, ringbuffer_update(&rb, RINGBUFFER_READ, "efghij", 6)); 212 EXPECT_EQ(5, rb.nbytes); 213 EXPECT_EQ(0, memcmp(rb.root, "ab2efghi\0\0\0\0\0\0\0\0", rb.size)); 214 /* w 215 * |ab2efghi--------| 216 * r 217 */ 218 219 EXPECT_EQ(5, ringbuffer_update(&rb, RINGBUFFER_WRITE, "klmnop", 6)); 220 EXPECT_EQ(5, rb.nbytes); 221 EXPECT_EQ(0, memcmp(rb.root, "ab2klmno\0\0\0\0\0\0\0\0", rb.size)); 222 /* w 223 * |ab2klmno--------| 224 * r 225 */ 226 227 EXPECT_EQ(10, ringbuffer_write(&rb, "0123456789", 10)); 228 EXPECT_EQ(15, rb.nbytes); 229 EXPECT_EQ(0, memcmp(rb.root, "892klmno01234567", rb.size)); 230 /* w 231 * |892klmno01234567| 232 * r 233 */ 234 235 EXPECT_EQ(10, ringbuffer_update(&rb, RINGBUFFER_WRITE, "abcdefghij", 10)); 236 EXPECT_EQ(15, rb.nbytes); 237 EXPECT_EQ(0, memcmp(rb.root, "ij2klmnoabcdefgh", rb.size)); 238 /* w 239 * |ij2klmnoabcdefgh| 240 * r 241 */ 242 243 ringbuffer_consumed(&rb, 6); 244 EXPECT_EQ(9, rb.nbytes); 245 EXPECT_EQ(rb.root + 9, rb.read_head); 246 /* w 247 * |ij2klmnoabcdefgh| 248 * r 249 */ 250 251 EXPECT_EQ(8, ringbuffer_update(&rb, RINGBUFFER_READ, "12345678", 8)); 252 EXPECT_EQ(9, rb.nbytes); 253 EXPECT_EQ(0, memcmp(rb.root, "8j2klmnoa1234567", rb.size)); 254 /* w 255 * |8j2klmnoa1234567| 256 * r 257 */ 258 ringbuffer_destruct(&rb); 259 } 260 261 TEST_F(Ringbuffer, memcpy) 262 { 263 char buffer[1024]; 264 ringbuffer_t src, dst; 265 266 EXPECT_EQ(1, ringbuffer_initialize(&src, 16)); 267 EXPECT_EQ(8, ringbuffer_write(&src, "01234567", 8)); 268 269 EXPECT_EQ(1, ringbuffer_initialize(&dst, 16)); 270 271 EXPECT_EQ(0, ringbuffer_memcpy(&dst, &src, 4)); 272 EXPECT_EQ(4, dst.nbytes); 273 EXPECT_EQ(4, ringbuffer_read(&dst, buffer, 4)); 274 EXPECT_EQ(0, memcmp(buffer, "0123", 4)); 275 276 ringbuffer_destruct(&src); 277 ringbuffer_destruct(&dst); 278 } 279