• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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