📄 translate-test.c
字号:
/* * translate-test.c -- test the eol and keyword translation subroutine * * ==================================================================== * 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/. * ==================================================================== *//* Advice to those adding new tests to this file: * ============================================== * * Read the doc string for substitute_and_verify(), then read the * test functions themselves -- they're small, and they'll be very * easy to understand once you know substitute_and_verify(). */#include <stdio.h>#include <string.h>#include <apr_general.h>#include <apr_file_io.h>#include "svn_wc.h"#include "svn_pools.h"#include "svn_subst.h"#include "../svn_test.h"/*** Helpers ***//* (Almost) all the tests share the same test data. */const char *lines[] = { "Line 1: fairly boring subst test data... blah blah", "Line 2: fairly boring subst test data... blah blah.", "Line 3: Valid $LastChangedRevision$, started unexpanded.", "Line 4: fairly boring subst test data... blah blah.", "Line 5: Valid $Rev$, started unexpanded.", "Line 6: fairly boring subst test data... blah blah.", "Line 7: fairly boring subst test data... blah blah.", "Line 8: Valid $LastChangedBy$, started unexpanded.", "Line 9: Valid $Author$, started unexpanded.", "Line 10: fairly boring subst test data... blah blah.", "Line 11: fairly boring subst test data... blah blah.", "Line 12: Valid $LastChangedDate$, started unexpanded.", "Line 13: Valid $Date$, started unexpanded.", "Line 14: fairly boring subst test data... blah blah.", "Line 15: fairly boring subst test data... blah blah.", "Line 16: Valid $HeadURL$, started unexpanded.", "Line 17: Valid $URL$, started unexpanded.", "Line 18: fairly boring subst test data... blah blah.", "Line 19: Invalid expanded keyword spanning two lines: $Author: ", /* The idea here is that, were it not broken across two lines, "$Author: Line 20: jrandom$" would be a valid if odd, keyword. */ "Line 20: jrandom$ remainder of invalid keyword spanning two lines.", "Line 21: fairly boring subst test data... blah blah.", "Line 22: an unknown keyword $LastChangedSocks$.", "Line 23: fairly boring subst test data... blah blah.", /* In line 24, the third dollar sign terminates the first, and the fourth should therefore remain a literal dollar sign. */ "Line 24: keyword in a keyword: $Author: $Date$ $", "Line 25: fairly boring subst test data... blah blah.", "Line 26: Emptily expanded keyword $Rev: $.", "Line 27: fairly boring subst test data... blah blah.", "Line 28: fairly boring subst test data... blah blah.", "Line 29: Valid $LastChangedRevision: 1729 $, started expanded.", "Line 30: Valid $Rev: 1729 $, started expanded.", "Line 31: fairly boring subst test data... blah blah.", "Line 32: fairly boring subst test data... blah blah.", "Line 33: Valid $LastChangedDate: 2002-01-01 $, started expanded.", "Line 34: Valid $Date: 2002-01-01 $, started expanded.", "Line 35: fairly boring subst test data... blah blah.", "Line 36: fairly boring subst test data... blah blah.", "Line 37: Valid $LastChangedBy: jrandom $, started expanded.", "Line 38: Valid $Author: jrandom $, started expanded.", "Line 39: fairly boring subst test data... blah blah.", "Line 40: fairly boring subst test data... blah blah.", "Line 41: Valid $HeadURL: http://tomato/mauve $, started expanded.", "Line 42: Valid $URL: http://tomato/mauve $, started expanded.", "Line 43: fairly boring subst test data... blah blah.", "Line 44: fairly boring subst test data... blah blah.", "Line 45: Invalid $LastChangedRevisionWithSuffix$, started unexpanded.", "Line 46: Valid $Rev:$ is missing a space.", "Line 47: fairly boring subst test data... blah blah.", "Line 48: Two keywords back to back: $Author$$Rev$.", "Line 49: One keyword, one not, back to back: $Author$Rev$.", "Line 50: a series of dollar signs $$$$$$$$$$$$$$$$$$$$$$$$$$$$.", "Line 51: same, but with embedded keyword $$$$$$$$Date$$$$$$$$$$.", "Line 52: same, with expanded, empty keyword $$$$$$Date: $$$$$$.", "Line 53: $This is a lengthy line designed to test a bug that was " "reported about keyword expansion. The problem was that a line " "had more than SVN_KEYWORD_MAX_LEN (255 at the time) characters " "after an initial dollar sign, which triggered a buglet in our " "svn_subst_copy_and_translate() function and resulted in, in some cases " "a SEGFAULT, and in others a filthy corrupt commit. ", "", /* Lines 54-69 are blank to test consecutive newlines */ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "$Author$Rev$.", /* Line 70-73 test places where '$' abuts a newline. */ ".$veR$Author$", "$", "$$", /* Line 74-75 test for keywords containing '$', issue #1780 */ "Line 74: Valid $Author: jran$dom $, started expanded.", "Line 75: Valid $URL: http://tomato/mau$ve $, started expanded.", /* Line 76-78 tests for a string with an unknown keyword of 252-254 bytes long */ "$ " " " " " " $$", "$ " " " " " " $$", "$ " " " " " " $$", /* Testing border cases, line 79-82 test for valid keywords, keywords on line 83-84 are too long */ "Line 79: Valid $Author: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa $, started expanded.", "Line 80: Valid $Author: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaa" "aaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaa $, started " "expanded.", /* keyword from first dollar sign to last = 254 chars */ "Line 81: Valid $Author: aaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaa$$$ $, started " "expanded.", /* keyword from first dollar sign to last = 255 chars */ "Line 82: Valid $Author: aaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaa$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$ $, started " "expanded.", /* keyword from first dollar sign to last = 256 chars */ "Line 83: Invalid $Author: aaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaa$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$ $, started " "expanded.", "Line 84: Invalid $Author: aaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaa$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$ $, started " "expanded.", "Line 85: end of subst test data." };/* Return a randomly selected eol sequence. */static const char *random_eol_marker(void){ /* Select a random eol marker from this set. */ static int seeded = 0; /* ### todo: allowing '\r' to be in this list of possible random eol_markers causes problems for the current testing framework which expects a 1:1 ratio of input-line-count to output-line-count. Problems occur when there are two consecutive line ending markers where the first is '\r' and the second is '\n' -- our translation routine reads that as a single '\r\n' which throws off the linecount on the output side, and fouls up substitute_and_verify. */ const char *eol_markers[] = { "\n", "\r\n" }; if (! seeded) { srand(1729); /* we want errors to be reproducible */ seeded = 1; } return eol_markers[rand() % ((sizeof(eol_markers)) / (sizeof(*eol_markers)))];}/* Create FNAME with global `lines' as initial data. Use EOL_STR as * the end-of-line marker between lines, or if EOL_STR is NULL, choose * a random marker at each opportunity. Use POOL for any temporary * allocation. */static svn_error_t *create_file(const char *fname, const char *eol_str, apr_pool_t *pool){ apr_status_t apr_err; apr_file_t *f; apr_size_t i, j; apr_err = apr_file_open(&f, fname, (APR_WRITE | APR_CREATE | APR_EXCL | APR_BINARY), APR_OS_DEFAULT, pool); if (apr_err) return svn_error_create(apr_err, NULL, fname); for (i = 0; i < (sizeof(lines) / sizeof(*lines)); i++) { const char *this_eol_str = eol_str ? eol_str : random_eol_marker(); apr_err = apr_file_printf(f, lines[i]); /* Is it overly paranoid to use putc(), because of worry about fprintf() doing a newline conversion? */ for (j = 0; this_eol_str[j]; j++) { apr_err = apr_file_putc(this_eol_str[j], f); if (apr_err) return svn_error_create(apr_err, NULL, fname); } } apr_err = apr_file_close(f); if (apr_err) return svn_error_create(apr_err, NULL, fname); return SVN_NO_ERROR;}/* If FNAME is a regular file, remove it; if it doesn't exist at all, return success. Otherwise, return error. */static svn_error_t *remove_file(const char *fname, apr_pool_t *pool){ apr_status_t apr_err; apr_finfo_t finfo; if (apr_stat(&finfo, fname, APR_FINFO_TYPE, pool) == APR_SUCCESS) { if (finfo.filetype == APR_REG) { apr_err = apr_file_remove(fname, pool); if (apr_err) return svn_error_create(apr_err, NULL, fname); } else return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "non-file '%s' is in the way", fname); } return SVN_NO_ERROR;}/* Set up, run, and verify the results of a substitution. * * Create a file TEST_NAME.src using global `lines' as the initial * data, with SRC_EOL as the line separator, then convert it to file * TEST_NAME.dst (using DST_EOL, REPAIR, EXPAND, REV, AUTHOR, DATE, * and URL as svn_subst_copy_and_translate() does), and verify that the * conversion worked. Null SRC_EOL means create a mixed eol src * file. * * If the verification succeeds, remove both files and return * SVN_NO_ERROR. * * If the verification fails, leave the files for post-mortem. If the * failure is due to non-eol data being wrong, return * SVN_ERR_MALFORMED_FILE. If the problem is an incorrect eol marker, * return SVN_ERR_IO_UNKNOWN_EOL. If the problem is that a mixed eol * style was repaired even though no repair flag was passed, return * SVN_ERR_TEST_FAILED. * * Use POOL for temporary allocation. * * Note: as with svn_subst_copy_and_translate(), if any of DST_EOL, REV, * AUTHOR, DATE, and/or URL is null, then that substitution is not * performed. */static svn_error_t *substitute_and_verify(const char *test_name, const char *src_eol, const char *dst_eol, svn_boolean_t repair, const char *rev, const char *date, const char *author, const char *url, svn_boolean_t expand, apr_pool_t *pool){ svn_error_t *err; svn_stringbuf_t *contents; apr_hash_t *keywords = apr_hash_make(pool); apr_size_t idx = 0; apr_size_t i; const char *expect[(sizeof(lines) / sizeof(*lines))]; const char *src_fname = apr_pstrcat(pool, test_name, ".src", NULL); const char *dst_fname = apr_pstrcat(pool, test_name, ".dst", NULL); svn_string_t *val; apr_pool_t *subpool = svn_pool_create(pool); /** Clean up from previous tests, set up src data, and convert. **/ SVN_ERR(remove_file(src_fname, pool)); SVN_ERR(remove_file(dst_fname, pool)); SVN_ERR(create_file(src_fname, src_eol, pool)); if (rev) { val = svn_string_create(rev, pool); apr_hash_set(keywords, SVN_KEYWORD_REVISION_LONG, APR_HASH_KEY_STRING, val); apr_hash_set(keywords, SVN_KEYWORD_REVISION_MEDIUM, APR_HASH_KEY_STRING, val); apr_hash_set(keywords, SVN_KEYWORD_REVISION_SHORT, APR_HASH_KEY_STRING, val); } if (date) { val = svn_string_create(date, pool); apr_hash_set(keywords, SVN_KEYWORD_DATE_LONG, APR_HASH_KEY_STRING, val); apr_hash_set(keywords, SVN_KEYWORD_DATE_SHORT, APR_HASH_KEY_STRING, val); } if (author) { val = svn_string_create(author, pool); apr_hash_set(keywords, SVN_KEYWORD_AUTHOR_LONG, APR_HASH_KEY_STRING, val); apr_hash_set(keywords, SVN_KEYWORD_AUTHOR_SHORT, APR_HASH_KEY_STRING, val); } if (url) { val = svn_string_create(url, pool); apr_hash_set(keywords, SVN_KEYWORD_URL_LONG, APR_HASH_KEY_STRING, val); apr_hash_set(keywords, SVN_KEYWORD_URL_SHORT, APR_HASH_KEY_STRING, val); } err = svn_subst_copy_and_translate3(src_fname, dst_fname, dst_eol, repair, keywords, expand, FALSE, subpool); svn_pool_destroy(subpool); /* Conversion should have failed, if src has mixed eol, and the repair flag was not set, and we requested eol translation. */ if ((! src_eol) && dst_eol && (! repair)) { if (! err) { return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "translation of '%s' should have failed, but didn't", src_fname); } else if (err->apr_err != SVN_ERR_IO_INCONSISTENT_EOL) { return svn_error_createf (SVN_ERR_TEST_FAILED, err, "translation of '%s' should fail, but not with this error", src_fname); } else { svn_error_clear(err); SVN_ERR(remove_file(src_fname, pool)); return SVN_NO_ERROR; } } else if (err) return err; /** Verify that the conversion worked. **/ for (i = 0; i < (sizeof(expect) / sizeof(*expect)); i++) expect[i] = lines[i]; /* Certain lines contain keywords; expect their expansions. */ if (rev) { if (expand) { expect[3 - 1] = apr_pstrcat(pool, "Line 3: ", "Valid $LastChangedRevision: ", rev, " $, started unexpanded.", NULL); expect[5 - 1] = apr_pstrcat(pool, "Line 5: ", "Valid $Rev: ", rev, " $, started unexpanded.", NULL); expect[26 - 1] = apr_pstrcat(pool, "Line 26: ", "Emptily expanded keyword $Rev: ", rev," $.", NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -