FreeRDP
Loading...
Searching...
No Matches
TestStream.c
1#include <winpr/crt.h>
2#include <winpr/print.h>
3#include <winpr/crypto.h>
4#include <winpr/stream.h>
5
6WINPR_ATTR_NODISCARD
7static BOOL TestStream_Verify(wStream* s, size_t mincap, size_t len, size_t pos)
8{
9 if (Stream_Buffer(s) == nullptr)
10 {
11 printf("stream buffer is null\n");
12 return FALSE;
13 }
14
15 if (Stream_ConstPointer(s) == nullptr)
16 {
17 printf("stream pointer is null\n");
18 return FALSE;
19 }
20
21 if (Stream_PointerAs(s, BYTE) < Stream_Buffer(s))
22 {
23 printf("stream pointer (%p) or buffer (%p) is invalid\n", Stream_ConstPointer(s),
24 (void*)Stream_Buffer(s));
25 return FALSE;
26 }
27
28 if (Stream_Capacity(s) < mincap)
29 {
30 printf("stream capacity is %" PRIuz " but minimum expected value is %" PRIuz "\n",
31 Stream_Capacity(s), mincap);
32 return FALSE;
33 }
34
35 if (Stream_Length(s) != len)
36 {
37 printf("stream has unexpected length (%" PRIuz " instead of %" PRIuz ")\n",
38 Stream_Length(s), len);
39 return FALSE;
40 }
41
42 if (Stream_GetPosition(s) != pos)
43 {
44 printf("stream has unexpected position (%" PRIuz " instead of %" PRIuz ")\n",
45 Stream_GetPosition(s), pos);
46 return FALSE;
47 }
48
49 if (Stream_GetPosition(s) > Stream_Length(s))
50 {
51 printf("stream position (%" PRIuz ") exceeds length (%" PRIuz ")\n", Stream_GetPosition(s),
52 Stream_Length(s));
53 return FALSE;
54 }
55
56 if (Stream_GetPosition(s) > Stream_Capacity(s))
57 {
58 printf("stream position (%" PRIuz ") exceeds capacity (%" PRIuz ")\n",
59 Stream_GetPosition(s), Stream_Capacity(s));
60 return FALSE;
61 }
62
63 if (Stream_Length(s) > Stream_Capacity(s))
64 {
65 printf("stream length (%" PRIuz ") exceeds capacity (%" PRIuz ")\n", Stream_Length(s),
66 Stream_Capacity(s));
67 return FALSE;
68 }
69
70 if (Stream_GetRemainingLength(s) != len - pos)
71 {
72 printf("stream remaining length (%" PRIuz " instead of %" PRIuz ")\n",
73 Stream_GetRemainingLength(s), len - pos);
74 return FALSE;
75 }
76
77 return TRUE;
78}
79
80WINPR_ATTR_NODISCARD
81static BOOL TestStream_New(void)
82{
83 /* Test creation of a 0-size stream with no buffer */
84 wStream* s = Stream_New(nullptr, 0);
85
86 if (s)
87 return FALSE;
88 Stream_Free(s, TRUE);
89
90 return TRUE;
91}
92
93WINPR_ATTR_NODISCARD
94static BOOL TestStream_Static(void)
95{
96 BYTE buffer[20] = WINPR_C_ARRAY_INIT;
97 wStream staticStream = WINPR_C_ARRAY_INIT;
98 wStream* s = &staticStream;
99 UINT16 v = 0;
100 /* Test creation of a static stream */
101 Stream_StaticInit(s, buffer, sizeof(buffer));
102 Stream_Write_UINT16(s, 0xcab1);
103 Stream_ResetPosition(s);
104 Stream_Read_UINT16(s, v);
105
106 if (v != 0xcab1)
107 return FALSE;
108
109 Stream_ResetPosition(s);
110 Stream_Write_UINT16(s, 1);
111
112 if (!Stream_EnsureRemainingCapacity(s, 10)) /* we can ask for 10 bytes */
113 return FALSE;
114
115 /* 30 is bigger than the buffer, it will be reallocated on the heap */
116 if (!Stream_EnsureRemainingCapacity(s, 30) || !s->isOwner)
117 return FALSE;
118
119 Stream_Write_UINT16(s, 2);
120 Stream_ResetPosition(s);
121 Stream_Read_UINT16(s, v);
122
123 if (v != 1)
124 return FALSE;
125
126 Stream_Read_UINT16(s, v);
127
128 if (v != 2)
129 return FALSE;
130
131 // Intentional warning as the stream is not allocated.
132 // Still, Stream_Free should not release such memory, therefore this statement
133 // is required to test that.
134 WINPR_PRAGMA_DIAG_PUSH
135 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
136 Stream_Free(s, TRUE);
137 WINPR_PRAGMA_DIAG_POP
138 return TRUE;
139}
140
141WINPR_ATTR_NODISCARD
142static BOOL TestStream_Create(size_t count, BOOL selfAlloc)
143{
144 size_t len = 0;
145 size_t cap = 0;
146 wStream* s = nullptr;
147 void* buffer = nullptr;
148
149 for (size_t i = 0; i < count; i++)
150 {
151 len = cap = i + 1;
152
153 if (selfAlloc)
154 {
155 if (!(buffer = malloc(cap)))
156 {
157 printf("%s: failed to allocate buffer of size %" PRIuz "\n", __func__, cap);
158 goto fail;
159 }
160 }
161
162 if (!(s = Stream_New(selfAlloc ? buffer : nullptr, len)))
163 {
164 printf("%s: Stream_New failed for stream #%" PRIuz "\n", __func__, i);
165 goto fail;
166 }
167
168 if (!TestStream_Verify(s, cap, len, 0))
169 {
170 goto fail;
171 }
172
173 for (size_t pos = 0; pos < len; pos++)
174 {
175 if (!Stream_SetPosition(s, pos))
176 goto fail;
177 Stream_SealLength(s);
178
179 if (!TestStream_Verify(s, cap, pos, pos))
180 {
181 goto fail;
182 }
183 }
184
185 if (selfAlloc)
186 {
187 memset(buffer, (BYTE)(i % 256), cap);
188
189 if (memcmp(buffer, Stream_Buffer(s), cap) != 0)
190 {
191 printf("%s: buffer memory corruption\n", __func__);
192 goto fail;
193 }
194 }
195
196 Stream_Free(s, buffer == nullptr);
197 free(buffer);
198 }
199
200 return TRUE;
201fail:
202 free(buffer);
203
204 if (s)
205 {
206 Stream_Free(s, buffer == nullptr);
207 }
208
209 return FALSE;
210}
211
212WINPR_ATTR_NODISCARD
213static BOOL TestStream_Extent(UINT32 maxSize)
214{
215 wStream* s = nullptr;
216 BOOL result = FALSE;
217
218 if (!(s = Stream_New(nullptr, 1)))
219 {
220 printf("%s: Stream_New failed\n", __func__);
221 return FALSE;
222 }
223
224 for (UINT32 i = 1; i < maxSize; i++)
225 {
226 if (i % 2)
227 {
228 if (!Stream_EnsureRemainingCapacity(s, i))
229 goto fail;
230 }
231 else
232 {
233 if (!Stream_EnsureCapacity(s, i))
234 goto fail;
235 }
236
237 if (!Stream_SetPosition(s, i))
238 goto fail;
239 Stream_SealLength(s);
240
241 if (!TestStream_Verify(s, i, i, i))
242 {
243 printf("%s: failed to verify stream in iteration %" PRIu32 "\n", __func__, i);
244 goto fail;
245 }
246 }
247
248 result = TRUE;
249fail:
250
251 if (s)
252 {
253 Stream_Free(s, TRUE);
254 }
255
256 return result;
257}
258
259#define Stream_Peek_UINT8_BE Stream_Peek_UINT8
260#define Stream_Read_UINT8_BE Stream_Read_UINT8
261#define Stream_Peek_Get_UINT8_BE Stream_Peek_Get_UINT8
262#define Stream_Get_UINT8_BE Stream_Get_UINT8
263#define Stream_Peek_INT8_BE Stream_Peek_INT8
264#define Stream_Peek_Get_INT8_BE Stream_Peek_Get_INT8
265#define Stream_Read_INT8_BE Stream_Read_INT8
266#define Stream_Get_INT8_BE Stream_Get_INT8
267
268#define TestStream_PeekAndRead(_s, _r, _t) \
269 do \
270 { \
271 _t _a = 0; \
272 _t _b = 0; \
273 BYTE* _p = Stream_Buffer(_s); \
274 Stream_ResetPosition(_s); \
275 Stream_Peek_##_t(_s, _a); \
276 Stream_Read_##_t(_s, _b); \
277 if (_a != _b) \
278 { \
279 printf("%s: test1 " #_t "_LE failed\n", __func__); \
280 (_r) = FALSE; \
281 } \
282 Stream_Rewind(_s, sizeof(_t)); \
283 const _t _d = Stream_Peek_Get_##_t(_s); \
284 const _t _c = Stream_Get_##_t(_s); \
285 if (_c != _d) \
286 { \
287 printf("%s: test1 " #_t "_LE failed\n", __func__); \
288 (_r) = FALSE; \
289 } \
290 for (size_t _i = 0; _i < sizeof(_t); _i++) \
291 { \
292 if (((_a >> (_i * 8)) & 0xFF) != _p[_i]) \
293 { \
294 printf("%s: test2 " #_t "_LE failed\n", __func__); \
295 (_r) = FALSE; \
296 break; \
297 } \
298 } \
299 /* printf("a: 0x%016llX\n", a); */ \
300 Stream_ResetPosition(_s); \
301 Stream_Peek_##_t##_BE(_s, _a); \
302 Stream_Read_##_t##_BE(_s, _b); \
303 if (_a != _b) \
304 { \
305 printf("%s: test1 " #_t "_BE failed\n", __func__); \
306 (_r) = FALSE; \
307 } \
308 Stream_Rewind(_s, sizeof(_t)); \
309 const _t _e = Stream_Peek_Get_##_t##_BE(_s); \
310 const _t _f = Stream_Get_##_t##_BE(_s); \
311 if (_e != _f) \
312 { \
313 printf("%s: test1 " #_t "_BE failed\n", __func__); \
314 (_r) = FALSE; \
315 } \
316 for (size_t _i = 0; _i < sizeof(_t); _i++) \
317 { \
318 if (((_a >> (_i * 8)) & 0xFF) != _p[sizeof(_t) - _i - 1]) \
319 { \
320 printf("%s: test2 " #_t "_BE failed\n", __func__); \
321 (_r) = FALSE; \
322 break; \
323 } \
324 } \
325 /* printf("a: 0x%016llX\n", a); */ \
326 } while (0)
327
328WINPR_ATTR_NODISCARD
329static BOOL TestStream_WriteAndRead(UINT64 value)
330{
331 union
332 {
333 UINT8 u8;
334 UINT16 u16;
335 UINT32 u32;
336 UINT64 u64;
337 INT8 i8;
338 INT16 i16;
339 INT32 i32;
340 INT64 i64;
341 } val;
342 val.u64 = value;
343
344 wStream* s = Stream_New(nullptr, 1024);
345 if (!s)
346 return FALSE;
347 BOOL rc = FALSE;
348
349 {
350 Stream_Write_UINT8(s, val.u8);
351 Stream_Rewind_UINT8(s);
352 const UINT8 ru8 = Stream_Get_UINT8(s);
353 Stream_Rewind_UINT8(s);
354 if (val.u8 != ru8)
355 goto fail;
356 }
357 {
358 Stream_Write_UINT16(s, val.u16);
359 Stream_Rewind_UINT16(s);
360 const UINT16 ru = Stream_Get_UINT16(s);
361 Stream_Rewind_UINT16(s);
362 if (val.u16 != ru)
363 goto fail;
364 }
365 {
366 Stream_Write_UINT16_BE(s, val.u16);
367 Stream_Rewind_UINT16(s);
368 const UINT16 ru = Stream_Get_UINT16_BE(s);
369 Stream_Rewind_UINT16(s);
370 if (val.u16 != ru)
371 goto fail;
372 }
373 {
374 Stream_Write_UINT32(s, val.u32);
375 Stream_Rewind_UINT32(s);
376 const UINT32 ru = Stream_Get_UINT32(s);
377 Stream_Rewind_UINT32(s);
378 if (val.u32 != ru)
379 goto fail;
380 }
381 {
382 Stream_Write_UINT32_BE(s, val.u32);
383 Stream_Rewind_UINT32(s);
384 const UINT32 ru = Stream_Get_UINT32_BE(s);
385 Stream_Rewind_UINT32(s);
386 if (val.u32 != ru)
387 goto fail;
388 }
389 {
390 Stream_Write_UINT64(s, val.u64);
391 Stream_Rewind_UINT64(s);
392 const UINT64 ru = Stream_Get_UINT64(s);
393 Stream_Rewind_UINT64(s);
394 if (val.u64 != ru)
395 goto fail;
396 }
397 {
398 Stream_Write_UINT64_BE(s, val.u64);
399 Stream_Rewind_UINT64(s);
400 const UINT64 ru = Stream_Get_UINT64_BE(s);
401 Stream_Rewind_UINT64(s);
402 if (val.u64 != ru)
403 goto fail;
404 }
405 {
406 Stream_Write_INT8(s, val.i8);
407 Stream_Rewind(s, 1);
408 const INT8 ru8 = Stream_Get_INT8(s);
409 Stream_Rewind(s, 1);
410 if (val.i8 != ru8)
411 goto fail;
412 }
413 {
414 Stream_Write_INT16(s, val.i16);
415 Stream_Rewind(s, 2);
416 const INT16 ru = Stream_Get_INT16(s);
417 Stream_Rewind(s, 2);
418 if (val.i16 != ru)
419 goto fail;
420 }
421 {
422 Stream_Write_INT16_BE(s, val.i16);
423 Stream_Rewind(s, 2);
424 const INT16 ru = Stream_Get_INT16_BE(s);
425 Stream_Rewind(s, 2);
426 if (val.i16 != ru)
427 goto fail;
428 }
429 {
430 Stream_Write_INT32(s, val.i32);
431 Stream_Rewind(s, 4);
432 const INT32 ru = Stream_Get_INT32(s);
433 Stream_Rewind(s, 4);
434 if (val.i32 != ru)
435 goto fail;
436 }
437 {
438 Stream_Write_INT32_BE(s, val.i32);
439 Stream_Rewind(s, 4);
440 const INT32 ru = Stream_Get_INT32_BE(s);
441 Stream_Rewind(s, 4);
442 if (val.i32 != ru)
443 goto fail;
444 }
445 {
446 Stream_Write_INT64(s, val.i64);
447 Stream_Rewind(s, 8);
448 const INT64 ru = Stream_Get_INT64(s);
449 Stream_Rewind(s, 8);
450 if (val.i64 != ru)
451 goto fail;
452 }
453 {
454 Stream_Write_INT64_BE(s, val.i64);
455 Stream_Rewind(s, 8);
456 const INT64 ru = Stream_Get_INT64_BE(s);
457 Stream_Rewind(s, 8);
458 if (val.i64 != ru)
459 goto fail;
460 }
461
462 rc = TRUE;
463fail:
464 Stream_Free(s, TRUE);
465 return rc;
466}
467
468WINPR_ATTR_NODISCARD
469static BOOL TestStream_Reading(void)
470{
471 BYTE src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
472 wStream* s = nullptr;
473 BOOL result = TRUE;
474
475 if (!(s = Stream_New(src, sizeof(src))))
476 {
477 printf("%s: Stream_New failed\n", __func__);
478 return FALSE;
479 }
480
481 TestStream_PeekAndRead(s, result, UINT8);
482 TestStream_PeekAndRead(s, result, INT8);
483 TestStream_PeekAndRead(s, result, UINT16);
484 TestStream_PeekAndRead(s, result, INT16);
485 TestStream_PeekAndRead(s, result, UINT32);
486 TestStream_PeekAndRead(s, result, INT32);
487 TestStream_PeekAndRead(s, result, UINT64);
488 TestStream_PeekAndRead(s, result, INT64);
489 Stream_Free(s, FALSE);
490 return result;
491}
492
493WINPR_ATTR_NODISCARD
494static BOOL TestStream_Write(void)
495{
496 BOOL rc = FALSE;
497 UINT8 u8 = 0;
498 UINT16 u16 = 0;
499 UINT32 u32 = 0;
500 UINT64 u64 = 0;
501 const BYTE data[] = "someteststreamdata";
502 wStream* s = Stream_New(nullptr, 100);
503
504 if (!s)
505 goto out;
506
507 if (s->pointer != s->buffer)
508 goto out;
509
510 Stream_Write(s, data, sizeof(data));
511
512 if (memcmp(Stream_Buffer(s), data, sizeof(data)) == 0)
513 rc = TRUE;
514
515 if (s->pointer != s->buffer + sizeof(data))
516 goto out;
517
518 Stream_ResetPosition(s);
519
520 if (s->pointer != s->buffer)
521 goto out;
522
523 Stream_Write_UINT8(s, 42);
524
525 if (s->pointer != s->buffer + 1)
526 goto out;
527
528 Stream_ResetPosition(s);
529
530 if (s->pointer != s->buffer)
531 goto out;
532
533 Stream_Peek_UINT8(s, u8);
534
535 if (u8 != 42)
536 goto out;
537
538 Stream_Write_UINT16(s, 0x1234);
539
540 if (s->pointer != s->buffer + 2)
541 goto out;
542
543 Stream_ResetPosition(s);
544
545 if (s->pointer != s->buffer)
546 goto out;
547
548 Stream_Peek_UINT16(s, u16);
549
550 if (u16 != 0x1234)
551 goto out;
552
553 Stream_Write_UINT32(s, 0x12345678UL);
554
555 if (s->pointer != s->buffer + 4)
556 goto out;
557
558 Stream_ResetPosition(s);
559
560 if (s->pointer != s->buffer)
561 goto out;
562
563 Stream_Peek_UINT32(s, u32);
564
565 if (u32 != 0x12345678UL)
566 goto out;
567
568 Stream_Write_UINT64(s, 0x1234567890ABCDEFULL);
569
570 if (s->pointer != s->buffer + 8)
571 goto out;
572
573 Stream_ResetPosition(s);
574
575 if (s->pointer != s->buffer)
576 goto out;
577
578 Stream_Peek_UINT64(s, u64);
579
580 if (u64 != 0x1234567890ABCDEFULL)
581 goto out;
582
583out:
584 Stream_Free(s, TRUE);
585 return rc;
586}
587
588WINPR_ATTR_NODISCARD
589static BOOL TestStream_Seek(void)
590{
591 BOOL rc = FALSE;
592 wStream* s = Stream_New(nullptr, 100);
593
594 if (!s)
595 goto out;
596
597 if (s->pointer != s->buffer)
598 goto out;
599
600 Stream_Seek(s, 5);
601
602 if (s->pointer != s->buffer + 5)
603 goto out;
604
605 Stream_Seek_UINT8(s);
606
607 if (s->pointer != s->buffer + 6)
608 goto out;
609
610 Stream_Seek_UINT16(s);
611
612 if (s->pointer != s->buffer + 8)
613 goto out;
614
615 Stream_Seek_UINT32(s);
616
617 if (s->pointer != s->buffer + 12)
618 goto out;
619
620 Stream_Seek_UINT64(s);
621
622 if (s->pointer != s->buffer + 20)
623 goto out;
624
625 rc = TRUE;
626out:
627 Stream_Free(s, TRUE);
628 return rc;
629}
630
631WINPR_ATTR_NODISCARD
632static BOOL TestStream_Rewind(void)
633{
634 BOOL rc = FALSE;
635 wStream* s = Stream_New(nullptr, 100);
636
637 if (!s)
638 goto out;
639
640 if (s->pointer != s->buffer)
641 goto out;
642
643 Stream_Seek(s, 100);
644
645 if (s->pointer != s->buffer + 100)
646 goto out;
647
648 Stream_Rewind(s, 10);
649
650 if (s->pointer != s->buffer + 90)
651 goto out;
652
653 Stream_Rewind_UINT8(s);
654
655 if (s->pointer != s->buffer + 89)
656 goto out;
657
658 Stream_Rewind_UINT16(s);
659
660 if (s->pointer != s->buffer + 87)
661 goto out;
662
663 Stream_Rewind_UINT32(s);
664
665 if (s->pointer != s->buffer + 83)
666 goto out;
667
668 Stream_Rewind_UINT64(s);
669
670 if (s->pointer != s->buffer + 75)
671 goto out;
672
673 rc = TRUE;
674out:
675 Stream_Free(s, TRUE);
676 return rc;
677}
678
679WINPR_ATTR_NODISCARD
680static BOOL TestStream_Zero(void)
681{
682 BOOL rc = FALSE;
683 const BYTE data[] = "someteststreamdata";
684 wStream* s = Stream_New(nullptr, sizeof(data));
685
686 if (!s)
687 goto out;
688
689 Stream_Write(s, data, sizeof(data));
690
691 if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
692 goto out;
693
694 Stream_ResetPosition(s);
695
696 if (s->pointer != s->buffer)
697 goto out;
698
699 Stream_Zero(s, 5);
700
701 if (s->pointer != s->buffer + 5)
702 goto out;
703
704 if (memcmp(Stream_ConstPointer(s), data + 5, sizeof(data) - 5) != 0)
705 goto out;
706
707 Stream_ResetPosition(s);
708
709 if (s->pointer != s->buffer)
710 goto out;
711
712 for (UINT32 x = 0; x < 5; x++)
713 {
714 UINT8 val = 0;
715 Stream_Read_UINT8(s, val);
716
717 if (val != 0)
718 goto out;
719 }
720
721 rc = TRUE;
722out:
723 Stream_Free(s, TRUE);
724 return rc;
725}
726
727WINPR_ATTR_NODISCARD
728static BOOL TestStream_Fill(void)
729{
730 BOOL rc = FALSE;
731 const BYTE fill[7] = "XXXXXXX";
732 const BYTE data[] = "someteststreamdata";
733 wStream* s = Stream_New(nullptr, sizeof(data));
734
735 if (!s)
736 goto out;
737
738 Stream_Write(s, data, sizeof(data));
739
740 if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
741 goto out;
742
743 Stream_ResetPosition(s);
744
745 if (s->pointer != s->buffer)
746 goto out;
747
748 Stream_Fill(s, fill[0], sizeof(fill));
749
750 if (s->pointer != s->buffer + sizeof(fill))
751 goto out;
752
753 if (memcmp(Stream_ConstPointer(s), data + sizeof(fill), sizeof(data) - sizeof(fill)) != 0)
754 goto out;
755
756 Stream_ResetPosition(s);
757
758 if (s->pointer != s->buffer)
759 goto out;
760
761 if (memcmp(Stream_ConstPointer(s), fill, sizeof(fill)) != 0)
762 goto out;
763
764 rc = TRUE;
765out:
766 Stream_Free(s, TRUE);
767 return rc;
768}
769
770WINPR_ATTR_NODISCARD
771static BOOL TestStream_Copy(void)
772{
773 BOOL rc = FALSE;
774 const BYTE data[] = "someteststreamdata";
775 wStream* s = Stream_New(nullptr, sizeof(data));
776 wStream* d = Stream_New(nullptr, sizeof(data));
777
778 if (!s || !d)
779 goto out;
780
781 if (s->pointer != s->buffer)
782 goto out;
783
784 Stream_Write(s, data, sizeof(data));
785
786 if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
787 goto out;
788
789 if (s->pointer != s->buffer + sizeof(data))
790 goto out;
791
792 Stream_ResetPosition(s);
793
794 if (s->pointer != s->buffer)
795 goto out;
796
797 Stream_Copy(s, d, sizeof(data));
798
799 if (s->pointer != s->buffer + sizeof(data))
800 goto out;
801
802 if (d->pointer != d->buffer + sizeof(data))
803 goto out;
804
805 if (Stream_GetPosition(s) != Stream_GetPosition(d))
806 goto out;
807
808 if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
809 goto out;
810
811 if (memcmp(Stream_Buffer(d), data, sizeof(data)) != 0)
812 goto out;
813
814 rc = TRUE;
815out:
816 Stream_Free(s, TRUE);
817 Stream_Free(d, TRUE);
818 return rc;
819}
820
821WINPR_ATTR_NODISCARD
822static BOOL TestStream_WriteUTF16(void)
823{
824 const char name[] = "UVC Camera (046d:0825)";
825 const char channel[] = "usb-0000:00:07.0-3";
826 const size_t length = strnlen(name, sizeof(name));
827 BOOL success = FALSE;
828 wStream* s = Stream_New(nullptr, 256);
829 if (!s)
830 return FALSE;
831
832 /* Both an aligned RDPECAM header and an unaligned destination. */
833 for (size_t offset = 1; offset <= 2; offset++)
834 {
835 for (size_t fill = 0; fill <= 1; fill++)
836 {
837 memset(Stream_Buffer(s), 0xAA, Stream_Capacity(s));
838 Stream_SetPosition(s, offset);
839 const SSIZE_T rc =
840 Stream_Write_UTF16_String_From_UTF8(s, length + 1, name, length, (BOOL)fill);
841 const size_t end = offset + (length + fill) * sizeof(WCHAR);
842 if ((rc != (SSIZE_T)length) || (Stream_GetPosition(s) != end))
843 goto out;
844 Stream_Write(s, channel, strnlen(channel, sizeof(channel)) + 1);
845 for (size_t i = 0; i < length; i++)
846 {
847 const BYTE* ptr = Stream_Buffer(s) + offset + i * sizeof(WCHAR);
848 if ((ptr[0] != (BYTE)name[i]) || (ptr[1] != 0))
849 goto out;
850 }
851 if (fill && ((Stream_Buffer(s)[end - 2] != 0) || (Stream_Buffer(s)[end - 1] != 0)))
852 goto out;
853 if (strncmp((const char*)Stream_Buffer(s) + end, channel, sizeof(channel)) != 0)
854 goto out;
855 }
856 }
857
858 /* Allow truncation. */
859 Stream_ResetPosition(s);
860 if (Stream_Write_UTF16_String_From_UTF8(s, 2, name, length, TRUE) != 2)
861 goto out;
862
863 const size_t pos = Stream_GetPosition(s);
864 if (pos != 2 * sizeof(WCHAR))
865 goto out;
866
867 success = TRUE;
868out:
869 if (!success)
870 printf("UTF-16 stream serialization failed\n");
871 Stream_Free(s, TRUE);
872 return success;
873}
874
875int TestStream(int argc, char* argv[])
876{
877 WINPR_UNUSED(argc);
878 WINPR_UNUSED(argv);
879 if (!TestStream_WriteUTF16())
880 return 15;
881
882 if (!TestStream_Create(200, FALSE))
883 return 1;
884
885 if (!TestStream_Create(200, TRUE))
886 return 2;
887
888 if (!TestStream_Extent(4096))
889 return 3;
890
891 if (!TestStream_Reading())
892 return 4;
893
894 if (!TestStream_New())
895 return 5;
896
897 if (!TestStream_Write())
898 return 6;
899
900 if (!TestStream_Seek())
901 return 7;
902
903 if (!TestStream_Rewind())
904 return 8;
905
906 if (!TestStream_Zero())
907 return 9;
908
909 if (!TestStream_Fill())
910 return 10;
911
912 if (!TestStream_Copy())
913 return 11;
914
915 if (!TestStream_Static())
916 return 12;
917
918 if (!TestStream_WriteAndRead(0x1234567890abcdef))
919 return 13;
920
921 for (size_t x = 0; x < 10; x++)
922 {
923 UINT64 val = 0;
924 if (winpr_RAND(&val, sizeof(val)) < 0)
925 return -1;
926 if (!TestStream_WriteAndRead(val))
927 return 14;
928 }
929 return 0;
930}