Index: tests/SerializationTest.cpp |
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp |
index 9e63249c621569e9f5b876c6d78c8e4ac0e500f2..26c7fb06f4ab90a0fbfc3083eb12c29d6d1f62bb 100644 |
--- a/tests/SerializationTest.cpp |
+++ b/tests/SerializationTest.cpp |
@@ -5,8 +5,13 @@ |
* found in the LICENSE file. |
*/ |
+#include "SkBitmapDevice.h" |
+#include "SkBitmapSource.h" |
+#include "SkCanvas.h" |
+#include "SkMallocPixelRef.h" |
#include "SkOrderedWriteBuffer.h" |
#include "SkValidatingReadBuffer.h" |
+#include "SkXfermodeImageFilter.h" |
#include "Test.h" |
static const uint32_t kArraySize = 64; |
@@ -22,6 +27,13 @@ static void TestAlignment(T* testObj, skiatest::Reporter* reporter) { |
} |
template<typename T> struct SerializationUtils { |
+ // Generic case for flattenables |
+ static void Write(SkOrderedWriteBuffer& writer, const T* flattenable) { |
+ writer.writeFlattenable(flattenable); |
+ } |
+ static void Read(SkValidatingReadBuffer& reader, T** flattenable) { |
+ *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType()); |
+ } |
}; |
template<> struct SerializationUtils<SkMatrix> { |
@@ -127,6 +139,45 @@ static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { |
} |
template<typename T> |
+static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed, |
+ skiatest::Reporter* reporter) { |
+ SkOrderedWriteBuffer writer(1024); |
+ writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); |
+ SerializationUtils<T>::Write(writer, testObj); |
+ size_t bytesWritten = writer.bytesWritten(); |
+ REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); |
+ |
+ unsigned char dataWritten[1024]; |
+ writer.writeToMemory(dataWritten); |
+ |
+ // Make sure this fails when it should (test with smaller size, but still multiple of 4) |
+ SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); |
+ T* obj = NULL; |
+ SerializationUtils<T>::Read(buffer, &obj); |
+ REPORTER_ASSERT(reporter, !buffer.validate(true)); |
+ REPORTER_ASSERT(reporter, NULL == obj); |
+ |
+ // Make sure this succeeds when it should |
+ SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); |
+ const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); |
+ T* obj2 = NULL; |
+ SerializationUtils<T>::Read(buffer2, &obj2); |
+ const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); |
+ if (shouldSucceed) { |
+ // This should have succeeded, since there are enough bytes to read this |
+ REPORTER_ASSERT(reporter, buffer2.validate(true)); |
+ REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); |
+ REPORTER_ASSERT(reporter, NULL != obj2); |
+ } else { |
+ // If the deserialization was supposed to fail, make sure it did |
+ REPORTER_ASSERT(reporter, !buffer.validate(true)); |
+ REPORTER_ASSERT(reporter, NULL == obj2); |
+ } |
+ |
+ return obj2; // Return object to perform further validity tests on it |
+} |
+ |
+template<typename T> |
static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { |
SkOrderedWriteBuffer writer(1024); |
writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); |
@@ -152,6 +203,35 @@ static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { |
REPORTER_ASSERT(reporter, success); |
} |
+static void TestBitmapSerialization(const SkBitmap& validBitmap, |
+ const SkBitmap& invalidBitmap, |
+ bool shouldSucceed, |
+ skiatest::Reporter* reporter) { |
+ SkBitmapSource validBitmapSource(validBitmap); |
+ SkBitmapSource invalidBitmapSource(invalidBitmap); |
+ SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); |
+ SkXfermodeImageFilter xfermodeImageFilter(mode, &invalidBitmapSource, &validBitmapSource); |
+ |
+ SkAutoTUnref<SkImageFilter> deserializedFilter( |
+ TestFlattenableSerialization<SkImageFilter>( |
+ &xfermodeImageFilter, shouldSucceed, reporter)); |
+ |
+ // Try to render a small bitmap using the invalid deserialized filter |
+ // to make sure we don't crash while trying to render it |
+ if (shouldSucceed) { |
+ SkBitmap bitmap; |
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 24, 24); |
+ bitmap.allocPixels(); |
+ SkBitmapDevice device(bitmap); |
+ SkCanvas canvas(&device); |
+ canvas.clear(0x00000000); |
+ SkPaint paint; |
+ paint.setImageFilter(deserializedFilter); |
+ canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24))); |
+ canvas.drawBitmap(bitmap, 0, 0, &paint); |
+ } |
+} |
+ |
static void Tests(skiatest::Reporter* reporter) { |
// Test matrix serialization |
{ |
@@ -212,6 +292,29 @@ static void Tests(skiatest::Reporter* reporter) { |
SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax }; |
TestArraySerialization(data, reporter); |
} |
+ |
+ // Test invalid deserializations |
+ { |
+ SkBitmap validBitmap; |
+ validBitmap.setConfig(SkBitmap::kARGB_8888_Config, 256, 256); |
+ |
+ // Create a bitmap with a really large height |
+ SkBitmap invalidBitmap; |
+ invalidBitmap.setConfig(SkBitmap::kARGB_8888_Config, 256, 1000000000); |
+ |
+ // The deserialization should succeed, and the rendering shouldn't crash, |
+ // even when the device fails to initialize, due to its size |
+ TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); |
+ |
+ // Create a bitmap with a pixel ref too small |
+ SkBitmap invalidBitmap2; |
+ invalidBitmap2.setConfig(SkBitmap::kARGB_8888_Config, 256, 256); |
+ invalidBitmap2.setPixelRef(SkNEW_ARGS(SkMallocPixelRef, |
+ (NULL, 256, NULL)))->unref(); |
+ |
+ // The deserialization should detect the pixel ref being too small and fail |
+ TestBitmapSerialization(validBitmap, invalidBitmap2, false, reporter); |
+ } |
} |
#include "TestClassDef.h" |