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