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
test_loop_stream(skiatest::Reporter * reporter,SkStream * stream,const void * src,size_t len,int repeat)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
test_filestreams(skiatest::Reporter * reporter,const char * tmpDir)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
TestWStream(skiatest::Reporter * reporter)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
TestPackedUInt(skiatest::Reporter * reporter)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.
TestDereferencingData(SkMemoryStream * memStream)175 static void TestDereferencingData(SkMemoryStream* memStream) {
176 memStream->read(NULL, 0);
177 memStream->getMemoryBase();
178 SkAutoDataUnref data(memStream->copyToData());
179 }
180
TestNullData()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
DEF_TEST(Stream,reporter)191 DEF_TEST(Stream, reporter) {
192 TestWStream(reporter);
193 TestPackedUInt(reporter);
194 TestNullData();
195 }
196