Writer32Test.cpp revision cae5d8d5705081cb4d22af7a30be0f01bffce745
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10
11#include "SkRandom.h"
12#include "SkReader32.h"
13#include "SkWriter32.h"
14#include "Test.h"
15
16static void check_contents(skiatest::Reporter* reporter, const SkWriter32& writer,
17                           const void* expected, size_t size) {
18    SkAutoSMalloc<256> storage(size);
19    REPORTER_ASSERT(reporter, writer.bytesWritten() == size);
20    writer.flatten(storage.get());
21    REPORTER_ASSERT(reporter, !memcmp(storage.get(), expected, size));
22}
23
24static void test_rewind(skiatest::Reporter* reporter) {
25    SkSWriter32<32> writer(32);
26    int32_t array[3] = { 1, 2, 4 };
27
28    REPORTER_ASSERT(reporter, 0 == writer.bytesWritten());
29    for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
30        writer.writeInt(array[i]);
31    }
32    check_contents(reporter, writer, array, sizeof(array));
33
34    writer.rewindToOffset(2*sizeof(int32_t));
35    REPORTER_ASSERT(reporter, sizeof(array) - 4 == writer.bytesWritten());
36    writer.writeInt(3);
37    REPORTER_ASSERT(reporter, sizeof(array) == writer.bytesWritten());
38    array[2] = 3;
39    check_contents(reporter, writer, array, sizeof(array));
40
41    // test rewinding past allocated chunks. This used to crash because we
42    // didn't truncate our link-list after freeing trailing blocks
43    {
44        SkWriter32 writer(64);
45        for (int i = 0; i < 100; ++i) {
46            writer.writeInt(i);
47        }
48        REPORTER_ASSERT(reporter, 100*4 == writer.bytesWritten());
49        for (int j = 100*4; j >= 0; j -= 16) {
50            writer.rewindToOffset(j);
51        }
52        REPORTER_ASSERT(reporter, writer.bytesWritten() < 16);
53    }
54}
55
56static void test_ptr(skiatest::Reporter* reporter) {
57    SkSWriter32<32> writer(32);
58
59    void* p0 = reporter;
60    void* p1 = &writer;
61
62    // try writing ptrs where at least one of them may be at a non-multiple of
63    // 8 boundary, to confirm this works on 64bit machines.
64
65    writer.writePtr(p0);
66    writer.write8(0x33);
67    writer.writePtr(p1);
68    writer.write8(0x66);
69
70    size_t size = writer.size();
71    REPORTER_ASSERT(reporter, 2 * sizeof(void*) + 2 * sizeof(int32_t));
72
73    char buffer[32];
74    SkASSERT(sizeof(buffer) >= size);
75    writer.flatten(buffer);
76
77    SkReader32 reader(buffer, size);
78    REPORTER_ASSERT(reporter, reader.readPtr() == p0);
79    REPORTER_ASSERT(reporter, reader.readInt() == 0x33);
80    REPORTER_ASSERT(reporter, reader.readPtr() == p1);
81    REPORTER_ASSERT(reporter, reader.readInt() == 0x66);
82}
83
84static void test1(skiatest::Reporter* reporter, SkWriter32* writer) {
85    const uint32_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
86    for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) {
87        REPORTER_ASSERT(reporter, i*4 == writer->size());
88        writer->write32(data[i]);
89        uint32_t* addr = writer->peek32(i * 4);
90        REPORTER_ASSERT(reporter, data[i] == *addr);
91    }
92
93    char buffer[sizeof(data)];
94    REPORTER_ASSERT(reporter, sizeof(buffer) == writer->size());
95    writer->flatten(buffer);
96    REPORTER_ASSERT(reporter, !memcmp(data, buffer, sizeof(buffer)));
97}
98
99static void test2(skiatest::Reporter* reporter, SkWriter32* writer) {
100    static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz";
101    size_t i;
102
103    size_t len = 0;
104    for (i = 0; i <= 26; ++i) {
105        len += SkWriter32::WriteStringSize(gStr, i);
106        writer->writeString(gStr, i);
107    }
108    REPORTER_ASSERT(reporter, writer->size() == len);
109
110    SkAutoMalloc storage(len);
111    writer->flatten(storage.get());
112
113    SkReader32 reader;
114    reader.setMemory(storage.get(), len);
115    for (i = 0; i <= 26; ++i) {
116        REPORTER_ASSERT(reporter, !reader.eof());
117        const char* str = reader.readString(&len);
118        REPORTER_ASSERT(reporter, i == len);
119        REPORTER_ASSERT(reporter, strlen(str) == len);
120        REPORTER_ASSERT(reporter, !memcmp(str, gStr, len));
121        // Ensure that the align4 of the string is padded with zeroes.
122        size_t alignedSize = SkAlign4(len + 1);
123        for (size_t j = len; j < alignedSize; j++) {
124            REPORTER_ASSERT(reporter, 0 == str[j]);
125        }
126    }
127    REPORTER_ASSERT(reporter, reader.eof());
128}
129
130static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) {
131    // Create some random data to write.
132    const size_t dataSize = 10<<2;
133    SkASSERT(SkIsAlign4(dataSize));
134
135    SkAutoMalloc originalData(dataSize);
136    {
137        SkMWCRandom rand(0);
138        uint32_t* ptr = static_cast<uint32_t*>(originalData.get());
139        uint32_t* stop = ptr + (dataSize>>2);
140        while (ptr < stop) {
141            *ptr++ = rand.nextU();
142        }
143
144        // Write  the random data to the writer at different lengths for
145        // different alignments.
146        for (size_t len = 0; len < dataSize; len++) {
147            writer->writePad(originalData.get(), len);
148        }
149    }
150
151    uint32_t totalBytes = writer->size();
152
153    SkAutoMalloc readStorage(totalBytes);
154    writer->flatten(readStorage.get());
155
156    SkReader32 reader;
157    reader.setMemory(readStorage.get(), totalBytes);
158
159    for (size_t len = 0; len < dataSize; len++) {
160        const char* readPtr = static_cast<const char*>(reader.skip(len));
161        // Ensure that the data read is the same as what was written.
162        REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0);
163        // Ensure that the rest is padded with zeroes.
164        const char* stop = readPtr + SkAlign4(len);
165        readPtr += len;
166        while (readPtr < stop) {
167            REPORTER_ASSERT(reporter, *readPtr++ == 0);
168        }
169    }
170}
171
172static void Tests(skiatest::Reporter* reporter) {
173    // dynamic allocator
174    {
175        SkWriter32 writer(256 * 4);
176        test1(reporter, &writer);
177
178        writer.reset();
179        test2(reporter, &writer);
180
181        writer.reset();
182        testWritePad(reporter, &writer);
183    }
184
185    // storage-block
186    {
187        SkWriter32 writer(0);
188        uint32_t storage[256];
189        writer.reset(storage, sizeof(storage));
190        // These three writes are small enough to fit in storage.
191        test1(reporter, &writer);
192        REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage());
193
194        writer.reset(storage, sizeof(storage));
195        test2(reporter, &writer);
196        REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage());
197
198        writer.reset(storage, sizeof(storage));
199        testWritePad(reporter, &writer);
200        REPORTER_ASSERT(reporter, writer.wroteOnlyToStorage());
201
202        // Try overflowing the storage-block.
203        uint32_t smallStorage[8];
204        writer.reset(smallStorage, sizeof(smallStorage));
205        test2(reporter, &writer);
206        REPORTER_ASSERT(reporter, !writer.wroteOnlyToStorage());
207    }
208
209    // small storage
210    {
211        SkSWriter32<8 * sizeof(intptr_t)> writer(100);
212        test1(reporter, &writer);
213        writer.reset(); // should just rewind our storage
214        test2(reporter, &writer);
215
216        writer.reset();
217        testWritePad(reporter, &writer);
218    }
219
220    // large storage
221    {
222        SkSWriter32<1024 * sizeof(intptr_t)> writer(100);
223        test1(reporter, &writer);
224        writer.reset(); // should just rewind our storage
225        test2(reporter, &writer);
226
227        writer.reset();
228        testWritePad(reporter, &writer);
229    }
230
231    test_ptr(reporter);
232    test_rewind(reporter);
233}
234
235#include "TestClassDef.h"
236DEFINE_TESTCLASS("Writer32", Writer32Class, Tests)
237