/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Test.h" #include "SkFixedAlloc.h" namespace { static int created, destroyed; struct Foo { Foo(int X, float Y) : x(X), y(Y) { created++; } ~Foo() { destroyed++; } int x; float y; }; struct Big { Big() {} uint32_t array[128]; }; } DEF_TEST(FixedAlloc, r) { // Basic mechanics. { uint8_t buf[128]; SkFixedAlloc fa(buf, sizeof(buf)); Foo* foo = fa.make(3, 4.0f); REPORTER_ASSERT(r, foo); REPORTER_ASSERT(r, foo->x == 3); REPORTER_ASSERT(r, foo->y == 4.0f); REPORTER_ASSERT(r, created == 1); REPORTER_ASSERT(r, destroyed == 0); Foo* bar = fa.make(8, 1.0f); REPORTER_ASSERT(r, bar); REPORTER_ASSERT(r, bar->x == 8); REPORTER_ASSERT(r, bar->y == 1.0f); REPORTER_ASSERT(r, created == 2); REPORTER_ASSERT(r, destroyed == 0); fa.undo(); REPORTER_ASSERT(r, created == 2); REPORTER_ASSERT(r, destroyed == 1); } REPORTER_ASSERT(r, created == 2); REPORTER_ASSERT(r, destroyed == 2); { // Test alignment gurantees. uint8_t buf[64]; SkFixedAlloc fa(buf+3, sizeof(buf)-3); Foo* foo = fa.make(3, 4.0f); REPORTER_ASSERT(r, SkIsAlign4((uintptr_t)foo)); REPORTER_ASSERT(r, created == 3); REPORTER_ASSERT(r, destroyed == 2); // Might as well test reset() while we're at it. fa.reset(); REPORTER_ASSERT(r, created == 3); REPORTER_ASSERT(r, destroyed == 3); } REPORTER_ASSERT(r, created == 3); REPORTER_ASSERT(r, destroyed == 3); } DEF_TEST(FallbackAlloc, r) { // SkFixedAlloc will eventually fail when it runs out of space in its buffer. int buf[32]; SkFixedAlloc fixed(buf, sizeof(buf)); bool fixed_failed = false; for (int i = 0; i < 32; i++) { // (Remember, there is some overhead to each make() call.) fixed_failed = fixed_failed || (fixed.make(i) == nullptr); } REPORTER_ASSERT(r, fixed_failed); // SkFallbackAlloc will always succeed, using the heap as required. fixed.reset(); SkFallbackAlloc fallback(&fixed); bool fallback_failed = false; for (int i = 0; i < 32; i++) { fallback_failed = fallback_failed || (fallback.make(i) == nullptr); } REPORTER_ASSERT(r, !fallback_failed); // Test small, big, small allocations to make sure once we go to the heap we stay there. fallback.reset(); auto smallA = fallback.make(2); auto big = fallback.make(); auto smallB = fallback.make(3); auto in_buf = [&](void* ptr) { return (uintptr_t)(buf+0 ) <= (uintptr_t)ptr && (uintptr_t)(buf+32) > (uintptr_t)ptr; }; REPORTER_ASSERT(r, in_buf(smallA)); REPORTER_ASSERT(r, !in_buf(big)); REPORTER_ASSERT(r, !in_buf(smallB)); }