Home | History | Annotate | Download | only in tests
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 
     11 #include "SkRandom.h"
     12 #include "SkReader32.h"
     13 #include "SkWriter32.h"
     14 #include "Test.h"
     15 
     16 static void check_contents(skiatest::Reporter* reporter, const SkWriter32& writer,
     17                            const void* expected, size_t size) {
     18     SkAutoSMalloc<256> storage(size);
     19     REPORTER_ASSERT(reporter, writer.bytesWritten() == size);
     20     writer.flatten(storage.get());
     21     REPORTER_ASSERT(reporter, !memcmp(storage.get(), expected, size));
     22 }
     23 
     24 static void test_string_null(skiatest::Reporter* reporter) {
     25     uint8_t storage[8];
     26     SkWriter32 writer(0, storage, sizeof(storage));
     27     SkReader32 reader(storage, sizeof(storage));
     28 
     29     const char* str;
     30     size_t len;
     31 
     32     // Can we write NULL?
     33     writer.writeString(NULL);
     34     const int32_t null[] = { 0xFFFF };
     35     check_contents(reporter, writer, null, sizeof(null));
     36     str = reader.readString(&len);
     37     REPORTER_ASSERT(reporter, NULL == str);
     38     REPORTER_ASSERT(reporter, 0 == len);
     39 
     40     writer.reset(storage, sizeof(storage));
     41     reader.rewind();
     42 
     43     // Is NULL distinct from ""?
     44     writer.writeString("");
     45     const int32_t empty[] = { 0x0, 0x0 };
     46     check_contents(reporter, writer, empty, sizeof(empty));
     47     str = reader.readString(&len);
     48     REPORTER_ASSERT(reporter, 0 == strcmp("", str));
     49     REPORTER_ASSERT(reporter, 0 == len);
     50 }
     51 
     52 static void test_rewind(skiatest::Reporter* reporter) {
     53     SkSWriter32<32> writer(32);
     54     int32_t array[3] = { 1, 2, 4 };
     55 
     56     REPORTER_ASSERT(reporter, 0 == writer.bytesWritten());
     57     for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
     58         writer.writeInt(array[i]);
     59     }
     60     check_contents(reporter, writer, array, sizeof(array));
     61 
     62     writer.rewindToOffset(2*sizeof(int32_t));
     63     REPORTER_ASSERT(reporter, sizeof(array) - 4 == writer.bytesWritten());
     64     writer.writeInt(3);
     65     REPORTER_ASSERT(reporter, sizeof(array) == writer.bytesWritten());
     66     array[2] = 3;
     67     check_contents(reporter, writer, array, sizeof(array));
     68 
     69     // test rewinding past allocated chunks. This used to crash because we
     70     // didn't truncate our link-list after freeing trailing blocks
     71     {
     72         SkWriter32 writer(64);
     73         for (int i = 0; i < 100; ++i) {
     74             writer.writeInt(i);
     75         }
     76         REPORTER_ASSERT(reporter, 100*4 == writer.bytesWritten());
     77         for (int j = 100*4; j >= 0; j -= 16) {
     78             writer.rewindToOffset(j);
     79         }
     80         REPORTER_ASSERT(reporter, writer.bytesWritten() < 16);
     81     }
     82 }
     83 
     84 static void test_ptr(skiatest::Reporter* reporter) {
     85     SkSWriter32<32> writer(32);
     86 
     87     void* p0 = reporter;
     88     void* p1 = &writer;
     89 
     90     // try writing ptrs where at least one of them may be at a non-multiple of
     91     // 8 boundary, to confirm this works on 64bit machines.
     92 
     93     writer.writePtr(p0);
     94     writer.write8(0x33);
     95     writer.writePtr(p1);
     96     writer.write8(0x66);
     97 
     98     size_t size = writer.size();
     99     REPORTER_ASSERT(reporter, 2 * sizeof(void*) + 2 * sizeof(int32_t));
    100 
    101     char buffer[32];
    102     SkASSERT(sizeof(buffer) >= size);
    103     writer.flatten(buffer);
    104 
    105     SkReader32 reader(buffer, size);
    106     REPORTER_ASSERT(reporter, reader.readPtr() == p0);
    107     REPORTER_ASSERT(reporter, reader.readInt() == 0x33);
    108     REPORTER_ASSERT(reporter, reader.readPtr() == p1);
    109     REPORTER_ASSERT(reporter, reader.readInt() == 0x66);
    110 }
    111 
    112 static void test1(skiatest::Reporter* reporter, SkWriter32* writer) {
    113     const uint32_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    114     for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) {
    115         REPORTER_ASSERT(reporter, i*4 == writer->size());
    116         writer->write32(data[i]);
    117         uint32_t* addr = writer->peek32(i * 4);
    118         REPORTER_ASSERT(reporter, data[i] == *addr);
    119     }
    120 
    121     char buffer[sizeof(data)];
    122     REPORTER_ASSERT(reporter, sizeof(buffer) == writer->size());
    123     writer->flatten(buffer);
    124     REPORTER_ASSERT(reporter, !memcmp(data, buffer, sizeof(buffer)));
    125 }
    126 
    127 static void test2(skiatest::Reporter* reporter, SkWriter32* writer) {
    128     static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz";
    129     size_t i;
    130 
    131     size_t len = 0;
    132     for (i = 0; i <= 26; ++i) {
    133         len += SkWriter32::WriteStringSize(gStr, i);
    134         writer->writeString(gStr, i);
    135     }
    136     REPORTER_ASSERT(reporter, writer->size() == len);
    137 
    138     SkAutoMalloc storage(len);
    139     writer->flatten(storage.get());
    140 
    141     SkReader32 reader;
    142     reader.setMemory(storage.get(), len);
    143     for (i = 0; i <= 26; ++i) {
    144         REPORTER_ASSERT(reporter, !reader.eof());
    145         const char* str = reader.readString(&len);
    146         REPORTER_ASSERT(reporter, i == len);
    147         REPORTER_ASSERT(reporter, strlen(str) == len);
    148         REPORTER_ASSERT(reporter, !memcmp(str, gStr, len));
    149         // Ensure that the align4 of the string is padded with zeroes.
    150         size_t alignedSize = SkAlign4(len + 1);
    151         for (size_t j = len; j < alignedSize; j++) {
    152             REPORTER_ASSERT(reporter, 0 == str[j]);
    153         }
    154     }
    155     REPORTER_ASSERT(reporter, reader.eof());
    156 }
    157 
    158 static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) {
    159     // Create some random data to write.
    160     const size_t dataSize = 10<<2;
    161     SkASSERT(SkIsAlign4(dataSize));
    162 
    163     SkAutoMalloc originalData(dataSize);
    164     {
    165         SkMWCRandom rand(0);
    166         uint32_t* ptr = static_cast<uint32_t*>(originalData.get());
    167         uint32_t* stop = ptr + (dataSize>>2);
    168         while (ptr < stop) {
    169             *ptr++ = rand.nextU();
    170         }
    171 
    172         // Write  the random data to the writer at different lengths for
    173         // different alignments.
    174         for (size_t len = 0; len < dataSize; len++) {
    175             writer->writePad(originalData.get(), len);
    176         }
    177     }
    178 
    179     uint32_t totalBytes = writer->size();
    180 
    181     SkAutoMalloc readStorage(totalBytes);
    182     writer->flatten(readStorage.get());
    183 
    184     SkReader32 reader;
    185     reader.setMemory(readStorage.get(), totalBytes);
    186 
    187     for (size_t len = 0; len < dataSize; len++) {
    188         const char* readPtr = static_cast<const char*>(reader.skip(len));
    189         // Ensure that the data read is the same as what was written.
    190         REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0);
    191         // Ensure that the rest is padded with zeroes.
    192         const char* stop = readPtr + SkAlign4(len);
    193         readPtr += len;
    194         while (readPtr < stop) {
    195             REPORTER_ASSERT(reporter, *readPtr++ == 0);
    196         }
    197     }
    198 }
    199 
    200 static void Tests(skiatest::Reporter* reporter) {
    201     // dynamic allocator
    202     {
    203         SkWriter32 writer(256 * 4);
    204         test1(reporter, &writer);
    205 
    206         writer.reset();
    207         test2(reporter, &writer);
    208 
    209         writer.reset();
    210         testWritePad(reporter, &writer);
    211     }
    212 
    213     // storage-block
    214     {
    215         SkWriter32 writer(0);
    216         uint32_t storage[256];
    217         writer.reset(storage, sizeof(storage));
    218         // These three writes are small enough to fit in storage.
    219         test1(reporter, &writer);
    220         REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage());
    221 
    222         writer.reset(storage, sizeof(storage));
    223         test2(reporter, &writer);
    224         REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage());
    225 
    226         writer.reset(storage, sizeof(storage));
    227         testWritePad(reporter, &writer);
    228         REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage());
    229 
    230         // Try overflowing the storage-block.
    231         uint32_t smallStorage[8];
    232         writer.reset(smallStorage, sizeof(smallStorage));
    233         test2(reporter, &writer);
    234         REPORTER_ASSERT(reporter, !writer.wroteOnlyToStorage());
    235     }
    236 
    237     // small storage
    238     {
    239         SkSWriter32<8 * sizeof(intptr_t)> writer(100);
    240         test1(reporter, &writer);
    241         writer.reset(); // should just rewind our storage
    242         test2(reporter, &writer);
    243 
    244         writer.reset();
    245         testWritePad(reporter, &writer);
    246     }
    247 
    248     // large storage
    249     {
    250         SkSWriter32<1024 * sizeof(intptr_t)> writer(100);
    251         test1(reporter, &writer);
    252         writer.reset(); // should just rewind our storage
    253         test2(reporter, &writer);
    254 
    255         writer.reset();
    256         testWritePad(reporter, &writer);
    257     }
    258 
    259     test_string_null(reporter);
    260     test_ptr(reporter);
    261     test_rewind(reporter);
    262 }
    263 
    264 #include "TestClassDef.h"
    265 DEFINE_TESTCLASS("Writer32", Writer32Class, Tests)
    266