FreeRDP
TestStream.c
1 #include <winpr/crt.h>
2 #include <winpr/print.h>
3 #include <winpr/stream.h>
4 
5 static BOOL TestStream_Verify(wStream* s, size_t mincap, size_t len, size_t pos)
6 {
7  if (Stream_Buffer(s) == NULL)
8  {
9  printf("stream buffer is null\n");
10  return FALSE;
11  }
12 
13  if (Stream_ConstPointer(s) == NULL)
14  {
15  printf("stream pointer is null\n");
16  return FALSE;
17  }
18 
19  if (Stream_PointerAs(s, BYTE) < Stream_Buffer(s))
20  {
21  printf("stream pointer (%p) or buffer (%p) is invalid\n", Stream_ConstPointer(s),
22  (void*)Stream_Buffer(s));
23  return FALSE;
24  }
25 
26  if (Stream_Capacity(s) < mincap)
27  {
28  printf("stream capacity is %" PRIuz " but minimum expected value is %" PRIuz "\n",
29  Stream_Capacity(s), mincap);
30  return FALSE;
31  }
32 
33  if (Stream_Length(s) != len)
34  {
35  printf("stream has unexpected length (%" PRIuz " instead of %" PRIuz ")\n",
36  Stream_Length(s), len);
37  return FALSE;
38  }
39 
40  if (Stream_GetPosition(s) != pos)
41  {
42  printf("stream has unexpected position (%" PRIuz " instead of %" PRIuz ")\n",
43  Stream_GetPosition(s), pos);
44  return FALSE;
45  }
46 
47  if (Stream_GetPosition(s) > Stream_Length(s))
48  {
49  printf("stream position (%" PRIuz ") exceeds length (%" PRIuz ")\n", Stream_GetPosition(s),
50  Stream_Length(s));
51  return FALSE;
52  }
53 
54  if (Stream_GetPosition(s) > Stream_Capacity(s))
55  {
56  printf("stream position (%" PRIuz ") exceeds capacity (%" PRIuz ")\n",
57  Stream_GetPosition(s), Stream_Capacity(s));
58  return FALSE;
59  }
60 
61  if (Stream_Length(s) > Stream_Capacity(s))
62  {
63  printf("stream length (%" PRIuz ") exceeds capacity (%" PRIuz ")\n", Stream_Length(s),
64  Stream_Capacity(s));
65  return FALSE;
66  }
67 
68  if (Stream_GetRemainingLength(s) != len - pos)
69  {
70  printf("stream remaining length (%" PRIuz " instead of %" PRIuz ")\n",
71  Stream_GetRemainingLength(s), len - pos);
72  return FALSE;
73  }
74 
75  return TRUE;
76 }
77 
78 static BOOL TestStream_New(void)
79 {
80  /* Test creation of a 0-size stream with no buffer */
81  wStream* s = Stream_New(NULL, 0);
82 
83  if (s)
84  return FALSE;
85  Stream_Free(s, TRUE);
86 
87  return TRUE;
88 }
89 
90 static BOOL TestStream_Static(void)
91 {
92  BYTE buffer[20] = { 0 };
93  wStream staticStream = { 0 };
94  wStream* s = &staticStream;
95  UINT16 v = 0;
96  /* Test creation of a static stream */
97  Stream_StaticInit(s, buffer, sizeof(buffer));
98  Stream_Write_UINT16(s, 0xcab1);
99  Stream_SetPosition(s, 0);
100  Stream_Read_UINT16(s, v);
101 
102  if (v != 0xcab1)
103  return FALSE;
104 
105  Stream_SetPosition(s, 0);
106  Stream_Write_UINT16(s, 1);
107 
108  if (!Stream_EnsureRemainingCapacity(s, 10)) /* we can ask for 10 bytes */
109  return FALSE;
110 
111  /* 30 is bigger than the buffer, it will be reallocated on the heap */
112  if (!Stream_EnsureRemainingCapacity(s, 30) || !s->isOwner)
113  return FALSE;
114 
115  Stream_Write_UINT16(s, 2);
116  Stream_SetPosition(s, 0);
117  Stream_Read_UINT16(s, v);
118 
119  if (v != 1)
120  return FALSE;
121 
122  Stream_Read_UINT16(s, v);
123 
124  if (v != 2)
125  return FALSE;
126 
127  // Intentional warning as the stream is not allocated.
128  // Still, Stream_Free should not release such memory, therefore this statement
129  // is required to test that.
130  WINPR_PRAGMA_DIAG_PUSH
131  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
132  Stream_Free(s, TRUE);
133  WINPR_PRAGMA_DIAG_POP
134  return TRUE;
135 }
136 
137 static BOOL TestStream_Create(size_t count, BOOL selfAlloc)
138 {
139  size_t len = 0;
140  size_t cap = 0;
141  wStream* s = NULL;
142  void* buffer = NULL;
143 
144  for (size_t i = 0; i < count; i++)
145  {
146  len = cap = i + 1;
147 
148  if (selfAlloc)
149  {
150  if (!(buffer = malloc(cap)))
151  {
152  printf("%s: failed to allocate buffer of size %" PRIuz "\n", __func__, cap);
153  goto fail;
154  }
155  }
156 
157  if (!(s = Stream_New(selfAlloc ? buffer : NULL, len)))
158  {
159  printf("%s: Stream_New failed for stream #%" PRIuz "\n", __func__, i);
160  goto fail;
161  }
162 
163  if (!TestStream_Verify(s, cap, len, 0))
164  {
165  goto fail;
166  }
167 
168  for (size_t pos = 0; pos < len; pos++)
169  {
170  Stream_SetPosition(s, pos);
171  Stream_SealLength(s);
172 
173  if (!TestStream_Verify(s, cap, pos, pos))
174  {
175  goto fail;
176  }
177  }
178 
179  if (selfAlloc)
180  {
181  memset(buffer, (BYTE)(i % 256), cap);
182 
183  if (memcmp(buffer, Stream_Buffer(s), cap) != 0)
184  {
185  printf("%s: buffer memory corruption\n", __func__);
186  goto fail;
187  }
188  }
189 
190  Stream_Free(s, buffer ? FALSE : TRUE);
191  free(buffer);
192  }
193 
194  return TRUE;
195 fail:
196  free(buffer);
197 
198  if (s)
199  {
200  Stream_Free(s, buffer ? FALSE : TRUE);
201  }
202 
203  return FALSE;
204 }
205 
206 static BOOL TestStream_Extent(UINT32 maxSize)
207 {
208  wStream* s = NULL;
209  BOOL result = FALSE;
210 
211  if (!(s = Stream_New(NULL, 1)))
212  {
213  printf("%s: Stream_New failed\n", __func__);
214  return FALSE;
215  }
216 
217  for (UINT32 i = 1; i < maxSize; i++)
218  {
219  if (i % 2)
220  {
221  if (!Stream_EnsureRemainingCapacity(s, i))
222  goto fail;
223  }
224  else
225  {
226  if (!Stream_EnsureCapacity(s, i))
227  goto fail;
228  }
229 
230  Stream_SetPosition(s, i);
231  Stream_SealLength(s);
232 
233  if (!TestStream_Verify(s, i, i, i))
234  {
235  printf("%s: failed to verify stream in iteration %" PRIu32 "\n", __func__, i);
236  goto fail;
237  }
238  }
239 
240  result = TRUE;
241 fail:
242 
243  if (s)
244  {
245  Stream_Free(s, TRUE);
246  }
247 
248  return result;
249 }
250 
251 #define Stream_Peek_UINT8_BE Stream_Peek_UINT8
252 #define Stream_Read_UINT8_BE Stream_Read_UINT8
253 #define Stream_Peek_Get_UINT8_BE Stream_Peek_Get_UINT8
254 #define Stream_Get_UINT8_BE Stream_Get_UINT8
255 #define Stream_Peek_INT8_BE Stream_Peek_INT8
256 #define Stream_Peek_Get_INT8_BE Stream_Peek_Get_INT8
257 #define Stream_Read_INT8_BE Stream_Read_INT8
258 #define Stream_Get_INT8_BE Stream_Get_INT8
259 
260 #define TestStream_PeekAndRead(_s, _r, _t) \
261  do \
262  { \
263  _t _a = 0; \
264  _t _b = 0; \
265  BYTE* _p = Stream_Buffer(_s); \
266  Stream_SetPosition(_s, 0); \
267  Stream_Peek_##_t(_s, _a); \
268  Stream_Read_##_t(_s, _b); \
269  if (_a != _b) \
270  { \
271  printf("%s: test1 " #_t "_LE failed\n", __func__); \
272  (_r) = FALSE; \
273  } \
274  Stream_Rewind(_s, sizeof(_t)); \
275  const _t _d = Stream_Peek_Get_##_t(_s); \
276  const _t _c = Stream_Get_##_t(_s); \
277  if (_c != _d) \
278  { \
279  printf("%s: test1 " #_t "_LE failed\n", __func__); \
280  (_r) = FALSE; \
281  } \
282  for (size_t _i = 0; _i < sizeof(_t); _i++) \
283  { \
284  if (((_a >> (_i * 8)) & 0xFF) != _p[_i]) \
285  { \
286  printf("%s: test2 " #_t "_LE failed\n", __func__); \
287  (_r) = FALSE; \
288  break; \
289  } \
290  } \
291  /* printf("a: 0x%016llX\n", a); */ \
292  Stream_SetPosition(_s, 0); \
293  Stream_Peek_##_t##_BE(_s, _a); \
294  Stream_Read_##_t##_BE(_s, _b); \
295  if (_a != _b) \
296  { \
297  printf("%s: test1 " #_t "_BE failed\n", __func__); \
298  (_r) = FALSE; \
299  } \
300  Stream_Rewind(_s, sizeof(_t)); \
301  const _t _e = Stream_Peek_Get_##_t##_BE(_s); \
302  const _t _f = Stream_Get_##_t##_BE(_s); \
303  if (_e != _f) \
304  { \
305  printf("%s: test1 " #_t "_BE failed\n", __func__); \
306  (_r) = FALSE; \
307  } \
308  for (size_t _i = 0; _i < sizeof(_t); _i++) \
309  { \
310  if (((_a >> (_i * 8)) & 0xFF) != _p[sizeof(_t) - _i - 1]) \
311  { \
312  printf("%s: test2 " #_t "_BE failed\n", __func__); \
313  (_r) = FALSE; \
314  break; \
315  } \
316  } \
317  /* printf("a: 0x%016llX\n", a); */ \
318  } while (0)
319 
320 static BOOL TestStream_Reading(void)
321 {
322  BYTE src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
323  wStream* s = NULL;
324  BOOL result = TRUE;
325 
326  if (!(s = Stream_New(src, sizeof(src))))
327  {
328  printf("%s: Stream_New failed\n", __func__);
329  return FALSE;
330  }
331 
332  TestStream_PeekAndRead(s, result, UINT8);
333  TestStream_PeekAndRead(s, result, INT8);
334  TestStream_PeekAndRead(s, result, UINT16);
335  TestStream_PeekAndRead(s, result, INT16);
336  TestStream_PeekAndRead(s, result, UINT32);
337  TestStream_PeekAndRead(s, result, INT32);
338  TestStream_PeekAndRead(s, result, UINT64);
339  TestStream_PeekAndRead(s, result, INT64);
340  Stream_Free(s, FALSE);
341  return result;
342 }
343 
344 static BOOL TestStream_Write(void)
345 {
346  BOOL rc = FALSE;
347  UINT8 u8 = 0;
348  UINT16 u16 = 0;
349  UINT32 u32 = 0;
350  UINT64 u64 = 0;
351  const BYTE data[] = "someteststreamdata";
352  wStream* s = Stream_New(NULL, 100);
353 
354  if (!s)
355  goto out;
356 
357  if (s->pointer != s->buffer)
358  goto out;
359 
360  Stream_Write(s, data, sizeof(data));
361 
362  if (memcmp(Stream_Buffer(s), data, sizeof(data)) == 0)
363  rc = TRUE;
364 
365  if (s->pointer != s->buffer + sizeof(data))
366  goto out;
367 
368  Stream_SetPosition(s, 0);
369 
370  if (s->pointer != s->buffer)
371  goto out;
372 
373  Stream_Write_UINT8(s, 42);
374 
375  if (s->pointer != s->buffer + 1)
376  goto out;
377 
378  Stream_SetPosition(s, 0);
379 
380  if (s->pointer != s->buffer)
381  goto out;
382 
383  Stream_Peek_UINT8(s, u8);
384 
385  if (u8 != 42)
386  goto out;
387 
388  Stream_Write_UINT16(s, 0x1234);
389 
390  if (s->pointer != s->buffer + 2)
391  goto out;
392 
393  Stream_SetPosition(s, 0);
394 
395  if (s->pointer != s->buffer)
396  goto out;
397 
398  Stream_Peek_UINT16(s, u16);
399 
400  if (u16 != 0x1234)
401  goto out;
402 
403  Stream_Write_UINT32(s, 0x12345678UL);
404 
405  if (s->pointer != s->buffer + 4)
406  goto out;
407 
408  Stream_SetPosition(s, 0);
409 
410  if (s->pointer != s->buffer)
411  goto out;
412 
413  Stream_Peek_UINT32(s, u32);
414 
415  if (u32 != 0x12345678UL)
416  goto out;
417 
418  Stream_Write_UINT64(s, 0x1234567890ABCDEFULL);
419 
420  if (s->pointer != s->buffer + 8)
421  goto out;
422 
423  Stream_SetPosition(s, 0);
424 
425  if (s->pointer != s->buffer)
426  goto out;
427 
428  Stream_Peek_UINT64(s, u64);
429 
430  if (u64 != 0x1234567890ABCDEFULL)
431  goto out;
432 
433 out:
434  Stream_Free(s, TRUE);
435  return rc;
436 }
437 
438 static BOOL TestStream_Seek(void)
439 {
440  BOOL rc = FALSE;
441  wStream* s = Stream_New(NULL, 100);
442 
443  if (!s)
444  goto out;
445 
446  if (s->pointer != s->buffer)
447  goto out;
448 
449  Stream_Seek(s, 5);
450 
451  if (s->pointer != s->buffer + 5)
452  goto out;
453 
454  Stream_Seek_UINT8(s);
455 
456  if (s->pointer != s->buffer + 6)
457  goto out;
458 
459  Stream_Seek_UINT16(s);
460 
461  if (s->pointer != s->buffer + 8)
462  goto out;
463 
464  Stream_Seek_UINT32(s);
465 
466  if (s->pointer != s->buffer + 12)
467  goto out;
468 
469  Stream_Seek_UINT64(s);
470 
471  if (s->pointer != s->buffer + 20)
472  goto out;
473 
474  rc = TRUE;
475 out:
476  Stream_Free(s, TRUE);
477  return rc;
478 }
479 
480 static BOOL TestStream_Rewind(void)
481 {
482  BOOL rc = FALSE;
483  wStream* s = Stream_New(NULL, 100);
484 
485  if (!s)
486  goto out;
487 
488  if (s->pointer != s->buffer)
489  goto out;
490 
491  Stream_Seek(s, 100);
492 
493  if (s->pointer != s->buffer + 100)
494  goto out;
495 
496  Stream_Rewind(s, 10);
497 
498  if (s->pointer != s->buffer + 90)
499  goto out;
500 
501  Stream_Rewind_UINT8(s);
502 
503  if (s->pointer != s->buffer + 89)
504  goto out;
505 
506  Stream_Rewind_UINT16(s);
507 
508  if (s->pointer != s->buffer + 87)
509  goto out;
510 
511  Stream_Rewind_UINT32(s);
512 
513  if (s->pointer != s->buffer + 83)
514  goto out;
515 
516  Stream_Rewind_UINT64(s);
517 
518  if (s->pointer != s->buffer + 75)
519  goto out;
520 
521  rc = TRUE;
522 out:
523  Stream_Free(s, TRUE);
524  return rc;
525 }
526 
527 static BOOL TestStream_Zero(void)
528 {
529  BOOL rc = FALSE;
530  const BYTE data[] = "someteststreamdata";
531  wStream* s = Stream_New(NULL, sizeof(data));
532 
533  if (!s)
534  goto out;
535 
536  Stream_Write(s, data, sizeof(data));
537 
538  if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
539  goto out;
540 
541  Stream_SetPosition(s, 0);
542 
543  if (s->pointer != s->buffer)
544  goto out;
545 
546  Stream_Zero(s, 5);
547 
548  if (s->pointer != s->buffer + 5)
549  goto out;
550 
551  if (memcmp(Stream_ConstPointer(s), data + 5, sizeof(data) - 5) != 0)
552  goto out;
553 
554  Stream_SetPosition(s, 0);
555 
556  if (s->pointer != s->buffer)
557  goto out;
558 
559  for (UINT32 x = 0; x < 5; x++)
560  {
561  UINT8 val = 0;
562  Stream_Read_UINT8(s, val);
563 
564  if (val != 0)
565  goto out;
566  }
567 
568  rc = TRUE;
569 out:
570  Stream_Free(s, TRUE);
571  return rc;
572 }
573 
574 static BOOL TestStream_Fill(void)
575 {
576  BOOL rc = FALSE;
577  const BYTE fill[7] = "XXXXXXX";
578  const BYTE data[] = "someteststreamdata";
579  wStream* s = Stream_New(NULL, sizeof(data));
580 
581  if (!s)
582  goto out;
583 
584  Stream_Write(s, data, sizeof(data));
585 
586  if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
587  goto out;
588 
589  Stream_SetPosition(s, 0);
590 
591  if (s->pointer != s->buffer)
592  goto out;
593 
594  Stream_Fill(s, fill[0], sizeof(fill));
595 
596  if (s->pointer != s->buffer + sizeof(fill))
597  goto out;
598 
599  if (memcmp(Stream_ConstPointer(s), data + sizeof(fill), sizeof(data) - sizeof(fill)) != 0)
600  goto out;
601 
602  Stream_SetPosition(s, 0);
603 
604  if (s->pointer != s->buffer)
605  goto out;
606 
607  if (memcmp(Stream_ConstPointer(s), fill, sizeof(fill)) != 0)
608  goto out;
609 
610  rc = TRUE;
611 out:
612  Stream_Free(s, TRUE);
613  return rc;
614 }
615 
616 static BOOL TestStream_Copy(void)
617 {
618  BOOL rc = FALSE;
619  const BYTE data[] = "someteststreamdata";
620  wStream* s = Stream_New(NULL, sizeof(data));
621  wStream* d = Stream_New(NULL, sizeof(data));
622 
623  if (!s || !d)
624  goto out;
625 
626  if (s->pointer != s->buffer)
627  goto out;
628 
629  Stream_Write(s, data, sizeof(data));
630 
631  if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
632  goto out;
633 
634  if (s->pointer != s->buffer + sizeof(data))
635  goto out;
636 
637  Stream_SetPosition(s, 0);
638 
639  if (s->pointer != s->buffer)
640  goto out;
641 
642  Stream_Copy(s, d, sizeof(data));
643 
644  if (s->pointer != s->buffer + sizeof(data))
645  goto out;
646 
647  if (d->pointer != d->buffer + sizeof(data))
648  goto out;
649 
650  if (Stream_GetPosition(s) != Stream_GetPosition(d))
651  goto out;
652 
653  if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
654  goto out;
655 
656  if (memcmp(Stream_Buffer(d), data, sizeof(data)) != 0)
657  goto out;
658 
659  rc = TRUE;
660 out:
661  Stream_Free(s, TRUE);
662  Stream_Free(d, TRUE);
663  return rc;
664 }
665 
666 int TestStream(int argc, char* argv[])
667 {
668  WINPR_UNUSED(argc);
669  WINPR_UNUSED(argv);
670 
671  if (!TestStream_Create(200, FALSE))
672  return 1;
673 
674  if (!TestStream_Create(200, TRUE))
675  return 2;
676 
677  if (!TestStream_Extent(4096))
678  return 3;
679 
680  if (!TestStream_Reading())
681  return 4;
682 
683  if (!TestStream_New())
684  return 5;
685 
686  if (!TestStream_Write())
687  return 6;
688 
689  if (!TestStream_Seek())
690  return 7;
691 
692  if (!TestStream_Rewind())
693  return 8;
694 
695  if (!TestStream_Zero())
696  return 9;
697 
698  if (!TestStream_Fill())
699  return 10;
700 
701  if (!TestStream_Copy())
702  return 11;
703 
704  if (!TestStream_Static())
705  return 12;
706 
707  return 0;
708 }