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 "Test.h" 9 #include "TestClassDef.h" 10 #include "SkBitmapDevice.h" 11 #include "SkBitmapSource.h" 12 #include "SkCanvas.h" 13 #include "SkMallocPixelRef.h" 14 #include "SkOrderedWriteBuffer.h" 15 #include "SkValidatingReadBuffer.h" 16 #include "SkXfermodeImageFilter.h" 17 18 static const uint32_t kArraySize = 64; 19 20 template<typename T> 21 static void TestAlignment(T* testObj, skiatest::Reporter* reporter) { 22 // Test memory read/write functions directly 23 unsigned char dataWritten[1024]; 24 size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten); 25 REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory); 26 size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory); 27 REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory); 28 } 29 30 template<typename T> struct SerializationUtils { 31 // Generic case for flattenables 32 static void Write(SkOrderedWriteBuffer& writer, const T* flattenable) { 33 writer.writeFlattenable(flattenable); 34 } 35 static void Read(SkValidatingReadBuffer& reader, T** flattenable) { 36 *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType()); 37 } 38 }; 39 40 template<> struct SerializationUtils<SkMatrix> { 41 static void Write(SkOrderedWriteBuffer& writer, const SkMatrix* matrix) { 42 writer.writeMatrix(*matrix); 43 } 44 static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) { 45 reader.readMatrix(matrix); 46 } 47 }; 48 49 template<> struct SerializationUtils<SkPath> { 50 static void Write(SkOrderedWriteBuffer& writer, const SkPath* path) { 51 writer.writePath(*path); 52 } 53 static void Read(SkValidatingReadBuffer& reader, SkPath* path) { 54 reader.readPath(path); 55 } 56 }; 57 58 template<> struct SerializationUtils<SkRegion> { 59 static void Write(SkOrderedWriteBuffer& writer, const SkRegion* region) { 60 writer.writeRegion(*region); 61 } 62 static void Read(SkValidatingReadBuffer& reader, SkRegion* region) { 63 reader.readRegion(region); 64 } 65 }; 66 67 template<> struct SerializationUtils<unsigned char> { 68 static void Write(SkOrderedWriteBuffer& writer, unsigned char* data, uint32_t arraySize) { 69 writer.writeByteArray(data, arraySize); 70 } 71 static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) { 72 return reader.readByteArray(data, arraySize); 73 } 74 }; 75 76 template<> struct SerializationUtils<SkColor> { 77 static void Write(SkOrderedWriteBuffer& writer, SkColor* data, uint32_t arraySize) { 78 writer.writeColorArray(data, arraySize); 79 } 80 static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) { 81 return reader.readColorArray(data, arraySize); 82 } 83 }; 84 85 template<> struct SerializationUtils<int32_t> { 86 static void Write(SkOrderedWriteBuffer& writer, int32_t* data, uint32_t arraySize) { 87 writer.writeIntArray(data, arraySize); 88 } 89 static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) { 90 return reader.readIntArray(data, arraySize); 91 } 92 }; 93 94 template<> struct SerializationUtils<SkPoint> { 95 static void Write(SkOrderedWriteBuffer& writer, SkPoint* data, uint32_t arraySize) { 96 writer.writePointArray(data, arraySize); 97 } 98 static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) { 99 return reader.readPointArray(data, arraySize); 100 } 101 }; 102 103 template<> struct SerializationUtils<SkScalar> { 104 static void Write(SkOrderedWriteBuffer& writer, SkScalar* data, uint32_t arraySize) { 105 writer.writeScalarArray(data, arraySize); 106 } 107 static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) { 108 return reader.readScalarArray(data, arraySize); 109 } 110 }; 111 112 template<typename T> 113 static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { 114 SkOrderedWriteBuffer writer(1024); 115 writer.setFlags(SkOrderedWriteBuffer::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 142 template<typename T> 143 static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed, 144 skiatest::Reporter* reporter) { 145 SkOrderedWriteBuffer writer(1024); 146 writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); 147 SerializationUtils<T>::Write(writer, testObj); 148 size_t bytesWritten = writer.bytesWritten(); 149 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 150 151 unsigned char dataWritten[1024]; 152 SkASSERT(bytesWritten <= sizeof(dataWritten)); 153 writer.writeToMemory(dataWritten); 154 155 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 156 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 157 T* obj = NULL; 158 SerializationUtils<T>::Read(buffer, &obj); 159 REPORTER_ASSERT(reporter, !buffer.isValid()); 160 REPORTER_ASSERT(reporter, NULL == obj); 161 162 // Make sure this succeeds when it should 163 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 164 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 165 T* obj2 = NULL; 166 SerializationUtils<T>::Read(buffer2, &obj2); 167 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 168 if (shouldSucceed) { 169 // This should have succeeded, since there are enough bytes to read this 170 REPORTER_ASSERT(reporter, buffer2.isValid()); 171 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 172 REPORTER_ASSERT(reporter, NULL != obj2); 173 } else { 174 // If the deserialization was supposed to fail, make sure it did 175 REPORTER_ASSERT(reporter, !buffer.isValid()); 176 REPORTER_ASSERT(reporter, NULL == obj2); 177 } 178 179 return obj2; // Return object to perform further validity tests on it 180 } 181 182 template<typename T> 183 static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { 184 SkOrderedWriteBuffer writer(1024); 185 writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); 186 SerializationUtils<T>::Write(writer, data, kArraySize); 187 size_t bytesWritten = writer.bytesWritten(); 188 // This should write the length (in 4 bytes) and the array 189 REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten); 190 191 unsigned char dataWritten[1024]; 192 writer.writeToMemory(dataWritten); 193 194 // Make sure this fails when it should 195 SkValidatingReadBuffer buffer(dataWritten, bytesWritten); 196 T dataRead[kArraySize]; 197 bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2); 198 // This should have failed, since the provided size was too small 199 REPORTER_ASSERT(reporter, !success); 200 201 // Make sure this succeeds when it should 202 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 203 success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize); 204 // This should have succeeded, since there are enough bytes to read this 205 REPORTER_ASSERT(reporter, success); 206 } 207 208 static void TestBitmapSerialization(const SkBitmap& validBitmap, 209 const SkBitmap& invalidBitmap, 210 bool shouldSucceed, 211 skiatest::Reporter* reporter) { 212 SkBitmapSource validBitmapSource(validBitmap); 213 SkBitmapSource invalidBitmapSource(invalidBitmap); 214 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); 215 SkXfermodeImageFilter xfermodeImageFilter(mode, &invalidBitmapSource, &validBitmapSource); 216 217 SkAutoTUnref<SkImageFilter> deserializedFilter( 218 TestFlattenableSerialization<SkImageFilter>( 219 &xfermodeImageFilter, shouldSucceed, reporter)); 220 221 // Try to render a small bitmap using the invalid deserialized filter 222 // to make sure we don't crash while trying to render it 223 if (shouldSucceed) { 224 SkBitmap bitmap; 225 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 24, 24); 226 bitmap.allocPixels(); 227 SkBitmapDevice device(bitmap); 228 SkCanvas canvas(&device); 229 canvas.clear(0x00000000); 230 SkPaint paint; 231 paint.setImageFilter(deserializedFilter); 232 canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24))); 233 canvas.drawBitmap(bitmap, 0, 0, &paint); 234 } 235 } 236 237 DEF_TEST(Serialization, reporter) { 238 // Test matrix serialization 239 { 240 SkMatrix matrix = SkMatrix::I(); 241 TestObjectSerialization(&matrix, reporter); 242 } 243 244 // Test path serialization 245 { 246 SkPath path; 247 TestObjectSerialization(&path, reporter); 248 } 249 250 // Test region serialization 251 { 252 SkRegion region; 253 TestObjectSerialization(®ion, reporter); 254 } 255 256 // Test rrect serialization 257 { 258 // SkRRect does not initialize anything. 259 // An uninitialized SkRRect can be serialized, 260 // but will branch on uninitialized data when deserialized. 261 SkRRect rrect; 262 SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30); 263 SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} }; 264 rrect.setRectRadii(rect, corners); 265 TestAlignment(&rrect, reporter); 266 } 267 268 // Test readByteArray 269 { 270 unsigned char data[kArraySize] = { 1, 2, 3 }; 271 TestArraySerialization(data, reporter); 272 } 273 274 // Test readColorArray 275 { 276 SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED }; 277 TestArraySerialization(data, reporter); 278 } 279 280 // Test readIntArray 281 { 282 int32_t data[kArraySize] = { 1, 2, 4, 8 }; 283 TestArraySerialization(data, reporter); 284 } 285 286 // Test readPointArray 287 { 288 SkPoint data[kArraySize] = { {6, 7}, {42, 128} }; 289 TestArraySerialization(data, reporter); 290 } 291 292 // Test readScalarArray 293 { 294 SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax }; 295 TestArraySerialization(data, reporter); 296 } 297 298 // Test invalid deserializations 299 { 300 SkBitmap validBitmap; 301 validBitmap.setConfig(SkBitmap::kARGB_8888_Config, 256, 256); 302 303 // Create a bitmap with a really large height 304 SkBitmap invalidBitmap; 305 invalidBitmap.setConfig(SkBitmap::kARGB_8888_Config, 256, 1000000000); 306 307 // The deserialization should succeed, and the rendering shouldn't crash, 308 // even when the device fails to initialize, due to its size 309 TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); 310 311 // Create a bitmap with a pixel ref too small 312 SkImageInfo info; 313 info.fWidth = 256; 314 info.fHeight = 256; 315 info.fColorType = kPMColor_SkColorType; 316 info.fAlphaType = kPremul_SkAlphaType; 317 318 SkBitmap invalidBitmap2; 319 invalidBitmap2.setConfig(info); 320 321 // Hack to force invalid, by making the pixelref smaller than its 322 // owning bitmap. 323 info.fWidth = 32; 324 info.fHeight = 1; 325 326 invalidBitmap2.setPixelRef(SkMallocPixelRef::NewAllocate( 327 info, invalidBitmap2.rowBytes(), NULL))->unref(); 328 329 // The deserialization should detect the pixel ref being too small and fail 330 TestBitmapSerialization(validBitmap, invalidBitmap2, false, reporter); 331 } 332 } 333