Add more CTL content

This commit is contained in:
Justine Tunney 2024-06-28 19:07:35 -07:00
parent 38921dc46b
commit 021c53ba32
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
56 changed files with 1747 additions and 298 deletions

View file

@ -18,6 +18,7 @@ TEST_CTL_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_STDIO \
LIBC_THREAD \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \

View file

@ -18,6 +18,7 @@
#include "ctl/accumulate.h"
#include "ctl/array.h"
#include "libc/mem/leaks.h"
// #include <array>
// #include <numeric>
@ -48,4 +49,6 @@ main()
// Test accumulation with single element
if (ctl::accumulate(arr.begin(), arr.begin() + 1, 0) != 1)
return 5;
CheckForMemoryLeaks();
}

View file

@ -18,6 +18,7 @@
#include "ctl/advance.h"
#include "ctl/array.h"
#include "libc/mem/leaks.h"
// #include <array>
// #include <iterator>
@ -53,4 +54,6 @@ main()
ctl::advance(it, -2);
if (it != arr.begin())
return 5;
CheckForMemoryLeaks();
}

View file

@ -18,6 +18,7 @@
#include "ctl/all_of.h"
#include "ctl/array.h"
#include "libc/mem/leaks.h"
#include <algorithm>
#include <array>
@ -49,4 +50,6 @@ main()
// Test with no elements satisfying the condition
if (ctl::all_of(arr1.begin(), arr1.end(), [](int n) { return n > 10; }))
return 5;
CheckForMemoryLeaks();
}

View file

@ -18,6 +18,7 @@
#include "ctl/any_of.h"
#include "ctl/array.h"
#include "libc/mem/leaks.h"
// #include <algorithm>
// #include <array>
@ -48,4 +49,6 @@ main()
// Test with a different condition
if (!ctl::any_of(arr1.begin(), arr1.end(), [](int n) { return n > 5; }))
return 5;
CheckForMemoryLeaks();
}

View file

@ -17,8 +17,11 @@
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/array.h"
#include "ctl/string.h"
#include "libc/mem/leaks.h"
// #include <array>
// #include <string>
// #define ctl std
int
@ -264,4 +267,21 @@ main()
if (rit != arr.rend())
return 4;
}
{
ctl::array<ctl::string, 2> A = { "hi", "theretheretheretherethere" };
if (A.size() != 2)
return 76;
if (A[0] != "hi")
return 77;
if (A[1] != "theretheretheretherethere")
return 78;
A = { "theretheretheretherethere", "hi" };
if (A[0] != "theretheretheretherethere")
return 79;
if (A[1] != "hi")
return 80;
}
CheckForMemoryLeaks();
}

View file

@ -20,6 +20,7 @@
#include "ctl/back_inserter.h"
#include "ctl/copy.h"
#include "ctl/vector.h"
#include "libc/mem/leaks.h"
// #include <array>
// #include <iterator>
@ -29,33 +30,38 @@
int
main()
{
ctl::vector<int> vec = { 1, 2, 3 };
ctl::array<int, 3> arr = { 4, 5, 6 };
// Use back_inserter to append elements from arr to vec
ctl::copy(arr.begin(), arr.end(), ctl::back_inserter(vec));
{
ctl::vector<int> vec = { 1, 2, 3 };
ctl::array<int, 3> arr = { 4, 5, 6 };
// Check if vec now contains all elements
if (vec.size() != 6)
return 1;
if (vec[0] != 1 || vec[1] != 2 || vec[2] != 3 || vec[3] != 4 ||
vec[4] != 5 || vec[5] != 6)
return 2;
// Use back_inserter to append elements from arr to vec
ctl::copy(arr.begin(), arr.end(), ctl::back_inserter(vec));
// Use back_inserter with a single element
ctl::back_inserter(vec) = 7;
// Check if vec now contains all elements
if (vec.size() != 6)
return 1;
if (vec[0] != 1 || vec[1] != 2 || vec[2] != 3 || vec[3] != 4 ||
vec[4] != 5 || vec[5] != 6)
return 2;
// Check if the new element was added
if (vec.size() != 7)
return 3;
if (vec[6] != 7)
return 4;
// Use back_inserter with a single element
ctl::back_inserter(vec) = 7;
// Test with an empty source range
ctl::array<int, 0> empty_arr;
ctl::copy(empty_arr.begin(), empty_arr.end(), ctl::back_inserter(vec));
// Check if the new element was added
if (vec.size() != 7)
return 3;
if (vec[6] != 7)
return 4;
// Check that no elements were added
if (vec.size() != 7)
return 5;
// Test with an empty source range
ctl::array<int, 0> empty_arr;
ctl::copy(empty_arr.begin(), empty_arr.end(), ctl::back_inserter(vec));
// Check that no elements were added
if (vec.size() != 7)
return 5;
}
CheckForMemoryLeaks();
}

View file

@ -18,49 +18,56 @@
#include "ctl/array.h"
#include "ctl/copy.h"
#include "libc/mem/leaks.h"
// #include <iterator>
// #include <algorithm>
// #include <array>
// #include <iterator>
// #define ctl std
int
main()
{
ctl::array<int, 5> src = { 1, 2, 3, 4, 5 };
ctl::array<int, 5> dest = { 0, 0, 0, 0, 0 };
// Test basic copy
ctl::copy(src.begin(), src.end(), dest.begin());
for (size_t i = 0; i < 5; ++i) {
if (dest[i] != src[i])
return 1;
{
ctl::array<int, 5> src = { 1, 2, 3, 4, 5 };
ctl::array<int, 5> dest = { 0, 0, 0, 0, 0 };
// Test basic copy
ctl::copy(src.begin(), src.end(), dest.begin());
for (size_t i = 0; i < 5; ++i) {
if (dest[i] != src[i])
return 1;
}
// Test partial copy
ctl::array<int, 5> dest2 = { 0, 0, 0, 0, 0 };
ctl::copy(src.begin(), src.begin() + 3, dest2.begin());
if (dest2[0] != 1 || dest2[1] != 2 || dest2[2] != 3 || dest2[3] != 0 ||
dest2[4] != 0)
return 2;
// Test copy to middle of destination
ctl::array<int, 7> dest3 = { 0, 0, 0, 0, 0, 0, 0 };
ctl::copy(src.begin(), src.end(), dest3.begin() + 1);
if (dest3[0] != 0 || dest3[1] != 1 || dest3[2] != 2 || dest3[3] != 3 ||
dest3[4] != 4 || dest3[5] != 5 || dest3[6] != 0)
return 3;
// Test copy with empty range
ctl::array<int, 5> dest4 = { 0, 0, 0, 0, 0 };
ctl::copy(src.begin(), src.begin(), dest4.begin());
for (size_t i = 0; i < 5; ++i) {
if (dest4[i] != 0)
return 4;
}
// Test copy return value
ctl::array<int, 5> dest5 = { 0, 0, 0, 0, 0 };
auto result = ctl::copy(src.begin(), src.end(), dest5.begin());
if (result != dest5.end())
return 5;
}
// Test partial copy
ctl::array<int, 5> dest2 = { 0, 0, 0, 0, 0 };
ctl::copy(src.begin(), src.begin() + 3, dest2.begin());
if (dest2[0] != 1 || dest2[1] != 2 || dest2[2] != 3 || dest2[3] != 0 ||
dest2[4] != 0)
return 2;
// Test copy to middle of destination
ctl::array<int, 7> dest3 = { 0, 0, 0, 0, 0, 0, 0 };
ctl::copy(src.begin(), src.end(), dest3.begin() + 1);
if (dest3[0] != 0 || dest3[1] != 1 || dest3[2] != 2 || dest3[3] != 3 ||
dest3[4] != 4 || dest3[5] != 5 || dest3[6] != 0)
return 3;
// Test copy with empty range
ctl::array<int, 5> dest4 = { 0, 0, 0, 0, 0 };
ctl::copy(src.begin(), src.begin(), dest4.begin());
for (size_t i = 0; i < 5; ++i) {
if (dest4[i] != 0)
return 4;
}
// Test copy return value
ctl::array<int, 5> dest5 = { 0, 0, 0, 0, 0 };
auto result = ctl::copy(src.begin(), src.end(), dest5.begin());
if (result != dest5.end())
return 5;
CheckForMemoryLeaks();
}

114
test/ctl/mutex_test.cc Normal file
View file

@ -0,0 +1,114 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
//
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/mutex.h"
#include "libc/mem/leaks.h"
// #include <mutex>
// #define ctl std
ctl::mutex mtx;
int shared_resource = 0;
const int NUM_THREADS = 5;
const int ITERATIONS = 100000;
void*
increment_resource(void* arg)
{
for (int i = 0; i < ITERATIONS; ++i) {
mtx.lock();
++shared_resource;
mtx.unlock();
}
return nullptr;
}
void*
decrement_resource(void* arg)
{
for (int i = 0; i < ITERATIONS; ++i) {
mtx.lock();
--shared_resource;
mtx.unlock();
}
return nullptr;
}
int
test_basic_locking()
{
shared_resource = 0;
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i)
if (pthread_create(&threads[i], 0, increment_resource, 0) != 0)
return 1;
for (int i = 0; i < NUM_THREADS; ++i)
if (pthread_join(threads[i], 0) != 0)
return 2;
return (shared_resource == NUM_THREADS * ITERATIONS) ? 0 : 3;
}
int
test_lock_contention()
{
shared_resource = 0;
pthread_t threads[NUM_THREADS * 2];
for (int i = 0; i < NUM_THREADS; ++i)
if (pthread_create(&threads[i], 0, increment_resource, 0) != 0 ||
pthread_create(&threads[i + NUM_THREADS],
nullptr,
decrement_resource,
nullptr) != 0)
return 4;
for (int i = 0; i < NUM_THREADS * 2; ++i)
if (pthread_join(threads[i], 0) != 0)
return 5;
return (shared_resource == 0) ? 0 : 6;
}
int
test_try_lock()
{
ctl::mutex try_mtx;
if (!try_mtx.try_lock())
return 7;
if (try_mtx.try_lock())
return 8;
try_mtx.unlock();
return 0;
}
int
main()
{
int result;
result = test_basic_locking();
if (result != 0)
return result;
result = test_lock_contention();
if (result != 0)
return result;
result = test_try_lock();
if (result != 0)
return result;
CheckForMemoryLeaks();
}

130
test/ctl/sort_test.cc Normal file
View file

@ -0,0 +1,130 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
//
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/is_sorted.h"
#include "ctl/sort.h"
#include "ctl/string.h"
#include "ctl/vector.h"
#include "libc/mem/leaks.h"
#include "libc/stdio/rand.h"
// #include <algorithm>
// #include <string>
// #include <vector>
// #define ctl std
// Test sorting integers
int
test_sort_integers()
{
ctl::vector<int> v = { 5, 2, 8, 1, 9, 3, 7, 6, 4 };
ctl::sort(v.begin(), v.end());
if (!ctl::is_sorted(v.begin(), v.end(), ctl::less<int>()))
return 1;
return 0;
}
// Test sorting with custom comparator
int
test_sort_custom_compare()
{
ctl::vector<int> v = { 5, 2, 8, 1, 9, 3, 7, 6, 4 };
ctl::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
if (!ctl::is_sorted(v.begin(), v.end(), [](int a, int b) { return a > b; }))
return 2;
return 0;
}
// Test sorting strings
int
test_sort_strings()
{
ctl::vector<ctl::string> v = { "banana", "apple", "cherry", "date" };
ctl::sort(v.begin(), v.end());
if (!ctl::is_sorted(v.begin(), v.end(), ctl::less<ctl::string>()))
return 3;
return 0;
}
// Test sorting with large number of elements
int
test_sort_large()
{
const int SIZE = 10000;
ctl::vector<int> v(SIZE);
for (int i = 0; i < SIZE; ++i)
v[i] = rand() % SIZE;
ctl::sort(v.begin(), v.end());
if (!is_sorted(v.begin(), v.end(), ctl::less<int>()))
return 4;
return 0;
}
// Test sorting already sorted vector
int
test_sort_sorted()
{
ctl::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ctl::sort(v.begin(), v.end());
if (!is_sorted(v.begin(), v.end(), ctl::less<int>()))
return 5;
return 0;
}
// Test sorting reverse sorted vector
int
test_sort_reverse()
{
ctl::vector<int> v = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
ctl::sort(v.begin(), v.end());
if (!is_sorted(v.begin(), v.end(), ctl::less<int>()))
return 6;
return 0;
}
int
main()
{
int result;
result = test_sort_integers();
if (result != 0)
return result;
result = test_sort_custom_compare();
if (result != 0)
return result;
result = test_sort_strings();
if (result != 0)
return result;
result = test_sort_large();
if (result != 0)
return result;
result = test_sort_sorted();
if (result != 0)
return result;
result = test_sort_reverse();
if (result != 0)
return result;
CheckForMemoryLeaks();
}

View file

@ -17,8 +17,8 @@
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/string.h"
#include <__utility/move.h>
#include "ctl/utility.h"
#include "libc/mem/leaks.h"
#include "libc/calls/struct/timespec.h"
#include "libc/runtime/runtime.h"
@ -100,7 +100,7 @@ main()
BENCH(1000000, 1, {
ctl::string s(small);
ctl::string s2(std::move(s));
ctl::string s2(ctl::move(s));
});
BENCH(1000000, 1, {
@ -119,7 +119,7 @@ main()
BENCH(1000000, 1, {
ctl::string s(big);
ctl::string s2(std::move(s));
ctl::string s2(ctl::move(s));
});
BENCH(1000000, 1, {
@ -142,5 +142,5 @@ main()
BENCH(1000000, 1, { ctl::string s(big_trunc); });
}
return 0;
CheckForMemoryLeaks();
}

View file

@ -16,13 +16,14 @@
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/is_same.h"
#include "ctl/string.h"
#include "ctl/type_traits.h"
#include "libc/mem/leaks.h"
#include "libc/str/str.h"
// #include <string>
// #include <utility>
// #define ctl std
using String = ctl::string;

View file

@ -173,5 +173,4 @@ main(int argc, char* argv[])
}
CheckForMemoryLeaks();
return 0;
}

161
test/ctl/tuple_test.cc Normal file
View file

@ -0,0 +1,161 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
//
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/string.h"
#include "ctl/tuple.h"
#include "libc/mem/leaks.h"
// #include <string>
// #include <tuple>
// #define ctl std
int
test_tuple_creation()
{
ctl::tuple<int, double, ctl::string> t(1, 2.5, "hello");
if (ctl::get<0>(t) != 1 || ctl::get<1>(t) != 2.5 ||
ctl::get<2>(t) != "hello") {
return 1;
}
return 0;
}
int
test_make_tuple()
{
auto t = ctl::make_tuple(1, 2.5, ctl::string("hello"));
if (ctl::get<0>(t) != 1 || ctl::get<1>(t) != 2.5 ||
ctl::get<2>(t) != "hello") {
return 2;
}
return 0;
}
int
test_tuple_get()
{
ctl::tuple<int, double, ctl::string> t(1, 2.5, "hello");
if (ctl::get<0>(t) != 1)
return 3;
if (ctl::get<1>(t) != 2.5)
return 4;
if (ctl::get<2>(t) != "hello")
return 5;
return 0;
}
int
test_tuple_comparison()
{
auto t1 = ctl::make_tuple(1, 2.5, "hello");
auto t2 = ctl::make_tuple(1, 2.5, "hello");
auto t3 = ctl::make_tuple(2, 3.5, "world");
if (!(t1 == t2))
return 6;
if (t1 != t2)
return 7;
if (t1 == t3)
return 8;
if (!(t1 != t3))
return 9;
return 0;
}
int
test_tuple_assignment()
{
ctl::tuple<int, double, ctl::string> t1(1, 2.5, "hello");
ctl::tuple<int, double, ctl::string> t2;
t2 = t1;
if (!(t1 == t2))
return 10;
return 0;
}
int
test_tuple_move()
{
ctl::tuple<int, double, ctl::string> t1(1, 2.5, "hello");
ctl::tuple<int, double, ctl::string> t2(ctl::move(t1));
if (ctl::get<0>(t2) != 1 || ctl::get<1>(t2) != 2.5 ||
ctl::get<2>(t2) != "hello") {
return 11;
}
return 0;
}
int
test_empty_tuple()
{
ctl::tuple<> t;
ctl::tuple<> t2;
if (!(t == t2))
return 12;
return 0;
}
int
test_single_element_tuple()
{
ctl::tuple<int> t(42);
if (ctl::get<0>(t) != 42)
return 13;
return 0;
}
int
main()
{
int result;
result = test_tuple_creation();
if (result != 0)
return result;
result = test_make_tuple();
if (result != 0)
return result;
result = test_tuple_get();
if (result != 0)
return result;
result = test_tuple_comparison();
if (result != 0)
return result;
result = test_tuple_assignment();
if (result != 0)
return result;
result = test_tuple_move();
if (result != 0)
return result;
result = test_empty_tuple();
if (result != 0)
return result;
result = test_single_element_tuple();
if (result != 0)
return result;
CheckForMemoryLeaks();
}

View file

@ -16,7 +16,7 @@
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ctl/type_traits.h"
#include "ctl/is_same.h"
#include "ctl/unique_ptr.h"
#include "libc/mem/leaks.h"
@ -41,29 +41,30 @@ MkRaw()
return ctl::make_unique_for_overwrite<T>();
}
#undef ctl
// #undef ctl
static int g = 0;
struct SetsGDeleter
{
void operator()(auto*) const noexcept
void operator()(auto* x) const noexcept
{
++g;
delete x;
}
};
struct StatefulDeleter
{
char state;
void operator()(auto*) const noexcept
void operator()(auto* x) const noexcept
{
}
};
struct FinalDeleter final
{
void operator()(auto*) const noexcept
void operator()(auto* x) const noexcept
{
}
};
@ -99,6 +100,7 @@ struct Derived : Base
int
main()
{
{
Ptr<int> x(new int(5));
}
@ -186,9 +188,9 @@ main()
g = 0;
{
auto x = Mk<SetsGDtor>();
x.release();
delete x.release();
}
if (g)
if (g != 1)
return 13;
}
@ -224,8 +226,5 @@ main()
Ptr<Base> z(ctl::move(y));
}
// next is 18
// TODO(mrdomino): Fix memory leaks reported by MODE=dbg
// CheckForMemoryLeaks();
CheckForMemoryLeaks();
}