/* * ra-dav-local.c : basic tests for the RA LOCAL library * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #include #include #ifdef _MSC_VER #include #define getcwd _getcwd #else #include /* for getcwd() */ #endif #include "svn_string.h" #include "svn_utf.h" #include "svn_error.h" #include "svn_delta.h" #include "svn_ra.h" #include "svn_client.h" #include "../svn_test.h" #include "../svn_test_fs.h" #include "../../libsvn_ra_local/ra_local.h" /*-------------------------------------------------------------------*/ /** Helper routines. **/ /* Helper function. Set URL to a "file://" url for the current directory, suffixed by the forward-slash-style relative path SUFFIX, performing all allocation in POOL. */ static svn_error_t * current_directory_url(const char **url, const char *suffix, apr_pool_t *pool) { /* 8KB is a lot, but it almost guarantees that any path will fit. */ char curdir[8192]; const char *utf8_ls_curdir, *utf8_is_curdir, *unencoded_url; if (! getcwd(curdir, sizeof(curdir))) return svn_error_create(SVN_ERR_BASE, NULL, "getcwd() failed"); SVN_ERR(svn_utf_cstring_to_utf8(&utf8_ls_curdir, curdir, pool)); utf8_is_curdir = svn_path_internal_style(utf8_ls_curdir, pool); unencoded_url = apr_psprintf(pool, "file://%s%s%s%s", (utf8_is_curdir[0] != '/') ? "/" : "", utf8_is_curdir, (suffix[0] && suffix[0] != '/') ? "/" : "", suffix); *url = svn_path_uri_encode(unencoded_url, pool); return SVN_NO_ERROR; } static svn_error_t * make_and_open_local_repos(svn_ra_plugin_t **plugin, void **session, const char *repos_name, const char *fs_type, apr_pool_t *pool) { svn_repos_t *repos; void *ra_baton; const char *url; svn_ra_callbacks_t *cbtable = apr_pcalloc(pool, sizeof(*cbtable)); SVN_ERR(svn_test__create_repos(&repos, repos_name, fs_type, pool)); SVN_ERR(svn_ra_init_ra_libs(&ra_baton, pool)); /* Get the plugin which handles "file:" URLs */ SVN_ERR(svn_ra_get_ra_library(plugin, ra_baton, "file:", pool)); SVN_ERR(current_directory_url(&url, repos_name, pool)); /* Open an RA session into this repository. */ SVN_ERR((*plugin)->open(session, url, cbtable, NULL, NULL, pool)); return SVN_NO_ERROR; } /*-------------------------------------------------------------------*/ /** The tests **/ /* Open an RA session to a local repository. */ static svn_error_t * open_ra_session(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { svn_ra_plugin_t *plugin; void *session; *msg = "open an ra session to a local repository"; if (msg_only) return SVN_NO_ERROR; SVN_ERR(make_and_open_local_repos(&plugin, &session, "test-repo-open", opts->fs_type, pool)); return SVN_NO_ERROR; } /* Discover the youngest revision in a repository. */ static svn_error_t * get_youngest_rev(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { svn_ra_plugin_t *plugin; void *session; svn_revnum_t latest_rev; *msg = "get the youngest revision in a repository"; if (msg_only) return SVN_NO_ERROR; SVN_ERR(make_and_open_local_repos(&plugin, &session, "test-repo-getrev", opts->fs_type, pool)); /* Get the youngest revision and make sure it's 0. */ SVN_ERR(plugin->get_latest_revnum(session, &latest_rev, pool)); if (latest_rev != 0) return svn_error_create(SVN_ERR_FS_GENERAL, NULL, "youngest rev isn't 0!"); return SVN_NO_ERROR; } /* Helper function. Run svn_ra_local__split_URL with interest only in the return error code */ static apr_status_t try_split_url(const char *url, apr_pool_t *pool) { svn_repos_t *repos; const char *repos_path, *fs_path; svn_error_t *err; apr_status_t apr_err; err = svn_ra_local__split_URL(&repos, &repos_path, &fs_path, url, pool); if (! err) return SVN_NO_ERROR; apr_err = err->apr_err; svn_error_clear(err); return apr_err; } static svn_error_t * split_url_syntax(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { apr_status_t apr_err; *msg = "svn_ra_local__split_URL: syntax validation"; if (msg_only) return SVN_NO_ERROR; /* TEST 1: Make sure we can recognize bad URLs (this should not require a filesystem) */ /* Use `blah' for scheme instead of `file' */ apr_err = try_split_url("blah:///bin/svn", pool); if (apr_err != SVN_ERR_RA_ILLEGAL_URL) return svn_error_create (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL failed to catch bad URL (scheme)"); /* Use only single slash after scheme */ apr_err = try_split_url("file:/path/to/repos", pool); if (apr_err != SVN_ERR_RA_ILLEGAL_URL) return svn_error_create (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL failed to catch bad URL (slashes)"); /* Use only a hostname, with no path */ apr_err = try_split_url("file://hostname", pool); if (apr_err != SVN_ERR_RA_ILLEGAL_URL) return svn_error_create (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL failed to catch bad URL (no path)"); return SVN_NO_ERROR; } static svn_error_t * split_url_bad_host(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { apr_status_t apr_err; *msg = "svn_ra_local__split_URL: invalid host names"; if (msg_only) return SVN_NO_ERROR; /* Give a hostname other than `' or `localhost' */ apr_err = try_split_url("file://myhost/repos/path", pool); if (apr_err != SVN_ERR_RA_ILLEGAL_URL) return svn_error_create (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL failed to catch bad URL (hostname)"); return SVN_NO_ERROR; } static svn_error_t * split_url_host(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { apr_status_t apr_err; *msg = "svn_ra_local__split_URL: valid host names"; if (msg_only) return SVN_NO_ERROR; /* Make sure we *don't* fuss about a good URL (note that this URL still doesn't point to an existing versioned resource) */ apr_err = try_split_url("file:///repos/path", pool); if (apr_err == SVN_ERR_RA_ILLEGAL_URL) return svn_error_create (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL cried foul about a good URL (no hostname)"); apr_err = try_split_url("file://localhost/repos/path", pool); if (apr_err == SVN_ERR_RA_ILLEGAL_URL) return svn_error_create (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL cried foul about a good URL (localhost)"); return SVN_NO_ERROR; } /* Helper function. Creates a repository in the current working directory named REPOS_PATH, then assembes a URL that points to that FS, plus additional cruft (IN_REPOS_PATH) that theoretically refers to a versioned resource in that repository Finally, it runs this URL through svn_ra_local__split_URL to verify that it accurately separates the filesystem path and the repository path cruft. */ static svn_error_t * check_split_url(const char *repos_path, const char *in_repos_path, const char *fs_type, apr_pool_t *pool) { svn_repos_t *repos; const char *url, *root_url, *repos_part, *in_repos_part; /* Create a filesystem and repository */ SVN_ERR(svn_test__create_repos(&repos, repos_path, fs_type, pool)); SVN_ERR(current_directory_url(&root_url, repos_path, pool)); url = apr_pstrcat(pool, root_url, in_repos_path, NULL); /* Run this URL through our splitter... */ SVN_ERR(svn_ra_local__split_URL(&repos, &repos_part, &in_repos_part, url, pool)); if ((strcmp(repos_part, root_url)) || (strcmp(in_repos_part, in_repos_path))) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "svn_ra_local__split_URL failed to properly split the URL\n%s\n%s\n%s\n%s", repos_part, root_url, in_repos_part, in_repos_path); return SVN_NO_ERROR; } static svn_error_t * split_url_test(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { *msg = "test svn_ra_local__split_URL correctness"; if (msg_only) return SVN_NO_ERROR; /* TEST 2: Given well-formed URLs, make sure that we can correctly find where the filesystem portion of the path ends and the in-repository path begins. */ SVN_ERR(check_split_url("test-repo-split-fs1", "/trunk/foobar/quux.c", opts->fs_type, pool)); SVN_ERR(check_split_url("test-repo-split-fs2", "/alpha/beta/gamma/delta/epsilon/zeta/eta/theta", opts->fs_type, pool)); return SVN_NO_ERROR; } /* The test table. */ #if defined(WIN32) || defined(__CYGWIN__) #define HAS_UNC_HOST 1 #else #define HAS_UNC_HOST 0 #endif struct svn_test_descriptor_t test_funcs[] = { SVN_TEST_NULL, SVN_TEST_PASS(open_ra_session), SVN_TEST_PASS(get_youngest_rev), SVN_TEST_PASS(split_url_syntax), SVN_TEST_SKIP(split_url_bad_host, HAS_UNC_HOST), SVN_TEST_PASS(split_url_host), SVN_TEST_PASS(split_url_test), SVN_TEST_NULL };