2 * Unix SMB/CIFS implementation.
4 * Copyright (C) 2018 Andreas Schneider <asn@samba.org>
5 * Copyright (C) 2022 Douglas Bagnall <dbagnall@samba.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #include "../stable_sort.h"
32 static int cmp_integer(int *a
, int *b
)
34 if (a
== NULL
|| b
== NULL
) {
49 static void test_stable_sort(void **state
)
51 int a
[6] = { 6, 3, 2, 7, 9, 4 };
54 ok
= stable_sort(a
, tmp
,
55 6, sizeof(int), (samba_compare_fn_t
)cmp_integer
);
58 assert_int_equal(a
[0], 2);
59 assert_int_equal(a
[1], 3);
60 assert_int_equal(a
[2], 4);
61 assert_int_equal(a
[3], 6);
62 assert_int_equal(a
[4], 7);
63 assert_int_equal(a
[5], 9);
66 static void test_stable_sort_talloc_short(void **state
)
68 int a
[6] = { 6, 3, 2, 7, 9, 4 };
70 ret
= stable_sort_talloc(NULL
, a
, 6, sizeof(int),
71 (samba_compare_fn_t
)cmp_integer
);
74 assert_int_equal(a
[0], 2);
75 assert_int_equal(a
[1], 3);
76 assert_int_equal(a
[2], 4);
77 assert_int_equal(a
[3], 6);
78 assert_int_equal(a
[4], 7);
79 assert_int_equal(a
[5], 9);
82 static void test_stable_sort_talloc_long(void **state
)
86 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
87 int *a
= talloc_array(mem_ctx
, int, n
);
88 for (i
= 0; i
< n
; i
++) {
92 ret
= stable_sort_talloc(mem_ctx
, a
, n
, sizeof(int),
93 (samba_compare_fn_t
)cmp_integer
);
96 for (i
= 0; i
< n
; i
++) {
97 assert_int_equal(a
[i
], 1 + i
);
103 * Sort an array of structs with:
104 * - unwieldy uneven size
105 * - sort key not at the start
106 * - comparison depends on context
108 * which are things we sometimes do.
111 struct contrived_struct
{
119 static int cmp_contrived_struct(struct contrived_struct
*as
,
120 struct contrived_struct
*bs
)
128 static int cmp_contrived_struct_rev(struct contrived_struct
*as
,
129 struct contrived_struct
*bs
)
131 /* will sort in reverseo order */
139 static void test_stable_sort_talloc_contrived_struct(void **state
)
143 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
144 size_t key_index
= 0;
146 struct contrived_struct
*a
= talloc_zero_array(mem_ctx
,
147 struct contrived_struct
,
150 /* we don't really want a good RNG, we want mess and repeated values. */
151 uint32_t x
= 89, y
= (uint32_t)-6, z
= 11;
152 for (i
= 0; i
< n
; i
++) {
153 a
[i
].index
= &key_index
;
154 a
[i
].key
[0] = (x
& 0xffff) - 0x8000;
155 a
[i
].key
[1] = z
& 255;
156 /* key[2] is original order, useful for checking stability */
159 y
*= z
+ (x
+ 0x5555);
163 /* 1. sort by key[0] */
164 ret
= stable_sort_talloc(mem_ctx
, a
, n
,
165 sizeof(struct contrived_struct
),
166 (samba_compare_fn_t
)cmp_contrived_struct
);
169 for (i
= 1; i
< n
; i
++) {
170 int value
= a
[i
].key
[0];
171 assert_true(value
>= prev
);
173 /* we can test the stability by comparing key[2] */
174 assert_true(a
[i
].key
[2] >= a
[i
- 1].key
[2]);
179 /* 2. sort by key[1]. key[0] now indicates stability. */
181 ret
= stable_sort_talloc(mem_ctx
, a
, n
,
182 sizeof(struct contrived_struct
),
183 (samba_compare_fn_t
)cmp_contrived_struct
);
186 for (i
= 1; i
< n
; i
++) {
187 int value
= a
[i
].key
[1];
188 assert_true(value
>= prev
);
190 assert_true(a
[i
].key
[0] >= a
[i
- 1].key
[0]);
196 * 3. sort by key[2]. key[1] would now indicate stability, but we know
197 * that key[2] has no duplicates, so stability is moot.
200 ret
= stable_sort_talloc(mem_ctx
, a
, n
,
201 sizeof(struct contrived_struct
),
202 (samba_compare_fn_t
)cmp_contrived_struct
);
205 for (i
= 1; i
< n
; i
++) {
206 int value
= a
[i
].key
[2];
207 assert_true(value
> prev
);
212 * 4. sort by key[0] again, using descending sort order. key[2] should
213 * still be in ascending order where there are duplicate key[0] values.
216 ret
= stable_sort_talloc(mem_ctx
, a
, n
,
217 sizeof(struct contrived_struct
),
218 (samba_compare_fn_t
)cmp_contrived_struct_rev
);
221 for (i
= 1; i
< n
; i
++) {
222 int value
= a
[i
].key
[0];
223 assert_true(value
<= prev
);
225 assert_true(a
[i
].key
[2] >= a
[i
- 1].key
[2]);
233 static int cmp_integer_xor_blob(int *_a
, int *_b
, int *opaque
)
235 int a
= *_a
^ *opaque
;
236 int b
= *_b
^ *opaque
;
249 static void test_stable_sort_talloc_r(void **state
)
253 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
256 int *a
= talloc_array(mem_ctx
, int, n
);
257 for (i
= 0; i
< n
; i
++) {
258 a
[i
] = (i
* 7) & 255;
261 ok
= stable_sort_talloc_r(mem_ctx
, a
, n
, sizeof(int),
262 (samba_compare_with_context_fn_t
)cmp_integer_xor_blob
,
266 for (i
= 1; i
< n
; i
++) {
267 assert_true((a
[i
- 1] ^ opaque
) <= (a
[i
] ^ opaque
));
272 static void test_stable_sort_silly_size(void **state
)
282 (samba_compare_fn_t
)cmp_integer
);
286 static void test_stable_sort_null_array(void **state
)
295 (samba_compare_fn_t
)cmp_integer
);
304 const struct CMUnitTest tests
[] = {
305 cmocka_unit_test(test_stable_sort
),
306 cmocka_unit_test(test_stable_sort_talloc_short
),
307 cmocka_unit_test(test_stable_sort_talloc_long
),
308 cmocka_unit_test(test_stable_sort_talloc_contrived_struct
),
309 cmocka_unit_test(test_stable_sort_talloc_r
),
310 cmocka_unit_test(test_stable_sort_silly_size
),
311 cmocka_unit_test(test_stable_sort_null_array
),
314 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
316 return cmocka_run_group_tests(tests
, NULL
, NULL
);