Writer32Test.cpp revision 6fcbfcead5dc1b61fa5b4c139a1a3714e8c58091
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11#include "SkRandom.h" 12#include "SkReader32.h" 13#include "SkWriter32.h" 14#include "Test.h" 15 16static void check_contents(skiatest::Reporter* reporter, const SkWriter32& writer, 17 const void* expected, size_t size) { 18 SkAutoSMalloc<256> storage(size); 19 REPORTER_ASSERT(reporter, writer.bytesWritten() == size); 20 writer.flatten(storage.get()); 21 REPORTER_ASSERT(reporter, !memcmp(storage.get(), expected, size)); 22} 23 24 25static void test_reserve(skiatest::Reporter* reporter) { 26 // There used to be a bug where we'd assert your first reservation had to 27 // fit in external storage if you used it. This would crash in debug mode. 28 uint8_t storage[4]; 29 SkWriter32 writer(0, storage, sizeof(storage)); 30 writer.reserve(40); 31} 32 33static void test_string_null(skiatest::Reporter* reporter) { 34 uint8_t storage[8]; 35 SkWriter32 writer(0, storage, sizeof(storage)); 36 37 // Can we write NULL? 38 writer.writeString(NULL); 39 const int32_t expected[] = { 0x0, 0x0 }; 40 check_contents(reporter, writer, expected, sizeof(expected)); 41} 42 43static void test_rewind(skiatest::Reporter* reporter) { 44 SkSWriter32<32> writer(32); 45 int32_t array[3] = { 1, 2, 4 }; 46 47 REPORTER_ASSERT(reporter, 0 == writer.bytesWritten()); 48 for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 49 writer.writeInt(array[i]); 50 } 51 check_contents(reporter, writer, array, sizeof(array)); 52 53 writer.rewindToOffset(2*sizeof(int32_t)); 54 REPORTER_ASSERT(reporter, sizeof(array) - 4 == writer.bytesWritten()); 55 writer.writeInt(3); 56 REPORTER_ASSERT(reporter, sizeof(array) == writer.bytesWritten()); 57 array[2] = 3; 58 check_contents(reporter, writer, array, sizeof(array)); 59 60 // test rewinding past allocated chunks. This used to crash because we 61 // didn't truncate our link-list after freeing trailing blocks 62 { 63 SkWriter32 writer(64); 64 for (int i = 0; i < 100; ++i) { 65 writer.writeInt(i); 66 } 67 REPORTER_ASSERT(reporter, 100*4 == writer.bytesWritten()); 68 for (int j = 100*4; j >= 0; j -= 16) { 69 writer.rewindToOffset(j); 70 } 71 REPORTER_ASSERT(reporter, writer.bytesWritten() < 16); 72 } 73} 74 75static void test_ptr(skiatest::Reporter* reporter) { 76 SkSWriter32<32> writer(32); 77 78 void* p0 = reporter; 79 void* p1 = &writer; 80 81 // try writing ptrs where at least one of them may be at a non-multiple of 82 // 8 boundary, to confirm this works on 64bit machines. 83 84 writer.writePtr(p0); 85 writer.write8(0x33); 86 writer.writePtr(p1); 87 writer.write8(0x66); 88 89 size_t size = writer.size(); 90 REPORTER_ASSERT(reporter, 2 * sizeof(void*) + 2 * sizeof(int32_t)); 91 92 char buffer[32]; 93 SkASSERT(sizeof(buffer) >= size); 94 writer.flatten(buffer); 95 96 SkReader32 reader(buffer, size); 97 REPORTER_ASSERT(reporter, reader.readPtr() == p0); 98 REPORTER_ASSERT(reporter, reader.readInt() == 0x33); 99 REPORTER_ASSERT(reporter, reader.readPtr() == p1); 100 REPORTER_ASSERT(reporter, reader.readInt() == 0x66); 101} 102 103static void test1(skiatest::Reporter* reporter, SkWriter32* writer) { 104 const uint32_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 105 for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) { 106 REPORTER_ASSERT(reporter, i*4 == writer->size()); 107 writer->write32(data[i]); 108 uint32_t* addr = writer->peek32(i * 4); 109 REPORTER_ASSERT(reporter, data[i] == *addr); 110 } 111 112 char buffer[sizeof(data)]; 113 REPORTER_ASSERT(reporter, sizeof(buffer) == writer->size()); 114 writer->flatten(buffer); 115 REPORTER_ASSERT(reporter, !memcmp(data, buffer, sizeof(buffer))); 116} 117 118static void test2(skiatest::Reporter* reporter, SkWriter32* writer) { 119 static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz"; 120 size_t i; 121 122 size_t len = 0; 123 for (i = 0; i <= 26; ++i) { 124 len += SkWriter32::WriteStringSize(gStr, i); 125 writer->writeString(gStr, i); 126 } 127 REPORTER_ASSERT(reporter, writer->size() == len); 128 129 SkAutoMalloc storage(len); 130 writer->flatten(storage.get()); 131 132 SkReader32 reader; 133 reader.setMemory(storage.get(), len); 134 for (i = 0; i <= 26; ++i) { 135 REPORTER_ASSERT(reporter, !reader.eof()); 136 const char* str = reader.readString(&len); 137 REPORTER_ASSERT(reporter, i == len); 138 REPORTER_ASSERT(reporter, strlen(str) == len); 139 REPORTER_ASSERT(reporter, !memcmp(str, gStr, len)); 140 // Ensure that the align4 of the string is padded with zeroes. 141 size_t alignedSize = SkAlign4(len + 1); 142 for (size_t j = len; j < alignedSize; j++) { 143 REPORTER_ASSERT(reporter, 0 == str[j]); 144 } 145 } 146 REPORTER_ASSERT(reporter, reader.eof()); 147} 148 149static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) { 150 // Create some random data to write. 151 const size_t dataSize = 10<<2; 152 SkASSERT(SkIsAlign4(dataSize)); 153 154 SkAutoMalloc originalData(dataSize); 155 { 156 SkRandom rand(0); 157 uint32_t* ptr = static_cast<uint32_t*>(originalData.get()); 158 uint32_t* stop = ptr + (dataSize>>2); 159 while (ptr < stop) { 160 *ptr++ = rand.nextU(); 161 } 162 163 // Write the random data to the writer at different lengths for 164 // different alignments. 165 for (size_t len = 0; len < dataSize; len++) { 166 writer->writePad(originalData.get(), len); 167 } 168 } 169 170 uint32_t totalBytes = writer->size(); 171 172 SkAutoMalloc readStorage(totalBytes); 173 writer->flatten(readStorage.get()); 174 175 SkReader32 reader; 176 reader.setMemory(readStorage.get(), totalBytes); 177 178 for (size_t len = 0; len < dataSize; len++) { 179 const char* readPtr = static_cast<const char*>(reader.skip(len)); 180 // Ensure that the data read is the same as what was written. 181 REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0); 182 // Ensure that the rest is padded with zeroes. 183 const char* stop = readPtr + SkAlign4(len); 184 readPtr += len; 185 while (readPtr < stop) { 186 REPORTER_ASSERT(reporter, *readPtr++ == 0); 187 } 188 } 189} 190 191static void Tests(skiatest::Reporter* reporter) { 192 // dynamic allocator 193 { 194 SkWriter32 writer(256 * 4); 195 test1(reporter, &writer); 196 197 writer.reset(); 198 test2(reporter, &writer); 199 200 writer.reset(); 201 testWritePad(reporter, &writer); 202 } 203 204 // storage-block 205 { 206 SkWriter32 writer(0); 207 uint32_t storage[256]; 208 writer.reset(storage, sizeof(storage)); 209 // These three writes are small enough to fit in storage. 210 test1(reporter, &writer); 211 REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage()); 212 213 writer.reset(storage, sizeof(storage)); 214 test2(reporter, &writer); 215 REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage()); 216 217 writer.reset(storage, sizeof(storage)); 218 testWritePad(reporter, &writer); 219 REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage()); 220 221 // Try overflowing the storage-block. 222 uint32_t smallStorage[8]; 223 writer.reset(smallStorage, sizeof(smallStorage)); 224 test2(reporter, &writer); 225 REPORTER_ASSERT(reporter, !writer.wroteOnlyToStorage()); 226 } 227 228 // small storage 229 { 230 SkSWriter32<8 * sizeof(intptr_t)> writer(100); 231 test1(reporter, &writer); 232 writer.reset(); // should just rewind our storage 233 test2(reporter, &writer); 234 235 writer.reset(); 236 testWritePad(reporter, &writer); 237 } 238 239 // large storage 240 { 241 SkSWriter32<1024 * sizeof(intptr_t)> writer(100); 242 test1(reporter, &writer); 243 writer.reset(); // should just rewind our storage 244 test2(reporter, &writer); 245 246 writer.reset(); 247 testWritePad(reporter, &writer); 248 } 249 250 test_reserve(reporter); 251 test_string_null(reporter); 252 test_ptr(reporter); 253 test_rewind(reporter); 254} 255 256#include "TestClassDef.h" 257DEFINE_TESTCLASS("Writer32", Writer32Class, Tests) 258