180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Test.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRandom.h"
1058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkOSFile.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkData.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifndef SK_BUILD_FOR_WIN
15096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include <unistd.h>
16096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include <fcntl.h>
17096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif
18096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define MAX_SIZE    (256 * 1024)
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerstatic void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
22096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                             const void* src, size_t len, int repeat) {
23096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    SkAutoSMalloc<256> storage(len);
24096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    void* tmp = storage.get();
25096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
26096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    for (int i = 0; i < repeat; ++i) {
27096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        size_t bytes = stream->read(tmp, len);
28096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        REPORTER_ASSERT(reporter, bytes == len);
29096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
30096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
31096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
32096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    // expect EOF
33096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    size_t bytes = stream->read(tmp, 1);
34096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == bytes);
3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // isAtEnd might not return true until after the first failing read.
3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, stream->isAtEnd());
37096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
38096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
39096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerstatic void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString path = SkOSPath::SkPathJoin(tmpDir, "wstream_test");
41096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
42096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    const char s[] = "abcdefghijklmnopqrstuvwxyz";
43096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
44096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    {
45096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkFILEWStream writer(path.c_str());
46096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (!writer.isValid()) {
47096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            SkString msg;
48096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            msg.printf("Failed to create tmp file %s\n", path.c_str());
4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            reporter->reportFailed(msg);
50096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            return;
51096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
52096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
53096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        for (int i = 0; i < 100; ++i) {
54096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            writer.write(s, 26);
55096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
56096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
57096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
58096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    {
59096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkFILEStream stream(path.c_str());
60096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        REPORTER_ASSERT(reporter, stream.isValid());
61096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        test_loop_stream(reporter, &stream, s, 26, 100);
6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate());
6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream2.get(), s, 26, 100);
65096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
66096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
67096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    {
6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        FILE* file = ::fopen(path.c_str(), "rb");
6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership);
70096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        REPORTER_ASSERT(reporter, stream.isValid());
71096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        test_loop_stream(reporter, &stream, s, 26, 100);
7258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate());
7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream2.get(), s, 26, 100);
75096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
76096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
77096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestWStream(skiatest::Reporter* reporter) {
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDynamicMemoryWStream  ds;
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char s[] = "abcdefghijklmnopqrstuvwxyz";
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int i;
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (i = 0; i < 100; i++) {
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        REPORTER_ASSERT(reporter, ds.write(s, 26));
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* dst = new char[100 * 26 + 1];
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[100*26] = '*';
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ds.copyTo(dst);
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, dst[100*26] == '*');
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (i = 0; i < 100; i++) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream(ds.detachAsStream());
9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, ds.getOffset() == 0);
9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream.get(), s, 26, 100);
10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate());
10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream2.get(), s, 26, 100);
10358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
10458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream3(stream->fork());
10558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, stream3->isAtEnd());
10658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        char tmp;
10758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        size_t bytes = stream->read(&tmp, 1);
10858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == bytes);
10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        stream3->rewind();
11058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream3.get(), s, 26, 100);
11158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (i = 0; i < 100; i++) {
11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, ds.write(s, 26));
11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    {
11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkData> data(ds.copyToData());
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        REPORTER_ASSERT(reporter, 100 * 26 == data->size());
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0);
12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    {
12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Test that this works after a copyToData.
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream(ds.detachAsStream());
12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, ds.getOffset() == 0);
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream.get(), s, 26, 100);
12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate());
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_loop_stream(reporter, stream2.get(), s, 26, 100);
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete[] dst;
134096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString tmpDir = skiatest::Test::GetTmpDir();
13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!tmpDir.isEmpty()) {
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        test_filestreams(reporter, tmpDir.c_str());
138096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestPackedUInt(skiatest::Reporter* reporter) {
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // so we test values around each of those transitions (and a few others)
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const size_t sizes[] = {
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t i;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[sizeof(sizes) * 4];
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMemoryWStream wstream(buffer, sizeof(buffer));
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool success = wstream.writePackedUInt(sizes[i]);
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        REPORTER_ASSERT(reporter, success);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wstream.flush();
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMemoryStream rstream(buffer, sizeof(buffer));
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t n = rstream.readPackedUInt();
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sizes[i] != n) {
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("-- %d: sizes:%x n:%x\n", i, sizes[i], n);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        REPORTER_ASSERT(reporter, sizes[i] == n);
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
172d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger// Test that setting an SkMemoryStream to a NULL data does not result in a crash when calling
173d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger// methods that access fData.
174d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerstatic void TestDereferencingData(SkMemoryStream* memStream) {
175d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    memStream->read(NULL, 0);
176d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    memStream->getMemoryBase();
177d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoDataUnref data(memStream->copyToData());
178d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
179d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
180d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerstatic void TestNullData() {
181d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkData* nullData = NULL;
182d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkMemoryStream memStream(nullData);
183d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    TestDereferencingData(&memStream);
184d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
185d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    memStream.setData(nullData);
186d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    TestDereferencingData(&memStream);
187d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
188d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
189d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestStreams(skiatest::Reporter* reporter) {
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestWStream(reporter);
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestPackedUInt(reporter);
193d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    TestNullData();
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "TestClassDef.h"
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_TESTCLASS("Stream", StreamTestClass, TestStreams)
198