diff --git a/.github/workflows/dstruct-test.yml b/.github/workflows/dstruct-test.yml index e1d8ea3..6597554 100644 --- a/.github/workflows/dstruct-test.yml +++ b/.github/workflows/dstruct-test.yml @@ -15,15 +15,19 @@ jobs: runs-on: ubuntu-latest + defaults: + run: + working-directory: tests + steps: - uses: actions/checkout@v3 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@master - name: set build mode - run: xmake f -m debug + run: xmake f -m debug -y - name: build examples|test - run: xmake + run: xmake -y - name: run all test run: xmake r @@ -31,14 +35,18 @@ jobs: runs-on: windows-latest + defaults: + run: + working-directory: tests + steps: - uses: actions/checkout@v3 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@master - name: set build mode - run: xmake f -m debug + run: xmake f -m debug -y - name: build examples|test - run: xmake + run: xmake -y - name: run all test run: xmake r \ No newline at end of file diff --git a/README.md b/README.md index ff819aa..c42548b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# DStruct +# DStruct | 重构WIP - [开发看板](https://github.com/users/Sunrisepeak/projects/12) DStruct 是一个易于移植且结构简洁的数据结构模板库 diff --git a/core/common.hpp b/core/common.hpp index defd3b3..e177ae7 100644 --- a/core/common.hpp +++ b/core/common.hpp @@ -18,19 +18,6 @@ namespace dstruct { -#define DSTRUCT_TYPE_SPEC_HELPER(DStruct) \ -public: \ - using ValueType = typename DStruct::ValueType; \ - using ReferenceType = typename DStruct::ReferenceType; \ - using ConstReferenceType = typename DStruct::ConstReferenceType; \ - using PointerType = typename DStruct::PointerType; \ - using ConstPointerType = typename DStruct::ConstPointerType; \ - using SizeType = typename DStruct::SizeType; \ - using DifferenceType = typename DStruct::DifferenceType; \ -public: \ - using IteratorType = typename DStruct::IteratorType; \ - using ConstIteratorType = typename DStruct::ConstIteratorType; - #define DSTRUCT_COPY_SEMANTICS(DStruct) \ DStruct(const DStruct &ds) : DStruct() { *this = ds; } \ DStruct & operator=(const DStruct &ds) { \ diff --git a/core/ds/array/Array.hpp b/core/ds/array/Array.hpp index 8168359..2243022 100644 --- a/core/ds/array/Array.hpp +++ b/core/ds/array/Array.hpp @@ -17,88 +17,125 @@ namespace dstruct { template -class Array : public DStructTypeSpec_ { +class Array : public DStructTypeSpec_ { + + DSTRUCT_TYPE_SPEC_HELPER(Array) public: // big Five Array() = default; - Array(typename Array::ConstReferenceType element) { + Array(ConstReferenceType element) { for (int i = 0; i < N; i++) { - mC_d[i] = element; + mData[i] = element; } } - Array(const Array &arr) { *this = arr; } - Array & operator=(const Array &arr) { - for (int i = 0; i < N; i++) { - mC_d[i] = arr.mC_d[i]; + Array(port::initializer_list &&list) { + auto it = list.begin(); + int i = 0; + + while (it != list.end() && i < N) { + mData[i] = dstruct::move(*it); + it++; + i++; } - return *this; - } - Array(Array &&arr) { *this = dstruct::move(arr); }; - Array & operator=(Array &&arr) { - for (int i = 0; i < N; i++) mC_d[i] = dstruct::move(arr.mC_d[i]); - return *this; + while (i < N) { + mData[i] = T(); + i++; + } } - ~Array() = default; // array: auto-destroy for every element - public: // Capacity - bool empty() const { + bool empty() const noexcept { return N == 0; } - typename Array::SizeType size() const { + SizeType size() const noexcept { return N; } - typename Array::SizeType capacity() const { - return N; + SizeType capacity() const noexcept { + return N == 0 ? 1 : N; } public: // Access - typename Array::ConstReferenceType back() const { - return mC_d[N - 1]; + ConstReferenceType back() const noexcept { + return mData[N - 1]; + } + + ReferenceType back() noexcept { + return mData[N - 1]; + } + + ConstReferenceType front() const noexcept { + return mData[0]; } - typename Array::ConstReferenceType front() const { - return mC_d[0]; + ReferenceType front() noexcept { + return mData[0]; } - typename Array::ConstReferenceType operator[](int index) const { + ConstReferenceType operator[](int index) const noexcept { if (index < 0) index = N + index; - return mC_d[index]; + return mData[index]; } -public: // Modifiers - typename Array::ReferenceType operator[](int index) { + ReferenceType operator[](int index) noexcept { if (index < 0) index = N + index; - return mC_d[index]; + return mData[index]; } -public: // iterator - typename Array::IteratorType begin() { - return mC_d; + PointerType data() noexcept { + return mData; + } + + ConstPointerType data() const noexcept { + return mData; } - typename Array::ConstIteratorType begin() const { - return mC_d; +public: // iterator + IteratorType begin() noexcept { return mData; } + ConstIteratorType begin() const noexcept { return mData; } + ConstIteratorType cbegin() const noexcept { return mData; } + + IteratorType end() noexcept { return mData + N; } + ConstIteratorType end() const noexcept { return mData + N; } + ConstIteratorType cend() const noexcept { return mData + N; } + +public: // Method chaining + using SortCmpFunc = bool (*)(ConstReferenceType, ConstReferenceType); + Array & sort(SortCmpFunc cmp = [](ConstReferenceType a, ConstReferenceType b) { return a < b; }) noexcept { + // tmp-impl + for (int i = 0; i < N - 1; ++i) { + for (int j = 0; j < N - 1 - i; ++j) { + if (!cmp(mData[j], mData[j + 1])) { + dstruct::swap(mData[j], mData[j + 1]); + } + } + } + return *this; } - typename Array::IteratorType end() { - return mC_d + N; + Array & reverse() { + for (int i = 0; i < N / 2; i++) { + dstruct::swap((*this)[i], (*this)[-1 - i]); + } + return *this; } - typename Array::ConstIteratorType end() const { - return mC_d + N; + Array & swap(Array &arr) { + for (int i = 0; i < N; i++) { + dstruct::swap(mData[i], arr.mData[i]); + } + return *this; } protected: - T mC_d[N == 0 ? 1 : N]; + T mData[N == 0 ? 1 : N]; }; // Array }; diff --git a/core/utils.hpp b/core/utils.hpp index e8cdef1..88e1601 100644 --- a/core/utils.hpp +++ b/core/utils.hpp @@ -48,6 +48,26 @@ struct IsPointer { const static bool value = true; }; +template +struct IsConst { + const static bool value = false; +}; + +template +struct IsConst { + const static bool value = true; +}; + +template +struct IsConst { + const static bool value = true; +}; + +template +struct IsConst { + const static bool value = true; +}; + template struct less { bool operator()(const T& a, const T& b) const { diff --git a/dstruct.hpp b/dstruct.hpp index eb40918..b39ee41 100644 --- a/dstruct.hpp +++ b/dstruct.hpp @@ -12,6 +12,10 @@ //#define ENABLE_SMA +// base + +#include + #include #include diff --git a/xmake.lua b/examples/xmake.lua similarity index 55% rename from xmake.lua rename to examples/xmake.lua index c438064..7ef0a14 100644 --- a/xmake.lua +++ b/examples/xmake.lua @@ -4,10 +4,7 @@ set_languages("cxx11") --add_defines("NDEBUG") -add_includedirs( - ".", - "tests" -) +add_includedirs("..") --add_includedirs("port/libc") --[[ @@ -16,84 +13,80 @@ target("dstruct_cpp_test") add_files("tests/cpp_test.cpp") --]] -target("dstruct_test") - set_kind("binary") - add_files("tests/main.cpp") - target("dstruct_array") set_kind("binary") - add_files("examples/array/array.cpp") + add_files("array/array.cpp") target("dstruct_vector") set_kind("binary") - add_files("examples/array/vector.cpp") + add_files("array/vector.cpp") target("dstruct_string") set_kind("binary") - add_files("examples/string.cpp") + add_files("string.cpp") target("embedded_list") set_kind("binary") - add_files("examples/linked-list/embedded_list.cpp") + add_files("linked-list/embedded_list.cpp") target("dstruct_single_linked_list") set_kind("binary") - add_files("examples/linked-list/single_linked_list.cpp") + add_files("linked-list/single_linked_list.cpp") target("dstruct_double_linked_list") set_kind("binary") - add_files("examples/linked-list/double_linked_list.cpp") + add_files("linked-list/double_linked_list.cpp") target("dstruct_queue") set_kind("binary") - add_files("examples/queue/queue.cpp") + add_files("queue/queue.cpp") target("dstruct_deque") set_kind("binary") - add_files("examples/queue/deque.cpp") + add_files("queue/deque.cpp") target("dstruct_stack") set_kind("binary") - add_files("examples/stack/stack.cpp") + add_files("stack/stack.cpp") target("dstruct_xvalue_stack") set_kind("binary") - add_files("examples/stack/xvalue_stack.cpp") + add_files("stack/xvalue_stack.cpp") target("dstruct_heap") set_kind("binary") - add_files("examples/heap.cpp") + add_files("heap.cpp") target("dstruct_binary_search_tree") set_kind("binary") - add_files("examples/tree/binary_search_tree.cpp") + add_files("tree/binary_search_tree.cpp") target("dstruct_avl_tree") set_kind("binary") - add_files("examples/tree/avl_tree.cpp") + add_files("tree/avl_tree.cpp") target("dstruct_ufset") set_kind("binary") - add_files("examples/set/ufset.cpp") + add_files("set/ufset.cpp") target("dstruct_map") set_kind("binary") - add_files("examples/map.cpp") + add_files("map.cpp") target("dstruct_smemory_vector") set_kind("binary") - add_files("examples/smemory_vector.cpp") + add_files("smemory_vector.cpp") -- algorithms target("dstruct_for_each") set_kind("binary") - add_files("examples/algorithms/for_each.cpp") + add_files("algorithms/for_each.cpp") target("dstruct_heap_algo") set_kind("binary") - add_files("examples/algorithms/heap_algo.cpp") + add_files("algorithms/heap_algo.cpp") -- other target("dstruct_static_mem_allocator") set_kind("binary") - add_files("examples/static_mem_allocator.cpp") \ No newline at end of file + add_files("static_mem_allocator.cpp") \ No newline at end of file diff --git a/port/dstruct-port.h b/port/dstruct-port.h index e14bc32..4f02b57 100644 --- a/port/dstruct-port.h +++ b/port/dstruct-port.h @@ -10,8 +10,15 @@ #ifndef DSTRUCT_PORT_HPP_DSTRUCT #define DSTRUCT_PORT_HPP_DSTRUCT +#include + namespace dstruct { -namespace port { // pls impl/port the alloc +namespace port { + + template + using initializer_list = std::initializer_list; + + // pls impl/port the alloc static void *allocate(int bytes); static void deallocate(void *addr, int bytes); } // namespace port end diff --git a/port/std/initializer_list.hpp b/port/std/initializer_list.hpp new file mode 100644 index 0000000..f372e66 --- /dev/null +++ b/port/std/initializer_list.hpp @@ -0,0 +1,15 @@ +// Use of this source code is governed by Apache-2.0 License +// that can be found in the License file. +// +// Copyright (C) 2023 - present Sunrisepeak +// +// Author: Sunrisepeak (speakshen@163.com) +// ProjectLinks: https://github.com/Sunrisepeak/DStruct +// + +#ifndef INITIALIZER_LIST_HPP_DSTRUCT +#define INITIALIZER_LIST_HPP_DSTRUCT + +#include + +#endif \ No newline at end of file diff --git a/spec/DStructSpec.hpp b/spec/DStructSpec.hpp index 6de7657..f5b568c 100644 --- a/spec/DStructSpec.hpp +++ b/spec/DStructSpec.hpp @@ -174,6 +174,19 @@ class DStructTypeSpec { template class Iterator> using DStructTypeSpec_ = DStructTypeSpec, Iterator>; +#define DSTRUCT_TYPE_SPEC_HELPER(DStruct) \ +public: \ + using ValueType = typename DStruct::ValueType; \ + using ReferenceType = typename DStruct::ReferenceType; \ + using ConstReferenceType = typename DStruct::ConstReferenceType; \ + using PointerType = typename DStruct::PointerType; \ + using ConstPointerType = typename DStruct::ConstPointerType; \ + using SizeType = typename DStruct::SizeType; \ + using DifferenceType = typename DStruct::DifferenceType; \ +public: \ + using IteratorType = typename DStruct::IteratorType; \ + using ConstIteratorType = typename DStruct::ConstIteratorType; + }; #endif \ No newline at end of file diff --git a/tests/TestBase.hpp b/tests/TestBase.hpp index bf39cb1..b4861b6 100644 --- a/tests/TestBase.hpp +++ b/tests/TestBase.hpp @@ -10,138 +10,120 @@ #ifndef TEST_BASE_HPP_DSTRUCT #define TEST_BASE_HPP_DSTRUCT -//#include -#include +namespace dstruct { -#define ENABLE_LOG 0 -#define TEST_LOG(...) \ -if (ENABLE_LOG) { \ - printf("\033[32mDStruct LOG [I]: \t%s: ", __func__); \ - printf(__VA_ARGS__); \ - printf("\033[0m\n"); \ -} +class BigFiveTest { +public: -namespace test { + struct Obj { + Obj() : moved { false } { get_test_data_e().mConstructor++; } -struct Destory { -public: - Destory() : mCnt_e { 1 } { - TEST_LOG("Destory"); - } + Obj(const Obj &obj) { + get_test_data_e().mCopyConstructor++; + moved = obj.moved; + } - Destory(const Destory &des) : mCnt_e { des.mCnt_e } { - TEST_LOG("Copy Destory"); - } + Obj & operator=(const Obj &obj) { + if (this == &obj) get_test_data_e().mSelfAssignment++; - ~Destory() { - mCnt_e--; - DSTRUCT_ASSERT(mCnt_e == 0); - TEST_LOG("~Destory"); - } -private: - int mCnt_e; -}; + if (this != &obj) { + this->~Obj(); + get_test_data_e().mCopyAssignment++; + moved = obj.moved; + } -template -static void test_destroy() { - DStruct ds; - Destory des; - int testNums = 10; + return *this; + } - for(int i = 0; i < testNums; i++) { - DSTRUCT_ASSERT(ds.size() == i); - ds.push(des); - } + Obj(Obj &&obj) { + get_test_data_e().mMoveConstructor++; + moved = obj.moved; - for(int i = testNums; i > 0; i--) { - DSTRUCT_ASSERT(ds.size() == i); - ds.pop(); - } + // set move flag + obj.moved = true; + } - DSTRUCT_ASSERT(ds.empty()); -} + Obj & operator=(Obj &&obj) { + if (this == &obj) get_test_data_e().mSelfAssignment++; -static void test_arr_destroy() { + if (this != &obj) { + this->~Obj(); + get_test_data_e().mMoveAssignment++; + moved = obj.moved; - { // test auto - dstruct::Array ds1; - dstruct::Array ds2{Destory()}; - } + // set obj move flag + obj.moved = true; + } - //std::cout << std::endl; - Destory des; - //std::cout << std::endl; + return *this; + } - { - dstruct::Array ds; - for(int i = 10; i < 20; i++) { - ds[i] = des; + ~Obj() { + if (!moved) { + get_test_data_e().mDestructor++; + } } - } - //std::cout << std::endl; -} + bool moved; + }; -static void test_sma_allocator() { - using MyMemAlloc = dstruct::StaticMemAllocator<1024, 1024>; // define a 1024byte static allocator +public: // checker + static int constructor() { + return get_test_data_e().mConstructor; + } -// allocate/release memory - test + static int destructor() { + return get_test_data_e().mDestructor; + } - int memSize = 1024; - dstruct::Array memArr; - for (int i = 0; i < memArr.size(); i++) { - memArr[i] = MyMemAlloc::allocate(memSize /= 2); - if (i > 0) { - TEST_LOG("%p %p", memArr[i - 1], memArr[i]); - DSTRUCT_ASSERT(reinterpret_cast(memArr[i - 1]) + memSize * 2 == memArr[i]); - } + static int copy_constructor() { + return get_test_data_e().mCopyConstructor; } - // release all memory - memSize = 1024; - for (int i = 0; i < memArr.size(); i++) { - MyMemAlloc::deallocate(memArr[i], memSize /= 2); + static int copy_assignment() { + return get_test_data_e().mCopyAssignment; } -// memory merge - test1 + static int move_constructor() { + return get_test_data_e().mMoveConstructor; + } - // try to alloc a 1024byte mem-block, it should get a nullptr(alloc failed) - // exist memory fragment - auto *mem1024 = MyMemAlloc::allocate(1024); - if (mem1024 == nullptr) { - MyMemAlloc::memory_merge(); + static int move_assignment() { + return get_test_data_e().mMoveAssignment; } - - DSTRUCT_ASSERT(mem1024 == nullptr); - - SMA_MEM_VERIFY(mem1024 = MyMemAlloc::allocate(1024)); // ok - only debug - - DSTRUCT_ASSERT(MyMemAlloc::deallocate(mem1024, 1024) == true); - -// memory merge - test2 - { // list-index 0 3 7 63 1 31 15 0 - int memAllocSeq[8] {8, 32, 64, 512, 16, 256, 128, 8}; - - for (int i = 0; i < memArr.size(); i++) { - memArr[i] = MyMemAlloc::allocate(memAllocSeq[i]); - if (i > 0) { - TEST_LOG("%p %p", memArr[i - 1], memArr[i]); - DSTRUCT_ASSERT(reinterpret_cast(memArr[i - 1]) + memAllocSeq[i - 1] == memArr[i]); - } - } - for (int i = 0; i < memArr.size(); i++) { - MyMemAlloc::deallocate(memArr[i], memAllocSeq[i]); - } + static int self_assignment() { + return get_test_data_e().mSelfAssignment; + } + +public: + + static void clear_status() { + get_test_data_e().mConstructor = 0; + get_test_data_e().mDestructor = 0; + get_test_data_e().mCopyConstructor = 0; + get_test_data_e().mCopyAssignment = 0; + get_test_data_e().mMoveConstructor = 0; + get_test_data_e().mMoveAssignment = 0; + } - DSTRUCT_ASSERT(MyMemAlloc::max_free_mblock_size() == 512); - TEST_LOG(" max_free_mblock_size - %d", MyMemAlloc::max_free_mblock_size()); - MyMemAlloc::memory_merge(); - TEST_LOG(" max_free_mblock_size - %d", MyMemAlloc::max_free_mblock_size()); - DSTRUCT_ASSERT(MyMemAlloc::max_free_mblock_size() == 1024); +private: + struct TestData { + int mConstructor = 0; + int mDestructor = 0; + int mCopyConstructor = 0; + int mCopyAssignment = 0; + int mMoveConstructor = 0; + int mMoveAssignment = 0; + int mSelfAssignment = 0; + }; + + static TestData & get_test_data_e() { + static TestData data; + return data; } -} +}; -} +}; #endif \ No newline at end of file diff --git a/tests/array.cpp b/tests/array.cpp new file mode 100644 index 0000000..59449dc --- /dev/null +++ b/tests/array.cpp @@ -0,0 +1,219 @@ +// Use of this source code is governed by Apache-2.0 License +// that can be found in the License file. +// +// Copyright (C) 2023 - present Sunrisepeak +// +// Author: Sunrisepeak (speakshen@163.com) +// ProjectLinks: https://github.com/Sunrisepeak/DStruct +// + +#include + +#include + +#include + +#include "TestBase.hpp" + +using dstruct::BigFiveTest; + +constexpr int ARR_SIZE = 10; + +// Base Test + +TEST(Array, destructor) { + BigFiveTest::clear_status(); + { + dstruct::Array arr; + EXPECT_EQ(BigFiveTest::constructor(), ARR_SIZE); + } + EXPECT_EQ(BigFiveTest::destructor(), ARR_SIZE); +} + +TEST(Array, copy_sema) { + BigFiveTest::clear_status(); + { + dstruct::Array arr1; + EXPECT_EQ(BigFiveTest::constructor(), ARR_SIZE); + dstruct::Array arr2(arr1); + EXPECT_EQ(BigFiveTest::copy_constructor(), ARR_SIZE); + arr1 = arr2; + EXPECT_EQ(BigFiveTest::copy_assignment(), ARR_SIZE); + EXPECT_EQ(BigFiveTest::destructor(), ARR_SIZE); + } + EXPECT_EQ(BigFiveTest::destructor(), 3 * ARR_SIZE); +} + +TEST(Array, move_sema) { + BigFiveTest::clear_status(); + { + dstruct::Array arr1; + EXPECT_EQ(BigFiveTest::constructor(), ARR_SIZE); + dstruct::Array arr2(std::move(arr1)); + EXPECT_EQ(BigFiveTest::constructor(), ARR_SIZE); + EXPECT_EQ(BigFiveTest::move_constructor(), ARR_SIZE); + EXPECT_EQ(BigFiveTest::destructor(), 0); + arr1 = std::move(arr2); + EXPECT_EQ(BigFiveTest::move_assignment(), ARR_SIZE); + EXPECT_EQ(BigFiveTest::destructor(), 0); + } + EXPECT_EQ(BigFiveTest::destructor(), ARR_SIZE); +} + +TEST(Array, initialization_list) { + BigFiveTest::clear_status(); + { + dstruct::Array arr1 = {2, 2, 3, 3}; + std::array arr2 = {2, 2, 3, 3}; + for (int i = 0; i < ARR_SIZE; i++) { + EXPECT_EQ(arr1[i], arr2[i]); + } + } + { + dstruct::Array arr1 = {1, 2, 3, 4, 5, 6 /*unused*/}; + std::array arr2 = {1, 2, 3, 4, 5}; + for (int i = 0; i < 5; i++) { + EXPECT_EQ(arr1[i], arr2[i]); + } + } +} + +// Capacity Test + +TEST(Array, capacity) { + { + dstruct::Array arr1; + std::array arr2; + EXPECT_EQ(arr1.empty(), arr2.empty()); + EXPECT_EQ(arr1.size(), arr2.size()); + } + { + dstruct::Array arr1; + std::array arr2; + EXPECT_EQ(arr1.empty(), arr2.empty()); + EXPECT_EQ(arr1.size(), arr2.size()); + EXPECT_EQ(arr1.capacity(), 1); // special for dstruct::Array + } +} + +// Element Acess Test + +TEST(Array, front_and_back) { + { + dstruct::Array arr1 = {2, 2, 3, 3}; + std::array arr2 = {2, 2, 3, 3}; + EXPECT_EQ(arr1.front(), arr2.front()); + EXPECT_EQ(arr1.back(), arr2.back()); + dstruct::swap(arr1.front(), arr1.back()); + EXPECT_EQ(arr1.back(), arr2.front()); + EXPECT_EQ(arr2.back(), arr1.front()); + } + + { + const dstruct::Array arr = {2, 2, 3, 3}; + static_assert(dstruct::IsConst::value); + static_assert(dstruct::IsConst::value); + } +} + +TEST(Array, subscript_operator) { + { + dstruct::Array arr1 = {2, 2, 3, 3}; + std::array arr2 = {2, 2, 3, 3}; + for (int i = 0, j = -ARR_SIZE; i < arr1.size(); i++, j++) { + EXPECT_EQ(arr1[i], arr2[i]); + EXPECT_EQ(arr1[j], arr2[i]); + } + arr1[-1] = arr2.back() = 1; + EXPECT_EQ(arr1.back(), arr2.back()); + } + + { + const dstruct::Array arr = {2, 2, 3, 3}; + static_assert(dstruct::IsConst::value); + } +} + +TEST(Array, data) { + { + dstruct::Array arr = {2, 2, 3, 3}; + auto intPtr = arr.data(); + for (int i = 0; i < arr.size(); i++) { + EXPECT_EQ(intPtr[i], arr[i]); + } + + arr.data()[2] = 4; + EXPECT_EQ(4, arr[2]); + } + + { + const dstruct::Array arr = {2, 2, 3, 3}; + static_assert(dstruct::IsConst::value); + } +} + +// Iterator + +TEST(Array, iterator) { + { + dstruct::Array arr1 = {2, 2, 3, 3}; + dstruct::Array arr2 = {2, 2, 3, 3}; + + auto it = arr1.begin(); + for (int i = 0; i < arr1.size(); i++, it++) { + EXPECT_EQ(*it, arr1[i]); + *it *= 2; + } + EXPECT_EQ(it, arr1.end()); + + int index = 0; + for (auto const_it = arr1.cbegin(); const_it != arr1.cend(); ++const_it, ++index) { + EXPECT_EQ(*const_it, arr2[index] * 2); + } + } + + { + const dstruct::Array arr = {2, 2, 3, 3}; + static_assert(dstruct::IsConst::value); + } +} + +// Method chaining + +TEST(Array, sort) { + BigFiveTest::clear_status(); + dstruct::Array arr = {3, 2, 1, 5, 4, 0}; + arr.sort(); + for (int i = 0; i < 6; i++) { + EXPECT_EQ(arr[i], i); + } + + int cmpVal = 5; + for (auto val : arr.sort([](auto a, auto b) { return b < a; })) { + EXPECT_EQ(val, cmpVal); + cmpVal--; + } +} + +TEST(Array, reverse) { + dstruct::Array arr = {3, 2, 1, 5, 4, 0}; + arr.sort().reverse(); + for (int i = 0; i < arr.size(); i++) { + EXPECT_EQ(arr[i], arr.size() - 1 - i); + } +} + +TEST(Array, swap) { + dstruct::Array arr1 = {3, 2, 1, 5, 4, 0}; + auto arr2 = arr1; + int oldBackValue = arr1.back(); + arr1.sort(); + for (int i = 0; i < arr1.size(); i++) { + EXPECT_EQ(arr1[i], i); + } + arr2.swap(arr1); + for (int i = 0; i < arr2.size(); i++) { + EXPECT_EQ(arr2[i], i); + } + EXPECT_EQ(arr1[-1], oldBackValue); +} \ No newline at end of file diff --git a/tests/cpp_test.cpp b/tests/cpp_test.cpp deleted file mode 100644 index 9f5fcee..0000000 --- a/tests/cpp_test.cpp +++ /dev/null @@ -1,110 +0,0 @@ -template -class A { -public: - using Type = T; -}; - -template -struct B : public A { - B() { - typename B::Type i; - } -}; - -#include -#include -struct C { - C() { - std::cout << "C()" << std::endl; - } - - ~C() { - std::cout << "~C()" << std::endl; - } -}; - -#include - -class Parent { -private: - int privateData; - -public: - Parent(int data) : privateData(data) {} - - friend void FriendFunction(const Parent& obj); -}; - -/* ok -void FriendFunction(const Parent& obj) { - std::cout << "Accessing privateData from FriendFunction: " << obj.privateData << std::endl; -} -*/ - -template -void FriendFunction(const T& obj) { - //std::cout << "Accessing privateData from FriendFunction: " << obj.privateData << std::endl; -} - -class Child : public Parent { -public: - Child(int data) : Parent(data) {} -}; - -template -struct TypeHelper { - using _int8_t = typename D::_int8_t; - using _int16_t = typename D::_int16_t; -}; - -struct Type1 { - using _int8_t = char; - using _int16_t = short; -}; - -template -struct Type2 : TypeHelper { -/* // error: need use typename TypeHelper::_int16_t - _int16_t test() { - _int8_t i = 40; - return i; - } -*/ -}; - -int main() { - - std::cout << "\n\nTesting: " << __FILE__ << std::endl; -// test 1 - B b; -// test 2 - using IntPtr = int *; - int val = 1; - const IntPtr ptr = &val; - *ptr = 1; -// test 3: reference to dynamic obj - C *cPtr = new C(); - { - C &refC = *cPtr; - } // refC lifetime end - delete cPtr; -// test 4: cpp17 for - std::map tmp {{1,2},{3,4}}; - for(auto& x:tmp) { - std::cout << x.first << x.second; - } -// test 5: Parent friend function - Child child(42); - FriendFunction(child); //通过子类对象调用 friend 函数 - -// test6: const T & -{ // ok - int val = 5; - const int &data = val; - std::cout << &val << " -- " << &data << std::endl; -} - -// test7: Type - Type2 t; - return 0; -} \ No newline at end of file diff --git a/tests/main.cpp b/tests/main.cpp index 9a3a065..8777f05 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,14 +1,15 @@ -#include - -#include "TestBase.hpp" - -int main() { - std::cout << "\nTesting: " << __FILE__; - - test::test_arr_destroy(); - test::test_destroy>(); - - test::test_sma_allocator(); - - std::cout << " pass" << std::endl; +// Use of this source code is governed by Apache-2.0 License +// that can be found in the License file. +// +// Copyright (C) 2023 - present Sunrisepeak +// +// Author: Sunrisepeak (speakshen@163.com) +// ProjectLinks: https://github.com/Sunrisepeak/DStruct +// + +#include + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/tests/xmake.lua b/tests/xmake.lua new file mode 100644 index 0000000..9fdfc76 --- /dev/null +++ b/tests/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +set_languages("cxx14") + +add_requires("gtest 1.14") + +add_includedirs("..") + +target("dstruct_test") + set_kind("binary") + add_files("*.cpp") + add_packages("gtest") \ No newline at end of file