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