Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2011 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 "SkRandom.h"
      9 #include "SkReader32.h"
     10 #include "SkWriter32.h"
     11 #include "Test.h"
     12 
     13 static void check_contents(skiatest::Reporter* reporter, const SkWriter32& writer,
     14                            const void* expected, size_t size) {
     15     SkAutoSMalloc<256> storage(size);
     16     REPORTER_ASSERT(reporter, writer.bytesWritten() == size);
     17     writer.flatten(storage.get());
     18     REPORTER_ASSERT(reporter, !memcmp(storage.get(), expected, size));
     19 }
     20 
     21 
     22 static void test_reserve(skiatest::Reporter* reporter) {
     23     // There used to be a bug where we'd assert your first reservation had to
     24     // fit in external storage if you used it.  This would crash in debug mode.
     25     uint8_t storage[4];
     26     SkWriter32 writer(storage, sizeof(storage));
     27     writer.reserve(40);
     28 }
     29 
     30 static void test_string_null(skiatest::Reporter* reporter) {
     31     uint8_t storage[8];
     32     SkWriter32 writer(storage, sizeof(storage));
     33 
     34     // Can we write NULL?
     35     writer.writeString(NULL);
     36     const int32_t expected[] = { 0x0, 0x0 };
     37     check_contents(reporter, writer, expected, sizeof(expected));
     38 }
     39 
     40 static void test_rewind(skiatest::Reporter* reporter) {
     41     SkSWriter32<32> writer;
     42     int32_t array[3] = { 1, 2, 4 };
     43 
     44     REPORTER_ASSERT(reporter, 0 == writer.bytesWritten());
     45     for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
     46         writer.writeInt(array[i]);
     47     }
     48     check_contents(reporter, writer, array, sizeof(array));
     49 
     50     writer.rewindToOffset(2*sizeof(int32_t));
     51     REPORTER_ASSERT(reporter, sizeof(array) - 4 == writer.bytesWritten());
     52     writer.writeInt(3);
     53     REPORTER_ASSERT(reporter, sizeof(array) == writer.bytesWritten());
     54     array[2] = 3;
     55     check_contents(reporter, writer, array, sizeof(array));
     56 
     57     // test rewinding past allocated chunks. This used to crash because we
     58     // didn't truncate our link-list after freeing trailing blocks
     59     {
     60         SkWriter32 writer;
     61         for (int i = 0; i < 100; ++i) {
     62             writer.writeInt(i);
     63         }
     64         REPORTER_ASSERT(reporter, 100*4 == writer.bytesWritten());
     65         for (int j = 100*4; j >= 0; j -= 16) {
     66             writer.rewindToOffset(j);
     67         }
     68         REPORTER_ASSERT(reporter, writer.bytesWritten() < 16);
     69     }
     70 }
     71 
     72 static void test_ptr(skiatest::Reporter* reporter) {
     73     SkSWriter32<32> writer;
     74 
     75     void* p0 = reporter;
     76     void* p1 = &writer;
     77 
     78     // try writing ptrs where at least one of them may be at a non-multiple of
     79     // 8 boundary, to confirm this works on 64bit machines.
     80 
     81     writer.writePtr(p0);
     82     writer.write8(0x33);
     83     writer.writePtr(p1);
     84     writer.write8(0x66);
     85 
     86     size_t size = writer.bytesWritten();
     87     REPORTER_ASSERT(reporter, 2 * sizeof(void*) + 2 * sizeof(int32_t));
     88 
     89     char buffer[32];
     90     SkASSERT(sizeof(buffer) >= size);
     91     writer.flatten(buffer);
     92 
     93     SkReader32 reader(buffer, size);
     94     REPORTER_ASSERT(reporter, reader.readPtr() == p0);
     95     REPORTER_ASSERT(reporter, reader.readInt() == 0x33);
     96     REPORTER_ASSERT(reporter, reader.readPtr() == p1);
     97     REPORTER_ASSERT(reporter, reader.readInt() == 0x66);
     98 }
     99 
    100 static void test1(skiatest::Reporter* reporter, SkWriter32* writer) {
    101     const uint32_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    102     for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) {
    103         REPORTER_ASSERT(reporter, i*4 == writer->bytesWritten());
    104         writer->write32(data[i]);
    105         REPORTER_ASSERT(reporter, data[i] == writer->readTAt<uint32_t>(i * 4));
    106     }
    107 
    108     char buffer[sizeof(data)];
    109     REPORTER_ASSERT(reporter, sizeof(buffer) == writer->bytesWritten());
    110     writer->flatten(buffer);
    111     REPORTER_ASSERT(reporter, !memcmp(data, buffer, sizeof(buffer)));
    112 }
    113 
    114 static void test2(skiatest::Reporter* reporter, SkWriter32* writer) {
    115     static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz";
    116     size_t i;
    117 
    118     size_t len = 0;
    119     for (i = 0; i <= 26; ++i) {
    120         len += SkWriter32::WriteStringSize(gStr, i);
    121         writer->writeString(gStr, i);
    122     }
    123     REPORTER_ASSERT(reporter, writer->bytesWritten() == len);
    124 
    125     SkAutoMalloc storage(len);
    126     writer->flatten(storage.get());
    127 
    128     SkReader32 reader;
    129     reader.setMemory(storage.get(), len);
    130     for (i = 0; i <= 26; ++i) {
    131         REPORTER_ASSERT(reporter, !reader.eof());
    132         const char* str = reader.readString(&len);
    133         REPORTER_ASSERT(reporter, i == len);
    134         REPORTER_ASSERT(reporter, strlen(str) == len);
    135         REPORTER_ASSERT(reporter, !memcmp(str, gStr, len));
    136         // Ensure that the align4 of the string is padded with zeroes.
    137         size_t alignedSize = SkAlign4(len + 1);
    138         for (size_t j = len; j < alignedSize; j++) {
    139             REPORTER_ASSERT(reporter, 0 == str[j]);
    140         }
    141     }
    142     REPORTER_ASSERT(reporter, reader.eof());
    143 }
    144 
    145 static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) {
    146     // Create some random data to write.
    147     const size_t dataSize = 10<<2;
    148     SkASSERT(SkIsAlign4(dataSize));
    149 
    150     SkAutoMalloc originalData(dataSize);
    151     {
    152         SkRandom rand(0);
    153         uint32_t* ptr = static_cast<uint32_t*>(originalData.get());
    154         uint32_t* stop = ptr + (dataSize>>2);
    155         while (ptr < stop) {
    156             *ptr++ = rand.nextU();
    157         }
    158 
    159         // Write  the random data to the writer at different lengths for
    160         // different alignments.
    161         for (size_t len = 0; len < dataSize; len++) {
    162             writer->writePad(originalData.get(), len);
    163         }
    164     }
    165 
    166     uint32_t totalBytes = writer->bytesWritten();
    167 
    168     SkAutoMalloc readStorage(totalBytes);
    169     writer->flatten(readStorage.get());
    170 
    171     SkReader32 reader;
    172     reader.setMemory(readStorage.get(), totalBytes);
    173 
    174     for (size_t len = 0; len < dataSize; len++) {
    175         const char* readPtr = static_cast<const char*>(reader.skip(len));
    176         // Ensure that the data read is the same as what was written.
    177         REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0);
    178         // Ensure that the rest is padded with zeroes.
    179         const char* stop = readPtr + SkAlign4(len);
    180         readPtr += len;
    181         while (readPtr < stop) {
    182             REPORTER_ASSERT(reporter, *readPtr++ == 0);
    183         }
    184     }
    185 }
    186 
    187 static void testOverwriteT(skiatest::Reporter* reporter, SkWriter32* writer) {
    188     const size_t padding = 64;
    189 
    190     const uint32_t uint1 = 0x12345678;
    191     const uint32_t uint2 = 0x98765432;
    192     const SkScalar scalar1 = 1234.5678f;
    193     const SkScalar scalar2 = 9876.5432f;
    194     const SkRect rect1 = SkRect::MakeXYWH(1, 2, 3, 4);
    195     const SkRect rect2 = SkRect::MakeXYWH(5, 6, 7, 8);
    196 
    197     for (size_t i = 0; i < (padding / 4); ++i) {
    198         writer->write32(0);
    199     }
    200 
    201     writer->write32(uint1);
    202     writer->writeRect(rect1);
    203     writer->writeScalar(scalar1);
    204 
    205     for (size_t i = 0; i < (padding / 4); ++i) {
    206         writer->write32(0);
    207     }
    208 
    209     REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint1);
    210     REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect1);
    211     REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>(
    212                         padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar1);
    213 
    214     writer->overwriteTAt(padding, uint2);
    215     writer->overwriteTAt(padding + sizeof(uint32_t), rect2);
    216     writer->overwriteTAt(padding + sizeof(uint32_t) + sizeof(SkRect), scalar2);
    217 
    218     REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint2);
    219     REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect2);
    220     REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>(
    221                         padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar2);
    222 }
    223 
    224 DEF_TEST(Writer32_dynamic, reporter) {
    225     SkWriter32 writer;
    226     test1(reporter, &writer);
    227 
    228     writer.reset();
    229     test2(reporter, &writer);
    230 
    231     writer.reset();
    232     testWritePad(reporter, &writer);
    233 
    234     writer.reset();
    235     testOverwriteT(reporter, &writer);
    236 }
    237 
    238 DEF_TEST(Writer32_contiguous, reporter) {
    239     uint32_t storage[256];
    240     SkWriter32 writer;
    241     writer.reset(storage, sizeof(storage));
    242     // This write is small enough to fit in storage, so it's contiguous.
    243     test1(reporter, &writer);
    244     REPORTER_ASSERT(reporter, writer.contiguousArray() != NULL);
    245 
    246     // Everything other aspect of contiguous/non-contiguous is an
    247     // implementation detail, not part of the public contract for
    248     // SkWriter32, and so not tested here.
    249 }
    250 
    251 DEF_TEST(Writer32_small, reporter) {
    252     SkSWriter32<8 * sizeof(intptr_t)> writer;
    253     test1(reporter, &writer);
    254     writer.reset(); // should just rewind our storage
    255     test2(reporter, &writer);
    256 
    257     writer.reset();
    258     testWritePad(reporter, &writer);
    259 
    260     writer.reset();
    261     testOverwriteT(reporter, &writer);
    262 }
    263 
    264 DEF_TEST(Writer32_large, reporter) {
    265     SkSWriter32<1024 * sizeof(intptr_t)> writer;
    266     test1(reporter, &writer);
    267     writer.reset(); // should just rewind our storage
    268     test2(reporter, &writer);
    269 
    270     writer.reset();
    271     testWritePad(reporter, &writer);
    272 
    273     writer.reset();
    274     testOverwriteT(reporter, &writer);
    275 }
    276 
    277 DEF_TEST(Writer32_misc, reporter) {
    278     test_reserve(reporter);
    279     test_string_null(reporter);
    280     test_ptr(reporter);
    281     test_rewind(reporter);
    282 }
    283 
    284 DEF_TEST(Writer32_snapshot, reporter) {
    285     int32_t array[] = { 1, 2, 4, 11 };
    286     SkSWriter32<sizeof(array) + 4> writer;
    287     writer.write(array, sizeof(array));
    288     check_contents(reporter, writer, array, sizeof(array));
    289     const void* beforeData = writer.contiguousArray();
    290     SkAutoDataUnref snapshot(writer.snapshotAsData());
    291     // check the snapshot forced a copy of the static data
    292     REPORTER_ASSERT(reporter, snapshot->data() != beforeData);
    293     REPORTER_ASSERT(reporter, snapshot->size() == writer.bytesWritten());
    294 }
    295 
    296 DEF_TEST(Writer32_snapshot_dynamic, reporter) {
    297     int32_t array[] = { 1, 2, 4, 11 };
    298     SkWriter32 writer;
    299     writer.write(array, sizeof(array));
    300     check_contents(reporter, writer, array, sizeof(array));
    301     // force a capacity increase so we can test COW behaviour
    302     writer.write(array, sizeof(array));
    303     writer.rewindToOffset(sizeof(array));
    304     const void* beforeData = writer.contiguousArray();
    305     SkAutoDataUnref snapshot(writer.snapshotAsData());
    306     // check the snapshot still points to the same data as the writer
    307     REPORTER_ASSERT(reporter, writer.contiguousArray() == beforeData);
    308     REPORTER_ASSERT(reporter, snapshot->data() == beforeData);
    309     REPORTER_ASSERT(reporter, snapshot->size() == writer.bytesWritten());
    310     // write more data that would fit in the buffer
    311     writer.write(array, sizeof(array));
    312     // test it triggered COW anyway
    313     REPORTER_ASSERT(reporter, writer.contiguousArray() != beforeData);
    314 }
    315