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