[libc-commits] [libc] 5eb6b82 - [libc] Add an implementation of qsort.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Fri Sep 24 12:23:02 PDT 2021
Author: Siva Chandra Reddy
Date: 2021-09-24T19:22:45Z
New Revision: 5eb6b8272931473f3b279db5d2c0006993fda21a
URL: https://github.com/llvm/llvm-project/commit/5eb6b8272931473f3b279db5d2c0006993fda21a
DIFF: https://github.com/llvm/llvm-project/commit/5eb6b8272931473f3b279db5d2c0006993fda21a.diff
LOG: [libc] Add an implementation of qsort.
A fuzzer for qsort has also been added.
Reviewed By: michaelrj
Differential Revision: https://reviews.llvm.org/D110382
Added:
libc/fuzzing/stdlib/CMakeLists.txt
libc/fuzzing/stdlib/qsort_fuzz.cpp
libc/src/stdlib/qsort.cpp
libc/src/stdlib/qsort.h
libc/test/src/stdlib/qsort_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/api.td
libc/config/linux/x86_64/entrypoints.txt
libc/fuzzing/CMakeLists.txt
libc/spec/spec.td
libc/spec/stdc.td
libc/src/stdlib/CMakeLists.txt
libc/test/src/stdlib/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 619e628e5d3a7..937cc531049ec 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -61,6 +61,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.ldiv
libc.src.stdlib.llabs
libc.src.stdlib.lldiv
+ libc.src.stdlib.qsort
libc.src.stdlib.strtol
libc.src.stdlib.strtoll
libc.src.stdlib.strtoul
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 095f25faa521c..d4fec7a52f234 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -287,13 +287,20 @@ def BSearchCompareTDefn : TypeDecl<"__bsearchcompare_t"> {
}];
}
+def QSortCompareTDefn : TypeDecl<"__qsortcompare_t"> {
+ let Decl = [{
+ typedef int(*__qsortcompare_t)(const void *, const void *);
+ }];
+}
+
def StdlibAPI : PublicAPI<"stdlib.h"> {
let TypeDeclarations = [
DivT,
LDivT,
LLDivT,
SizeT,
- BSearchCompareTDefn
+ BSearchCompareTDefn,
+ QSortCompareTDefn,
];
}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 7c87b6fb81a8f..b261a1a1d7614 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -61,6 +61,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.ldiv
libc.src.stdlib.llabs
libc.src.stdlib.lldiv
+ libc.src.stdlib.qsort
libc.src.stdlib.strtol
libc.src.stdlib.strtoll
libc.src.stdlib.strtoul
diff --git a/libc/fuzzing/CMakeLists.txt b/libc/fuzzing/CMakeLists.txt
index aed5402250e59..5d8a23352470e 100644
--- a/libc/fuzzing/CMakeLists.txt
+++ b/libc/fuzzing/CMakeLists.txt
@@ -2,4 +2,5 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer")
add_custom_target(libc-fuzzer)
add_subdirectory(math)
+add_subdirectory(stdlib)
add_subdirectory(string)
diff --git a/libc/fuzzing/stdlib/CMakeLists.txt b/libc/fuzzing/stdlib/CMakeLists.txt
new file mode 100644
index 0000000000000..db827f57075f2
--- /dev/null
+++ b/libc/fuzzing/stdlib/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_libc_fuzzer(
+ qsort_fuzz
+ SRCS
+ qsort_fuzz.cpp
+ DEPENDS
+ libc.src.stdlib.qsort
+)
+
diff --git a/libc/fuzzing/stdlib/qsort_fuzz.cpp b/libc/fuzzing/stdlib/qsort_fuzz.cpp
new file mode 100644
index 0000000000000..dbbc8e96f9243
--- /dev/null
+++ b/libc/fuzzing/stdlib/qsort_fuzz.cpp
@@ -0,0 +1,46 @@
+//===-- qsort_fuzz.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Fuzzing test for llvm-libc qsort implementation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/qsort.h"
+#include <stdint.h>
+
+static int int_compare(const void *l, const void *r) {
+ int li = *reinterpret_cast<const int *>(l);
+ int ri = *reinterpret_cast<const int *>(r);
+ if (li == ri)
+ return 0;
+ else if (li > ri)
+ return 1;
+ else
+ return -1;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ const size_t array_size = size / sizeof(int);
+ if (array_size == 0)
+ return 0;
+
+ int *array = new int[array_size];
+ const int *data_as_int = reinterpret_cast<const int *>(data);
+ for (size_t i = 0; i < array_size; ++i)
+ array[i] = data_as_int[i];
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ for (size_t i = 0; i < array_size - 1; ++i) {
+ if (array[i] > array[i + 1])
+ __builtin_trap();
+ }
+
+ delete[] array;
+ return 0;
+}
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 40ab413c2a939..d19c87d0623a5 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -92,6 +92,7 @@ def SigHandlerT : NamedType<"__sighandler_t">;
def TimeTType : NamedType<"time_t">;
def BSearchCompareT : NamedType<"__bsearchcompare_t">;
+def QSortCompareT : NamedType<"__qsortcompare_t">;
//added because __assert_fail needs it.
def UnsignedType : NamedType<"unsigned">;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 9889436a5fafb..2b6488142206c 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -481,6 +481,7 @@ def StdC : StandardSpec<"stdc"> {
LLDivTType,
SizeTType,
BSearchCompareT,
+ QSortCompareT,
], // Types
[], // Enumerations
[
@@ -500,6 +501,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"ldiv", RetValSpec<LDivTType>, [ArgSpec<LongType>, ArgSpec<LongType>]>,
FunctionSpec<"lldiv", RetValSpec<LLDivTType>, [ArgSpec<LongLongType>, ArgSpec<LongLongType>]>,
+ FunctionSpec<"qsort", RetValSpec<VoidType>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<QSortCompareT>]>,
+
FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
FunctionSpec<"strtoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
FunctionSpec<"strtoul", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index f46a6b9c6413f..6fb35aaca19d8 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -141,6 +141,16 @@ add_entrypoint_object(
libc.include.stdlib
)
+add_entrypoint_object(
+ qsort
+ SRCS
+ qsort.cpp
+ HDRS
+ qsort.h
+ DEPENDS
+ libc.include.stdlib
+)
+
if(NOT LLVM_LIBC_FULL_BUILD)
return()
endif()
diff --git a/libc/src/stdlib/qsort.cpp b/libc/src/stdlib/qsort.cpp
new file mode 100644
index 0000000000000..4eaff618d0a7a
--- /dev/null
+++ b/libc/src/stdlib/qsort.cpp
@@ -0,0 +1,120 @@
+//===-- Implementation of qsort -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/qsort.h"
+#include "src/__support/common.h"
+
+#include <stdint.h>
+
+namespace __llvm_libc {
+
+namespace internal {
+
+// A simple quicksort implementation using the Hoare partition scheme.
+
+class Array {
+ typedef int (*comparator)(const void *, const void *);
+
+ uint8_t *array;
+ size_t array_size;
+ size_t elem_size;
+ comparator compare;
+
+public:
+ Array(uint8_t *a, size_t s, size_t e, comparator c)
+ : array(a), array_size(s), elem_size(e), compare(c) {}
+
+ uint8_t *get(size_t i) const { return array + i * elem_size; }
+
+ void swap(size_t i, size_t j) const {
+ uint8_t *elem_i = get(i);
+ uint8_t *elem_j = get(j);
+ for (size_t b = 0; b < elem_size; ++b) {
+ uint8_t temp = elem_i[b];
+ elem_i[b] = elem_j[b];
+ elem_j[b] = temp;
+ }
+ }
+
+ int elem_compare(size_t i, const uint8_t *other) const {
+ return compare(get(i), other);
+ }
+
+ size_t size() const { return array_size; }
+
+ // Make an Array starting at index |i| and size |s|.
+ Array make_array(size_t i, size_t s) const {
+ return Array(get(i), s, elem_size, compare);
+ }
+};
+
+static size_t partition(const Array &array) {
+ const size_t array_size = array.size();
+ size_t pivot_index = array_size / 2;
+ uint8_t *pivot = array.get(pivot_index);
+ size_t i = 0;
+ size_t j = array_size - 1;
+
+ while (true) {
+ int compare_i, compare_j;
+
+ while ((compare_i = array.elem_compare(i, pivot)) < 0)
+ ++i;
+ while ((compare_j = array.elem_compare(j, pivot)) > 0)
+ --j;
+
+ // At some point i will crossover j so we will definitely break out of
+ // this while loop.
+ if (i >= j)
+ return j + 1;
+
+ array.swap(i, j);
+
+ // The pivot itself might have got swapped so we will update the pivot.
+ if (i == pivot_index) {
+ pivot = array.get(j);
+ pivot_index = j;
+ } else if (j == pivot_index) {
+ pivot = array.get(i);
+ pivot_index = i;
+ }
+
+ if (compare_i == 0 && compare_j == 0) {
+ // If we do not move the pointers, we will end up with an
+ // infinite loop as i and j will be stuck without advancing.
+ ++i;
+ --j;
+ }
+ }
+}
+
+static void quicksort(const Array &array) {
+ const size_t array_size = array.size();
+ if (array_size <= 1)
+ return;
+ size_t split_index = partition(array);
+ if (array_size <= 2) {
+ // The partition operation sorts the two element array.
+ return;
+ }
+ quicksort(array.make_array(0, split_index));
+ quicksort(array.make_array(split_index, array.size() - split_index));
+}
+
+} // namespace internal
+
+LLVM_LIBC_FUNCTION(void, qsort,
+ (void *array, size_t array_size, size_t elem_size,
+ int (*compare)(const void *, const void *))) {
+ if (array == nullptr || array_size == 0 || elem_size == 0)
+ return;
+ internal::quicksort(internal::Array(reinterpret_cast<uint8_t *>(array),
+ array_size, elem_size, compare));
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdlib/qsort.h b/libc/src/stdlib/qsort.h
new file mode 100644
index 0000000000000..d716089e484df
--- /dev/null
+++ b/libc/src/stdlib/qsort.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for qsort -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDLIB_QSORT_H
+#define LLVM_LIBC_SRC_STDLIB_QSORT_H
+
+#include <stdlib.h>
+
+namespace __llvm_libc {
+
+void qsort(void *array, size_t array_size, size_t elem_size,
+ int (*compare)(const void *, const void *));
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDLIB_QSORT_H
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index e39130650d433..ce66488bb3405 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -178,3 +178,14 @@ add_libc_unittest(
libc.include.stdlib
libc.src.stdlib.bsearch
)
+
+add_libc_unittest(
+ qsort_test
+ SUITE
+ libc_stdlib_unittests
+ SRCS
+ qsort_test.cpp
+ DEPENDS
+ libc.include.stdlib
+ libc.src.stdlib.qsort
+)
diff --git a/libc/test/src/stdlib/qsort_test.cpp b/libc/test/src/stdlib/qsort_test.cpp
new file mode 100644
index 0000000000000..8de8beee598d9
--- /dev/null
+++ b/libc/test/src/stdlib/qsort_test.cpp
@@ -0,0 +1,265 @@
+//===-- Unittests for qsort -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/qsort.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <stdlib.h>
+
+static int int_compare(const void *l, const void *r) {
+ int li = *reinterpret_cast<const int *>(l);
+ int ri = *reinterpret_cast<const int *>(r);
+ if (li == ri)
+ return 0;
+ else if (li > ri)
+ return 1;
+ else
+ return -1;
+}
+
+TEST(LlvmLibcQsortTest, SortedArray) {
+ int array[25] = {10, 23, 33, 35, 55, 70, 71, 100, 110,
+ 123, 133, 135, 155, 170, 171, 1100, 1110, 1123,
+ 1133, 1135, 1155, 1170, 1171, 11100, 12310};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 10);
+ ASSERT_LE(array[1], 23);
+ ASSERT_LE(array[2], 33);
+ ASSERT_LE(array[3], 35);
+ ASSERT_LE(array[4], 55);
+ ASSERT_LE(array[5], 70);
+ ASSERT_LE(array[6], 71);
+ ASSERT_LE(array[7], 100);
+ ASSERT_LE(array[8], 110);
+ ASSERT_LE(array[9], 123);
+ ASSERT_LE(array[10], 133);
+ ASSERT_LE(array[11], 135);
+ ASSERT_LE(array[12], 155);
+ ASSERT_LE(array[13], 170);
+ ASSERT_LE(array[14], 171);
+ ASSERT_LE(array[15], 1100);
+ ASSERT_LE(array[16], 1110);
+ ASSERT_LE(array[17], 1123);
+ ASSERT_LE(array[18], 1133);
+ ASSERT_LE(array[19], 1135);
+ ASSERT_LE(array[20], 1155);
+ ASSERT_LE(array[21], 1170);
+ ASSERT_LE(array[22], 1171);
+ ASSERT_LE(array[23], 11100);
+ ASSERT_LE(array[24], 12310);
+}
+
+TEST(LlvmLibcQsortTest, ReverseSortedArray) {
+ int array[25] = {25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,
+ 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ for (int i = 0; i < int(array_size - 1); ++i)
+ ASSERT_LE(array[i], i + 1);
+}
+
+TEST(LlvmLibcQsortTest, AllEqualElements) {
+ int array[25] = {100, 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ for (size_t i = 0; i < array_size - 1; ++i)
+ ASSERT_LE(array[i], 100);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedArray1) {
+ int array[25] = {10, 23, 8, 35, 55, 45, 40, 100, 110, 123, 90, 80, 70,
+ 60, 171, 11, 1, -1, -5, -10, 1155, 1170, 1171, 12, -100};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], -100);
+ ASSERT_LE(array[1], -10);
+ ASSERT_LE(array[2], -5);
+ ASSERT_LE(array[3], -1);
+ ASSERT_LE(array[4], 1);
+ ASSERT_LE(array[5], 8);
+ ASSERT_LE(array[6], 10);
+ ASSERT_LE(array[7], 11);
+ ASSERT_LE(array[8], 12);
+ ASSERT_LE(array[9], 23);
+ ASSERT_LE(array[10], 35);
+ ASSERT_LE(array[11], 40);
+ ASSERT_LE(array[12], 45);
+ ASSERT_LE(array[13], 55);
+ ASSERT_LE(array[14], 60);
+ ASSERT_LE(array[15], 70);
+ ASSERT_LE(array[16], 80);
+ ASSERT_LE(array[17], 90);
+ ASSERT_LE(array[18], 100);
+ ASSERT_LE(array[19], 110);
+ ASSERT_LE(array[20], 123);
+ ASSERT_LE(array[21], 171);
+ ASSERT_LE(array[22], 1155);
+ ASSERT_LE(array[23], 1170);
+ ASSERT_LE(array[24], 1171);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedArray2) {
+ int array[7] = {10, 40, 45, 55, 35, 23, 60};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 10);
+ ASSERT_LE(array[1], 23);
+ ASSERT_LE(array[2], 35);
+ ASSERT_LE(array[3], 40);
+ ASSERT_LE(array[4], 45);
+ ASSERT_LE(array[5], 55);
+ ASSERT_LE(array[6], 60);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedArrayDuplicateElements1) {
+ int array[6] = {10, 10, 20, 20, 5, 5};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 5);
+ ASSERT_LE(array[1], 5);
+ ASSERT_LE(array[2], 10);
+ ASSERT_LE(array[3], 10);
+ ASSERT_LE(array[4], 20);
+ ASSERT_LE(array[5], 20);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedArrayDuplicateElements2) {
+ int array[10] = {20, 10, 10, 10, 10, 20, 21, 21, 21, 21};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 10);
+ ASSERT_LE(array[1], 10);
+ ASSERT_LE(array[2], 10);
+ ASSERT_LE(array[3], 10);
+ ASSERT_LE(array[4], 20);
+ ASSERT_LE(array[5], 20);
+ ASSERT_LE(array[6], 21);
+ ASSERT_LE(array[7], 21);
+ ASSERT_LE(array[8], 21);
+ ASSERT_LE(array[9], 21);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedArrayDuplicateElements3) {
+ int array[10] = {20, 30, 30, 30, 30, 20, 21, 21, 21, 21};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 20);
+ ASSERT_LE(array[1], 20);
+ ASSERT_LE(array[2], 21);
+ ASSERT_LE(array[3], 21);
+ ASSERT_LE(array[4], 21);
+ ASSERT_LE(array[5], 21);
+ ASSERT_LE(array[6], 30);
+ ASSERT_LE(array[7], 30);
+ ASSERT_LE(array[8], 30);
+ ASSERT_LE(array[9], 30);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedThreeElementArray1) {
+ int array[3] = {14999024, 0, 3};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 0);
+ ASSERT_LE(array[1], 3);
+ ASSERT_LE(array[2], 14999024);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedThreeElementArray2) {
+ int array[3] = {3, 14999024, 0};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 0);
+ ASSERT_LE(array[1], 3);
+ ASSERT_LE(array[2], 14999024);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedThreeElementArray3) {
+ int array[3] = {3, 0, 14999024};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 0);
+ ASSERT_LE(array[1], 3);
+ ASSERT_LE(array[2], 14999024);
+}
+
+TEST(LlvmLibcQsortTest, SameElementThreeElementArray) {
+ int array[3] = {12345, 12345, 12345};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 12345);
+ ASSERT_LE(array[1], 12345);
+ ASSERT_LE(array[2], 12345);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedTwoElementArray1) {
+ int array[2] = {14999024, 0};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 0);
+ ASSERT_LE(array[1], 14999024);
+}
+
+TEST(LlvmLibcQsortTest, UnsortedTwoElementArray2) {
+ int array[2] = {0, 14999024};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 0);
+ ASSERT_LE(array[1], 14999024);
+}
+
+TEST(LlvmLibcQsortTest, SameElementTwoElementArray) {
+ int array[2] = {12345, 12345};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], 12345);
+ ASSERT_LE(array[1], 12345);
+}
+
+TEST(LlvmLibcQSortTest, SingleElementArray) {
+ constexpr int elem = 12345;
+ int array[1] = {elem};
+ constexpr size_t array_size = sizeof(array) / sizeof(int);
+
+ __llvm_libc::qsort(array, array_size, sizeof(int), int_compare);
+
+ ASSERT_LE(array[0], elem);
+}
More information about the libc-commits
mailing list