1 /*
2  * Copyright (c) 2021 Friedt Professional Engineering Services, Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define _GNU_SOURCE
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <zephyr/ztest.h>
11 
compare_ints(const void * a,const void * b)12 static int compare_ints(const void *a, const void *b)
13 {
14 	int aa = *(const int *)a;
15 	int bb = *(const int *)b;
16 
17 	return (aa > bb) - (aa < bb);
18 }
19 
20 /**
21  *
22  * @brief Test qsort function
23  *
24  */
ZTEST(libc_common,test_qsort)25 ZTEST(libc_common, test_qsort)
26 {
27 	{
28 		int actual_int[] = { 1, 3, 2 };
29 		const int expect_int[] = { 1, 3, 2 };
30 
31 		qsort(actual_int + 1, 0, sizeof(int), compare_ints);
32 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
33 				  "out-of-bounds modifications detected");
34 	}
35 
36 	{
37 		int actual_int[] = { 42 };
38 		const int expect_int[] = { 42 };
39 
40 		qsort(actual_int, ARRAY_SIZE(actual_int), sizeof(int), compare_ints);
41 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
42 				  "size 1 not sorted");
43 	}
44 
45 	{
46 		int actual_int[] = { 42, -42 };
47 		const int expect_int[] = { -42, 42 };
48 
49 		qsort(actual_int, ARRAY_SIZE(actual_int), sizeof(int), compare_ints);
50 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
51 				  "size 2 not sorted");
52 	}
53 
54 	{
55 		int actual_int[] = { 42, -42, 0 };
56 		const int expect_int[] = { -42, 0, 42 };
57 
58 		qsort(actual_int, ARRAY_SIZE(actual_int), sizeof(int), compare_ints);
59 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
60 				  "size 3 not sorted");
61 	}
62 
63 	{
64 		int actual_int[] = { 42, -42, 0, -42 };
65 		const int expect_int[] = { -42, -42, 0, 42 };
66 
67 		qsort(actual_int, ARRAY_SIZE(actual_int), sizeof(int), compare_ints);
68 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
69 				  "error handling duplicates");
70 	}
71 
72 	{
73 		/*
74 		 * NUMS="$(for i in `seq 0 63`; do echo -n "$(((RANDOM - 16384) % 100)), "; done)"
75 		 * slightly modified to ensure that there were 0, -ve and +ve duplicates
76 		 */
77 		static int actual_int[] = {
78 			1,   18,  -78, 35,  -67, -71, -12, -69, -60, 91,  -15, -99, -33,
79 			-52, 52,  -4,  -89, -7,	 22,  -52, -87, 32,  -23, 30,  -35, -9,
80 			15,  -61, 36,  -49, 24,	 -72, -63, 77,	88,  -93, 13,  49,  41,
81 			35,  -5,  -72, -46, 64,	 -46, -97, -88, 90,  63,  49,  12,  -58,
82 			-76, 54,  75,  49,  11,	 61,  42,  0,	-42, 42,  -42,
83 		};
84 
85 		/* echo $(echo "$NUMS" | sed -e 's/,/\n/g' | sort -n | sed -e 's/\(.*\)/\1,\ /g') */
86 		static const int expect_int[] = {
87 			-99, -97, -93, -89, -88, -87, -78, -76, -72, -72, -71, -69, -67,
88 			-63, -61, -60, -58, -52, -52, -49, -46, -46, -42, -42, -35, -33,
89 			-23, -15, -12, -9,  -7,	 -5,  -4,  0,	1,   11,  12,  13,  15,
90 			18,  22,  24,  30,  32,	 35,  35,  36,	41,  42,  42,  49,  49,
91 			49,  52,  54,  61,  63,	 64,  75,  77,	88,  90,  91,
92 		};
93 
94 		qsort(actual_int, ARRAY_SIZE(actual_int), sizeof(int), compare_ints);
95 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
96 				  "size 64 not sorted");
97 	}
98 
99 	{
100 		/*
101 		 * NUMS="$(for i in `seq 0 92`; do echo -n "$(((RANDOM - 16384) % 100)), "; done)"
102 		 * slightly modified to ensure that there were 0, -ve and +ve duplicates
103 		 */
104 		static int actual_int[] = {
105 			1,   18,  -78, 35,  -67, -71, -12, -69, -60, 91,  -15, -99, -33, -52,
106 			52,  -4,  -89, -7,  22,	 -52, -87, 32,	-23, 30,  -35, -9,  15,	 -61,
107 			36,  -49, 24,  -72, -63, 77,  88,  -93, 13,  49,  41,  35,  -5,	 -72,
108 			-46, 64,  -46, -97, 90,	 63,  49,  12,	-58, -76, 54,  75,  49,	 11,
109 			61,  -45, 92,  7,   74,	 -3,  -9,  96,	83,  33,  15,  -40, -84, -57,
110 			40,  -93, -27, 38,  24,	 41,  -70, -51, -88, 27,  94,  51,  -11, -2,
111 			-21, -70, -6,  77,  42,	 0,   -42, 42,	-42,
112 		};
113 
114 		/* echo $(echo "$NUMS" | sed -e 's/,/\n/g' | sort -n | sed -e 's/\(.*\)/\1,\ /g') */
115 		static const int expect_int[] = {
116 			-99, -97, -93, -93, -89, -88, -87, -84, -78, -76, -72, -72, -71, -70,
117 			-70, -69, -67, -63, -61, -60, -58, -57, -52, -52, -51, -49, -46, -46,
118 			-45, -42, -42, -40, -35, -33, -27, -23, -21, -15, -12, -11, -9,	 -9,
119 			-7,  -6,  -5,  -4,  -3,	 -2,  0,   1,	7,   11,  12,  13,  15,	 15,
120 			18,  22,  24,  24,  27,	 30,  32,  33,	35,  35,  36,  38,  40,	 41,
121 			41,  42,  42,  49,  49,	 49,  51,  52,	54,  61,  63,  64,  74,	 75,
122 			77,  77,  83,  88,  90,	 91,  92,  94,	96,
123 		};
124 
125 		qsort(actual_int, ARRAY_SIZE(actual_int), sizeof(int), compare_ints);
126 		zassert_mem_equal(actual_int, expect_int, sizeof(expect_int),
127 				  "size 93 not sorted");
128 	}
129 }
130 
compare_ints_with_boolp_arg(const void * a,const void * b,void * argp)131 static int compare_ints_with_boolp_arg(const void *a, const void *b, void *argp)
132 {
133 	int aa = *(const int *)a;
134 	int bb = *(const int *)b;
135 
136 	*(bool *)argp = true;
137 
138 	return (aa > bb) - (aa < bb);
139 }
140 
ZTEST(libc_common,test_qsort_r)141 ZTEST(libc_common, test_qsort_r)
142 {
143 	bool arg = false;
144 
145 	const int expect_int[] = { 1, 5, 7 };
146 	int actual_int[] = { 1, 7, 5 };
147 
148 	qsort_r(actual_int, ARRAY_SIZE(actual_int), sizeof(actual_int[0]),
149 		compare_ints_with_boolp_arg, &arg);
150 
151 	zassert_mem_equal(actual_int, expect_int, sizeof(expect_int), "array not sorted");
152 	zassert_true(arg, "arg not modified");
153 }
154