~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/tests/libsvn_subr/io-test.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <stdio.h>
27
27
 
28
28
#include <apr.h>
 
29
#include <apr_version.h>
29
30
 
30
31
#include "svn_pools.h"
31
32
#include "svn_string.h"
 
33
#include "svn_io.h"
32
34
#include "private/svn_skel.h"
 
35
#include "private/svn_dep_compat.h"
 
36
#include "private/svn_io_private.h"
33
37
 
34
38
#include "../svn_test.h"
35
39
#include "../svn_test_fs.h"
37
41
 
38
42
/* Helpers to create the test data directory. */
39
43
 
40
 
#define TEST_DIR "io-test-temp"
 
44
#define TEST_DIR_PREFIX "io-test-temp"
41
45
 
42
46
/* The definition for the test data files. */
43
47
struct test_file_definition_t
64
68
    char* created_path;
65
69
  };
66
70
 
67
 
struct test_file_definition_t test_file_definitions[] =
 
71
static struct test_file_definition_t test_file_definitions_template[] =
68
72
  {
69
73
    {"empty",                 "",      0},
70
74
    {"single_a",              "a",     1},
119
123
 
120
124
static svn_error_t *
121
125
create_test_file(struct test_file_definition_t* definition,
 
126
                 const char *testname,
122
127
                 apr_pool_t *pool,
123
128
                 apr_pool_t *scratch_pool)
124
129
{
127
132
  apr_off_t midpos = definition->size / 2;
128
133
  svn_error_t *err = NULL;
129
134
  int i;
 
135
  const char *test_dir = apr_pstrcat(pool, TEST_DIR_PREFIX, testname, NULL);
130
136
 
131
137
  if (definition->size < 5)
132
138
    SVN_ERR_ASSERT(strlen(definition->data) >= (apr_size_t)definition->size);
134
140
    SVN_ERR_ASSERT(strlen(definition->data) >= 5);
135
141
 
136
142
 
137
 
  definition->created_path = svn_dirent_join(TEST_DIR,
138
 
                                  definition->name,
139
 
                                  pool);
 
143
  definition->created_path = svn_dirent_join(test_dir,
 
144
                                             definition->name,
 
145
                                             pool);
140
146
 
141
147
  SVN_ERR(svn_io_file_open(&file_h,
142
148
                           definition->created_path,
174
180
 
175
181
/* Function to prepare the whole set of on-disk files to be compared. */
176
182
static svn_error_t *
177
 
create_comparison_candidates(apr_pool_t *scratch_pool)
 
183
create_comparison_candidates(struct test_file_definition_t **definitions,
 
184
                             const char *testname,
 
185
                             apr_pool_t *pool)
178
186
{
179
187
  svn_node_kind_t kind;
180
 
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
188
  apr_pool_t *iterpool = svn_pool_create(pool);
181
189
  struct test_file_definition_t *candidate;
182
190
  svn_error_t *err = SVN_NO_ERROR;
 
191
  apr_size_t count = 0;
 
192
  const char *test_dir = apr_pstrcat(pool, TEST_DIR_PREFIX,
 
193
                                     testname, NULL);
183
194
 
184
195
  /* If there's already a directory named io-test-temp, delete it.
185
196
     Doing things this way means that repositories stick around after
186
197
     a failure for postmortem analysis, but also that tests can be
187
198
     re-run without cleaning out the repositories created by prior
188
199
     runs.  */
189
 
  SVN_ERR(svn_io_check_path(TEST_DIR, &kind, scratch_pool));
 
200
  SVN_ERR(svn_io_check_path(test_dir, &kind, pool));
190
201
 
191
202
  if (kind == svn_node_dir)
192
 
    SVN_ERR(svn_io_remove_dir2(TEST_DIR, TRUE, NULL, NULL, scratch_pool));
 
203
    SVN_ERR(svn_io_remove_dir2(test_dir, TRUE, NULL, NULL, pool));
193
204
  else if (kind != svn_node_none)
194
205
    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
195
206
                             "There is already a file named '%s'",
196
 
                             TEST_DIR);
197
 
 
198
 
  SVN_ERR(svn_io_dir_make(TEST_DIR, APR_OS_DEFAULT, scratch_pool));
199
 
 
200
 
  svn_test_add_dir_cleanup(TEST_DIR);
201
 
 
202
 
  for (candidate = test_file_definitions;
 
207
                             test_dir);
 
208
 
 
209
  SVN_ERR(svn_io_dir_make(test_dir, APR_OS_DEFAULT, pool));
 
210
 
 
211
  svn_test_add_dir_cleanup(test_dir);
 
212
 
 
213
  for (candidate = test_file_definitions_template;
203
214
       candidate->name != NULL;
204
215
       candidate += 1)
 
216
    count++;
 
217
 
 
218
  *definitions = apr_pmemdup(pool, test_file_definitions_template,
 
219
                             (count + 1) * sizeof(**definitions));
 
220
  for (candidate = *definitions; candidate->name != NULL; candidate += 1)
205
221
    {
206
222
      svn_pool_clear(iterpool);
207
 
      err = create_test_file(candidate, scratch_pool, iterpool);
 
223
      err = create_test_file(candidate, testname, pool, iterpool);
208
224
      if (err)
209
225
        break;
210
226
    }
227
243
  svn_error_t *err = SVN_NO_ERROR;
228
244
  svn_error_t *cmp_err;
229
245
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
246
  struct test_file_definition_t *test_file_definitions;
230
247
 
231
 
  SVN_ERR(create_comparison_candidates(scratch_pool));
 
248
  SVN_ERR(create_comparison_candidates(&test_file_definitions,
 
249
                                       "test_two_file_size_comparison",
 
250
                                       scratch_pool));
232
251
 
233
252
  for (outer = test_file_definitions; outer->name != NULL; outer += 1)
234
253
    {
278
297
  svn_error_t *err = SVN_NO_ERROR;
279
298
  svn_error_t *cmp_err;
280
299
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
300
  struct test_file_definition_t *test_file_definitions;
281
301
 
282
 
  SVN_ERR(create_comparison_candidates(scratch_pool));
 
302
  SVN_ERR(create_comparison_candidates(&test_file_definitions,
 
303
                                       "test_two_file_content_comparison",
 
304
                                       scratch_pool));
283
305
 
284
306
  for (outer = test_file_definitions; outer->name != NULL; outer += 1)
285
307
    {
331
353
  svn_error_t *err = SVN_NO_ERROR;
332
354
  svn_error_t *cmp_err;
333
355
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
356
  struct test_file_definition_t *test_file_definitions;
334
357
 
335
 
  SVN_ERR(create_comparison_candidates(scratch_pool));
 
358
  SVN_ERR(create_comparison_candidates(&test_file_definitions,
 
359
                                       "test_three_file_size_comparison",
 
360
                                       scratch_pool));
336
361
 
337
362
  for (outer = test_file_definitions; outer->name != NULL; outer += 1)
338
363
    {
411
436
  svn_error_t *err = SVN_NO_ERROR;
412
437
  svn_error_t *cmp_err;
413
438
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
439
  struct test_file_definition_t *test_file_definitions;
414
440
 
415
 
  SVN_ERR(create_comparison_candidates(scratch_pool));
 
441
  SVN_ERR(create_comparison_candidates(&test_file_definitions,
 
442
                                       "test_three_file_content_comparison",
 
443
                                       scratch_pool));
416
444
 
417
445
  for (outer = test_file_definitions; outer->name != NULL; outer += 1)
418
446
    {
507
535
  return SVN_NO_ERROR;
508
536
}
509
537
 
 
538
/* Move the read pointer in FILE to absolute position OFFSET and align
 
539
 * the read buffer to multiples of BLOCK_SIZE.  BUFFERED is set only if
 
540
 * FILE actually uses a read buffer.  Use POOL for allocations.
 
541
 */
 
542
static svn_error_t *
 
543
aligned_seek(apr_file_t *file,
 
544
             apr_size_t block_size,
 
545
             apr_size_t offset,
 
546
             svn_boolean_t buffered,
 
547
             apr_pool_t *pool)
 
548
{
 
549
  apr_off_t block_start;
 
550
  apr_off_t current;
 
551
 
 
552
  SVN_ERR(svn_io_file_aligned_seek(file, (apr_off_t)block_size,
 
553
                                   &block_start, (apr_off_t)offset, pool));
 
554
 
 
555
  /* block start shall be aligned to multiples of block_size.
 
556
     If it isn't, it must be aligned to APR's default block size(pre-1.3 APR)
 
557
   */
 
558
  if (buffered)
 
559
    {
 
560
      SVN_TEST_ASSERT(block_start % block_size == 0);
 
561
      SVN_TEST_ASSERT(offset - block_start < block_size);
 
562
    }
 
563
 
 
564
  /* we must be at the desired offset */
 
565
  current = 0;
 
566
  SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, pool));
 
567
  SVN_TEST_ASSERT(current == (apr_off_t)offset);
 
568
 
 
569
  return SVN_NO_ERROR;
 
570
}
 
571
 
 
572
/* Move the read pointer in FILE to absolute position OFFSET, align the
 
573
 * read buffer to multiples of BLOCK_SIZE and read one byte from that
 
574
 * position.  Verify that it matches the CONTENTS for that offset.
 
575
 * BUFFERED is set only if FILE actually uses a read buffer.
 
576
 * Use POOL for allocations.
 
577
 */
 
578
static svn_error_t *
 
579
aligned_read_at(apr_file_t *file,
 
580
                svn_stringbuf_t *contents,
 
581
                apr_size_t block_size,
 
582
                apr_size_t offset,
 
583
                svn_boolean_t buffered,
 
584
                apr_pool_t *pool)
 
585
{
 
586
  char c;
 
587
  SVN_ERR(aligned_seek(file, block_size, offset, buffered, pool));
 
588
 
 
589
  /* the data we read must match whatever we wrote there */
 
590
  SVN_ERR(svn_io_file_getc(&c, file, pool));
 
591
  SVN_TEST_ASSERT(c == contents->data[offset]);
 
592
 
 
593
  return SVN_NO_ERROR;
 
594
}
 
595
 
 
596
/* Verify that aligned seek with the given BLOCK_SIZE works for FILE.
 
597
 * CONTENTS is the data expected from FILE.  BUFFERED is set only if FILE
 
598
 * actually uses a read buffer.  Use POOL for allocations.
 
599
 */
 
600
static svn_error_t *
 
601
aligned_read(apr_file_t *file,
 
602
             svn_stringbuf_t *contents,
 
603
             apr_size_t block_size,
 
604
             svn_boolean_t buffered,
 
605
             apr_pool_t *pool)
 
606
{
 
607
  apr_size_t i;
 
608
  apr_size_t offset = 0;
 
609
  const apr_size_t prime = 78427;
 
610
 
 
611
  /* "random" access to different offsets */
 
612
  for (i = 0, offset = prime; i < 10; ++i, offset += prime)
 
613
    SVN_ERR(aligned_read_at(file, contents, block_size,
 
614
                            offset % contents->len, buffered, pool));
 
615
 
 
616
  /* we can seek to EOF */
 
617
  SVN_ERR(aligned_seek(file, contents->len, block_size, buffered, pool));
 
618
 
 
619
  /* reversed order access to all bytes */
 
620
  for (i = contents->len; i > 0; --i)
 
621
    SVN_ERR(aligned_read_at(file, contents, block_size, i - 1, buffered,
 
622
                            pool));
 
623
 
 
624
  /* forward order access to all bytes */
 
625
  for (i = 0; i < contents->len; ++i)
 
626
    SVN_ERR(aligned_read_at(file, contents, block_size, i, buffered, pool));
 
627
 
 
628
  return SVN_NO_ERROR;
 
629
}
 
630
 
 
631
static svn_error_t *
 
632
aligned_seek_test(apr_pool_t *pool)
 
633
{
 
634
  apr_size_t i;
 
635
  const char *tmp_dir;
 
636
  const char *tmp_file;
 
637
  apr_file_t *f;
 
638
  svn_stringbuf_t *contents;
 
639
  const apr_size_t file_size = 100000;
 
640
 
 
641
  /* create a temp folder & schedule it for automatic cleanup */
 
642
 
 
643
  SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "aligned_seek_tmp", pool));
 
644
  SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
 
645
  SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
 
646
  svn_test_add_dir_cleanup(tmp_dir);
 
647
 
 
648
  /* create a temp file with know contents */
 
649
 
 
650
  contents = svn_stringbuf_create_ensure(file_size, pool);
 
651
  for (i = 0; i < file_size; ++i)
 
652
    svn_stringbuf_appendbyte(contents, (char)rand());
 
653
 
 
654
  SVN_ERR(svn_io_write_unique(&tmp_file, tmp_dir, contents->data,
 
655
                              contents->len,
 
656
                              svn_io_file_del_on_pool_cleanup, pool));
 
657
 
 
658
  /* now, access read data with varying alignment sizes */
 
659
  SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ | APR_BUFFERED,
 
660
                           APR_OS_DEFAULT, pool));
 
661
  SVN_ERR(aligned_read(f, contents,   0x1000, TRUE, pool)); /* APR default */
 
662
  SVN_ERR(aligned_read(f, contents,   0x8000, TRUE, pool)); /* "unusual" 32K */
 
663
  SVN_ERR(aligned_read(f, contents,  0x10000, TRUE, pool)); /* FSX default */
 
664
  SVN_ERR(aligned_read(f, contents, 0x100000, TRUE, pool)); /* larger than file */
 
665
  SVN_ERR(aligned_read(f, contents,    10001, TRUE, pool)); /* odd, larger than
 
666
                                                               APR default */
 
667
  SVN_ERR(aligned_read(f, contents,     1003, TRUE, pool)); /* odd, smaller than
 
668
                                                               APR default */
 
669
  SVN_ERR(svn_io_file_close(f, pool));
 
670
 
 
671
  /* now, try read data with buffering disabled.
 
672
     That are a special case because APR reports a buffer size of 0. */
 
673
  SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ, APR_OS_DEFAULT, pool));
 
674
  SVN_ERR(aligned_read(f, contents,   0x1000, FALSE, pool));
 
675
  SVN_ERR(aligned_read(f, contents,   0x8000, FALSE, pool));
 
676
  SVN_ERR(aligned_read(f, contents,  0x10000, FALSE, pool));
 
677
  SVN_ERR(aligned_read(f, contents, 0x100000, FALSE, pool));
 
678
  SVN_ERR(aligned_read(f, contents,    10001, FALSE, pool));
 
679
  SVN_ERR(aligned_read(f, contents,     1003, FALSE, pool));
 
680
  SVN_ERR(svn_io_file_close(f, pool));
 
681
 
 
682
  return SVN_NO_ERROR;
 
683
}
 
684
 
 
685
static svn_error_t *
 
686
ignore_enoent(apr_pool_t *pool)
 
687
{
 
688
  const char *tmp_dir, *path;
 
689
  const svn_io_dirent2_t *dirent_p;
 
690
  apr_file_t *file;
 
691
 
 
692
  /* Create an empty directory. */
 
693
  SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "ignore_enoent", pool));
 
694
  SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
 
695
  SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
 
696
  svn_test_add_dir_cleanup(tmp_dir);
 
697
 
 
698
  /* Path does not exist. */
 
699
  path = svn_dirent_join(tmp_dir, "not-present", pool);
 
700
  SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, pool));
 
701
  SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
 
702
  SVN_ERR(svn_io_set_file_read_only(path, TRUE, pool));
 
703
  SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
 
704
  SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
 
705
  SVN_ERR(svn_io_set_file_executable(path, FALSE, TRUE, pool));
 
706
  SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, TRUE, TRUE, pool, pool));
 
707
  SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, FALSE, TRUE, pool, pool));
 
708
 
 
709
  /* Neither path nor parent exists. */
 
710
  path = svn_dirent_join(path, "not-present", pool);
 
711
  SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, pool));
 
712
  SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
 
713
  SVN_ERR(svn_io_set_file_read_only(path, TRUE, pool));
 
714
  SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
 
715
  SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
 
716
  SVN_ERR(svn_io_set_file_executable(path, FALSE, TRUE, pool));
 
717
  SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, TRUE, TRUE, pool, pool));
 
718
  SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, FALSE, TRUE, pool, pool));
 
719
 
 
720
  /* File does exist. */
 
721
  path = svn_dirent_join(tmp_dir, "present", pool);
 
722
  SVN_ERR(svn_io_file_open(&file, path,
 
723
                           APR_WRITE | APR_CREATE | APR_TRUNCATE,
 
724
                           APR_OS_DEFAULT,
 
725
                           pool));
 
726
  SVN_ERR(svn_io_file_close(file, pool));
 
727
 
 
728
  /* Path does not exist as child of file. */
 
729
  path = svn_dirent_join(path, "not-present", pool);
 
730
  SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, pool));
 
731
  SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
 
732
  SVN_ERR(svn_io_set_file_read_only(path, TRUE, pool));
 
733
  SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
 
734
  SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
 
735
  SVN_ERR(svn_io_set_file_executable(path, FALSE, TRUE, pool));
 
736
  SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, TRUE, TRUE, pool, pool));
 
737
  SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, FALSE, TRUE, pool, pool));
 
738
 
 
739
  return SVN_NO_ERROR;
 
740
}
 
741
 
 
742
static svn_error_t *
 
743
test_install_stream_to_longpath(apr_pool_t *pool)
 
744
{
 
745
  const char *tmp_dir;
 
746
  const char *final_abspath;
 
747
  const char *deep_dir;
 
748
  svn_stream_t *stream;
 
749
  svn_stringbuf_t *actual_content;
 
750
  int i;
 
751
 
 
752
  /* Create an empty directory. */
 
753
  SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "test_install_stream_to_longpath",
 
754
                                  pool));
 
755
  SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
 
756
  SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
 
757
  svn_test_add_dir_cleanup(tmp_dir);
 
758
 
 
759
  deep_dir = tmp_dir;
 
760
 
 
761
  /* Generate very long path (> 260 symbols) */
 
762
  for (i = 0; i < 26; i++)
 
763
    {
 
764
      deep_dir = svn_dirent_join(deep_dir, "1234567890", pool);
 
765
      SVN_ERR(svn_io_make_dir_recursively(deep_dir, pool));
 
766
    }
 
767
 
 
768
  final_abspath = svn_dirent_join(deep_dir, "stream1", pool);
 
769
  SVN_ERR(svn_stream__create_for_install(&stream, deep_dir, pool, pool));
 
770
  SVN_ERR(svn_stream_puts(stream, "stream1 content"));
 
771
  SVN_ERR(svn_stream_close(stream));
 
772
  SVN_ERR(svn_stream__install_stream(stream,
 
773
                                     final_abspath,
 
774
                                     TRUE,
 
775
                                     pool));
 
776
 
 
777
  SVN_ERR(svn_stringbuf_from_file2(&actual_content,
 
778
                                   final_abspath,
 
779
                                   pool));
 
780
 
 
781
  SVN_TEST_STRING_ASSERT(actual_content->data, "stream1 content");
 
782
 
 
783
  return SVN_NO_ERROR;
 
784
}
510
785
 
511
786
/* The test table.  */
512
787
 
513
 
struct svn_test_descriptor_t test_funcs[] =
 
788
static int max_threads = 3;
 
789
 
 
790
static struct svn_test_descriptor_t test_funcs[] =
514
791
  {
515
792
    SVN_TEST_NULL,
516
793
    SVN_TEST_PASS2(test_two_file_size_comparison,
523
800
                   "three file content comparison"),
524
801
    SVN_TEST_PASS2(read_length_line_shouldnt_loop,
525
802
                   "svn_io_read_length_line() shouldn't loop"),
 
803
    SVN_TEST_PASS2(aligned_seek_test,
 
804
                   "test aligned seek"),
 
805
    SVN_TEST_PASS2(ignore_enoent,
 
806
                   "test ignore-enoent"),
 
807
    SVN_TEST_PASS2(test_install_stream_to_longpath,
 
808
                   "test svn_stream__install_stream to long path"),
526
809
    SVN_TEST_NULL
527
810
  };
 
811
 
 
812
SVN_TEST_MAIN