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 "Test.h"
      9 #include "TestClassDef.h"
     10 #include "SkRandom.h"
     11 #include "SkOSFile.h"
     12 #include "SkStream.h"
     13 #include "SkData.h"
     14 
     15 #ifndef SK_BUILD_FOR_WIN
     16 #include <unistd.h>
     17 #include <fcntl.h>
     18 #endif
     19 
     20 #define MAX_SIZE    (256 * 1024)
     21 
     22 static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
     23                              const void* src, size_t len, int repeat) {
     24     SkAutoSMalloc<256> storage(len);
     25     void* tmp = storage.get();
     26 
     27     for (int i = 0; i < repeat; ++i) {
     28         size_t bytes = stream->read(tmp, len);
     29         REPORTER_ASSERT(reporter, bytes == len);
     30         REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
     31     }
     32 
     33     // expect EOF
     34     size_t bytes = stream->read(tmp, 1);
     35     REPORTER_ASSERT(reporter, 0 == bytes);
     36     // isAtEnd might not return true until after the first failing read.
     37     REPORTER_ASSERT(reporter, stream->isAtEnd());
     38 }
     39 
     40 static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
     41     SkString path = SkOSPath::SkPathJoin(tmpDir, "wstream_test");
     42 
     43     const char s[] = "abcdefghijklmnopqrstuvwxyz";
     44 
     45     {
     46         SkFILEWStream writer(path.c_str());
     47         if (!writer.isValid()) {
     48             SkString msg;
     49             msg.printf("Failed to create tmp file %s\n", path.c_str());
     50             reporter->reportFailed(msg);
     51             return;
     52         }
     53 
     54         for (int i = 0; i < 100; ++i) {
     55             writer.write(s, 26);
     56         }
     57     }
     58 
     59     {
     60         SkFILEStream stream(path.c_str());
     61         REPORTER_ASSERT(reporter, stream.isValid());
     62         test_loop_stream(reporter, &stream, s, 26, 100);
     63 
     64         SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate());
     65         test_loop_stream(reporter, stream2.get(), s, 26, 100);
     66     }
     67 
     68     {
     69         FILE* file = ::fopen(path.c_str(), "rb");
     70         SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership);
     71         REPORTER_ASSERT(reporter, stream.isValid());
     72         test_loop_stream(reporter, &stream, s, 26, 100);
     73 
     74         SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate());
     75         test_loop_stream(reporter, stream2.get(), s, 26, 100);
     76     }
     77 }
     78 
     79 static void TestWStream(skiatest::Reporter* reporter) {
     80     SkDynamicMemoryWStream  ds;
     81     const char s[] = "abcdefghijklmnopqrstuvwxyz";
     82     int i;
     83     for (i = 0; i < 100; i++) {
     84         REPORTER_ASSERT(reporter, ds.write(s, 26));
     85     }
     86     REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
     87 
     88     char* dst = new char[100 * 26 + 1];
     89     dst[100*26] = '*';
     90     ds.copyTo(dst);
     91     REPORTER_ASSERT(reporter, dst[100*26] == '*');
     92     for (i = 0; i < 100; i++) {
     93         REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
     94     }
     95 
     96     {
     97         SkAutoTUnref<SkStreamAsset> stream(ds.detachAsStream());
     98         REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
     99         REPORTER_ASSERT(reporter, ds.getOffset() == 0);
    100         test_loop_stream(reporter, stream.get(), s, 26, 100);
    101 
    102         SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate());
    103         test_loop_stream(reporter, stream2.get(), s, 26, 100);
    104 
    105         SkAutoTUnref<SkStreamAsset> stream3(stream->fork());
    106         REPORTER_ASSERT(reporter, stream3->isAtEnd());
    107         char tmp;
    108         size_t bytes = stream->read(&tmp, 1);
    109         REPORTER_ASSERT(reporter, 0 == bytes);
    110         stream3->rewind();
    111         test_loop_stream(reporter, stream3.get(), s, 26, 100);
    112     }
    113 
    114     for (i = 0; i < 100; i++) {
    115         REPORTER_ASSERT(reporter, ds.write(s, 26));
    116     }
    117     REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
    118 
    119     {
    120         SkAutoTUnref<SkData> data(ds.copyToData());
    121         REPORTER_ASSERT(reporter, 100 * 26 == data->size());
    122         REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0);
    123     }
    124 
    125     {
    126         // Test that this works after a copyToData.
    127         SkAutoTUnref<SkStreamAsset> stream(ds.detachAsStream());
    128         REPORTER_ASSERT(reporter, ds.getOffset() == 0);
    129         test_loop_stream(reporter, stream.get(), s, 26, 100);
    130 
    131         SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate());
    132         test_loop_stream(reporter, stream2.get(), s, 26, 100);
    133     }
    134     delete[] dst;
    135 
    136     SkString tmpDir = skiatest::Test::GetTmpDir();
    137     if (!tmpDir.isEmpty()) {
    138         test_filestreams(reporter, tmpDir.c_str());
    139     }
    140 }
    141 
    142 static void TestPackedUInt(skiatest::Reporter* reporter) {
    143     // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
    144     // so we test values around each of those transitions (and a few others)
    145     const size_t sizes[] = {
    146         0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
    147         0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
    148         0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
    149         0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
    150     };
    151 
    152 
    153     size_t i;
    154     char buffer[sizeof(sizes) * 4];
    155 
    156     SkMemoryWStream wstream(buffer, sizeof(buffer));
    157     for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
    158         bool success = wstream.writePackedUInt(sizes[i]);
    159         REPORTER_ASSERT(reporter, success);
    160     }
    161     wstream.flush();
    162 
    163     SkMemoryStream rstream(buffer, sizeof(buffer));
    164     for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
    165         size_t n = rstream.readPackedUInt();
    166         if (sizes[i] != n) {
    167             SkDebugf("-- %d: sizes:%x n:%x\n", i, sizes[i], n);
    168         }
    169         REPORTER_ASSERT(reporter, sizes[i] == n);
    170     }
    171 }
    172 
    173 // Test that setting an SkMemoryStream to a NULL data does not result in a crash when calling
    174 // methods that access fData.
    175 static void TestDereferencingData(SkMemoryStream* memStream) {
    176     memStream->read(NULL, 0);
    177     memStream->getMemoryBase();
    178     SkAutoDataUnref data(memStream->copyToData());
    179 }
    180 
    181 static void TestNullData() {
    182     SkData* nullData = NULL;
    183     SkMemoryStream memStream(nullData);
    184     TestDereferencingData(&memStream);
    185 
    186     memStream.setData(nullData);
    187     TestDereferencingData(&memStream);
    188 
    189 }
    190 
    191 DEF_TEST(Stream, reporter) {
    192     TestWStream(reporter);
    193     TestPackedUInt(reporter);
    194     TestNullData();
    195 }
    196