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