| /* | |
| * Copyright 2015 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/private/SkTemplates.h" | |
| #include "tests/Test.h" | |
| #include <cstddef> | |
| #include <utility> | |
| using namespace skia_private; | |
| // Tests for some of the helpers in SkTemplates.h | |
| static void test_automalloc_realloc(skiatest::Reporter* reporter) { | |
| AutoSTMalloc<1, int> array; | |
| // test we have a valid pointer, should not crash | |
| array[0] = 1; | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| // using realloc for init | |
| array.realloc(1); | |
| array[0] = 1; | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| // verify realloc can grow | |
| array.realloc(2); | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| // realloc can shrink | |
| array.realloc(1); | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| // should not crash | |
| array.realloc(0); | |
| // grow and shrink again | |
| array.realloc(10); | |
| for (int i = 0; i < 10; i++) { | |
| array[i] = 10 - i; | |
| } | |
| array.realloc(20); | |
| for (int i = 0; i < 10; i++) { | |
| REPORTER_ASSERT(reporter, array[i] == 10 - i); | |
| } | |
| array.realloc(10); | |
| for (int i = 0; i < 10; i++) { | |
| REPORTER_ASSERT(reporter, array[i] == 10 - i); | |
| } | |
| array.realloc(1); | |
| REPORTER_ASSERT(reporter, array[0] = 10); | |
| // resets mixed with realloc, below stack alloc size | |
| array.reset(0); | |
| array.realloc(1); | |
| array.reset(1); | |
| array[0] = 1; | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| // reset and realloc > stack size | |
| array.reset(2); | |
| array.realloc(3); | |
| array[0] = 1; | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| array.realloc(1); | |
| REPORTER_ASSERT(reporter, array[0] == 1); | |
| } | |
| DEF_TEST(Templates, reporter) { | |
| test_automalloc_realloc(reporter); | |
| } | |
| constexpr int static kStackPreallocCount = 10; | |
| // Ensures the containers in SkTemplates.h all have a consistent api. | |
| template<typename TContainer, typename TCount> | |
| static void test_container_apis(skiatest::Reporter* reporter) { | |
| REPORTER_ASSERT(reporter, !TContainer((TCount)0).get()); | |
| REPORTER_ASSERT(reporter, !TContainer((TCount)0).data()); | |
| REPORTER_ASSERT(reporter, TContainer((TCount)1).get()); | |
| REPORTER_ASSERT(reporter, TContainer((TCount)1).data()); | |
| REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount).get()); | |
| REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount).data()); | |
| REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount + 1).get()); | |
| REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount + 1).data()); | |
| TContainer container; | |
| // The default constructor may or may not init to empty, depending on the type of container. | |
| auto fillToN = [](TContainer& c, int n) -> void { | |
| for (int i = 0; i < n; ++i) { | |
| c[i] = n; | |
| } | |
| }; | |
| auto isFillToN = [](const TContainer& c, int n) -> bool { | |
| for (int i = 0; i < n; ++i) { | |
| if (c[i] != n) { return false; } | |
| } | |
| return true; | |
| }; | |
| { | |
| container.reset((TCount)1); | |
| fillToN(container, 1); | |
| REPORTER_ASSERT(reporter, container.get()); | |
| REPORTER_ASSERT(reporter, container.get() == container.data()); | |
| REPORTER_ASSERT(reporter, isFillToN(container, 1)); | |
| TContainer m(std::move(container)); | |
| REPORTER_ASSERT(reporter, isFillToN(m, 1)); | |
| } | |
| { | |
| container.reset((TCount)kStackPreallocCount); | |
| fillToN(container, kStackPreallocCount); | |
| REPORTER_ASSERT(reporter, container.get()); | |
| REPORTER_ASSERT(reporter, container.get() == container.data()); | |
| REPORTER_ASSERT(reporter, isFillToN(container, kStackPreallocCount)); | |
| TContainer m(std::move(container)); | |
| REPORTER_ASSERT(reporter, isFillToN(m, kStackPreallocCount)); | |
| } | |
| { | |
| container.reset((TCount)kStackPreallocCount + 1); | |
| fillToN(container, kStackPreallocCount + 1); | |
| REPORTER_ASSERT(reporter, container.get()); | |
| REPORTER_ASSERT(reporter, container.get() == container.data()); | |
| REPORTER_ASSERT(reporter, isFillToN(container, kStackPreallocCount + 1)); | |
| TContainer m(std::move(container)); | |
| REPORTER_ASSERT(reporter, isFillToN(m, kStackPreallocCount + 1)); | |
| } | |
| { | |
| container.reset((TCount)0); | |
| REPORTER_ASSERT(reporter, !container.get()); | |
| REPORTER_ASSERT(reporter, !container.data()); | |
| TContainer m(std::move(container)); | |
| REPORTER_ASSERT(reporter, !m.get()); | |
| REPORTER_ASSERT(reporter, !m.data()); | |
| } | |
| } | |
| DEF_TEST(TemplateContainerAPIsTrim, reporter) { | |
| AutoSTArray<kStackPreallocCount, int> c; | |
| c.trimTo(100); | |
| REPORTER_ASSERT(reporter, c.size() == 0); | |
| c.trimTo(1); | |
| REPORTER_ASSERT(reporter, c.size() == 0); | |
| c.trimTo(0); | |
| REPORTER_ASSERT(reporter, c.size() == 0); | |
| c.reset(1); | |
| REPORTER_ASSERT(reporter, c.size() == 1); | |
| c.trimTo(2); | |
| REPORTER_ASSERT(reporter, c.size() == 1); | |
| c.trimTo(1); | |
| REPORTER_ASSERT(reporter, c.size() == 1); | |
| c.trimTo(0); | |
| REPORTER_ASSERT(reporter, c.size() == 0); | |
| } | |
| DEF_TEST(TemplateContainerAPIs, reporter) { | |
| test_container_apis<AutoTArray<int>, int>(reporter); | |
| test_container_apis<AutoSTArray<kStackPreallocCount, int>, int>(reporter); | |
| test_container_apis<AutoTMalloc<int>, size_t>(reporter); | |
| test_container_apis<AutoSTMalloc<kStackPreallocCount, int>, size_t>(reporter); | |
| } | |
| // Ensures that realloc(0) results in a null pointer. | |
| template<typename TAutoMalloc> static void test_realloc_to_zero(skiatest::Reporter* reporter) { | |
| TAutoMalloc autoMalloc(kStackPreallocCount); | |
| REPORTER_ASSERT(reporter, autoMalloc.get()); | |
| autoMalloc.realloc(0); | |
| REPORTER_ASSERT(reporter, !autoMalloc.get()); | |
| autoMalloc.realloc(kStackPreallocCount + 1); | |
| REPORTER_ASSERT(reporter, autoMalloc.get()); | |
| autoMalloc.realloc(0); | |
| REPORTER_ASSERT(reporter, !autoMalloc.get()); | |
| autoMalloc.realloc(kStackPreallocCount); | |
| REPORTER_ASSERT(reporter, autoMalloc.get()); | |
| } | |
| DEF_TEST(AutoReallocToZero, reporter) { | |
| test_realloc_to_zero<AutoTMalloc<int> >(reporter); | |
| test_realloc_to_zero<AutoSTMalloc<kStackPreallocCount, int> >(reporter); | |
| } | |
| DEF_TEST(AutoTMallocSelfMove, r) { | |
| #if defined(__clang__) | |
| #pragma clang diagnostic push | |
| #pragma clang diagnostic ignored "-Wself-move" | |
| #elif defined(__GNUC__) && __GNUC__ >= 13 | |
| #pragma GCC diagnostic push | |
| #pragma GCC diagnostic ignored "-Wself-move" | |
| #endif | |
| AutoTMalloc<int> foo(20); | |
| REPORTER_ASSERT(r, foo.get()); | |
| foo = std::move(foo); | |
| REPORTER_ASSERT(r, foo.get()); // NOLINT(bugprone-use-after-move) | |
| #if defined(__clang__) | |
| #pragma clang diagnostic pop | |
| #elif defined(__GNUC__) && __GNUC__ >= 13 | |
| #pragma GCC diagnostic pop | |
| #endif | |
| } |