1 /* vdelta-test.c -- test driver for text deltas
2 *
3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 * ====================================================================
21 */
22
23 #define APR_WANT_STDIO
24 #include <apr_want.h>
25
26 #include <apr_general.h>
27 #include <assert.h>
28
29 #include "../svn_test.h"
30
31 #include "svn_ctype.h"
32 #include "svn_delta.h"
33 #include "svn_error.h"
34 #include "svn_pools.h"
35
36 #include "../../libsvn_delta/delta.h"
37 #include "delta-window-test.h"
38
39 static apr_off_t
print_delta_window(const svn_txdelta_window_t * window,const char * tag,int quiet,FILE * stream)40 print_delta_window(const svn_txdelta_window_t *window,
41 const char *tag, int quiet, FILE *stream)
42 {
43 if (quiet)
44 return delta_window_size_estimate(window);
45 else
46 return delta_window_print(window, tag, stream);
47 }
48
49
50 static void
do_one_diff(apr_file_t * source_file,apr_file_t * target_file,int * count,apr_off_t * len,int quiet,apr_pool_t * pool,const char * tag,FILE * stream)51 do_one_diff(apr_file_t *source_file, apr_file_t *target_file,
52 int *count, apr_off_t *len,
53 int quiet, apr_pool_t *pool,
54 const char *tag, FILE* stream)
55 {
56 svn_txdelta_stream_t *delta_stream = NULL;
57 svn_txdelta_window_t *delta_window = NULL;
58 apr_pool_t *fpool = svn_pool_create(pool);
59 apr_pool_t *wpool = svn_pool_create(pool);
60
61 *count = 0;
62 *len = 0;
63 svn_txdelta2(&delta_stream,
64 svn_stream_from_aprfile(source_file, fpool),
65 svn_stream_from_aprfile(target_file, fpool),
66 FALSE,
67 fpool);
68 do {
69 svn_error_t *err;
70 err = svn_txdelta_next_window(&delta_window, delta_stream, wpool);
71 if (err)
72 svn_handle_error2(err, stderr, TRUE, "vdelta-test: ");
73 if (delta_window != NULL)
74 {
75 *len += print_delta_window(delta_window, tag, quiet, stream);
76 svn_pool_clear(wpool);
77 ++*count;
78 }
79 } while (delta_window != NULL);
80 fprintf(stream, "%s: (LENGTH %" APR_OFF_T_FMT " +%d)\n", tag, *len, *count);
81
82 svn_pool_destroy(fpool);
83 svn_pool_destroy(wpool);
84 }
85
86
87 static void
do_one_test_cycle(apr_file_t * source_file_A,apr_file_t * target_file_A,apr_file_t * source_file_B,apr_file_t * target_file_B,int quiet,apr_pool_t * pool)88 do_one_test_cycle(apr_file_t *source_file_A, apr_file_t *target_file_A,
89 apr_file_t *source_file_B, apr_file_t *target_file_B,
90 int quiet, apr_pool_t *pool)
91 {
92 int count_A = 0;
93 apr_off_t len_A = 0;
94
95 int count_B = 0;
96 apr_off_t len_B = 0;
97
98 do_one_diff(source_file_A, target_file_A,
99 &count_A, &len_A, quiet, pool, "A ", stdout);
100
101 if (source_file_B)
102 {
103 apr_pool_t *fpool = svn_pool_create(pool);
104 apr_pool_t *wpool = svn_pool_create(pool);
105 svn_txdelta_stream_t *stream_A = NULL;
106 svn_txdelta_stream_t *stream_B = NULL;
107 svn_txdelta_window_t *window_A = NULL;
108 svn_txdelta_window_t *window_B = NULL;
109 svn_txdelta_window_t *window_AB = NULL;
110 int count_AB = 0;
111 apr_off_t len_AB = 0;
112
113 putc('\n', stdout);
114 do_one_diff(source_file_B, target_file_B,
115 &count_B, &len_B, quiet, pool, "B ", stdout);
116
117 putc('\n', stdout);
118
119 {
120 apr_off_t offset = 0;
121
122 apr_file_seek(source_file_A, APR_SET, &offset);
123 apr_file_seek(target_file_A, APR_SET, &offset);
124 apr_file_seek(source_file_B, APR_SET, &offset);
125 apr_file_seek(target_file_B, APR_SET, &offset);
126 }
127
128 svn_txdelta2(&stream_A,
129 svn_stream_from_aprfile(source_file_A, fpool),
130 svn_stream_from_aprfile(target_file_A, fpool),
131 FALSE,
132 fpool);
133 svn_txdelta2(&stream_B,
134 svn_stream_from_aprfile(source_file_B, fpool),
135 svn_stream_from_aprfile(target_file_B, fpool),
136 FALSE,
137 fpool);
138
139 for (count_AB = 0; count_AB < count_B; ++count_AB)
140 {
141 svn_error_t *err;
142
143 err = svn_txdelta_next_window(&window_A, stream_A, wpool);
144 if (err)
145 svn_handle_error2(err, stderr, TRUE, "vdelta-test: ");
146 err = svn_txdelta_next_window(&window_B, stream_B, wpool);
147 if (err)
148 svn_handle_error2(err, stderr, TRUE, "vdelta-test: ");
149
150 /* Note: It's not possible that window_B is null, we already
151 counted the number of windows in the second delta. */
152 assert(window_A != NULL || window_B->src_ops == 0);
153 if (window_B->src_ops == 0)
154 {
155 window_AB = window_B;
156 window_AB->sview_len = 0;
157 }
158 else
159 window_AB = svn_txdelta_compose_windows(window_A, window_B,
160 wpool);
161 len_AB += print_delta_window(window_AB, "AB", quiet, stdout);
162 svn_pool_clear(wpool);
163 }
164
165 fprintf(stdout, "AB: (LENGTH %" APR_OFF_T_FMT " +%d)\n",
166 len_AB, count_AB);
167 }
168 }
169
170
171 static apr_file_t *
open_binary_read(const char * path,apr_pool_t * pool)172 open_binary_read(const char *path, apr_pool_t *pool)
173 {
174 apr_status_t apr_err;
175 apr_file_t *fp;
176
177 apr_err = apr_file_open(&fp, path, (APR_READ | APR_BINARY),
178 APR_OS_DEFAULT, pool);
179
180 if (apr_err)
181 {
182 fprintf(stderr, "unable to open \"%s\" for reading\n", path);
183 exit(1);
184 }
185
186 return fp;
187 }
188
189
190 int
main(int argc,char ** argv)191 main(int argc, char **argv)
192 {
193 apr_file_t *source_file_A = NULL;
194 apr_file_t *target_file_A = NULL;
195
196 apr_file_t *source_file_B = NULL;
197 apr_file_t *target_file_B = NULL;
198
199 apr_pool_t *pool;
200 int quiet = 0;
201 int repeat = 1;
202
203 while (argc > 1)
204 {
205 const char *const arg = argv[1];
206 if (arg[0] != '-')
207 break;
208
209 if (arg[1] == 'q')
210 quiet = 1;
211 else if (svn_ctype_isdigit(arg[1]))
212 repeat = atoi(arg + 1);
213 else
214 break;
215 --argc; ++argv;
216 }
217
218 apr_initialize();
219 pool = svn_pool_create(NULL);
220
221 if (argc == 2)
222 {
223 target_file_A = open_binary_read(argv[1], pool);
224 }
225 else if (argc == 3)
226 {
227 source_file_A = open_binary_read(argv[1], pool);
228 target_file_A = open_binary_read(argv[2], pool);
229 }
230 else if (argc == 4)
231 {
232 source_file_A = open_binary_read(argv[1], pool);
233 target_file_A = open_binary_read(argv[2], pool);
234 source_file_B = open_binary_read(argv[2], pool);
235 target_file_B = open_binary_read(argv[3], pool);
236 }
237 else
238 {
239 fprintf(stderr,
240 "Usage: vdelta-test [-q] [-<repeat>] <target>\n"
241 " or: vdelta-test [-q] [-<repeat>] <source> <target>\n"
242 " or: vdelta-test [-q] [-<repeat>] "
243 "<source> <intermediate> <target>\n");
244 exit(1);
245 }
246
247 while (0 < repeat--)
248 {
249 apr_off_t offset = 0;
250
251 do_one_test_cycle(source_file_A, target_file_A,
252 source_file_B, target_file_B,
253 quiet, pool);
254
255 if (source_file_A) apr_file_seek(source_file_A, APR_SET, &offset);
256 if (target_file_A) apr_file_seek(target_file_A, APR_SET, &offset);
257 if (source_file_B) apr_file_seek(source_file_B, APR_SET, &offset);
258 if (target_file_B) apr_file_seek(target_file_B, APR_SET, &offset);
259 }
260
261 if (source_file_A) apr_file_close(source_file_A);
262 if (target_file_A) apr_file_close(target_file_A);
263 if (source_file_B) apr_file_close(source_file_B);
264 if (target_file_B) apr_file_close(source_file_B);
265
266 svn_pool_destroy(pool);
267 apr_terminate();
268 exit(0);
269 }
270