Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 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 "SkFrontBufferedStream.h"
     11 #include "SkRefCnt.h"
     12 #include "SkStream.h"
     13 #include "SkTypes.h"
     14 
     15 static void test_read(skiatest::Reporter* reporter, SkStream* bufferedStream,
     16                       const void* expectations, size_t bytesToRead) {
     17     // output for reading bufferedStream.
     18     SkAutoMalloc storage(bytesToRead);
     19 
     20     size_t bytesRead = bufferedStream->read(storage.get(), bytesToRead);
     21     REPORTER_ASSERT(reporter, bytesRead == bytesToRead || bufferedStream->isAtEnd());
     22     REPORTER_ASSERT(reporter, memcmp(storage.get(), expectations, bytesRead) == 0);
     23 }
     24 
     25 static void test_rewind(skiatest::Reporter* reporter,
     26                         SkStream* bufferedStream, bool shouldSucceed) {
     27     const bool success = bufferedStream->rewind();
     28     REPORTER_ASSERT(reporter, success == shouldSucceed);
     29 }
     30 
     31 // All tests will buffer this string, and compare output to the original.
     32 // The string is long to ensure that all of our lengths being tested are
     33 // smaller than the string length.
     34 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx";
     35 
     36 // Tests reading the stream across boundaries of what has been buffered so far and what
     37 // the total buffer size is.
     38 static void test_incremental_buffering(skiatest::Reporter* reporter, size_t bufferSize) {
     39     SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
     40 
     41     SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
     42 
     43     // First, test reading less than the max buffer size.
     44     test_read(reporter, bufferedStream, gAbcs, bufferSize / 2);
     45 
     46     // Now test rewinding back to the beginning and reading less than what was
     47     // already buffered.
     48     test_rewind(reporter, bufferedStream, true);
     49     test_read(reporter, bufferedStream, gAbcs, bufferSize / 4);
     50 
     51     // Now test reading part of what was buffered, and buffering new data.
     52     test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 2);
     53 
     54     // Now test reading what was buffered, buffering new data, and
     55     // reading directly from the stream.
     56     test_rewind(reporter, bufferedStream, true);
     57     test_read(reporter, bufferedStream, gAbcs, bufferSize << 1);
     58 
     59     // We have reached the end of the buffer, so rewinding will fail.
     60     // This test assumes that the stream is larger than the buffer; otherwise the
     61     // result of rewind should be true.
     62     test_rewind(reporter, bufferedStream, false);
     63 }
     64 
     65 static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t bufferSize) {
     66     SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
     67     SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
     68 
     69     // Read exactly the amount that fits in the buffer.
     70     test_read(reporter, bufferedStream, gAbcs, bufferSize);
     71 
     72     // Rewinding should succeed.
     73     test_rewind(reporter, bufferedStream, true);
     74 
     75     // Once again reading buffered info should succeed
     76     test_read(reporter, bufferedStream, gAbcs, bufferSize);
     77 
     78     // Read past the size of the buffer. At this point, we cannot return.
     79     test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1);
     80     test_rewind(reporter, bufferedStream, false);
     81 }
     82 
     83 static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) {
     84     SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
     85     SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
     86 
     87     // Skip half the buffer.
     88     bufferedStream->skip(bufferSize / 2);
     89 
     90     // Rewind, then read part of the buffer, which should have been read.
     91     test_rewind(reporter, bufferedStream, true);
     92     test_read(reporter, bufferedStream, gAbcs, bufferSize / 4);
     93 
     94     // Now skip beyond the buffered piece, but still within the total buffer.
     95     bufferedStream->skip(bufferSize / 2);
     96 
     97     // Test that reading will still work.
     98     test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 4);
     99 
    100     test_rewind(reporter, bufferedStream, true);
    101     test_read(reporter, bufferedStream, gAbcs, bufferSize);
    102 }
    103 
    104 // A custom class whose isAtEnd behaves the way Android's stream does - since it is an adaptor to a
    105 // Java InputStream, it does not know that it is at the end until it has attempted to read beyond
    106 // the end and failed. Used by test_read_beyond_buffer.
    107 class AndroidLikeMemoryStream : public SkMemoryStream {
    108 public:
    109     AndroidLikeMemoryStream(void* data, size_t size, bool ownMemory)
    110         : INHERITED(data, size, ownMemory)
    111         , fIsAtEnd(false) {}
    112 
    113     size_t read(void* dst, size_t requested) SK_OVERRIDE {
    114         size_t bytesRead = this->INHERITED::read(dst, requested);
    115         if (bytesRead < requested) {
    116             fIsAtEnd = true;
    117         }
    118         return bytesRead;
    119     }
    120 
    121     bool isAtEnd() const SK_OVERRIDE {
    122         return fIsAtEnd;
    123     }
    124 
    125 private:
    126     bool fIsAtEnd;
    127     typedef SkMemoryStream INHERITED;
    128 };
    129 
    130 // This test ensures that buffering the exact length of the stream and attempting to read beyond it
    131 // does not invalidate the buffer.
    132 static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferSize) {
    133     // Use a stream that behaves like Android's stream.
    134     AndroidLikeMemoryStream memStream((void*)gAbcs, bufferSize, false);
    135 
    136     // Create a buffer that matches the length of the stream.
    137     SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    138 
    139     // Attempt to read one more than the bufferSize
    140     test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1);
    141     test_rewind(reporter, bufferedStream.get(), true);
    142 
    143     // Ensure that the initial read did not invalidate the buffer.
    144     test_read(reporter, bufferedStream, gAbcs, bufferSize);
    145 }
    146 
    147 static void test_buffers(skiatest::Reporter* reporter, size_t bufferSize) {
    148     test_incremental_buffering(reporter, bufferSize);
    149     test_perfectly_sized_buffer(reporter, bufferSize);
    150     test_skipping(reporter, bufferSize);
    151     test_read_beyond_buffer(reporter, bufferSize);
    152 }
    153 
    154 DEF_TEST(FrontBufferedStream, reporter) {
    155     // Test 6 and 64, which are used by Android, as well as another arbitrary length.
    156     test_buffers(reporter, 6);
    157     test_buffers(reporter, 15);
    158     test_buffers(reporter, 64);
    159 }
    160