1/* Tests for <support/blob_repeat.h>
2 Copyright (C) 2018-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <stdio.h>
20#include <string.h>
21#include <support/blob_repeat.h>
22#include <support/check.h>
23
24static int
25do_test (void)
26{
27 struct support_blob_repeat repeat
28 = support_blob_repeat_allocate (element: "5", element_size: 1, count: 5);
29 TEST_COMPARE_BLOB (repeat.start, repeat.size, "55555", 5);
30 support_blob_repeat_free (&repeat);
31
32 repeat = support_blob_repeat_allocate (element: "ABC", element_size: 3, count: 3);
33 TEST_COMPARE_BLOB (repeat.start, repeat.size, "ABCABCABC", 9);
34 support_blob_repeat_free (&repeat);
35
36 repeat = support_blob_repeat_allocate (element: "abc", element_size: 4, count: 3);
37 TEST_COMPARE_BLOB (repeat.start, repeat.size, "abc\0abc\0abc", 12);
38 support_blob_repeat_free (&repeat);
39
40 size_t gigabyte = 1U << 30;
41 repeat = support_blob_repeat_allocate (element: "X", element_size: 1, count: gigabyte + 1);
42 if (repeat.start == NULL)
43 puts (s: "warning: not enough memory for 1 GiB mapping");
44 else
45 {
46 TEST_COMPARE (repeat.size, gigabyte + 1);
47 {
48 unsigned char *p = repeat.start;
49 for (size_t i = 0; i < gigabyte + 1; ++i)
50 if (p[i] != 'X')
51 FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i);
52
53 /* Check that there is no sharing across the mapping. */
54 p[0] = 'Y';
55 p[1U << 24] = 'Z';
56 for (size_t i = 0; i < gigabyte + 1; ++i)
57 if (i == 0)
58 TEST_COMPARE (p[i], 'Y');
59 else if (i == 1U << 24)
60 TEST_COMPARE (p[i], 'Z');
61 else if (p[i] != 'X')
62 FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i);
63 }
64 }
65 support_blob_repeat_free (&repeat);
66
67 for (int do_shared = 0; do_shared < 2; ++do_shared)
68 {
69 if (do_shared)
70 repeat = support_blob_repeat_allocate_shared (element: "012345678", element_size: 9,
71 count: 10 * 1000 * 1000);
72 else
73 repeat = support_blob_repeat_allocate (element: "012345678", element_size: 9,
74 count: 10 * 1000 * 1000);
75 if (repeat.start == NULL)
76 puts (s: "warning: not enough memory for large mapping");
77 else
78 {
79 unsigned char *p = repeat.start;
80 for (int i = 0; i < 10 * 1000 * 1000; ++i)
81 for (int j = 0; j <= 8; ++j)
82 if (p[i * 9 + j] != '0' + j)
83 {
84 printf (format: "error: element %d index %d\n", i, j);
85 TEST_COMPARE (p[i * 9 + j], '0' + j);
86 }
87
88 enum { total_size = 9 * 10 * 1000 * 1000 };
89 p[total_size - 1] = '\0';
90 asm ("" ::: "memory");
91 if (do_shared)
92 /* The write is repeated in multiple places earlier in the
93 string due to page sharing. */
94 TEST_VERIFY (strlen (repeat.start) < total_size - 1);
95 else
96 TEST_COMPARE (strlen (repeat.start), total_size - 1);
97 }
98 support_blob_repeat_free (&repeat);
99 }
100
101 return 0;
102}
103
104#include <support/test-driver.c>
105

source code of glibc/support/tst-support_blob_repeat.c