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 nullptr?
     35     writer.writeString(nullptr);
     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;
    148 
    149     SkAutoTMalloc<uint32_t> originalData(dataSize);
    150     {
    151         SkRandom rand(0);
    152         for (size_t i = 0; i < dataSize; i++) {
    153             originalData[(int) i] = rand.nextU();
    154         }
    155 
    156         // Write  the random data to the writer at different lengths for
    157         // different alignments.
    158         for (size_t len = 0; len < dataSize; len++) {
    159             writer->writePad(originalData.get(), len);
    160         }
    161     }
    162 
    163     size_t totalBytes = writer->bytesWritten();
    164 
    165     SkAutoMalloc readStorage(totalBytes);
    166     writer->flatten(readStorage.get());
    167 
    168     SkReader32 reader;
    169     reader.setMemory(readStorage.get(), totalBytes);
    170 
    171     for (size_t len = 0; len < dataSize; len++) {
    172         const char* readPtr = static_cast<const char*>(reader.skip(len));
    173         // Ensure that the data read is the same as what was written.
    174         REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0);
    175         // Ensure that the rest is padded with zeroes.
    176         const char* stop = readPtr + SkAlign4(len);
    177         readPtr += len;
    178         while (readPtr < stop) {
    179             REPORTER_ASSERT(reporter, *readPtr++ == 0);
    180         }
    181     }
    182 }
    183 
    184 static void testOverwriteT(skiatest::Reporter* reporter, SkWriter32* writer) {
    185     const size_t padding = 64;
    186 
    187     const uint32_t uint1 = 0x12345678;
    188     const uint32_t uint2 = 0x98765432;
    189     const SkScalar scalar1 = 1234.5678f;
    190     const SkScalar scalar2 = 9876.5432f;
    191     const SkRect rect1 = SkRect::MakeXYWH(1, 2, 3, 4);
    192     const SkRect rect2 = SkRect::MakeXYWH(5, 6, 7, 8);
    193 
    194     for (size_t i = 0; i < (padding / 4); ++i) {
    195         writer->write32(0);
    196     }
    197 
    198     writer->write32(uint1);
    199     writer->writeRect(rect1);
    200     writer->writeScalar(scalar1);
    201 
    202     for (size_t i = 0; i < (padding / 4); ++i) {
    203         writer->write32(0);
    204     }
    205 
    206     REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint1);
    207     REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect1);
    208     REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>(
    209                         padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar1);
    210 
    211     writer->overwriteTAt(padding, uint2);
    212     writer->overwriteTAt(padding + sizeof(uint32_t), rect2);
    213     writer->overwriteTAt(padding + sizeof(uint32_t) + sizeof(SkRect), scalar2);
    214 
    215     REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint2);
    216     REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect2);
    217     REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>(
    218                         padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar2);
    219 }
    220 
    221 DEF_TEST(Writer32_dynamic, reporter) {
    222     SkWriter32 writer;
    223     test1(reporter, &writer);
    224 
    225     writer.reset();
    226     test2(reporter, &writer);
    227 
    228     writer.reset();
    229     testWritePad(reporter, &writer);
    230 
    231     writer.reset();
    232     testOverwriteT(reporter, &writer);
    233 }
    234 
    235 DEF_TEST(Writer32_contiguous, reporter) {
    236     uint32_t storage[256];
    237     SkWriter32 writer;
    238     writer.reset(storage, sizeof(storage));
    239     // This write is small enough to fit in storage, so it's contiguous.
    240     test1(reporter, &writer);
    241     REPORTER_ASSERT(reporter, writer.contiguousArray() != nullptr);
    242 
    243     // Everything other aspect of contiguous/non-contiguous is an
    244     // implementation detail, not part of the public contract for
    245     // SkWriter32, and so not tested here.
    246 }
    247 
    248 DEF_TEST(Writer32_small, reporter) {
    249     SkSWriter32<8 * sizeof(intptr_t)> writer;
    250     test1(reporter, &writer);
    251     writer.reset(); // should just rewind our storage
    252     test2(reporter, &writer);
    253 
    254     writer.reset();
    255     testWritePad(reporter, &writer);
    256 
    257     writer.reset();
    258     testOverwriteT(reporter, &writer);
    259 }
    260 
    261 DEF_TEST(Writer32_large, reporter) {
    262     SkSWriter32<1024 * sizeof(intptr_t)> writer;
    263     test1(reporter, &writer);
    264     writer.reset(); // should just rewind our storage
    265     test2(reporter, &writer);
    266 
    267     writer.reset();
    268     testWritePad(reporter, &writer);
    269 
    270     writer.reset();
    271     testOverwriteT(reporter, &writer);
    272 }
    273 
    274 DEF_TEST(Writer32_misc, reporter) {
    275     test_reserve(reporter);
    276     test_string_null(reporter);
    277     test_ptr(reporter);
    278     test_rewind(reporter);
    279 }
    280 
    281