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 "SkAutoMalloc.h" 9 #include "SkRandom.h" 10 #include "SkReader32.h" 11 #include "SkWriter32.h" 12 #include "Test.h" 13 14 static void check_contents(skiatest::Reporter* reporter, const SkWriter32& writer, 15 const void* expected, size_t size) { 16 SkAutoSMalloc<256> storage(size); 17 REPORTER_ASSERT(reporter, writer.bytesWritten() == size); 18 writer.flatten(storage.get()); 19 REPORTER_ASSERT(reporter, !memcmp(storage.get(), expected, size)); 20 } 21 22 23 static void test_reserve(skiatest::Reporter* reporter) { 24 // There used to be a bug where we'd assert your first reservation had to 25 // fit in external storage if you used it. This would crash in debug mode. 26 uint8_t storage[4]; 27 SkWriter32 writer(storage, sizeof(storage)); 28 writer.reserve(40); 29 } 30 31 static void test_string_null(skiatest::Reporter* reporter) { 32 uint8_t storage[8]; 33 SkWriter32 writer(storage, sizeof(storage)); 34 35 // Can we write nullptr? 36 writer.writeString(nullptr); 37 const int32_t expected[] = { 0x0, 0x0 }; 38 check_contents(reporter, writer, expected, sizeof(expected)); 39 } 40 41 static void test_rewind(skiatest::Reporter* reporter) { 42 SkSWriter32<32> writer; 43 int32_t array[3] = { 1, 2, 4 }; 44 45 REPORTER_ASSERT(reporter, 0 == writer.bytesWritten()); 46 for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 47 writer.writeInt(array[i]); 48 } 49 check_contents(reporter, writer, array, sizeof(array)); 50 51 writer.rewindToOffset(2*sizeof(int32_t)); 52 REPORTER_ASSERT(reporter, sizeof(array) - 4 == writer.bytesWritten()); 53 writer.writeInt(3); 54 REPORTER_ASSERT(reporter, sizeof(array) == writer.bytesWritten()); 55 array[2] = 3; 56 check_contents(reporter, writer, array, sizeof(array)); 57 58 // test rewinding past allocated chunks. This used to crash because we 59 // didn't truncate our link-list after freeing trailing blocks 60 { 61 SkWriter32 writer; 62 for (int i = 0; i < 100; ++i) { 63 writer.writeInt(i); 64 } 65 REPORTER_ASSERT(reporter, 100*4 == writer.bytesWritten()); 66 for (int j = 100*4; j >= 0; j -= 16) { 67 writer.rewindToOffset(j); 68 } 69 REPORTER_ASSERT(reporter, writer.bytesWritten() < 16); 70 } 71 } 72 73 static void test_ptr(skiatest::Reporter* reporter) { 74 SkSWriter32<32> writer; 75 76 void* p0 = reporter; 77 void* p1 = &writer; 78 79 // try writing ptrs where at least one of them may be at a non-multiple of 80 // 8 boundary, to confirm this works on 64bit machines. 81 82 writer.writePtr(p0); 83 writer.write8(0x33); 84 writer.writePtr(p1); 85 writer.write8(0x66); 86 87 size_t size = writer.bytesWritten(); 88 REPORTER_ASSERT(reporter, 2 * sizeof(void*) + 2 * sizeof(int32_t)); 89 90 char buffer[32]; 91 SkASSERT(sizeof(buffer) >= size); 92 writer.flatten(buffer); 93 94 SkReader32 reader(buffer, size); 95 REPORTER_ASSERT(reporter, reader.readPtr() == p0); 96 REPORTER_ASSERT(reporter, reader.readInt() == 0x33); 97 REPORTER_ASSERT(reporter, reader.readPtr() == p1); 98 REPORTER_ASSERT(reporter, reader.readInt() == 0x66); 99 } 100 101 static void test1(skiatest::Reporter* reporter, SkWriter32* writer) { 102 const uint32_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 103 for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) { 104 REPORTER_ASSERT(reporter, i*4 == writer->bytesWritten()); 105 writer->write32(data[i]); 106 REPORTER_ASSERT(reporter, data[i] == writer->readTAt<uint32_t>(i * 4)); 107 } 108 109 char buffer[sizeof(data)]; 110 REPORTER_ASSERT(reporter, sizeof(buffer) == writer->bytesWritten()); 111 writer->flatten(buffer); 112 REPORTER_ASSERT(reporter, !memcmp(data, buffer, sizeof(buffer))); 113 } 114 115 static void test2(skiatest::Reporter* reporter, SkWriter32* writer) { 116 static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz"; 117 size_t i; 118 119 size_t len = 0; 120 for (i = 0; i <= 26; ++i) { 121 len += SkWriter32::WriteStringSize(gStr, i); 122 writer->writeString(gStr, i); 123 } 124 REPORTER_ASSERT(reporter, writer->bytesWritten() == len); 125 126 SkAutoMalloc storage(len); 127 writer->flatten(storage.get()); 128 129 SkReader32 reader; 130 reader.setMemory(storage.get(), len); 131 for (i = 0; i <= 26; ++i) { 132 REPORTER_ASSERT(reporter, !reader.eof()); 133 const char* str = reader.readString(&len); 134 REPORTER_ASSERT(reporter, i == len); 135 REPORTER_ASSERT(reporter, strlen(str) == len); 136 REPORTER_ASSERT(reporter, !memcmp(str, gStr, len)); 137 // Ensure that the align4 of the string is padded with zeroes. 138 size_t alignedSize = SkAlign4(len + 1); 139 for (size_t j = len; j < alignedSize; j++) { 140 REPORTER_ASSERT(reporter, 0 == str[j]); 141 } 142 } 143 REPORTER_ASSERT(reporter, reader.eof()); 144 } 145 146 static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) { 147 // Create some random data to write. 148 const size_t dataSize = 10; 149 150 SkAutoTMalloc<uint32_t> originalData(dataSize); 151 { 152 SkRandom rand(0); 153 for (size_t i = 0; i < dataSize; i++) { 154 originalData[(int) i] = rand.nextU(); 155 } 156 157 // Write the random data to the writer at different lengths for 158 // different alignments. 159 for (size_t len = 0; len < dataSize; len++) { 160 writer->writePad(originalData.get(), len); 161 } 162 } 163 164 size_t totalBytes = writer->bytesWritten(); 165 166 SkAutoMalloc readStorage(totalBytes); 167 writer->flatten(readStorage.get()); 168 169 SkReader32 reader; 170 reader.setMemory(readStorage.get(), totalBytes); 171 172 for (size_t len = 0; len < dataSize; len++) { 173 const char* readPtr = static_cast<const char*>(reader.skip(len)); 174 // Ensure that the data read is the same as what was written. 175 REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0); 176 // Ensure that the rest is padded with zeroes. 177 const char* stop = readPtr + SkAlign4(len); 178 readPtr += len; 179 while (readPtr < stop) { 180 REPORTER_ASSERT(reporter, *readPtr++ == 0); 181 } 182 } 183 } 184 185 static void testOverwriteT(skiatest::Reporter* reporter, SkWriter32* writer) { 186 const size_t padding = 64; 187 188 const uint32_t uint1 = 0x12345678; 189 const uint32_t uint2 = 0x98765432; 190 const SkScalar scalar1 = 1234.5678f; 191 const SkScalar scalar2 = 9876.5432f; 192 const SkRect rect1 = SkRect::MakeXYWH(1, 2, 3, 4); 193 const SkRect rect2 = SkRect::MakeXYWH(5, 6, 7, 8); 194 195 for (size_t i = 0; i < (padding / 4); ++i) { 196 writer->write32(0); 197 } 198 199 writer->write32(uint1); 200 writer->writeRect(rect1); 201 writer->writeScalar(scalar1); 202 203 for (size_t i = 0; i < (padding / 4); ++i) { 204 writer->write32(0); 205 } 206 207 REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint1); 208 REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect1); 209 REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>( 210 padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar1); 211 212 writer->overwriteTAt(padding, uint2); 213 writer->overwriteTAt(padding + sizeof(uint32_t), rect2); 214 writer->overwriteTAt(padding + sizeof(uint32_t) + sizeof(SkRect), scalar2); 215 216 REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint2); 217 REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect2); 218 REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>( 219 padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar2); 220 } 221 222 DEF_TEST(Writer32_dynamic, reporter) { 223 SkWriter32 writer; 224 test1(reporter, &writer); 225 226 writer.reset(); 227 test2(reporter, &writer); 228 229 writer.reset(); 230 testWritePad(reporter, &writer); 231 232 writer.reset(); 233 testOverwriteT(reporter, &writer); 234 } 235 236 DEF_TEST(Writer32_small, reporter) { 237 SkSWriter32<8 * sizeof(intptr_t)> writer; 238 test1(reporter, &writer); 239 writer.reset(); // should just rewind our storage 240 test2(reporter, &writer); 241 242 writer.reset(); 243 testWritePad(reporter, &writer); 244 245 writer.reset(); 246 testOverwriteT(reporter, &writer); 247 } 248 249 DEF_TEST(Writer32_large, reporter) { 250 SkSWriter32<1024 * sizeof(intptr_t)> writer; 251 test1(reporter, &writer); 252 writer.reset(); // should just rewind our storage 253 test2(reporter, &writer); 254 255 writer.reset(); 256 testWritePad(reporter, &writer); 257 258 writer.reset(); 259 testOverwriteT(reporter, &writer); 260 } 261 262 DEF_TEST(Writer32_misc, reporter) { 263 test_reserve(reporter); 264 test_string_null(reporter); 265 test_ptr(reporter); 266 test_rewind(reporter); 267 } 268 269 DEF_TEST(Writer32_data, reporter) { 270 const char* str = "0123456789"; 271 sk_sp<SkData> data0(SkData::MakeWithCString(str)); 272 sk_sp<SkData> data1(SkData::MakeEmpty()); 273 274 const size_t sizes[] = { 275 SkWriter32::WriteDataSize(nullptr), 276 SkWriter32::WriteDataSize(data0.get()), 277 SkWriter32::WriteDataSize(data1.get()), 278 }; 279 280 SkSWriter32<1000> writer; 281 size_t sizeWritten = 0; 282 283 writer.writeData(nullptr); 284 sizeWritten += sizes[0]; 285 REPORTER_ASSERT(reporter, sizeWritten == writer.bytesWritten()); 286 287 writer.writeData(data0.get()); 288 sizeWritten += sizes[1]; 289 REPORTER_ASSERT(reporter, sizeWritten == writer.bytesWritten()); 290 291 writer.writeData(data1.get()); 292 sizeWritten += sizes[2]; 293 REPORTER_ASSERT(reporter, sizeWritten == writer.bytesWritten()); 294 295 auto result(writer.snapshotAsData()); 296 297 SkReader32 reader(result->data(), result->size()); 298 auto d0(reader.readData()), 299 d1(reader.readData()), 300 d2(reader.readData()); 301 302 REPORTER_ASSERT(reporter, 0 == d0->size()); 303 REPORTER_ASSERT(reporter, strlen(str)+1 == d1->size()); 304 REPORTER_ASSERT(reporter, !memcmp(str, d1->data(), strlen(str)+1)); 305 REPORTER_ASSERT(reporter, 0 == d2->size()); 306 307 REPORTER_ASSERT(reporter, reader.offset() == sizeWritten); 308 REPORTER_ASSERT(reporter, reader.eof()); 309 } 310