/* * Copyright (C) 2023 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "blt/std/utility.h" #include #include template blt::scoped_buffer create_scoped_buffer(size_t size) { static std::random_device dev; static std::mt19937_64 engine(dev()); blt::scoped_buffer data(size); if constexpr (std::is_floating_point_v) { static std::uniform_real_distribution dist(std::numeric_limits::min(), std::numeric_limits::max()); for (auto& v : data) v = dist(engine); } else if (std::is_integral_v) { static std::uniform_int_distribution dist(std::numeric_limits::min(), std::numeric_limits::max()); for (auto& v : data) v = dist(engine); } return data; } template blt::scoped_buffer modify_copy(blt::scoped_buffer fill) { for (size_t i = 0; i < size_t(fill.size() / 2); i++) { std::swap(fill[i], fill[fill.size() - i - 1]); } return fill; } template T collect(blt::scoped_buffer buff) { T val = 0; for (auto v : buff) val = std::max(v, val); return val; } void blt::test::memory::copy() { BLT_INFO("Running memory copy tests"); auto int_buffer_small = create_scoped_buffer(16); auto int_buffer_medium = create_scoped_buffer(512); auto int_buffer_large = create_scoped_buffer(8192); auto float_buffer_small = create_scoped_buffer(16); auto float_buffer_medium = create_scoped_buffer(512); auto float_buffer_large = create_scoped_buffer(8192); auto int_small = collect(modify_copy(int_buffer_small)); auto int_medium = collect(modify_copy(int_buffer_medium)); auto int_large = collect(modify_copy(int_buffer_large)); auto float_small = collect(modify_copy(float_buffer_small)); auto float_medium = collect(modify_copy(float_buffer_medium)); auto float_large = collect(modify_copy(float_buffer_large)); BLT_TRACE("We collected values [%d, %d, %d]; [%f.0, %f.0, %f.0]", int_small, int_medium, int_large, float_small, float_medium, float_large); } void blt::test::memory::move() { BLT_INFO("Running memory move tests"); } void blt::test::memory::access() { BLT_INFO("Running memory construction tests"); } void blt::test::memory::static_vector_test() { blt::static_vector vec; for (size_t i = 0; i < 16; i++) vec[i] = static_cast(i * 2); for (size_t i = 0; i < 16; i++) BLT_DEBUG_STREAM << vec[i] << ' '; BLT_DEBUG_STREAM << '\n'; vec[3] = 120; vec[7] = 230; vec.reserve(vec.capacity()); for (auto v : vec) BLT_DEBUG_STREAM << v << ' '; BLT_DEBUG_STREAM << '\n'; vec.reserve(0); for (size_t i = 0; i < vec.capacity(); i++) { if (!vec.push_back(static_cast(i))) BLT_INFO("Failed to insert on %d", i); } if (!vec.push_back(10)) BLT_INFO("Vector unable to push, current size vs capacity: %d vs %d", vec.size(), vec.capacity()); for (auto v : vec) BLT_DEBUG_STREAM << v << ' '; BLT_DEBUG_STREAM << '\n'; } struct fucked_type2 { public: static constexpr size_t initial_value = 50; int T = 0; public: fucked_type2() { T = initial_value; //BLT_DEBUG("I HAVE BEEN CONSTRUCTED"); } void set(int t) { T = t; } ~fucked_type2() { //BLT_DEBUG("I HAVE BEEN DESTRUCTED!"); } }; #define ALLOC(alloc, amount) alloc.allocate(amount), amount /** * run tests to make sure that we can actually allocate blocks of memory. * we are using a custom type to ensure that the state is known and the example is complex enough * if this work then it should work for any generic type */ template void test_allocations_1() { std::vector> types; blt::area_allocator int_test{}; types.emplace_back(ALLOC(int_test, static_cast(allocator_size * 0.75))); for (size_t i = 0; i < static_cast(allocator_size * 0.30); i++) { types.emplace_back(ALLOC(int_test, 1)); auto v = std::pair{ALLOC(int_test, 1)}; v.first->set(120); int_test.deallocate(v.first, 1); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); } types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); bool passed = true; std::unordered_set used_pointers; for (const auto& pair : types) { for (size_t i = 0; i < pair.second; i++) { // every value should be the initial value assigned in the constructor // if this isn't the case there was an error. if (pair.first[i].T != fucked_type2::initial_value) { BLT_WARN("We have an allocated value that isn't initial at index %d (allocated in a block of size %d at pointer %p)", i, pair.second, pair.first); passed = false; break; } // every allocation here should be unique. // if we have a pointer in our list which is not unique, // we know we have an error if (BLT_CONTAINS(used_pointers, &pair.first[i])) { BLT_WARN( "We have found another pointer which was allocated as a unique block but isn't (in block %d with size %d; pointer in question: %p)", i, pair.second, pair.first); passed = false; break; } used_pointers.insert(&pair.first[i]); } int_test.deallocate(pair.first, pair.second); } if (passed) BLT_INFO("Test (1) with size %d passed!", allocator_size); else BLT_ERROR("Test (1) with size %d failed!", allocator_size); } void blt::test::memory::test() { test_allocations_1(); test_allocations_1<50>(); test_allocations_1<4096>(); std::vector> types; area_allocator int_test{}; //auto arr = int_test.allocate(10); types.emplace_back(ALLOC(int_test, 15)); types.emplace_back(ALLOC(int_test, 1)); auto v = std::pair{ALLOC(int_test, 1)}; v.first->set(120); int_test.deallocate(v.first, 1); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); types.emplace_back(ALLOC(int_test, 1)); //blt::black_box(arr4); BLT_INFO("CUM"); for (const auto& pair : types) { BLT_TRACE("Pointer: %p", pair.first); for (size_t i = 0; i < pair.second; i++) { BLT_TRACE_STREAM << pair.first[i].T << ' '; } BLT_TRACE_STREAM << '\n'; int_test.deallocate(pair.first, pair.second); BLT_INFO("-----------------"); } }