Serenity Operating System
at master 99 lines 2.6 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibTest/TestCase.h> 8 9#include <AK/Noncopyable.h> 10#include <AK/QuickSort.h> 11#include <AK/StdLibExtras.h> 12 13TEST_CASE(sorts_without_copy) 14{ 15 struct NoCopy { 16 AK_MAKE_NONCOPYABLE(NoCopy); 17 18 public: 19 NoCopy() = default; 20 NoCopy(NoCopy&&) = default; 21 22 NoCopy& operator=(NoCopy&&) = default; 23 24 int value { 0 }; 25 }; 26 27 Array<NoCopy, 64> array; 28 29 // Test the dual pivot quick sort. 30 for (size_t i = 0; i < 64; ++i) 31 array[i].value = (64 - i) % 32 + 32; 32 33 dual_pivot_quick_sort(array, 0, array.size() - 1, [](auto& a, auto& b) { return a.value < b.value; }); 34 35 for (size_t i = 0; i < 63; ++i) 36 EXPECT(array[i].value <= array[i + 1].value); 37 38 // Test the single pivot quick sort. 39 for (size_t i = 0; i < 64; ++i) 40 array[i].value = (64 - i) % 32 + 32; 41 42 AK::single_pivot_quick_sort(array.begin(), array.end(), [](auto& a, auto& b) { return a.value < b.value; }); 43 44 for (size_t i = 0; i < 63; ++i) 45 EXPECT(array[i].value <= array[i + 1].value); 46} 47 48// This test case may fail to construct a worst-case input if the pivot choice 49// of the underlying quick_sort no longer matches the one used here. 50// So it provides no strong guarantees about the properties of quick_sort. 51TEST_CASE(maximum_stack_depth) 52{ 53 int const size = 256; 54 int* data = new int[size]; 55 56 for (int i = 0; i < size; i++) { 57 data[i] = i; 58 } 59 60 // Construct the data in such a way that the assumed pivot choice 61 // of (size / 2) causes the partitions to be of worst case size. 62 for (int i = 0; i < size / 2; i++) { 63 swap(data[i], data[i + (size - i) / 2]); 64 } 65 66 // Measure the depth of the call stack through the less_than argument 67 // of quick_sort as it gets copied for each recursive call. 68 struct DepthMeasurer { 69 int& max_depth; 70 int depth { 0 }; 71 DepthMeasurer(int& max_depth) 72 : max_depth(max_depth) 73 { 74 } 75 DepthMeasurer(DepthMeasurer const& obj) 76 : max_depth(obj.max_depth) 77 { 78 depth = obj.depth + 1; 79 if (depth > max_depth) { 80 max_depth = depth; 81 } 82 } 83 bool operator()(int& a, int& b) 84 { 85 return a < b; 86 } 87 }; 88 89 int max_depth = 0; 90 DepthMeasurer measurer(max_depth); 91 AK::single_pivot_quick_sort(data, data + size, measurer); 92 93 EXPECT(max_depth <= 64); 94 95 for (int i = 0; i < size; i++) 96 EXPECT(data[i] == i); 97 98 delete[] data; 99}