FreeRDP
TestRingBuffer.c
1 
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include <freerdp/utils/ringbuffer.h>
24 
25 static BOOL test_overlaps(void)
26 {
27  RingBuffer rb;
28  DataChunk chunks[2];
29  BYTE bytes[200];
30  int nchunks = 0;
31  int counter = 0;
32 
33  for (size_t i = 0; i < sizeof(bytes); i++)
34  bytes[i] = (BYTE)i;
35 
36  ringbuffer_init(&rb, 5);
37  if (!ringbuffer_write(&rb, bytes, 4)) /* [0123.] */
38  goto error;
39  counter += 4;
40  ringbuffer_commit_read_bytes(&rb, 2); /* [..23.] */
41 
42  if (!ringbuffer_write(&rb, &bytes[counter], 2)) /* [5.234] */
43  goto error;
44  counter += 2;
45 
46  nchunks = ringbuffer_peek(&rb, chunks, 4);
47  if (nchunks != 2 || chunks[0].size != 3 || chunks[1].size != 1)
48  goto error;
49 
50  for (int x = 0, j = 2; x < nchunks; x++)
51  {
52  for (size_t k = 0; k < chunks[x].size; k++, j++)
53  {
54  if (chunks[x].data[k] != (BYTE)j)
55  goto error;
56  }
57  }
58 
59  ringbuffer_commit_read_bytes(&rb, 3); /* [5....] */
60  if (ringbuffer_used(&rb) != 1)
61  goto error;
62 
63  if (!ringbuffer_write(&rb, &bytes[counter], 6)) /* [56789ab....] */
64  goto error;
65 
66  ringbuffer_commit_read_bytes(&rb, 6); /* [......b....] */
67  nchunks = ringbuffer_peek(&rb, chunks, 10);
68  if (nchunks != 1 || chunks[0].size != 1 || (*chunks[0].data != 0xb))
69  goto error;
70 
71  if (ringbuffer_capacity(&rb) != 5)
72  goto error;
73 
74  ringbuffer_destroy(&rb);
75  return TRUE;
76 error:
77  ringbuffer_destroy(&rb);
78  return FALSE;
79 }
80 
81 int TestRingBuffer(int argc, char* argv[])
82 {
83  RingBuffer ringBuffer;
84  int testNo = 0;
85  BYTE* tmpBuf = NULL;
86  BYTE* rb_ptr = NULL;
87  DataChunk chunks[2];
88 
89  WINPR_UNUSED(argc);
90  WINPR_UNUSED(argv);
91 
92  if (!ringbuffer_init(&ringBuffer, 10))
93  {
94  (void)fprintf(stderr, "unable to initialize ringbuffer\n");
95  return -1;
96  }
97 
98  tmpBuf = (BYTE*)malloc(50);
99  if (!tmpBuf)
100  return -1;
101 
102  for (int i = 0; i < 50; i++)
103  tmpBuf[i] = (char)i;
104 
105  (void)fprintf(stderr, "%d: basic tests...", ++testNo);
106  if (!ringbuffer_write(&ringBuffer, tmpBuf, 5) || !ringbuffer_write(&ringBuffer, tmpBuf, 5) ||
107  !ringbuffer_write(&ringBuffer, tmpBuf, 5))
108  {
109  (void)fprintf(stderr, "error when writing bytes\n");
110  return -1;
111  }
112 
113  if (ringbuffer_used(&ringBuffer) != 15)
114  {
115  (void)fprintf(stderr, "invalid used size got %" PRIuz " when I would expect 15\n",
116  ringbuffer_used(&ringBuffer));
117  return -1;
118  }
119 
120  if (ringbuffer_peek(&ringBuffer, chunks, 10) != 1 || chunks[0].size != 10)
121  {
122  (void)fprintf(stderr, "error when reading bytes\n");
123  return -1;
124  }
125  ringbuffer_commit_read_bytes(&ringBuffer, chunks[0].size);
126 
127  /* check retrieved bytes */
128  for (size_t i = 0; i < chunks[0].size; i++)
129  {
130  if (chunks[0].data[i] != i % 5)
131  {
132  (void)fprintf(stderr, "invalid byte at %d, got %" PRIu8 " instead of %d\n", i,
133  chunks[0].data[i], i % 5);
134  return -1;
135  }
136  }
137 
138  if (ringbuffer_used(&ringBuffer) != 5)
139  {
140  (void)fprintf(stderr, "invalid used size after read got %" PRIuz " when I would expect 5\n",
141  ringbuffer_used(&ringBuffer));
142  return -1;
143  }
144 
145  /* write some more bytes to have writePtr < readPtr and data splitted in 2 chunks */
146  if (!ringbuffer_write(&ringBuffer, tmpBuf, 6) ||
147  ringbuffer_peek(&ringBuffer, chunks, 11) != 2 || chunks[0].size != 10 ||
148  chunks[1].size != 1)
149  {
150  (void)fprintf(stderr, "invalid read of splitted data\n");
151  return -1;
152  }
153 
154  ringbuffer_commit_read_bytes(&ringBuffer, 11);
155  (void)fprintf(stderr, "ok\n");
156 
157  (void)fprintf(stderr, "%d: peek with nothing to read...", ++testNo);
158  if (ringbuffer_peek(&ringBuffer, chunks, 10))
159  {
160  (void)fprintf(stderr, "peek returns some chunks\n");
161  return -1;
162  }
163  (void)fprintf(stderr, "ok\n");
164 
165  (void)fprintf(stderr, "%d: ensure_linear_write / read() shouldn't grow...", ++testNo);
166  for (int i = 0; i < 1000; i++)
167  {
168  rb_ptr = ringbuffer_ensure_linear_write(&ringBuffer, 50);
169  if (!rb_ptr)
170  {
171  (void)fprintf(stderr, "ringbuffer_ensure_linear_write() error\n");
172  return -1;
173  }
174 
175  memcpy(rb_ptr, tmpBuf, 50);
176 
177  if (!ringbuffer_commit_written_bytes(&ringBuffer, 50))
178  {
179  (void)fprintf(stderr, "ringbuffer_commit_written_bytes() error, i=%d\n", i);
180  return -1;
181  }
182 
183  // ringbuffer_commit_read_bytes(&ringBuffer, 25);
184  }
185 
186  for (int i = 0; i < 1000; i++)
187  ringbuffer_commit_read_bytes(&ringBuffer, 25);
188 
189  for (int i = 0; i < 1000; i++)
190  ringbuffer_commit_read_bytes(&ringBuffer, 25);
191 
192  if (ringbuffer_capacity(&ringBuffer) != 10)
193  {
194  (void)fprintf(stderr, "not the expected capacity, have %" PRIuz " and expects 10\n",
195  ringbuffer_capacity(&ringBuffer));
196  return -1;
197  }
198  (void)fprintf(stderr, "ok\n");
199 
200  (void)fprintf(stderr, "%d: free size is correctly computed...", ++testNo);
201  for (int i = 0; i < 1000; i++)
202  {
203  ringbuffer_ensure_linear_write(&ringBuffer, 50);
204  if (!ringbuffer_commit_written_bytes(&ringBuffer, 50))
205  {
206  (void)fprintf(stderr, "ringbuffer_commit_written_bytes() error, i=%d\n", i);
207  return -1;
208  }
209  }
210  ringbuffer_commit_read_bytes(&ringBuffer, 50ULL * 1000ULL);
211  (void)fprintf(stderr, "ok\n");
212 
213  ringbuffer_destroy(&ringBuffer);
214 
215  (void)fprintf(stderr, "%d: specific overlaps test...", ++testNo);
216  if (!test_overlaps())
217  {
218  (void)fprintf(stderr, "ko\n");
219  return -1;
220  }
221  (void)fprintf(stderr, "ok\n");
222 
223  ringbuffer_destroy(&ringBuffer);
224  free(tmpBuf);
225  return 0;
226 }
a piece of data in the ring buffer, exactly like a glibc iovec
Definition: ringbuffer.h:44
ring buffer meta data
Definition: ringbuffer.h:33