• 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 "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 
test_loop_stream(skiatest::Reporter * reporter,SkStream * stream,const void * src,size_t len,int repeat)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 
test_filestreams(skiatest::Reporter * reporter,const char * tmpDir)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 
TestWStream(skiatest::Reporter * reporter)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 
TestPackedUInt(skiatest::Reporter * reporter)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.
TestDereferencingData(SkMemoryStream * memStream)172 static void TestDereferencingData(SkMemoryStream* memStream) {
173     memStream->read(NULL, 0);
174     memStream->getMemoryBase();
175     SkAutoDataUnref data(memStream->copyToData());
176 }
177 
TestNullData()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 
DEF_TEST(Stream,reporter)188 DEF_TEST(Stream, reporter) {
189     TestWStream(reporter);
190     TestPackedUInt(reporter);
191     TestNullData();
192 }
193