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 "Test.h" 9 #include "TestClassDef.h" 10 #include "SkRandom.h" 11 #include "SkReader32.h" 12 #include "SkWriter32.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(0, 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(0, storage, sizeof(storage)); 34 35 // Can we write NULL? 36 writer.writeString(NULL); 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(32); 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(64); 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(32); 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 uint32_t* addr = writer->peek32(i * 4); 107 REPORTER_ASSERT(reporter, data[i] == *addr); 108 } 109 110 char buffer[sizeof(data)]; 111 REPORTER_ASSERT(reporter, sizeof(buffer) == writer->bytesWritten()); 112 writer->flatten(buffer); 113 REPORTER_ASSERT(reporter, !memcmp(data, buffer, sizeof(buffer))); 114 } 115 116 static void test2(skiatest::Reporter* reporter, SkWriter32* writer) { 117 static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz"; 118 size_t i; 119 120 size_t len = 0; 121 for (i = 0; i <= 26; ++i) { 122 len += SkWriter32::WriteStringSize(gStr, i); 123 writer->writeString(gStr, i); 124 } 125 REPORTER_ASSERT(reporter, writer->bytesWritten() == len); 126 127 SkAutoMalloc storage(len); 128 writer->flatten(storage.get()); 129 130 SkReader32 reader; 131 reader.setMemory(storage.get(), len); 132 for (i = 0; i <= 26; ++i) { 133 REPORTER_ASSERT(reporter, !reader.eof()); 134 const char* str = reader.readString(&len); 135 REPORTER_ASSERT(reporter, i == len); 136 REPORTER_ASSERT(reporter, strlen(str) == len); 137 REPORTER_ASSERT(reporter, !memcmp(str, gStr, len)); 138 // Ensure that the align4 of the string is padded with zeroes. 139 size_t alignedSize = SkAlign4(len + 1); 140 for (size_t j = len; j < alignedSize; j++) { 141 REPORTER_ASSERT(reporter, 0 == str[j]); 142 } 143 } 144 REPORTER_ASSERT(reporter, reader.eof()); 145 } 146 147 static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) { 148 // Create some random data to write. 149 const size_t dataSize = 10<<2; 150 SkASSERT(SkIsAlign4(dataSize)); 151 152 SkAutoMalloc originalData(dataSize); 153 { 154 SkRandom rand(0); 155 uint32_t* ptr = static_cast<uint32_t*>(originalData.get()); 156 uint32_t* stop = ptr + (dataSize>>2); 157 while (ptr < stop) { 158 *ptr++ = rand.nextU(); 159 } 160 161 // Write the random data to the writer at different lengths for 162 // different alignments. 163 for (size_t len = 0; len < dataSize; len++) { 164 writer->writePad(originalData.get(), len); 165 } 166 } 167 168 uint32_t totalBytes = writer->bytesWritten(); 169 170 SkAutoMalloc readStorage(totalBytes); 171 writer->flatten(readStorage.get()); 172 173 SkReader32 reader; 174 reader.setMemory(readStorage.get(), totalBytes); 175 176 for (size_t len = 0; len < dataSize; len++) { 177 const char* readPtr = static_cast<const char*>(reader.skip(len)); 178 // Ensure that the data read is the same as what was written. 179 REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0); 180 // Ensure that the rest is padded with zeroes. 181 const char* stop = readPtr + SkAlign4(len); 182 readPtr += len; 183 while (readPtr < stop) { 184 REPORTER_ASSERT(reporter, *readPtr++ == 0); 185 } 186 } 187 } 188 189 DEF_TEST(Writer32, reporter) { 190 // dynamic allocator 191 { 192 SkWriter32 writer(256 * 4); 193 test1(reporter, &writer); 194 195 writer.reset(); 196 test2(reporter, &writer); 197 198 writer.reset(); 199 testWritePad(reporter, &writer); 200 } 201 202 // storage-block 203 { 204 SkWriter32 writer(0); 205 uint32_t storage[256]; 206 writer.reset(storage, sizeof(storage)); 207 // These three writes are small enough to fit in storage. 208 test1(reporter, &writer); 209 REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage()); 210 211 writer.reset(storage, sizeof(storage)); 212 test2(reporter, &writer); 213 REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage()); 214 215 writer.reset(storage, sizeof(storage)); 216 testWritePad(reporter, &writer); 217 REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage()); 218 219 // Try overflowing the storage-block. 220 uint32_t smallStorage[8]; 221 writer.reset(smallStorage, sizeof(smallStorage)); 222 test2(reporter, &writer); 223 REPORTER_ASSERT(reporter, !writer.wroteOnlyToStorage()); 224 } 225 226 // small storage 227 { 228 SkSWriter32<8 * sizeof(intptr_t)> writer(100); 229 test1(reporter, &writer); 230 writer.reset(); // should just rewind our storage 231 test2(reporter, &writer); 232 233 writer.reset(); 234 testWritePad(reporter, &writer); 235 } 236 237 // large storage 238 { 239 SkSWriter32<1024 * sizeof(intptr_t)> writer(100); 240 test1(reporter, &writer); 241 writer.reset(); // should just rewind our storage 242 test2(reporter, &writer); 243 244 writer.reset(); 245 testWritePad(reporter, &writer); 246 } 247 248 test_reserve(reporter); 249 test_string_null(reporter); 250 test_ptr(reporter); 251 test_rewind(reporter); 252 } 253