Пример #1
0
/* Tests to parse non-valid git diffs. */
static svn_error_t *
test_bad_git_diff_headers(apr_pool_t *pool)
{
  svn_patch_file_t *patch_file;
  svn_patch_t *patch;
  svn_diff_hunk_t *hunk;

  SVN_ERR(create_patch_file(&patch_file, bad_git_diff_header, pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "iota.copied");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_copied);
  SVN_TEST_ASSERT(patch->hunks->nelts == 1);

  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "This is the file 'iota'." NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "This is the file 'iota'." NL
                        "some more bytes to 'iota'" NL,
                        pool));

  SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
  return SVN_NO_ERROR;
}
Пример #2
0
static svn_error_t *
short_string_table_body(svn_boolean_t do_load_store,
                        apr_pool_t *pool)
{
    apr_size_t indexes[STRING_COUNT] = { 0 };

    string_table_builder_t *builder;
    string_table_t *table;
    int i;

    builder = svn_fs_x__string_table_builder_create(pool);
    for (i = 0; i < STRING_COUNT; ++i)
        indexes[i] = svn_fs_x__string_table_builder_add(builder, basic_strings[i], 0);

    table = svn_fs_x__string_table_create(builder, pool);
    if (do_load_store)
        SVN_ERR(store_and_load_table(&table, pool));

    SVN_TEST_ASSERT(indexes[2] == indexes[6]);
    for (i = 0; i < STRING_COUNT; ++i)
    {
        apr_size_t len;
        const char *string
            = svn_fs_x__string_table_get(table, indexes[i], &len, pool);

        SVN_TEST_STRING_ASSERT(string, basic_strings[i]);
        SVN_TEST_ASSERT(len == strlen(string));
        SVN_TEST_ASSERT(len == strlen(basic_strings[i]));
    }

    SVN_TEST_STRING_ASSERT(svn_fs_x__string_table_get(table, STRING_COUNT,
                           NULL, pool), "");

    return SVN_NO_ERROR;
}
Пример #3
0
static svn_error_t *
test_svn_subst_translate_string2(apr_pool_t *pool)
{
  static const struct translate_string2_data_t tests[] =
    {
      /* No reencoding, no translation of line endings */
      { "abcdefz",
        "abcdefz", FALSE, FALSE },
      /* No reencoding, translation of line endings */
      { "     \r\n\r\n      \r\n        \r\n",
        "     \n\n      \n        \n", FALSE, TRUE },
      /* Reencoding, no translation of line endings */
      { "\xc7\xa9\xf4\xdf",
        "\xc3\x87\xc2\xa9\xc3\xb4\xc3\x9f", TRUE, FALSE },
      /* Reencoding, translation of line endings */
      { "\xc7\xa9\xf4\xdf\r\n",
        "\xc3\x87\xc2\xa9\xc3\xb4\xc3\x9f\n", TRUE, TRUE },
      { NULL, NULL, FALSE, FALSE }
    };
  const struct translate_string2_data_t *t;

  for (t = tests; t->source != NULL; t++)
  {
    svn_string_t *source_string = svn_string_create(t->source, pool);
    svn_string_t *new_value = NULL;
    svn_boolean_t translated_line_endings = ! t->translated_line_endings;
    svn_boolean_t translated_to_utf8;

    SVN_ERR(svn_subst_translate_string2(&new_value,
                                        NULL, &translated_line_endings,
                                        source_string, "ISO-8859-1", FALSE,
                                        pool, pool));
    SVN_TEST_STRING_ASSERT(new_value->data, t->expected_str);
    SVN_TEST_ASSERT(translated_line_endings == t->translated_line_endings);

    new_value = NULL;
    translated_to_utf8 = ! t->translated_to_utf8;
    translated_line_endings = ! t->translated_line_endings;
    SVN_ERR(svn_subst_translate_string2(&new_value, &translated_to_utf8,
                                        &translated_line_endings,
                                        source_string, "ISO-8859-1", FALSE,
                                        pool, pool));
    SVN_TEST_STRING_ASSERT(new_value->data, t->expected_str);
    SVN_TEST_ASSERT(translated_to_utf8 == t->translated_to_utf8);
    SVN_TEST_ASSERT(translated_line_endings == t->translated_line_endings);
  }

  /* Test that when REPAIR is FALSE, SVN_ERR_IO_INCONSISTENT_EOL is returned. */
    {
      svn_string_t *source_string = svn_string_create("  \r   \r\n  \n ", pool);
      svn_string_t *new_value = NULL;
      svn_error_t *err = svn_subst_translate_string2(&new_value, NULL, NULL,
                                                     source_string,
                                                     "ISO-8859-1", FALSE, pool,
                                                     pool);
      SVN_TEST_ASSERT_ERROR(err, SVN_ERR_IO_INCONSISTENT_EOL);
    }

  return SVN_NO_ERROR;
}
Пример #4
0
static svn_error_t *
test_expand(const svn_test_opts_t *opts,
            apr_pool_t *pool)
{
  svn_config_t *cfg;
  const char *cfg_file, *val;

  SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
  SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, TRUE, FALSE, pool));

  /* Get expanded "g" which requires expanding "c". */
  svn_config_get(cfg, &val, "section1", "g", NULL);

  /* Get expanded "c". */
  svn_config_get(cfg, &val, "section1", "c", NULL);

  /* With pool debugging enabled this ensures that the expanded value
     of "c" was not created in a temporary pool when expanding "g". */
  SVN_TEST_STRING_ASSERT(val, "bar");

  /* Get expanded "j" and "k" which have cyclic definitions.
   * They must return empty values. */
  svn_config_get(cfg, &val, "section1", "j", NULL);
  SVN_TEST_STRING_ASSERT(val, "");
  svn_config_get(cfg, &val, "section1", "k", NULL);
  SVN_TEST_STRING_ASSERT(val, "");

  /* Get expanded "l" which depends on a cyclic definition.
   * So, it also considered "undefined" and will be normalized to "". */
  svn_config_get(cfg, &val, "section1", "l", NULL);
  SVN_TEST_STRING_ASSERT(val, "");

  return SVN_NO_ERROR;
}
Пример #5
0
static svn_error_t *
test_parse_property_and_text_diff(apr_pool_t *pool)
{
  svn_patch_file_t *patch_file;
  svn_patch_t *patch;
  svn_prop_patch_t *prop_patch;
  svn_diff_hunk_t *hunk;
  apr_array_header_t *hunks;

  SVN_ERR(create_patch_file(&patch_file, property_and_text_unidiff, pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "iota");
  SVN_TEST_ASSERT(patch->hunks->nelts == 1);
  SVN_TEST_ASSERT(apr_hash_count(patch->prop_patches) == 1);

  /* Check contents of text hunk */
  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "This is the file 'iota'." NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "This is the file 'iota'." NL
                        "some more bytes to 'iota'" NL,
                        pool));

  /* Check the added property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_add",
                            APR_HASH_KEY_STRING);
  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_added);

  hunks = prop_patch->hunks;
  SVN_TEST_ASSERT(hunks->nelts == 1);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "",
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "value" NL,
                        pool));

  SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
  return SVN_NO_ERROR;
}
Пример #6
0
static svn_error_t *
test_svn_subst_translate_cstring2(apr_pool_t *pool)
{
  static const struct translate_cstring2_data_t tests[] =
    {
      /* Test the unusual case where EOL_STR is an empty string. */
      { "   \r   \n\r\n     \n\n\n", "", TRUE,
        "           " },
      /* Test the unusual case where EOL_STR is not a standard EOL string. */
      { "   \r   \n\r\n     \n\n\n", "z", TRUE,
        "   z   zz     zzz" },
      { "    \n    \n ", "buzz", FALSE,
        "    buzz    buzz " },
      { "    \r\n    \n", "buzz", TRUE ,
        "    buzz    buzz"},
      { NULL, NULL, FALSE, NULL }
    };
  const struct translate_cstring2_data_t *t;

  for (t = tests; t->source != NULL; t++)
    {
      const char *result = NULL;
      SVN_ERR(svn_subst_translate_cstring2(t->source, &result, t->eol_str,
                                           t->repair, NULL, FALSE, pool));
      SVN_TEST_STRING_ASSERT(result, t->expected_str);
    }

  return SVN_NO_ERROR;
}
Пример #7
0
static svn_error_t *
test_stream_base64(apr_pool_t *pool)
{
  svn_stream_t *stream;
  svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool);
  svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool);
  int i;
  static const char *strings[] = {
    "fairly boring test data... blah blah",
    "A",
    "abc",
    "012345679",
    NULL
  };

  stream = svn_stream_from_stringbuf(actual, pool);
  stream = svn_base64_decode(stream, pool);
  stream = svn_base64_encode(stream, pool);

  for (i = 0; strings[i]; i++)
    {
      apr_size_t len = strlen(strings[i]);

      svn_stringbuf_appendbytes(expected, strings[i], len);
      SVN_ERR(svn_stream_write(stream, strings[i], &len));
    }

  SVN_ERR(svn_stream_close(stream));

  SVN_TEST_STRING_ASSERT(actual->data, expected->data);

  return SVN_NO_ERROR;
}
Пример #8
0
/* Check that reading a line from HUNK equals what's inside EXPECTED.
 * If ORIGINAL is TRUE, read the original hunk text; else, read the
 * modified hunk text. */
static svn_error_t *
check_content(svn_diff_hunk_t *hunk, svn_boolean_t original,
              const char *expected, apr_pool_t *pool)
{
  svn_stream_t *exp;
  svn_stringbuf_t *exp_buf;
  svn_stringbuf_t *hunk_buf;
  svn_boolean_t exp_eof;
  svn_boolean_t hunk_eof;

  exp = svn_stream_from_string(svn_string_create(expected, pool),
                               pool);

  while (TRUE)
  {
    SVN_ERR(svn_stream_readline(exp, &exp_buf, NL, &exp_eof, pool));
    if (original)
      SVN_ERR(svn_diff_hunk_readline_original_text(hunk, &hunk_buf, NULL,
                                                   &hunk_eof, pool, pool));
    else
      SVN_ERR(svn_diff_hunk_readline_modified_text(hunk, &hunk_buf, NULL,
                                                   &hunk_eof, pool, pool));

    SVN_TEST_ASSERT(exp_eof == hunk_eof);
    if (exp_eof)
      break;
    SVN_TEST_STRING_ASSERT(exp_buf->data, hunk_buf->data);
  }

  if (!hunk_eof)
    SVN_TEST_ASSERT(hunk_buf->len == 0);

  return SVN_NO_ERROR;
}
Пример #9
0
static svn_error_t *
test_parse_unidiff_lacking_trailing_eol(apr_pool_t *pool)
{
  svn_patch_file_t *patch_file;
  svn_boolean_t reverse;
  svn_boolean_t ignore_whitespace;
  int i;
  apr_pool_t *iterpool;

  reverse = FALSE;
  ignore_whitespace = FALSE;
  iterpool = svn_pool_create(pool);
  for (i = 0; i < 2; i++)
    {
      svn_patch_t *patch;
      svn_diff_hunk_t *hunk;

      svn_pool_clear(iterpool);

      SVN_ERR(create_patch_file(&patch_file, unidiff_lacking_trailing_eol,
                                pool));

      /* We have one patch with one hunk. Parse it. */
      SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse,
                                        ignore_whitespace, iterpool,
                                        iterpool));
      SVN_TEST_ASSERT(patch);
      SVN_TEST_STRING_ASSERT(patch->old_filename, "A/C/gamma");
      SVN_TEST_STRING_ASSERT(patch->new_filename, "A/C/gamma");
      SVN_TEST_ASSERT(patch->hunks->nelts == 1);

      hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);
      SVN_ERR(check_content(hunk, ! reverse,
                            "This is the file 'gamma'." NL,
                            pool));

      SVN_ERR(check_content(hunk, reverse,
                            "This is the file 'gamma'." NL
                            "some more bytes to 'gamma'",
                            pool));

      reverse = !reverse;
      SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
    }
  svn_pool_destroy(iterpool);
  return SVN_NO_ERROR;
}
Пример #10
0
static svn_error_t *
test_svn_subst_build_keywords3(apr_pool_t *pool)
{
  /* Test expansion of custom keywords. */
  struct keywords_tests_data
    {
      const char *keyword_name;
      const char *keywords_string;
      const char *expanded_keyword;
      const char *rev;
      const char *url;
      const char *repos_root_url;
      /* Can't test date since expanded value depends on local clock. */
      const char *author;
    }
  tests[] =
    {
      {"FOO", "FOO=%P%_%a%_%b%_%%",
       "trunk/foo.txt stsp foo.txt %",
       "1234", "http://svn.example.com/repos/trunk/foo.txt",
       "http://svn.example.com/repos", "stsp"},
      {"FOO", "FOO=author%_=%_%a",
       "author = stsp",
       "1234", "http://svn.example.com/repos/trunk/foo.txt",
       "http://svn.example.com/repos", "stsp"},
      {"MyKeyword", "MyKeyword=%r%_%u%_%_%a",
       "4567 http://svn.example.com/svn/branches/myfile  jrandom",
       "4567", "http://svn.example.com/svn/branches/myfile",
       "http://svn.example.com/svn", "jrandom"},
      {"FreeBSD", "FreeBSD=%H",
       "head/README 222812  joel", /* date is not expanded in this test */
       "222812", "http://svn.freebsd.org/base/head/README",
       "http://svn.freebsd.org/base", "joel"},
      {"FreeBSD", "FreeBSD=%I",
       "README 222812  joel", /* date is not expanded in this test */
       "222812", "http://svn.freebsd.org/base/head/README",
       "http://svn.freebsd.org/base", "joel"},
      { NULL, NULL, NULL, NULL, NULL, NULL, NULL}
  };

  const struct keywords_tests_data *t;

  for (t = tests; t->keyword_name != NULL; t++)
    {
      apr_hash_t *kw;
      svn_string_t *expanded_keyword;

      SVN_ERR(svn_subst_build_keywords3(&kw, t->keywords_string,
                                        t->rev, t->url, t->repos_root_url,
                                        0 /* date */, t->author, pool));
      expanded_keyword = svn_hash_gets(kw, t->keyword_name);
      SVN_TEST_ASSERT(expanded_keyword != NULL);
      SVN_TEST_STRING_ASSERT(expanded_keyword->data, t->expanded_keyword);
    }

  return SVN_NO_ERROR;
}
Пример #11
0
static svn_error_t *
create_empty_table_body(svn_boolean_t do_load_store,
                        apr_pool_t *pool)
{
    string_table_builder_t *builder
        = svn_fs_x__string_table_builder_create(pool);
    string_table_t *table
        = svn_fs_x__string_table_create(builder, pool);

    SVN_TEST_STRING_ASSERT(svn_fs_x__string_table_get(table, 0, NULL, pool), "");

    if (do_load_store)
        SVN_ERR(store_and_load_table(&table, pool));

    SVN_TEST_STRING_ASSERT(svn_fs_x__string_table_get(table, 0, NULL, pool), "");

    return SVN_NO_ERROR;
}
Пример #12
0
static svn_error_t *
test_stringbuf_from_stream(apr_pool_t *pool)
{
  const char *test_cases[] =
    {
      "",
      "x",
      "this string is longer than the default 64 minimum block size used"
      "by the function under test",
      NULL
    };

  const char **test_case;
  for (test_case = test_cases; *test_case; ++test_case)
    {
      svn_stringbuf_t *result1, *result2, *result3, *result4;
      svn_stringbuf_t *original = svn_stringbuf_create(*test_case, pool);

      svn_stream_t *stream1 = svn_stream_from_stringbuf(original, pool);
      svn_stream_t *stream2 = svn_stream_from_stringbuf(original, pool);

      SVN_ERR(svn_stringbuf_from_stream(&result1, stream1, 0, pool));
      SVN_ERR(svn_stringbuf_from_stream(&result2, stream1, 0, pool));
      SVN_ERR(svn_stringbuf_from_stream(&result3, stream2, original->len,
                                        pool));
      SVN_ERR(svn_stringbuf_from_stream(&result4, stream2, original->len,
                                        pool));

      /* C-string contents must match */
      SVN_TEST_STRING_ASSERT(result1->data, original->data);
      SVN_TEST_STRING_ASSERT(result2->data, "");
      SVN_TEST_STRING_ASSERT(result3->data, original->data);
      SVN_TEST_STRING_ASSERT(result4->data, "");

      /* assumed length must match */
      SVN_TEST_ASSERT(result1->len == original->len);
      SVN_TEST_ASSERT(result2->len == 0);
      SVN_TEST_ASSERT(result3->len == original->len);
      SVN_TEST_ASSERT(result4->len == 0);
    }

  return SVN_NO_ERROR;
}
Пример #13
0
static svn_error_t *
test_git_diffs_with_spaces_diff(apr_pool_t *pool)
{
  svn_patch_file_t *patch_file;
  svn_patch_t *patch;

  SVN_ERR(create_patch_file(&patch_file, path_with_spaces_unidiff, pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "path 1");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "path 1");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
  SVN_TEST_ASSERT(patch->hunks->nelts == 0);

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "path one 1");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "path one 1");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
  SVN_TEST_ASSERT(patch->hunks->nelts == 0);

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "dir/ b/path");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "dir/ b/path");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
  SVN_TEST_ASSERT(patch->hunks->nelts == 0);

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, " b/path 1");
  SVN_TEST_STRING_ASSERT(patch->new_filename, " b/path 1");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
  SVN_TEST_ASSERT(patch->hunks->nelts == 0);

  SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
  return SVN_NO_ERROR;
}
Пример #14
0
static svn_error_t *
test_serialization(apr_pool_t *pool)
{
  svn_stringbuf_t *original_content;
  svn_stringbuf_t *written_content;
  svn_config_t *cfg;

  const struct
    {
      const char *section;
      const char *option;
      const char *value;
    } test_data[] =
    {
      { "my section", "value1", "some" },
      { "my section", "value2", "something" },
      { "another Section", "value1", "one" },
      { "another Section", "value2", "two" },
      { "another Section", "value 3", "more" },
    };
  int i;

  /* Format the original with the same formatting that the writer will use. */
  original_content = svn_stringbuf_create("\n[my section]\n"
                                          "value1=some\n"
                                          "value2=%(value1)sthing\n"
                                          "\n[another Section]\n"
                                          "value1=one\n"
                                          "value2=two\n"
                                          "value 3=more\n",
                                          pool);
  written_content = svn_stringbuf_create_empty(pool);

  SVN_ERR(svn_config_parse(&cfg,
                           svn_stream_from_stringbuf(original_content, pool),
                           TRUE, TRUE, pool));
  SVN_ERR(svn_config__write(svn_stream_from_stringbuf(written_content, pool),
                            cfg, pool));
  SVN_ERR(svn_config_parse(&cfg,
                           svn_stream_from_stringbuf(written_content, pool),
                           TRUE, TRUE, pool));

  /* The serialized and re-parsed config must have the expected contents. */
  for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
    {
      const char *val;
      svn_config_get(cfg, &val, test_data[i].section, test_data[i].option,
                     NULL);
      SVN_TEST_STRING_ASSERT(val, test_data[i].value);
    }

  return SVN_NO_ERROR;
}
Пример #15
0
static svn_error_t *
test_stream_seek_stringbuf(apr_pool_t *pool)
{
  svn_stream_t *stream;
  svn_stringbuf_t *stringbuf;
  char buf[4];
  apr_size_t len;
  svn_stream_mark_t *mark;

  stringbuf = svn_stringbuf_create("OneTwo", pool);
  stream = svn_stream_from_stringbuf(stringbuf, pool);
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "One");
  SVN_ERR(svn_stream_mark(stream, &mark, pool));
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Two");
  SVN_ERR(svn_stream_seek(stream, mark));
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Two");

  /* Go back to the begin of last word and try to skip some of it */
  SVN_ERR(svn_stream_seek(stream, mark));
  SVN_ERR(svn_stream_skip(stream, 2));
  /* The remaining line should be empty */
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[len] = '\0';
  SVN_TEST_ASSERT(len == 1);
  SVN_TEST_STRING_ASSERT(buf, "o");

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
Пример #16
0
static svn_error_t *
test_compress_lz4_empty(apr_pool_t *pool)
{
  svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool);
  svn_stringbuf_t *decompressed = svn_stringbuf_create_empty(pool);

  SVN_ERR(svn__compress_lz4("", 0, compressed));
  SVN_ERR(svn__decompress_lz4(compressed->data, compressed->len,
                              decompressed, 100));
  SVN_TEST_STRING_ASSERT(decompressed->data, "");

  return SVN_NO_ERROR;
}
Пример #17
0
static svn_error_t *
test_one_long_keyword(const char *keyword,
                      const char *expected,
                      apr_pool_t *pool)
{
  svn_string_t *src_string;
  svn_stream_t *src_stream, *dst_stream;
  svn_stringbuf_t *dst_stringbuf, *src_stringbuf;
  apr_hash_t *keywords = apr_hash_make(pool);
  svn_string_t *expanded = svn_string_create("abcdefg", pool);

  svn_hash_sets(keywords, keyword, expanded);

  /* Expand */
  src_string = svn_string_createf(pool, "$%s$", keyword);
  src_stream = svn_stream_from_string(src_string, pool);
  dst_stringbuf = svn_stringbuf_create_empty(pool);
  dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
  dst_stream = svn_subst_stream_translated(dst_stream, NULL, FALSE, keywords,
                                           TRUE, pool);
  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool));

  SVN_TEST_STRING_ASSERT(dst_stringbuf->data, expected);

  /* Unexpand */
  src_stringbuf = dst_stringbuf;
  src_stream = svn_stream_from_stringbuf(src_stringbuf, pool);
  dst_stringbuf = svn_stringbuf_create_empty(pool);
  dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
  dst_stream = svn_subst_stream_translated(dst_stream, NULL, FALSE, keywords,
                                           FALSE, pool);
  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool));

  SVN_TEST_STRING_ASSERT(dst_stringbuf->data, src_string->data);

  return SVN_NO_ERROR;
}
Пример #18
0
static svn_error_t *
test_repairing_svn_subst_translate_string2(apr_pool_t *pool)
{
    {
      svn_string_t *source_string = svn_string_create("  \r   \r\n  \n ", pool);
      svn_string_t *new_value = NULL;
      SVN_ERR(svn_subst_translate_string2(&new_value, NULL, NULL, source_string,
                                          "ISO-8859-1", TRUE, pool, pool));
      SVN_TEST_ASSERT(new_value != NULL);
      SVN_TEST_ASSERT(new_value->data != NULL);
      SVN_TEST_STRING_ASSERT(new_value->data, "  \n   \n  \n ");
    }

  return SVN_NO_ERROR;
}
Пример #19
0
static svn_error_t *
test_compress_lz4(apr_pool_t *pool)
{
  const char input[] =
    "aaaabbbbccccaaaaccccbbbbaaaabbbb"
    "aaaabbbbccccaaaaccccbbbbaaaabbbb"
    "aaaabbbbccccaaaaccccbbbbaaaabbbb";
  svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool);
  svn_stringbuf_t *decompressed = svn_stringbuf_create_empty(pool);

  SVN_ERR(svn__compress_lz4(input, sizeof(input), compressed));
  SVN_ERR(svn__decompress_lz4(compressed->data, compressed->len,
                              decompressed, 100));
  SVN_TEST_STRING_ASSERT(decompressed->data, input);

  return SVN_NO_ERROR;
}
Пример #20
0
static svn_error_t *
test_decompress_lz4(apr_pool_t *pool)
{
  const char input[] =
    "\x61\xc0\x61\x61\x61\x61\x62\x62\x62\x62\x63\x63\x63\x63\x0c\x00\x00\x08"
    "\x00\x00\x10\x00\x00\x0c\x00\x08\x08\x00\x00\x18\x00\x00\x14\x00\x00\x08"
    "\x00\x08\x18\x00\x00\x14\x00\x00\x10\x00\x00\x18\x00\x00\x0c\x00\x00\x08"
    "\x00\x00\x10\x00\x90\x61\x61\x61\x61\x62\x62\x62\x62";
  svn_stringbuf_t *decompressed = svn_stringbuf_create_empty(pool);

  SVN_ERR(svn__decompress_lz4(input, sizeof(input), decompressed, 100));
  SVN_TEST_STRING_ASSERT(decompressed->data,
                         "aaaabbbbccccaaaaccccbbbbaaaabbbb"
                         "aaaabbbbccccaaaaccccbbbbaaaabbbb"
                         "aaaabbbbccccaaaaccccbbbbaaaabbbb");

  return SVN_NO_ERROR;
}
Пример #21
0
static svn_error_t *
many_strings_table_body(svn_boolean_t do_load_store,
                        apr_pool_t *pool)
{
    /* cause multiple sub-tables (6 to be exact) to be created */
    enum { COUNT = 100 };

    svn_stringbuf_t *strings[COUNT] = { 0 };
    apr_size_t indexes[COUNT] = { 0 };

    string_table_builder_t *builder;
    string_table_t *table;
    int i;

    builder = svn_fs_x__string_table_builder_create(pool);
    for (i = 0; i < COUNT; ++i)
    {
        strings[i] = generate_string(APR_UINT64_C(0x1234567876543210) * (i + 1),
                                     (i * i) % 23000,  pool);
        indexes[i] = svn_fs_x__string_table_builder_add(builder,
                     strings[i]->data,
                     strings[i]->len);
    }

    table = svn_fs_x__string_table_create(builder, pool);
    if (do_load_store)
        SVN_ERR(store_and_load_table(&table, pool));

    for (i = 0; i < COUNT; ++i)
    {
        apr_size_t len;
        const char *string
            = svn_fs_x__string_table_get(table, indexes[i], &len, pool);

        SVN_TEST_STRING_ASSERT(string, strings[i]->data);
        SVN_TEST_ASSERT(len == strlen(string));
        SVN_TEST_ASSERT(len == strings[i]->len);
    }

    return SVN_NO_ERROR;
}
Пример #22
0
/* The body of the svn_subst_translate_string2_null_encoding test. It should
   only be called by test_svn_subst_translate_string2_null_encoding(), as this
   code assumes that the process locale has been changed to a locale that uses
   either CP-1252 or ISO-8859-1 for the default narrow string encoding. */
static svn_error_t *
test_svn_subst_translate_string2_null_encoding_helper(apr_pool_t *pool)
{
  {
    svn_string_t *new_value = NULL;
    svn_boolean_t translated_to_utf8 = FALSE;
    svn_boolean_t translated_line_endings = TRUE;
    /* The 'AE' ligature, which is 0xc6 in both ISO-8859-1 and Windows-1252 */
    svn_string_t *source_string = svn_string_create("\xc6", pool);

    SVN_ERR(svn_subst_translate_string2(&new_value, &translated_to_utf8,
                                        &translated_line_endings,
                                        source_string, NULL, FALSE,
                                        pool, pool));
    SVN_TEST_STRING_ASSERT(new_value->data, "\xc3\x86");
    SVN_TEST_ASSERT(translated_to_utf8);
    SVN_TEST_ASSERT(!translated_line_endings);
  }

  return SVN_NO_ERROR;
}
Пример #23
0
static svn_error_t *
test_svn_subst_truncated_keywords(apr_pool_t *pool)
{
  svn_string_t *src_string
    = svn_string_create("$Qq: "
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "012345678901234567890123456789012345678901234567"
                        " $", pool);
  svn_stream_t *src_stream = svn_stream_from_string(src_string, pool);
  svn_stringbuf_t *dst_stringbuf = svn_stringbuf_create_empty(pool);
  svn_stream_t *dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
  apr_hash_t *keywords = apr_hash_make(pool);
  svn_string_t *expanded
    = svn_string_create("01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "012345678901234567890123456789012345678901234567"
                        "xxxxxxxxxx",
                        pool);

  /* The source is already at the maximum length. */
  SVN_TEST_ASSERT(src_string->len == SVN_KEYWORD_MAX_LEN);

  svn_hash_sets(keywords, "Qq", expanded);
  dst_stream = svn_subst_stream_translated(dst_stream, NULL, FALSE, keywords,
                                           TRUE, pool);
  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool));

  /* The expanded value would make the keyword longer than the maximum
     allowed so it must be truncated; the remaining part of the
     expanded value is the same as the source. */
  SVN_TEST_STRING_ASSERT(dst_stringbuf->data, src_string->data);

  return SVN_NO_ERROR;
}
Пример #24
0
static svn_error_t *
test_expand(const svn_test_opts_t *opts,
            apr_pool_t *pool)
{
  svn_config_t *cfg;
  const char *cfg_file, *val;

  SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
  SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, TRUE, FALSE, pool));

  /* Get expanded "g" which requires expanding "c". */
  svn_config_get(cfg, &val, "section1", "g", NULL);

  /* Get expanded "c". */
  svn_config_get(cfg, &val, "section1", "c", NULL);

  /* With pool debugging enabled this ensures that the expanded value
     of "c" was not created in a temporary pool when expanding "g". */
  SVN_TEST_STRING_ASSERT(val, "bar");

  return SVN_NO_ERROR;
}
Пример #25
0
static svn_error_t *
test_parse_git_tree_and_text_diff(apr_pool_t *pool)
{
  /* ### Should we check for reversed diffs? */

  svn_patch_file_t *patch_file;
  svn_patch_t *patch;
  svn_diff_hunk_t *hunk;

  SVN_ERR(create_patch_file(&patch_file, git_tree_and_text_unidiff, pool));

  /* Parse a copied file with text modifications. */
  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "iota.copied");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_copied);
  SVN_TEST_ASSERT(patch->hunks->nelts == 1);

  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "This is the file 'iota'." NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "This is the file 'iota'." NL
                        "some more bytes to 'iota'" NL,
                        pool));

  /* Parse a moved file with text modifications. */
  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "A/mu");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "A/mu.moved");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_moved);
  SVN_TEST_ASSERT(patch->hunks->nelts == 1);

  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "This is the file 'mu'." NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "This is the file 'mu'." NL
                        "some more bytes to 'mu'" NL,
                        pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "/dev/null");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "new");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
  SVN_TEST_ASSERT(patch->hunks->nelts == 1);

  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "",
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "This is the file 'new'." NL,
                        pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "A/B/lambda");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "/dev/null");
  SVN_TEST_ASSERT(patch->operation == svn_diff_op_deleted);
  SVN_TEST_ASSERT(patch->hunks->nelts == 1);

  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "This is the file 'lambda'." NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "",
                        pool));

  SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
  return SVN_NO_ERROR;
}
Пример #26
0
static svn_error_t *
test_stream_seek_translated(apr_pool_t *pool)
{
  svn_stream_t *stream, *translated_stream;
  svn_stringbuf_t *stringbuf;
  char buf[44]; /* strlen("One$MyKeyword: my keyword was expanded $Two") + \0 */
  apr_size_t len;
  svn_stream_mark_t *mark;
  apr_hash_t *keywords;
  svn_string_t *keyword_val;

  keywords = apr_hash_make(pool);
  keyword_val = svn_string_create("my keyword was expanded", pool);
  apr_hash_set(keywords, "MyKeyword", APR_HASH_KEY_STRING, keyword_val);
  stringbuf = svn_stringbuf_create("One$MyKeyword$Two", pool);
  stream = svn_stream_from_stringbuf(stringbuf, pool);
  translated_stream = svn_subst_stream_translated(stream, APR_EOL_STR,
                                                  FALSE, keywords, TRUE, pool);
  /* Seek from outside of keyword to inside of keyword. */
  len = 25;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 25);
  buf[25] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "One$MyKeyword: my keyword");
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  SVN_ERR(svn_stream_reset(translated_stream));
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " was");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 2;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 2);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "as");

  /* Seek from inside of keyword to inside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 9;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 9);
  buf[9] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " expanded");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 9;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 9);
  buf[9] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " expanded");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 6));
  len = 3;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 3);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "ded");

  /* Seek from inside of keyword to outside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " $Tw");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " $Tw");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 2;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 2);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Tw");

  /* Seek from outside of keyword to outside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 1);
  buf[1] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "o");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 1);
  buf[1] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "o");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 0);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "");

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
Пример #27
0
/* Tests to parse a diff with three property changes, one is added, one is
 * modified and one is deleted. */
static svn_error_t *
test_parse_property_diff(apr_pool_t *pool)
{
  svn_patch_file_t *patch_file;
  svn_patch_t *patch;
  svn_prop_patch_t *prop_patch;
  svn_diff_hunk_t *hunk;
  apr_array_header_t *hunks;

  SVN_ERR(create_patch_file(&patch_file, property_unidiff, pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "iota");
  SVN_TEST_ASSERT(patch->hunks->nelts == 0);
  SVN_TEST_ASSERT(apr_hash_count(patch->prop_patches) == 3);

  /* Check the deleted property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_del",
                            APR_HASH_KEY_STRING);

  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_deleted);
  hunks = prop_patch->hunks;

  SVN_TEST_ASSERT(hunks->nelts == 1);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "value" NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "",
                        pool));

  /* Check the added property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_add",
                            APR_HASH_KEY_STRING);

  SVN_TEST_ASSERT(!strcmp("prop_add", prop_patch->name));
  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_added);
  hunks = prop_patch->hunks;

  SVN_TEST_ASSERT(hunks->nelts == 1);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "",
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "value" NL,
                        pool));

  /* Check the modified property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_mod",
                            APR_HASH_KEY_STRING);

  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_modified);
  hunks = prop_patch->hunks;

  SVN_TEST_ASSERT(hunks->nelts == 2);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "value" NL
                        "context" NL
                        "context" NL
                        "context" NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "new value" NL
                        "context" NL
                        "context" NL
                        "context" NL,
                        pool));

  hunk = APR_ARRAY_IDX(hunks, 1 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "context" NL
                        "context" NL
                        "context" NL
                        "value" NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "context" NL
                        "context" NL
                        "context" NL
                        "new value" NL,
                        pool));

  SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
  return SVN_NO_ERROR;
}
Пример #28
0
static svn_error_t *
test_parse_diff_symbols_in_prop_unidiff(apr_pool_t *pool)
{
  svn_patch_t *patch;
  svn_patch_file_t *patch_file;
  svn_prop_patch_t *prop_patch;
  svn_diff_hunk_t *hunk;
  apr_array_header_t *hunks;

  SVN_ERR(create_patch_file(&patch_file, diff_symbols_in_prop_unidiff, pool));

  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
                                    FALSE, /* reverse */
                                    FALSE, /* ignore_whitespace */
                                    pool, pool));
  SVN_TEST_ASSERT(patch);
  SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
  SVN_TEST_STRING_ASSERT(patch->new_filename, "iota");
  SVN_TEST_ASSERT(patch->hunks->nelts == 0);
  SVN_TEST_ASSERT(apr_hash_count(patch->prop_patches) == 3);

  /* Check the added property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_add",
                            APR_HASH_KEY_STRING);
  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_added);

  hunks = prop_patch->hunks;
  SVN_TEST_ASSERT(hunks->nelts == 1);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "",
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "Added: bogus_prop" NL
                        "## -0,0 +20 ##" NL
                        "@@ -1,2 +0,0 @@" NL,
                        pool));

  /* Check the deleted property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_del",
                            APR_HASH_KEY_STRING);
  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_deleted);

  hunks = prop_patch->hunks;
  SVN_TEST_ASSERT(hunks->nelts == 1);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "--- iota" NL
                        "+++ iota" NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "",
                        pool));

  /* Check the modified property */
  prop_patch = apr_hash_get(patch->prop_patches, "prop_mod",
                            APR_HASH_KEY_STRING);
  SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_modified);
  hunks = prop_patch->hunks;
  SVN_TEST_ASSERT(hunks->nelts == 2);
  hunk = APR_ARRAY_IDX(hunks, 0 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "## -1,2 +1,2 ##" NL
                        "## -1,5 -0,0 ##" NL
                        "@@ -1,5 -0,0 @@" NL
                        "Modified: prop_mod" NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "## -1,3 +1,3 ##" NL
                        "## -1,5 -0,0 ##" NL
                        "@@ -1,5 -0,0 @@" NL
                        "Modified: prop_mod" NL,
                        pool));

  hunk = APR_ARRAY_IDX(hunks, 1 , svn_diff_hunk_t *);

  SVN_ERR(check_content(hunk, TRUE,
                        "context" NL
                        "context" NL
                        "context" NL
                        "## -0,0 +1 ##" NL,
                        pool));

  SVN_ERR(check_content(hunk, FALSE,
                        "context" NL
                        "context" NL
                        "context" NL
                        "## -1,2 +1,4 ##" NL,
                        pool));

  SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
  return SVN_NO_ERROR;
}
static svn_error_t *
test_stubs(apr_pool_t *pool)
{
  svn_wc__db_t *db;
  const char *local_abspath;
  const char *local_relpath;
  svn_wc_adm_access_t *adm_access;
  svn_wc_adm_access_t *subdir_access;
  const svn_wc_entry_t *stub_entry;
  const svn_wc_entry_t *entry;
  const svn_wc_entry_t *test_entry;
  apr_hash_t *entries;

#undef WC_NAME
#define WC_NAME "test_stubs"

  SVN_ERR(create_open(&db, &local_abspath, WC_NAME, pool));

  /* The "M" entry is a subdir. Let's ensure we can reach its stub,
     and the actual contents.  */
  local_relpath = svn_dirent_join_many(pool,
                                       "fake-wc",
                                       WC_NAME,
                                       "M",
                                       NULL);

  SVN_ERR(svn_wc_adm_open3(&adm_access,
                           NULL /* associated */,
                           svn_dirent_join("fake-wc", WC_NAME, pool),
                           FALSE /* write_lock */,
                           0 /* levels_to_lock */,
                           NULL /* cancel_func */,
                           NULL /* cancel_baton */,
                           pool));

  /* Ensure we get the stub. NOTE: do this before we have associated the
     subdir baton with ADM_ACCESS.  */
  SVN_ERR(svn_wc_entry(&stub_entry, local_relpath, adm_access, TRUE, pool));
  SVN_TEST_STRING_ASSERT(stub_entry->name, "M");

  SVN_ERR(svn_wc_adm_open3(&subdir_access,
                           adm_access,
                           local_relpath,
                           FALSE /* write_lock */,
                           0 /* levels_to_lock */,
                           NULL /* cancel_func */,
                           NULL /* cancel_baton */,
                           pool));

  /* Ensure we get the real entry.  */
  SVN_ERR(svn_wc_entry(&entry, local_relpath, subdir_access, TRUE, pool));
  SVN_TEST_STRING_ASSERT(entry->name, "");

  /* Ensure that we get the SAME entry, even using the parent baton.  */
  SVN_ERR(svn_wc_entry(&test_entry, local_relpath, adm_access, TRUE, pool));
  SVN_TEST_ASSERT(test_entry == entry);

  /* Ensure we get the stub when reading entries with ADM_ACCESS.  */
  SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE /* show_hidden */,
                              pool));
  SVN_TEST_ASSERT(stub_entry
                  == apr_hash_get(entries, "M", APR_HASH_KEY_STRING));

  /* Ensure we get the real entry when reading entries with SUBDIR_ACCESS.  */
  SVN_ERR(svn_wc_entries_read(&entries, subdir_access, TRUE /* show_hidden */,
                              pool));
  SVN_TEST_ASSERT(entry
                  == apr_hash_get(entries, "", APR_HASH_KEY_STRING));

  return SVN_NO_ERROR;
}