Home | History | Annotate | Download | only in tests
      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(&region, 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