~ubuntu-branches/ubuntu/trusty/subversion/trusty-proposed

« back to all changes in this revision

Viewing changes to subversion/tests/libsvn_wc/pristine-store-test.c

  • Committer: Package Import Robot
  • Author(s): Andy Whitcroft
  • Date: 2012-06-21 15:36:36 UTC
  • mfrom: (0.4.13 sid)
  • Revision ID: package-import@ubuntu.com-20120621153636-amqqmuidgwgxz1ly
Tags: 1.7.5-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Create pot file on build.
  - Build a python-subversion-dbg package.
  - Build-depend on python-dbg.
  - Build-depend on default-jre-headless/-jdk.
  - Do not apply java-build patch.
  - debian/rules: Manually create the doxygen output directory, otherwise
    we get weird build failures when running parallel builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pristine-store-test.c :  test the pristine-store subsystem
 
3
 *
 
4
 * ====================================================================
 
5
 *    Licensed to the Apache Software Foundation (ASF) under one
 
6
 *    or more contributor license agreements.  See the NOTICE file
 
7
 *    distributed with this work for additional information
 
8
 *    regarding copyright ownership.  The ASF licenses this file
 
9
 *    to you under the Apache License, Version 2.0 (the
 
10
 *    "License"); you may not use this file except in compliance
 
11
 *    with the License.  You may obtain a copy of the License at
 
12
 *
 
13
 *      http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 *    Unless required by applicable law or agreed to in writing,
 
16
 *    software distributed under the License is distributed on an
 
17
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
18
 *    KIND, either express or implied.  See the License for the
 
19
 *    specific language governing permissions and limitations
 
20
 *    under the License.
 
21
 * ====================================================================
 
22
 */
 
23
 
 
24
#include <apr_pools.h>
 
25
#include <apr_general.h>
 
26
 
 
27
#include "svn_types.h"
 
28
 
 
29
/* Make sure SVN_DEPRECATED is defined as empty before including svn_io.h.
 
30
   We don't want to trigger deprecation warnings.  */
 
31
#ifdef SVN_DEPRECATED
 
32
#undef SVN_DEPRECATED
 
33
#endif
 
34
#define SVN_DEPRECATED
 
35
#include "svn_io.h"
 
36
 
 
37
#include "svn_dirent_uri.h"
 
38
#include "svn_pools.h"
 
39
#include "svn_repos.h"
 
40
#include "svn_wc.h"
 
41
#include "svn_client.h"
 
42
 
 
43
#include "utils.h"
 
44
 
 
45
#include "../../libsvn_wc/wc.h"
 
46
#include "../../libsvn_wc/wc_db.h"
 
47
#include "../../libsvn_wc/wc-queries.h"
 
48
#include "../../libsvn_wc/workqueue.h"
 
49
 
 
50
#include "private/svn_wc_private.h"
 
51
 
 
52
#include "../svn_test.h"
 
53
 
 
54
 
 
55
/* Create repos and WC, set *WC_ABSPATH to the WC path, and set *DB to a new
 
56
 * DB context. */
 
57
static svn_error_t *
 
58
create_repos_and_wc(const char **wc_abspath,
 
59
                    svn_wc__db_t **db,
 
60
                    const char *test_name,
 
61
                    const svn_test_opts_t *opts,
 
62
                    apr_pool_t *pool)
 
63
{
 
64
  svn_test__sandbox_t sandbox;
 
65
 
 
66
  SVN_ERR(svn_test__sandbox_create(&sandbox, test_name, opts, pool));
 
67
  *wc_abspath = sandbox.wc_abspath;
 
68
  *db = sandbox.wc_ctx->db;
 
69
 
 
70
  return SVN_NO_ERROR;
 
71
}
 
72
 
 
73
 
 
74
/* Write the string DATA into a new unique-named file in the directory
 
75
 * DIR_ABSPATH.  Set *FILE_ABSPATH to its absolute path and *CHECKSUM_SHA1
 
76
 * and *CHECKSUM_MD5 to its SHA-1 and MD-5 checksums.
 
77
 *
 
78
 * CHECKSUM_SHA1 and/or CHECKSUM_MD5 may be null if not required. */
 
79
static svn_error_t *
 
80
write_and_checksum_temp_file(const char **file_abspath,
 
81
                             svn_checksum_t **sha1_checksum,
 
82
                             svn_checksum_t **md5_checksum,
 
83
                             const char *data,
 
84
                             const char *dir_abspath,
 
85
                             apr_pool_t *pool)
 
86
{
 
87
  apr_file_t *file;
 
88
 
 
89
  SVN_ERR(svn_io_open_unique_file3(&file, file_abspath,
 
90
                                   dir_abspath, svn_io_file_del_none,
 
91
                                   pool, pool));
 
92
 
 
93
  SVN_ERR(svn_io_file_write_full(file, data, strlen(data), NULL, pool));
 
94
  SVN_ERR(svn_io_file_close(file, pool));
 
95
 
 
96
  if (sha1_checksum)
 
97
    SVN_ERR(svn_io_file_checksum2(sha1_checksum, *file_abspath,
 
98
                                  svn_checksum_sha1, pool));
 
99
  if (md5_checksum)
 
100
    SVN_ERR(svn_io_file_checksum2(md5_checksum, *file_abspath,
 
101
                                  svn_checksum_md5, pool));
 
102
 
 
103
  return SVN_NO_ERROR;
 
104
}
 
105
 
 
106
 
 
107
/* Exercise the pristine text API with a simple write and read. */
 
108
static svn_error_t *
 
109
pristine_write_read(const svn_test_opts_t *opts,
 
110
                    apr_pool_t *pool)
 
111
{
 
112
  svn_wc__db_t *db;
 
113
  const char *wc_abspath;
 
114
 
 
115
  const char *pristine_tmp_abspath;
 
116
 
 
117
  const char data[] = "Blah";
 
118
  svn_string_t *data_string = svn_string_create(data, pool);
 
119
  svn_checksum_t *data_sha1, *data_md5;
 
120
 
 
121
  SVN_ERR(create_repos_and_wc(&wc_abspath, &db,
 
122
                              "pristine_write_read", opts, pool));
 
123
 
 
124
  /* Write DATA into a new temporary pristine file, set PRISTINE_TMP_ABSPATH
 
125
   * to its path and set DATA_SHA1 and DATA_MD5 to its checksums. */
 
126
  {
 
127
    const char *pristine_tmp_dir;
 
128
 
 
129
    SVN_ERR(svn_wc__db_pristine_get_tempdir(&pristine_tmp_dir, db,
 
130
                                            wc_abspath, pool, pool));
 
131
    SVN_ERR(write_and_checksum_temp_file(&pristine_tmp_abspath,
 
132
                                         &data_sha1, &data_md5,
 
133
                                         data, pristine_tmp_dir, pool));
 
134
  }
 
135
 
 
136
  /* Ensure it's not already in the store. */
 
137
  {
 
138
    svn_boolean_t present;
 
139
 
 
140
    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
 
141
                                      pool));
 
142
    SVN_TEST_ASSERT(! present);
 
143
  }
 
144
 
 
145
  /* Install the new pristine file, referenced by its checksum. */
 
146
  SVN_ERR(svn_wc__db_pristine_install(db, pristine_tmp_abspath,
 
147
                                      data_sha1, data_md5, pool));
 
148
 
 
149
  /* Ensure it is now found in the store. */
 
150
  {
 
151
    svn_boolean_t present;
 
152
 
 
153
    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
 
154
                                      pool));
 
155
    SVN_TEST_ASSERT(present);
 
156
  }
 
157
 
 
158
  /* Look up its MD-5 from its SHA-1, and check it's the same MD-5. */
 
159
  {
 
160
    const svn_checksum_t *looked_up_md5;
 
161
 
 
162
    SVN_ERR(svn_wc__db_pristine_get_md5(&looked_up_md5, db, wc_abspath,
 
163
                                        data_sha1, pool, pool));
 
164
    SVN_TEST_ASSERT(looked_up_md5->kind == svn_checksum_md5);
 
165
    SVN_TEST_ASSERT(svn_checksum_match(data_md5, looked_up_md5));
 
166
  }
 
167
 
 
168
  /* Read the pristine text back and verify it's the same content. */
 
169
  {
 
170
    svn_stream_t *data_stream = svn_stream_from_string(data_string, pool);
 
171
    svn_stream_t *data_read_back;
 
172
    svn_boolean_t same;
 
173
 
 
174
    SVN_ERR(svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath,
 
175
                                     data_sha1, pool, pool));
 
176
    SVN_ERR(svn_stream_contents_same2(&same, data_read_back, data_stream,
 
177
                                      pool));
 
178
    SVN_TEST_ASSERT(same);
 
179
  }
 
180
 
 
181
  /* Trivially test the "remove if unreferenced" API: it's not referenced
 
182
     so we should be able to remove it. */
 
183
  {
 
184
    svn_error_t *err;
 
185
    svn_stream_t *data_read_back;
 
186
 
 
187
    SVN_ERR(svn_wc__db_pristine_remove(db, wc_abspath, data_sha1, pool));
 
188
    err = svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath,
 
189
                                   data_sha1, pool, pool);
 
190
    SVN_TEST_ASSERT(err != NULL);
 
191
    svn_error_clear(err);
 
192
  }
 
193
 
 
194
  /* Ensure it's no longer found in the store. */
 
195
  {
 
196
    svn_boolean_t present;
 
197
 
 
198
    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
 
199
                                      pool));
 
200
    SVN_TEST_ASSERT(! present);
 
201
  }
 
202
 
 
203
  return SVN_NO_ERROR;
 
204
}
 
205
 
 
206
/* Test deleting a pristine text while it is open for reading. */
 
207
static svn_error_t *
 
208
pristine_delete_while_open(const svn_test_opts_t *opts,
 
209
                           apr_pool_t *pool)
 
210
{
 
211
  svn_wc__db_t *db;
 
212
  const char *wc_abspath;
 
213
  const char *pristine_tmp_dir;
 
214
  svn_stream_t *contents;
 
215
 
 
216
  const char data[] = "Blah";
 
217
  svn_checksum_t *data_sha1, *data_md5;
 
218
 
 
219
  SVN_ERR(create_repos_and_wc(&wc_abspath, &db,
 
220
                              "pristine_delete_while_open", opts, pool));
 
221
 
 
222
  SVN_ERR(svn_wc__db_pristine_get_tempdir(&pristine_tmp_dir, db,
 
223
                                          wc_abspath, pool, pool));
 
224
 
 
225
  /* Install a pristine text. */
 
226
  {
 
227
    const char *path;
 
228
 
 
229
    SVN_ERR(write_and_checksum_temp_file(&path, &data_sha1, &data_md5,
 
230
                                         data, pristine_tmp_dir, pool));
 
231
    SVN_ERR(svn_wc__db_pristine_install(db, path, data_sha1, data_md5, pool));
 
232
  }
 
233
 
 
234
  /* Open it for reading */
 
235
  SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db, wc_abspath, data_sha1,
 
236
                                   pool, pool));
 
237
 
 
238
  /* Delete it */
 
239
  SVN_ERR(svn_wc__db_pristine_remove(db, wc_abspath, data_sha1, pool));
 
240
 
 
241
  /* Continue to read from it */
 
242
  {
 
243
    char buffer[4];
 
244
    apr_size_t len = 4;
 
245
 
 
246
    SVN_ERR(svn_stream_read(contents, buffer, &len));
 
247
    SVN_TEST_ASSERT(len == 4);
 
248
    SVN_TEST_ASSERT(memcmp(buffer, data, len) == 0);
 
249
  }
 
250
 
 
251
  /* Ensure it's no longer found in the store. (The file may still exist as
 
252
   * an orphan, depending on the implementation.) */
 
253
  {
 
254
    svn_boolean_t present;
 
255
 
 
256
    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
 
257
                                      pool));
 
258
    SVN_TEST_ASSERT(! present);
 
259
  }
 
260
 
 
261
  /* Close the read stream */
 
262
  SVN_ERR(svn_stream_close(contents));
 
263
 
 
264
  return SVN_NO_ERROR;
 
265
}
 
266
 
 
267
/* Check that the store rejects an attempt to replace an existing pristine
 
268
 * text with different text.
 
269
 *
 
270
 * White-box knowledge: The implementation compares the file sizes but
 
271
 * doesn't compare the text itself, so in this test we ensure the second
 
272
 * text is a different size. */
 
273
static svn_error_t *
 
274
reject_mismatching_text(const svn_test_opts_t *opts,
 
275
                        apr_pool_t *pool)
 
276
{
 
277
#ifdef SVN_DEBUG  /* The pristine store only checks this in debug mode. */
 
278
  svn_wc__db_t *db;
 
279
  const char *wc_abspath;
 
280
  const char *pristine_tmp_dir;
 
281
 
 
282
  const char data[] = "Blah";
 
283
  svn_checksum_t *data_sha1, *data_md5;
 
284
 
 
285
  const char data2[] = "Baz";
 
286
 
 
287
  SVN_ERR(create_repos_and_wc(&wc_abspath, &db,
 
288
                              "reject_mismatching_text", opts, pool));
 
289
 
 
290
  SVN_ERR(svn_wc__db_pristine_get_tempdir(&pristine_tmp_dir, db,
 
291
                                          wc_abspath, pool, pool));
 
292
 
 
293
  /* Install a pristine text. */
 
294
  {
 
295
    const char *path;
 
296
 
 
297
    SVN_ERR(write_and_checksum_temp_file(&path, &data_sha1, &data_md5,
 
298
                                         data, pristine_tmp_dir, pool));
 
299
    SVN_ERR(svn_wc__db_pristine_install(db, path, data_sha1, data_md5, pool));
 
300
  }
 
301
 
 
302
  /* Try to install the wrong pristine text against the same checksum.
 
303
   * Should fail. */
 
304
  {
 
305
    svn_error_t *err;
 
306
    const char *path;
 
307
 
 
308
    SVN_ERR(write_and_checksum_temp_file(&path, NULL, NULL,
 
309
                                         data2, pristine_tmp_dir, pool));
 
310
    err = svn_wc__db_pristine_install(db, path, data_sha1, data_md5, pool);
 
311
    SVN_TEST_ASSERT(err != NULL);
 
312
    SVN_TEST_ASSERT(err->apr_err == SVN_ERR_WC_CORRUPT_TEXT_BASE);
 
313
    svn_error_clear(err);
 
314
  }
 
315
 
 
316
  return SVN_NO_ERROR;
 
317
#else
 
318
  return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
 
319
                          "The consistency check to be tested is only "
 
320
                          "active in debug-mode builds");
 
321
#endif
 
322
}
 
323
 
 
324
 
 
325
struct svn_test_descriptor_t test_funcs[] =
 
326
  {
 
327
    SVN_TEST_NULL,
 
328
    SVN_TEST_OPTS_PASS(pristine_write_read,
 
329
                       "pristine_write_read"),
 
330
    SVN_TEST_OPTS_PASS(pristine_delete_while_open,
 
331
                       "pristine_delete_while_open"),
 
332
    SVN_TEST_OPTS_PASS(reject_mismatching_text,
 
333
                       "reject_mismatching_text"),
 
334
    SVN_TEST_NULL
 
335
  };