SerializationTest.cpp revision d923288e50b5a69afb0bdd5c161191b24cab8345
1/* 2 * Copyright 2013 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 "SkBitmapDevice.h" 9#include "SkBitmapSource.h" 10#include "SkCanvas.h" 11#include "SkMallocPixelRef.h" 12#include "SkTemplates.h" 13#include "SkWriteBuffer.h" 14#include "SkValidatingReadBuffer.h" 15#include "SkXfermodeImageFilter.h" 16#include "Test.h" 17 18static const uint32_t kArraySize = 64; 19static const int kBitmapSize = 256; 20 21template<typename T> 22static void TestAlignment(T* testObj, skiatest::Reporter* reporter) { 23 // Test memory read/write functions directly 24 unsigned char dataWritten[1024]; 25 size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten); 26 REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory); 27 size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory); 28 REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory); 29} 30 31template<typename T> struct SerializationUtils { 32 // Generic case for flattenables 33 static void Write(SkWriteBuffer& writer, const T* flattenable) { 34 writer.writeFlattenable(flattenable); 35 } 36 static void Read(SkValidatingReadBuffer& reader, T** flattenable) { 37 *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType()); 38 } 39}; 40 41template<> struct SerializationUtils<SkMatrix> { 42 static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) { 43 writer.writeMatrix(*matrix); 44 } 45 static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) { 46 reader.readMatrix(matrix); 47 } 48}; 49 50template<> struct SerializationUtils<SkPath> { 51 static void Write(SkWriteBuffer& writer, const SkPath* path) { 52 writer.writePath(*path); 53 } 54 static void Read(SkValidatingReadBuffer& reader, SkPath* path) { 55 reader.readPath(path); 56 } 57}; 58 59template<> struct SerializationUtils<SkRegion> { 60 static void Write(SkWriteBuffer& writer, const SkRegion* region) { 61 writer.writeRegion(*region); 62 } 63 static void Read(SkValidatingReadBuffer& reader, SkRegion* region) { 64 reader.readRegion(region); 65 } 66}; 67 68template<> struct SerializationUtils<unsigned char> { 69 static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) { 70 writer.writeByteArray(data, arraySize); 71 } 72 static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) { 73 return reader.readByteArray(data, arraySize); 74 } 75}; 76 77template<> struct SerializationUtils<SkColor> { 78 static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) { 79 writer.writeColorArray(data, arraySize); 80 } 81 static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) { 82 return reader.readColorArray(data, arraySize); 83 } 84}; 85 86template<> struct SerializationUtils<int32_t> { 87 static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) { 88 writer.writeIntArray(data, arraySize); 89 } 90 static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) { 91 return reader.readIntArray(data, arraySize); 92 } 93}; 94 95template<> struct SerializationUtils<SkPoint> { 96 static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) { 97 writer.writePointArray(data, arraySize); 98 } 99 static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) { 100 return reader.readPointArray(data, arraySize); 101 } 102}; 103 104template<> struct SerializationUtils<SkScalar> { 105 static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) { 106 writer.writeScalarArray(data, arraySize); 107 } 108 static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) { 109 return reader.readScalarArray(data, arraySize); 110 } 111}; 112 113template<typename T> 114static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { 115 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 116 SerializationUtils<T>::Write(writer, testObj); 117 size_t bytesWritten = writer.bytesWritten(); 118 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 119 120 unsigned char dataWritten[1024]; 121 writer.writeToMemory(dataWritten); 122 123 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 124 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 125 T obj; 126 SerializationUtils<T>::Read(buffer, &obj); 127 REPORTER_ASSERT(reporter, !buffer.isValid()); 128 129 // Make sure this succeeds when it should 130 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 131 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 132 T obj2; 133 SerializationUtils<T>::Read(buffer2, &obj2); 134 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 135 // This should have succeeded, since there are enough bytes to read this 136 REPORTER_ASSERT(reporter, buffer2.isValid()); 137 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 138 139 TestAlignment(testObj, reporter); 140} 141 142template<typename T> 143static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed, 144 skiatest::Reporter* reporter) { 145 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 146 SerializationUtils<T>::Write(writer, testObj); 147 size_t bytesWritten = writer.bytesWritten(); 148 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 149 150 unsigned char dataWritten[1024]; 151 SkASSERT(bytesWritten <= sizeof(dataWritten)); 152 writer.writeToMemory(dataWritten); 153 154 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 155 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 156 T* obj = NULL; 157 SerializationUtils<T>::Read(buffer, &obj); 158 REPORTER_ASSERT(reporter, !buffer.isValid()); 159 REPORTER_ASSERT(reporter, NULL == obj); 160 161 // Make sure this succeeds when it should 162 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 163 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 164 T* obj2 = NULL; 165 SerializationUtils<T>::Read(buffer2, &obj2); 166 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 167 if (shouldSucceed) { 168 // This should have succeeded, since there are enough bytes to read this 169 REPORTER_ASSERT(reporter, buffer2.isValid()); 170 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 171 REPORTER_ASSERT(reporter, NULL != obj2); 172 } else { 173 // If the deserialization was supposed to fail, make sure it did 174 REPORTER_ASSERT(reporter, !buffer.isValid()); 175 REPORTER_ASSERT(reporter, NULL == obj2); 176 } 177 178 return obj2; // Return object to perform further validity tests on it 179} 180 181template<typename T> 182static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { 183 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 184 SerializationUtils<T>::Write(writer, data, kArraySize); 185 size_t bytesWritten = writer.bytesWritten(); 186 // This should write the length (in 4 bytes) and the array 187 REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten); 188 189 unsigned char dataWritten[1024]; 190 writer.writeToMemory(dataWritten); 191 192 // Make sure this fails when it should 193 SkValidatingReadBuffer buffer(dataWritten, bytesWritten); 194 T dataRead[kArraySize]; 195 bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2); 196 // This should have failed, since the provided size was too small 197 REPORTER_ASSERT(reporter, !success); 198 199 // Make sure this succeeds when it should 200 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 201 success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize); 202 // This should have succeeded, since there are enough bytes to read this 203 REPORTER_ASSERT(reporter, success); 204} 205 206static void TestBitmapSerialization(const SkBitmap& validBitmap, 207 const SkBitmap& invalidBitmap, 208 bool shouldSucceed, 209 skiatest::Reporter* reporter) { 210 SkAutoTUnref<SkBitmapSource> validBitmapSource(SkBitmapSource::Create(validBitmap)); 211 SkAutoTUnref<SkBitmapSource> invalidBitmapSource(SkBitmapSource::Create(invalidBitmap)); 212 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); 213 SkAutoTUnref<SkXfermodeImageFilter> xfermodeImageFilter( 214 SkXfermodeImageFilter::Create(mode, invalidBitmapSource, validBitmapSource)); 215 216 SkAutoTUnref<SkImageFilter> deserializedFilter( 217 TestFlattenableSerialization<SkImageFilter>( 218 xfermodeImageFilter, shouldSucceed, reporter)); 219 220 // Try to render a small bitmap using the invalid deserialized filter 221 // to make sure we don't crash while trying to render it 222 if (shouldSucceed) { 223 SkBitmap bitmap; 224 bitmap.allocN32Pixels(24, 24); 225 SkCanvas canvas(bitmap); 226 canvas.clear(0x00000000); 227 SkPaint paint; 228 paint.setImageFilter(deserializedFilter); 229 canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24))); 230 canvas.drawBitmap(bitmap, 0, 0, &paint); 231 } 232} 233 234static bool setup_bitmap_for_canvas(SkBitmap* bitmap) { 235 SkImageInfo info = SkImageInfo::Make( 236 kBitmapSize, kBitmapSize, kN32_SkColorType, kPremul_SkAlphaType); 237 return bitmap->allocPixels(info); 238} 239 240static bool make_checkerboard_bitmap(SkBitmap& bitmap) { 241 bool success = setup_bitmap_for_canvas(&bitmap); 242 243 SkCanvas canvas(bitmap); 244 canvas.clear(0x00000000); 245 SkPaint darkPaint; 246 darkPaint.setColor(0xFF804020); 247 SkPaint lightPaint; 248 lightPaint.setColor(0xFF244484); 249 const int i = kBitmapSize / 8; 250 const SkScalar f = SkIntToScalar(i); 251 for (int y = 0; y < kBitmapSize; y += i) { 252 for (int x = 0; x < kBitmapSize; x += i) { 253 canvas.save(); 254 canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); 255 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint); 256 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint); 257 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint); 258 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint); 259 canvas.restore(); 260 } 261 } 262 263 return success; 264} 265 266static bool drawSomething(SkCanvas* canvas) { 267 SkPaint paint; 268 SkBitmap bitmap; 269 bool success = make_checkerboard_bitmap(bitmap); 270 271 canvas->save(); 272 canvas->scale(0.5f, 0.5f); 273 canvas->drawBitmap(bitmap, 0, 0, NULL); 274 canvas->restore(); 275 276 const char beforeStr[] = "before circle"; 277 const char afterStr[] = "after circle"; 278 279 paint.setAntiAlias(true); 280 281 paint.setColor(SK_ColorRED); 282 canvas->drawData(beforeStr, sizeof(beforeStr)); 283 canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint); 284 canvas->drawData(afterStr, sizeof(afterStr)); 285 paint.setColor(SK_ColorBLACK); 286 paint.setTextSize(SkIntToScalar(kBitmapSize/3)); 287 canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint); 288 289 return success; 290} 291 292DEF_TEST(Serialization, reporter) { 293 // Test matrix serialization 294 { 295 SkMatrix matrix = SkMatrix::I(); 296 TestObjectSerialization(&matrix, reporter); 297 } 298 299 // Test path serialization 300 { 301 SkPath path; 302 TestObjectSerialization(&path, reporter); 303 } 304 305 // Test region serialization 306 { 307 SkRegion region; 308 TestObjectSerialization(®ion, reporter); 309 } 310 311 // Test rrect serialization 312 { 313 // SkRRect does not initialize anything. 314 // An uninitialized SkRRect can be serialized, 315 // but will branch on uninitialized data when deserialized. 316 SkRRect rrect; 317 SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30); 318 SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} }; 319 rrect.setRectRadii(rect, corners); 320 TestAlignment(&rrect, reporter); 321 } 322 323 // Test readByteArray 324 { 325 unsigned char data[kArraySize] = { 1, 2, 3 }; 326 TestArraySerialization(data, reporter); 327 } 328 329 // Test readColorArray 330 { 331 SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED }; 332 TestArraySerialization(data, reporter); 333 } 334 335 // Test readIntArray 336 { 337 int32_t data[kArraySize] = { 1, 2, 4, 8 }; 338 TestArraySerialization(data, reporter); 339 } 340 341 // Test readPointArray 342 { 343 SkPoint data[kArraySize] = { {6, 7}, {42, 128} }; 344 TestArraySerialization(data, reporter); 345 } 346 347 // Test readScalarArray 348 { 349 SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax }; 350 TestArraySerialization(data, reporter); 351 } 352 353 // Test invalid deserializations 354 { 355 SkImageInfo info = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize); 356 357 SkBitmap validBitmap; 358 validBitmap.setConfig(info); 359 360 // Create a bitmap with a really large height 361 info.fHeight = 1000000000; 362 SkBitmap invalidBitmap; 363 invalidBitmap.setConfig(info); 364 365 // The deserialization should succeed, and the rendering shouldn't crash, 366 // even when the device fails to initialize, due to its size 367 TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); 368 } 369 370 // Test simple SkPicture serialization 371 { 372 SkPicture* pict = new SkPicture; 373 SkAutoUnref aur(pict); 374 bool didDraw = drawSomething(pict->beginRecording(kBitmapSize, kBitmapSize)); 375 REPORTER_ASSERT(reporter, didDraw); 376 pict->endRecording(); 377 378 // Serialize picture 379 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 380 pict->flatten(writer); 381 size_t size = writer.bytesWritten(); 382 SkAutoTMalloc<unsigned char> data(size); 383 writer.writeToMemory(static_cast<void*>(data.get())); 384 385 // Deserialize picture 386 SkValidatingReadBuffer reader(static_cast<void*>(data.get()), size); 387 SkAutoTUnref<SkPicture> readPict( 388 SkPicture::CreateFromBuffer(reader)); 389 REPORTER_ASSERT(reporter, NULL != readPict.get()); 390 } 391} 392