~sergei.glushchenko/+junk/page-scan-hack

« back to all changes in this revision

Viewing changes to src/libarchive/libarchive/test/test_write_disk_sparse.c

merge parallel compression branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003-2007 Tim Kientzle
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
17
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
#include "test.h"
 
26
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_sparse.c 201247 2009-12-30 05:59:21Z kientzle $");
 
27
 
 
28
/*
 
29
 * Write a file using archive_write_data call, read the file
 
30
 * back and verify the contents.  The data written includes large
 
31
 * blocks of nulls, so it should exercise the sparsification logic
 
32
 * if ARCHIVE_EXTRACT_SPARSE is enabled.
 
33
 */
 
34
static void
 
35
verify_write_data(struct archive *a, int sparse)
 
36
{
 
37
        static const char data[]="abcdefghijklmnopqrstuvwxyz";
 
38
        struct stat st;
 
39
        struct archive_entry *ae;
 
40
        size_t buff_size = 64 * 1024;
 
41
        char *buff, *p;
 
42
        const char *msg = sparse ? "sparse" : "non-sparse";
 
43
        FILE *f;
 
44
 
 
45
        buff = malloc(buff_size);
 
46
        assert(buff != NULL);
 
47
 
 
48
        ae = archive_entry_new();
 
49
        assert(ae != NULL);
 
50
        archive_entry_set_size(ae, 8 * buff_size);
 
51
        archive_entry_set_pathname(ae, "test_write_data");
 
52
        archive_entry_set_mode(ae, AE_IFREG | 0755);
 
53
        assertEqualIntA(a, 0, archive_write_header(a, ae));
 
54
 
 
55
        /* Use archive_write_data() to write three relatively sparse blocks. */
 
56
 
 
57
        /* First has non-null data at beginning. */
 
58
        memset(buff, 0, buff_size);
 
59
        memcpy(buff, data, sizeof(data));
 
60
        failure("%s", msg);
 
61
        assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));
 
62
 
 
63
        /* Second has non-null data in the middle. */
 
64
        memset(buff, 0, buff_size);
 
65
        memcpy(buff + buff_size / 2 - 3, data, sizeof(data));
 
66
        failure("%s", msg);
 
67
        assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));
 
68
 
 
69
        /* Third has non-null data at the end. */
 
70
        memset(buff, 0, buff_size);
 
71
        memcpy(buff + buff_size - sizeof(data), data, sizeof(data));
 
72
        failure("%s", msg);
 
73
        assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));
 
74
 
 
75
        failure("%s", msg);
 
76
        assertEqualIntA(a, 0, archive_write_finish_entry(a));
 
77
 
 
78
        /* Test the entry on disk. */
 
79
        assert(0 == stat(archive_entry_pathname(ae), &st));
 
80
        assertEqualInt(st.st_size, 8 * buff_size);
 
81
        f = fopen(archive_entry_pathname(ae), "rb");
 
82
        if (!assert(f != NULL))
 
83
                return;
 
84
 
 
85
        /* Check first block. */
 
86
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
87
        failure("%s", msg);
 
88
        assertEqualMem(buff, data, sizeof(data));
 
89
        for (p = buff + sizeof(data); p < buff + buff_size; ++p) {
 
90
                failure("offset: %d, %s", (int)(p - buff), msg);
 
91
                if (!assertEqualInt(0, *p))
 
92
                        break;
 
93
        }
 
94
 
 
95
        /* Check second block. */
 
96
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
97
        for (p = buff; p < buff + buff_size; ++p) {
 
98
                failure("offset: %d, %s", (int)(p - buff), msg);
 
99
                if (p == buff + buff_size / 2 - 3) {
 
100
                        assertEqualMem(p, data, sizeof(data));
 
101
                        p += sizeof(data);
 
102
                } else if (!assertEqualInt(0, *p))
 
103
                        break;
 
104
        }
 
105
 
 
106
        /* Check third block. */
 
107
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
108
        for (p = buff; p < buff + buff_size - sizeof(data); ++p) {
 
109
                failure("offset: %d, %s", (int)(p - buff), msg);
 
110
                if (!assertEqualInt(0, *p))
 
111
                        break;
 
112
        }
 
113
        failure("%s", msg);
 
114
        assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data));
 
115
 
 
116
        /* XXX more XXX */
 
117
 
 
118
        assertEqualInt(0, fclose(f));
 
119
        archive_entry_free(ae);
 
120
        free(buff);
 
121
}
 
122
 
 
123
/*
 
124
 * As above, but using the archive_write_data_block() call.
 
125
 */
 
126
static void
 
127
verify_write_data_block(struct archive *a, int sparse)
 
128
{
 
129
        static const char data[]="abcdefghijklmnopqrstuvwxyz";
 
130
        struct stat st;
 
131
        struct archive_entry *ae;
 
132
        size_t buff_size = 64 * 1024;
 
133
        char *buff, *p;
 
134
        const char *msg = sparse ? "sparse" : "non-sparse";
 
135
        FILE *f;
 
136
 
 
137
        buff = malloc(buff_size);
 
138
        assert(buff != NULL);
 
139
 
 
140
        ae = archive_entry_new();
 
141
        assert(ae != NULL);
 
142
        archive_entry_set_size(ae, 8 * buff_size);
 
143
        archive_entry_set_pathname(ae, "test_write_data_block");
 
144
        archive_entry_set_mode(ae, AE_IFREG | 0755);
 
145
        assertEqualIntA(a, 0, archive_write_header(a, ae));
 
146
 
 
147
        /* Use archive_write_data_block() to write three
 
148
           relatively sparse blocks. */
 
149
 
 
150
        /* First has non-null data at beginning. */
 
151
        memset(buff, 0, buff_size);
 
152
        memcpy(buff, data, sizeof(data));
 
153
        failure("%s", msg);
 
154
        assertEqualInt(ARCHIVE_OK,
 
155
            archive_write_data_block(a, buff, buff_size, 100));
 
156
 
 
157
        /* Second has non-null data in the middle. */
 
158
        memset(buff, 0, buff_size);
 
159
        memcpy(buff + buff_size / 2 - 3, data, sizeof(data));
 
160
        failure("%s", msg);
 
161
        assertEqualInt(ARCHIVE_OK,
 
162
            archive_write_data_block(a, buff, buff_size, buff_size + 200));
 
163
 
 
164
        /* Third has non-null data at the end. */
 
165
        memset(buff, 0, buff_size);
 
166
        memcpy(buff + buff_size - sizeof(data), data, sizeof(data));
 
167
        failure("%s", msg);
 
168
        assertEqualInt(ARCHIVE_OK,
 
169
            archive_write_data_block(a, buff, buff_size, buff_size * 2 + 300));
 
170
 
 
171
        failure("%s", msg);
 
172
        assertEqualIntA(a, 0, archive_write_finish_entry(a));
 
173
 
 
174
        /* Test the entry on disk. */
 
175
        assert(0 == stat(archive_entry_pathname(ae), &st));
 
176
        assertEqualInt(st.st_size, 8 * buff_size);
 
177
        f = fopen(archive_entry_pathname(ae), "rb");
 
178
        if (!assert(f != NULL))
 
179
                return;
 
180
 
 
181
        /* Check 100-byte gap at beginning */
 
182
        assertEqualInt(100, fread(buff, 1, 100, f));
 
183
        failure("%s", msg);
 
184
        for (p = buff; p < buff + 100; ++p) {
 
185
                failure("offset: %d, %s", (int)(p - buff), msg);
 
186
                if (!assertEqualInt(0, *p))
 
187
                        break;
 
188
        }
 
189
 
 
190
        /* Check first block. */
 
191
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
192
        failure("%s", msg);
 
193
        assertEqualMem(buff, data, sizeof(data));
 
194
        for (p = buff + sizeof(data); p < buff + buff_size; ++p) {
 
195
                failure("offset: %d, %s", (int)(p - buff), msg);
 
196
                if (!assertEqualInt(0, *p))
 
197
                        break;
 
198
        }
 
199
 
 
200
        /* Check 100-byte gap */
 
201
        assertEqualInt(100, fread(buff, 1, 100, f));
 
202
        failure("%s", msg);
 
203
        for (p = buff; p < buff + 100; ++p) {
 
204
                failure("offset: %d, %s", (int)(p - buff), msg);
 
205
                if (!assertEqualInt(0, *p))
 
206
                        break;
 
207
        }
 
208
 
 
209
        /* Check second block. */
 
210
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
211
        for (p = buff; p < buff + buff_size; ++p) {
 
212
                failure("offset: %d, %s", (int)(p - buff), msg);
 
213
                if (p == buff + buff_size / 2 - 3) {
 
214
                        assertEqualMem(p, data, sizeof(data));
 
215
                        p += sizeof(data);
 
216
                } else if (!assertEqualInt(0, *p))
 
217
                        break;
 
218
        }
 
219
 
 
220
        /* Check 100-byte gap */
 
221
        assertEqualInt(100, fread(buff, 1, 100, f));
 
222
        failure("%s", msg);
 
223
        for (p = buff; p < buff + 100; ++p) {
 
224
                failure("offset: %d, %s", (int)(p - buff), msg);
 
225
                if (!assertEqualInt(0, *p))
 
226
                        break;
 
227
        }
 
228
 
 
229
        /* Check third block. */
 
230
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
231
        for (p = buff; p < buff + buff_size - sizeof(data); ++p) {
 
232
                failure("offset: %d, %s", (int)(p - buff), msg);
 
233
                if (!assertEqualInt(0, *p))
 
234
                        break;
 
235
        }
 
236
        failure("%s", msg);
 
237
        assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data));
 
238
 
 
239
        /* Check another block size beyond last we wrote. */
 
240
        assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
 
241
        failure("%s", msg);
 
242
        for (p = buff; p < buff + buff_size; ++p) {
 
243
                failure("offset: %d, %s", (int)(p - buff), msg);
 
244
                if (!assertEqualInt(0, *p))
 
245
                        break;
 
246
        }
 
247
 
 
248
 
 
249
        /* XXX more XXX */
 
250
 
 
251
        assertEqualInt(0, fclose(f));
 
252
        free(buff);
 
253
        archive_entry_free(ae);
 
254
}
 
255
 
 
256
DEFINE_TEST(test_write_disk_sparse)
 
257
{
 
258
        struct archive *ad;
 
259
 
 
260
 
 
261
        /*
 
262
         * The return values, etc, of the write data functions
 
263
         * shouldn't change regardless of whether we've requested
 
264
         * sparsification.  (The performance and pattern of actual
 
265
         * write calls to the disk should vary, of course, but the
 
266
         * client program shouldn't see any difference.)
 
267
         */
 
268
        assert((ad = archive_write_disk_new()) != NULL);
 
269
        archive_write_disk_set_options(ad, 0);
 
270
        verify_write_data(ad, 0);
 
271
        verify_write_data_block(ad, 0);
 
272
        assertEqualInt(0, archive_write_finish(ad));
 
273
 
 
274
        assert((ad = archive_write_disk_new()) != NULL);
 
275
        archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_SPARSE);
 
276
        verify_write_data(ad, 1);
 
277
        verify_write_data_block(ad, 1);
 
278
        assertEqualInt(0, archive_write_finish(ad));
 
279
 
 
280
}