• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkChunkAlloc.h"
9 #include "SkUtils.h"
10 #include "Test.h"
11 
check_alloc(skiatest::Reporter * reporter,const SkChunkAlloc & alloc,size_t capacity,size_t used,int numBlocks)12 static void check_alloc(skiatest::Reporter* reporter, const SkChunkAlloc& alloc,
13                         size_t capacity, size_t used, int numBlocks) {
14     REPORTER_ASSERT(reporter, alloc.totalCapacity() >= capacity);
15     REPORTER_ASSERT(reporter, alloc.totalUsed() == used);
16     SkDEBUGCODE(REPORTER_ASSERT(reporter, alloc.blockCount() == numBlocks);)
17 }
18 
simple_alloc(skiatest::Reporter * reporter,SkChunkAlloc * alloc,size_t size)19 static void* simple_alloc(skiatest::Reporter* reporter, SkChunkAlloc* alloc, size_t size) {
20     void* ptr = alloc->allocThrow(size);
21     check_alloc(reporter, *alloc, size, size, 1);
22     REPORTER_ASSERT(reporter, alloc->contains(ptr));
23     return ptr;
24 }
25 
test_chunkalloc(skiatest::Reporter * reporter)26 static void test_chunkalloc(skiatest::Reporter* reporter) {
27     static const size_t kMin = 1024;
28     SkChunkAlloc alloc(kMin);
29 
30     //------------------------------------------------------------------------
31     // check empty
32     check_alloc(reporter, alloc, 0, 0, 0);
33     REPORTER_ASSERT(reporter, !alloc.contains(NULL));
34     REPORTER_ASSERT(reporter, !alloc.contains(reporter));
35 
36     // reset on empty allocator
37     alloc.reset();
38     check_alloc(reporter, alloc, 0, 0, 0);
39 
40     // rewind on empty allocator
41     alloc.rewind();
42     check_alloc(reporter, alloc, 0, 0, 0);
43 
44     //------------------------------------------------------------------------
45     // test reset when something is allocated
46     size_t size = kMin >> 1;
47     void* ptr = simple_alloc(reporter, &alloc, size);
48 
49     alloc.reset();
50     check_alloc(reporter, alloc, 0, 0, 0);
51     REPORTER_ASSERT(reporter, !alloc.contains(ptr));
52 
53     //------------------------------------------------------------------------
54     // test rewind when something is allocated
55     ptr = simple_alloc(reporter, &alloc, size);
56 
57     alloc.rewind();
58     check_alloc(reporter, alloc, size, 0, 1);
59     REPORTER_ASSERT(reporter, !alloc.contains(ptr));
60 
61     // use the available block
62     ptr = simple_alloc(reporter, &alloc, size);
63     alloc.reset();
64 
65     //------------------------------------------------------------------------
66     // test out allocating a second block
67     ptr = simple_alloc(reporter, &alloc, size);
68 
69     ptr = alloc.allocThrow(kMin);
70     check_alloc(reporter, alloc, 2*kMin, size+kMin, 2);
71     REPORTER_ASSERT(reporter, alloc.contains(ptr));
72 
73     //------------------------------------------------------------------------
74     // test out unalloc
75     size_t freed = alloc.unalloc(ptr);
76     REPORTER_ASSERT(reporter, freed == kMin);
77     check_alloc(reporter, alloc, 2*kMin, size, 2);
78     REPORTER_ASSERT(reporter, !alloc.contains(ptr));
79 }
80 
81 ///////////////////////////////////////////////////////////////////////////////
82 
set_zero(void * dst,size_t bytes)83 static void set_zero(void* dst, size_t bytes) {
84     char* ptr = (char*)dst;
85     for (size_t i = 0; i < bytes; ++i) {
86         ptr[i] = 0;
87     }
88 }
89 
90 #define MAX_ALIGNMENT   64
91 #define MAX_COUNT       ((MAX_ALIGNMENT) * 32)
92 #define PAD             32
93 #define TOTAL           (PAD + MAX_ALIGNMENT + MAX_COUNT + PAD)
94 
95 #define VALUE16         0x1234
96 #define VALUE32         0x12345678
97 
compare16(const uint16_t base[],uint16_t value,int count)98 static bool compare16(const uint16_t base[], uint16_t value, int count) {
99     for (int i = 0; i < count; ++i) {
100         if (base[i] != value) {
101             SkDebugf("[%d] expected %x found %x\n", i, value, base[i]);
102             return false;
103         }
104     }
105     return true;
106 }
107 
compare32(const uint32_t base[],uint32_t value,int count)108 static bool compare32(const uint32_t base[], uint32_t value, int count) {
109     for (int i = 0; i < count; ++i) {
110         if (base[i] != value) {
111             SkDebugf("[%d] expected %x found %x\n", i, value, base[i]);
112             return false;
113         }
114     }
115     return true;
116 }
117 
test_16(skiatest::Reporter * reporter)118 static void test_16(skiatest::Reporter* reporter) {
119     uint16_t buffer[TOTAL];
120 
121     for (int count = 0; count < MAX_COUNT; ++count) {
122         for (int alignment = 0; alignment < MAX_ALIGNMENT; ++alignment) {
123             set_zero(buffer, sizeof(buffer));
124 
125             uint16_t* base = &buffer[PAD + alignment];
126             sk_memset16(base, VALUE16, count);
127 
128             REPORTER_ASSERT(reporter,
129                 compare16(buffer,       0,       PAD + alignment) &&
130                 compare16(base,         VALUE16, count) &&
131                 compare16(base + count, 0,       TOTAL - count - PAD - alignment));
132         }
133     }
134 }
135 
test_32(skiatest::Reporter * reporter)136 static void test_32(skiatest::Reporter* reporter) {
137     uint32_t buffer[TOTAL];
138 
139     for (int count = 0; count < MAX_COUNT; ++count) {
140         for (int alignment = 0; alignment < MAX_ALIGNMENT; ++alignment) {
141             set_zero(buffer, sizeof(buffer));
142 
143             uint32_t* base = &buffer[PAD + alignment];
144             sk_memset32(base, VALUE32, count);
145 
146             REPORTER_ASSERT(reporter,
147                 compare32(buffer,       0,       PAD + alignment) &&
148                 compare32(base,         VALUE32, count) &&
149                 compare32(base + count, 0,       TOTAL - count - PAD - alignment));
150         }
151     }
152 }
153 
154 /**
155  *  Test sk_memset16 and sk_memset32.
156  *  For performance considerations, implementations may take different paths
157  *  depending on the alignment of the dst, and/or the size of the count.
158  */
DEF_TEST(Memset,reporter)159 DEF_TEST(Memset, reporter) {
160     test_16(reporter);
161     test_32(reporter);
162 
163     test_chunkalloc(reporter);
164 }
165