1 /*
2  * translate-test.c -- test the eol and keyword translation subroutine
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 
25 
26 /* Advice to those adding new tests to this file:
27  * ==============================================
28  *
29  * Read the doc string for substitute_and_verify(), then read the
30  * test functions themselves -- they're small, and they'll be very
31  * easy to understand once you know substitute_and_verify().
32  */
33 
34 
35 
36 #include <stdio.h>
37 #include <string.h>
38 #include <apr_general.h>
39 #include <apr_file_io.h>
40 
41 #include "../svn_test.h"
42 
43 #include "svn_pools.h"
44 #include "svn_subst.h"
45 
46 
47 
48 /*** Helpers ***/
49 
50 /* (Almost) all the tests share the same test data. */
51 static const char *lines[] =
52   {
53     "Line 1: fairly boring subst test data... blah blah",
54     "Line 2: fairly boring subst test data... blah blah.",
55     "Line 3: Valid $LastChangedRevision$, started unexpanded.",
56     "Line 4: fairly boring subst test data... blah blah.",
57     "Line 5: Valid $Rev$, started unexpanded.",
58     "Line 6: fairly boring subst test data... blah blah.",
59     "Line 7: fairly boring subst test data... blah blah.",
60     "Line 8: Valid $LastChangedBy$, started unexpanded.",
61     "Line 9: Valid $Author$, started unexpanded.",
62     "Line 10: fairly boring subst test data... blah blah.",
63     "Line 11: fairly boring subst test data... blah blah.",
64     "Line 12: Valid $LastChangedDate$, started unexpanded.",
65     "Line 13: Valid $Date$, started unexpanded.",
66     "Line 14: fairly boring subst test data... blah blah.",
67     "Line 15: fairly boring subst test data... blah blah.",
68     "Line 16: Valid $HeadURL$, started unexpanded.",
69     "Line 17: Valid $URL$, started unexpanded.",
70     "Line 18: fairly boring subst test data... blah blah.",
71     "Line 19: Invalid expanded keyword spanning two lines: $Author: ",
72     /* The idea here is that, were it not broken across two lines,
73        "$Author: Line 20: jrandom$" would be a valid if odd, keyword. */
74     "Line 20: jrandom$ remainder of invalid keyword spanning two lines.",
75     "Line 21: fairly boring subst test data... blah blah.",
76     "Line 22: an unknown keyword $LastChangedSocks$.",
77     "Line 23: fairly boring subst test data... blah blah.",
78     /* In line 24, the third dollar sign terminates the first, and the
79        fourth should therefore remain a literal dollar sign. */
80     "Line 24: keyword in a keyword: $Author: $Date$ $",
81     "Line 25: fairly boring subst test data... blah blah.",
82     "Line 26: Emptily expanded keyword $Rev: $.",
83     "Line 27: fairly boring subst test data... blah blah.",
84     "Line 28: fairly boring subst test data... blah blah.",
85     "Line 29: Valid $LastChangedRevision: 1729 $, started expanded.",
86     "Line 30: Valid $Rev: 1729 $, started expanded.",
87     "Line 31: fairly boring subst test data... blah blah.",
88     "Line 32: fairly boring subst test data... blah blah.",
89     "Line 33: Valid $LastChangedDate: 2002-01-01 $, started expanded.",
90     "Line 34: Valid $Date: 2002-01-01 $, started expanded.",
91     "Line 35: fairly boring subst test data... blah blah.",
92     "Line 36: fairly boring subst test data... blah blah.",
93     "Line 37: Valid $LastChangedBy: jrandom $, started expanded.",
94     "Line 38: Valid $Author: jrandom $, started expanded.",
95     "Line 39: fairly boring subst test data... blah blah.",
96     "Line 40: fairly boring subst test data... blah blah.",
97     "Line 41: Valid $HeadURL: http://tomato/mauve $, started expanded.",
98     "Line 42: Valid $URL: http://tomato/mauve $, started expanded.",
99     "Line 43: fairly boring subst test data... blah blah.",
100     "Line 44: fairly boring subst test data... blah blah.",
101     "Line 45: Invalid $LastChangedRevisionWithSuffix$, started unexpanded.",
102     "Line 46: Empty $Author:$, started expanded.",
103     "Line 47: fairly boring subst test data... blah blah.",
104     "Line 48: Two keywords back to back: $Author$$Rev$.",
105     "Line 49: One keyword, one not, back to back: $Author$Rev$.",
106     "Line 50: a series of dollar signs $$$$$$$$$$$$$$$$$$$$$$$$$$$$.",
107     "Line 51: same, but with embedded keyword $$$$$$$$Date$$$$$$$$$$.",
108     "Line 52: same, with expanded, empty keyword $$$$$$Date: $$$$$$.",
109     "Line 53: $This is a lengthy line designed to test a bug that was "
110     "reported about keyword expansion.  The problem was that a line "
111     "had more than SVN_KEYWORD_MAX_LEN (255 at the time) characters "
112     "after an initial dollar sign, which triggered a buglet in our "
113     "svn_subst_copy_and_translate() function and resulted in, in some cases "
114     "a SEGFAULT, and in others a filthy corrupt commit. ",
115     "", /* Lines 54-69 are blank to test consecutive newlines */
116     "",
117     "",
118     "",
119     "",
120     "",
121     "",
122     "",
123     "",
124     "",
125     "",
126     "",
127     "",
128     "",
129     "",
130     "",
131     "$Author$Rev$.", /* Line 70-73 test places where '$' abuts a newline. */
132     ".$veR$Author$",
133     "$",
134     "$$",
135     /* Line 74-75 test for keywords containing '$', issue #1780 */
136     "Line 74: Valid $Author: jran$dom $, started expanded.",
137     "Line 75: Valid $URL: http://tomato/mau$ve $, started expanded.",
138     /* Line 76-78 tests for a string with an unknown keyword of 252-254 bytes
139        long */
140     "$                                                                       "
141     "                                                                        "
142     "                                                                        "
143     "                                      $$",
144     "$                                                                       "
145     "                                                                        "
146     "                                                                        "
147     "                                       $$",
148     "$                                                                       "
149     "                                                                        "
150     "                                                                        "
151     "                                        $$",
152     /* Testing border cases, line 79-82 test for valid keywords, keywords on
153        line 83-84 are too long */
154     "Line 79: Valid $Author: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
155     "aaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
156     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
157     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa $, started expanded.",
158     "Line 80: Valid $Author: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaa"
159     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaa"
160     "aaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
161     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$aaaaaaa $, started "
162     "expanded.",
163     /* keyword from first dollar sign to last = 254 chars */
164     "Line 81: Valid $Author: aaaaaaaaaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaaaaaaaaa"
165     "aaaaaaaaaaaaa$aaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
166     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaa"
167     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaa$$$ $, started "
168     "expanded.",
169     /* keyword from first dollar sign to last = 255 chars */
170     "Line 82: Valid $Author: aaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
171     "aaaaaaaaaaaaaaaaaaaaaaaaaa$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
172     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaa"
173     "aaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$ $, started "
174     "expanded.",
175     /* keyword from first dollar sign to last = 256 chars */
176     "Line 83: Invalid $Author: aaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
177     "aaaaaaaaaaaaaaaaaaaaaaaaaa$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
178     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaa"
179     "aaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$ $, started "
180     "expanded.",
181     "Line 84: Invalid $Author: aaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
182     "aaaaaaaaaaaaaaaaaaaaaaaaaa$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
183     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaa"
184     "aaaaaaaaaaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$ $, started "
185     "expanded.",
186     "Line 85: end of subst test data."
187   };
188 
189 
190 /* Return a randomly selected eol sequence. */
191 static const char *
random_eol_marker(void)192 random_eol_marker(void)
193 {
194   /* Select a random eol marker from this set. */
195   static int seeded = 0;
196 
197   /* ### todo: allowing '\r' to be in this list of possible random
198      eol_markers causes problems for the current testing framework
199      which expects a 1:1 ratio of input-line-count to output-line-count.
200      Problems occur when there are two consecutive line ending markers
201      where the first is '\r' and the second is '\n' -- our
202      translation routine reads that as a single '\r\n' which throws
203      off the linecount on the output side, and fouls up substitute_and_verify.
204   */
205   const char *eol_markers[] = { "\n", "\r\n" };
206 
207   if (! seeded)
208     {
209       srand(1729);  /* we want errors to be reproducible */
210       seeded = 1;
211     }
212 
213   return eol_markers[rand()
214                      % ((sizeof(eol_markers)) / (sizeof(*eol_markers)))];
215 }
216 
217 
218 /* Create FNAME with global `lines' as initial data.  Use EOL_STR as
219  * the end-of-line marker between lines, or if EOL_STR is NULL, choose
220  * a random marker at each opportunity.  Use POOL for any temporary
221  * allocation.
222  */
223 static svn_error_t *
create_file(const char * fname,const char * eol_str,apr_pool_t * pool)224 create_file(const char *fname, const char *eol_str, apr_pool_t *pool)
225 {
226   apr_file_t *f;
227   apr_size_t i, j;
228 
229   SVN_ERR(svn_io_file_open(&f, fname,
230                           (APR_WRITE | APR_CREATE | APR_EXCL | APR_BINARY),
231                           APR_OS_DEFAULT, pool));
232 
233   for (i = 0; i < (sizeof(lines) / sizeof(*lines)); i++)
234     {
235       const char *this_eol_str = eol_str ? eol_str : random_eol_marker();
236 
237       apr_file_printf(f, "%s", lines[i]);
238 
239       /* Is it overly paranoid to use putc(), because of worry about
240          fprintf() doing a newline conversion? */
241       for (j = 0; this_eol_str[j]; j++)
242         {
243           SVN_ERR(svn_io_file_putc(this_eol_str[j], f, pool));
244         }
245     }
246 
247   return svn_error_trace(svn_io_file_close(f, pool));
248 }
249 
250 /* Set up, run, and verify the results of a substitution.
251  *
252  * Create a file TEST_NAME.src using global `lines' as the initial
253  * data, with SRC_EOL as the line separator, then convert it to file
254  * TEST_NAME.dst (using DST_EOL, REPAIR, EXPAND, REV, AUTHOR, DATE,
255  * and URL as svn_subst_copy_and_translate() does), and verify that the
256  * conversion worked.  Null SRC_EOL means create a mixed eol src
257  * file.
258  *
259  * If the verification succeeds, remove both files and return
260  * SVN_NO_ERROR.
261  *
262  * If the verification fails, leave the files for post-mortem.  If the
263  * failure is due to non-eol data being wrong, return
264  * SVN_ERR_MALFORMED_FILE.  If the problem is an incorrect eol marker,
265  * return SVN_ERR_IO_UNKNOWN_EOL.  If the problem is that a mixed eol
266  * style was repaired even though no repair flag was passed, return
267  * SVN_ERR_TEST_FAILED.
268  *
269  * Use POOL for temporary allocation.
270  *
271  * Note: as with svn_subst_copy_and_translate(), if any of DST_EOL, REV,
272  * AUTHOR, DATE, and/or URL is null, then that substitution is not
273  * performed.
274  */
275 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)276 substitute_and_verify(const char *test_name,
277                       const char *src_eol,
278                       const char *dst_eol,
279                       svn_boolean_t repair,
280                       const char *rev,
281                       const char *date,
282                       const char *author,
283                       const char *url,
284                       svn_boolean_t expand,
285                       apr_pool_t *pool)
286 {
287   svn_error_t *err;
288   svn_stringbuf_t *contents;
289   apr_hash_t *keywords = apr_hash_make(pool);
290   apr_size_t idx = 0;
291   apr_size_t i;
292   const char *expect[(sizeof(lines) / sizeof(*lines))];
293   const char *src_fname = apr_pstrcat(pool, test_name, ".src", SVN_VA_NULL);
294   const char *dst_fname = apr_pstrcat(pool, test_name, ".dst", SVN_VA_NULL);
295   svn_string_t *val;
296   apr_pool_t *subpool = svn_pool_create(pool);
297 
298   /** Clean up from previous tests, set up src data, and convert. **/
299   SVN_ERR(svn_io_remove_file2(src_fname, TRUE, pool));
300   SVN_ERR(svn_io_remove_file2(dst_fname, TRUE, pool));
301   SVN_ERR(create_file(src_fname, src_eol, pool));
302 
303   if (rev)
304     {
305       val = svn_string_create(rev, pool);
306       apr_hash_set(keywords, SVN_KEYWORD_REVISION_LONG,
307                    APR_HASH_KEY_STRING, val);
308       apr_hash_set(keywords, SVN_KEYWORD_REVISION_MEDIUM,
309                    APR_HASH_KEY_STRING, val);
310       apr_hash_set(keywords, SVN_KEYWORD_REVISION_SHORT,
311                    APR_HASH_KEY_STRING, val);
312     }
313   if (date)
314     {
315       val = svn_string_create(date, pool);
316       apr_hash_set(keywords, SVN_KEYWORD_DATE_LONG,
317                    APR_HASH_KEY_STRING, val);
318       apr_hash_set(keywords, SVN_KEYWORD_DATE_SHORT,
319                    APR_HASH_KEY_STRING, val);
320     }
321   if (author)
322     {
323       val = svn_string_create(author, pool);
324       apr_hash_set(keywords, SVN_KEYWORD_AUTHOR_LONG,
325                    APR_HASH_KEY_STRING, val);
326       apr_hash_set(keywords, SVN_KEYWORD_AUTHOR_SHORT,
327                    APR_HASH_KEY_STRING, val);
328     }
329   if (url)
330     {
331       val = svn_string_create(url, pool);
332       apr_hash_set(keywords, SVN_KEYWORD_URL_LONG,
333                    APR_HASH_KEY_STRING, val);
334       apr_hash_set(keywords, SVN_KEYWORD_URL_SHORT,
335                    APR_HASH_KEY_STRING, val);
336     }
337 
338   err = svn_subst_copy_and_translate4(src_fname, dst_fname, dst_eol, repair,
339                                       keywords, expand, FALSE,
340                                       NULL, NULL, subpool);
341   svn_pool_destroy(subpool);
342 
343   /* Conversion should have failed, if src has mixed eol, and the
344      repair flag was not set, and we requested eol translation. */
345   if ((! src_eol) && dst_eol && (! repair))
346     {
347       if (! err)
348         {
349           return svn_error_createf
350             (SVN_ERR_TEST_FAILED, NULL,
351              "translation of '%s' should have failed, but didn't", src_fname);
352         }
353       else if (err->apr_err != SVN_ERR_IO_INCONSISTENT_EOL)
354         {
355           return svn_error_createf
356             (SVN_ERR_TEST_FAILED, err,
357              "translation of '%s' should fail, but not with this error",
358              src_fname);
359         }
360       else
361         {
362           svn_error_clear(err);
363           SVN_ERR(svn_io_remove_file2(src_fname, FALSE, pool));
364           return SVN_NO_ERROR;
365         }
366 
367     }
368   else if (err)
369     return err;
370 
371 
372   /** Verify that the conversion worked. **/
373 
374   for (i = 0; i < (sizeof(expect) / sizeof(*expect)); i++)
375     expect[i] = lines[i];
376 
377   /* Certain lines contain keywords; expect their expansions. */
378   if (rev)
379     {
380       if (expand)
381         {
382           expect[3 - 1] =
383             apr_pstrcat(pool, "Line 3: ",
384                         "Valid $LastChangedRevision: ",
385                         rev,
386                         " $, started unexpanded.",
387                         SVN_VA_NULL);
388           expect[5 - 1] =
389             apr_pstrcat(pool, "Line 5: ",
390                         "Valid $Rev: ", rev, " $, started unexpanded.",
391                         SVN_VA_NULL);
392           expect[26 - 1] =
393             apr_pstrcat(pool, "Line 26: ",
394                         "Emptily expanded keyword $Rev: ", rev," $.",
395                         SVN_VA_NULL);
396           expect[29 - 1] =
397             apr_pstrcat(pool, "Line 29: ",
398                         "Valid $LastChangedRevision: ",
399                         rev,
400                         " $, started expanded.",
401                         SVN_VA_NULL);
402           expect[30 - 1] =
403             apr_pstrcat(pool, "Line 30: ",
404                         "Valid $Rev: ",
405                         rev,
406                         " $, started expanded.",
407                         SVN_VA_NULL);
408         }
409       else  /* unexpand */
410         {
411           /* Lines 3 and 5 remain unchanged. */
412           expect[26 - 1] =
413             "Line 26: Emptily expanded keyword $Rev$.";
414           expect[29 - 1] =
415             "Line 29: Valid $LastChangedRevision$, started expanded.";
416           expect[30 - 1] =
417             "Line 30: Valid $Rev$, started expanded.";
418         }
419     }
420 
421   if (date)
422     {
423       if (expand)
424         {
425           expect[12 - 1] =
426             apr_pstrcat(pool, "Line 12: ",
427                         "Valid $LastChangedDate: ",
428                         date,
429                         " $, started unexpanded.",
430                         SVN_VA_NULL);
431           expect[13 - 1] =
432             apr_pstrcat(pool, "Line 13: ",
433                         "Valid $Date: ", date, " $, started unexpanded.",
434                         SVN_VA_NULL);
435           expect[33 - 1] =
436             apr_pstrcat(pool, "Line 33: ",
437                         "Valid $LastChangedDate: ",
438                         date,
439                         " $, started expanded.",
440                         SVN_VA_NULL);
441           expect[34 - 1] =
442             apr_pstrcat(pool, "Line 34: ",
443                         "Valid $Date: ", date, " $, started expanded.",
444                         SVN_VA_NULL);
445           expect[51 - 1] =
446             apr_pstrcat(pool, "Line 51: ",
447                         "same, but with embedded keyword ",
448                         "$$$$$$$$Date: ", date, " $$$$$$$$$$.",
449                         SVN_VA_NULL);
450           expect[52 - 1] =
451             apr_pstrcat(pool, "Line 52: ",
452                         "same, with expanded, empty keyword ",
453                         "$$$$$$Date: ", date, " $$$$$$.",
454                         SVN_VA_NULL);
455         }
456       else  /* unexpand */
457         {
458           /* Lines 12 and 13 remain unchanged. */
459           expect[33 - 1] =
460             "Line 33: Valid $LastChangedDate$, started expanded.";
461           expect[34 - 1] =
462             "Line 34: Valid $Date$, started expanded.";
463           expect[51 - 1] =
464             "Line 51: same, but with embedded keyword $$$$$$$$Date$$$$$$$$$$.";
465           expect[52 - 1] =
466             "Line 52: same, with expanded, empty keyword $$$$$$Date$$$$$$.";
467         }
468     }
469 
470   if (author)
471     {
472       if (expand)
473         {
474           expect[8 - 1] =
475             apr_pstrcat(pool, "Line 8: ",
476                         "Valid $LastChangedBy: ",
477                         author,
478                         " $, started unexpanded.",
479                         SVN_VA_NULL);
480           expect[9 - 1] =
481             apr_pstrcat(pool, "Line 9: ",
482                         "Valid $Author: ", author, " $, started unexpanded.",
483                         SVN_VA_NULL);
484           expect[37 - 1] =
485             apr_pstrcat(pool, "Line 37: ",
486                         "Valid $LastChangedBy: ", author,
487                         " $, started expanded.", SVN_VA_NULL);
488           expect[38 - 1] =
489             apr_pstrcat(pool, "Line 38: ",
490                         "Valid $Author: ", author, " $, started expanded.",
491                         SVN_VA_NULL);
492           expect[46 - 1] =
493             apr_pstrcat(pool, "Line 46: ",
494                         "Empty $Author: ", author, " $, started expanded.",
495                         SVN_VA_NULL);
496           expect[71 - 1] =
497             apr_pstrcat(pool, ".$veR$Author: ", author, " $", SVN_VA_NULL);
498 
499           expect[74 - 1] =
500             apr_pstrcat(pool, "Line 74: ",
501                         "Valid $Author: ", author, " $, started expanded.",
502                         SVN_VA_NULL);
503           expect[79 - 1] =
504             apr_pstrcat(pool, "Line 79: ",
505                         "Valid $Author: ", author, " $, started expanded.",
506                         SVN_VA_NULL);
507           expect[80 - 1] =
508             apr_pstrcat(pool, "Line 80: ",
509                         "Valid $Author: ", author, " $, started expanded.",
510                         SVN_VA_NULL);
511           expect[81 - 1] =
512             apr_pstrcat(pool, "Line 81: ",
513                         "Valid $Author: ", author, " $, started expanded.",
514                         SVN_VA_NULL);
515           expect[82 - 1] =
516             apr_pstrcat(pool, "Line 82: ",
517                         "Valid $Author: ", author, " $, started expanded.",
518                         SVN_VA_NULL);
519         }
520       else  /* unexpand */
521         {
522           /* Lines 8, 9, and 71 remain unchanged. */
523           expect[37 - 1] =
524             "Line 37: Valid $LastChangedBy$, started expanded.";
525           expect[38 - 1] =
526             "Line 38: Valid $Author$, started expanded.";
527           expect[46 - 1] =
528             "Line 46: Empty $Author$, started expanded.";
529           expect[74 - 1] =
530             "Line 74: Valid $Author$, started expanded.";
531           expect[79 - 1] =
532             "Line 79: Valid $Author$, started expanded.";
533           expect[80 - 1] =
534             "Line 80: Valid $Author$, started expanded.";
535           expect[81 - 1] =
536             "Line 81: Valid $Author$, started expanded.";
537           expect[82 - 1] =
538             "Line 82: Valid $Author$, started expanded.";
539         }
540     }
541 
542   if (url)
543     {
544       if (expand)
545         {
546           expect[16 - 1] =
547             apr_pstrcat(pool, "Line 16: ",
548                         "Valid $HeadURL: ", url, " $, started unexpanded.",
549                         SVN_VA_NULL);
550           expect[17 - 1] =
551             apr_pstrcat(pool, "Line 17: ",
552                         "Valid $URL: ", url, " $, started unexpanded.",
553                         SVN_VA_NULL);
554           expect[41 - 1] =
555             apr_pstrcat(pool, "Line 41: ",
556                         "Valid $HeadURL: ", url, " $, started expanded.",
557                         SVN_VA_NULL);
558           expect[42 - 1] =
559             apr_pstrcat(pool, "Line 42: ",
560                         "Valid $URL: ", url, " $, started expanded.",
561                         SVN_VA_NULL);
562           expect[75 - 1] =
563             apr_pstrcat(pool, "Line 75: ",
564                         "Valid $URL: ", url, " $, started expanded.",
565                         SVN_VA_NULL);
566         }
567       else  /* unexpand */
568         {
569           /* Lines 16 and 17 and remain unchanged. */
570           expect[41 - 1] =
571             "Line 41: Valid $HeadURL$, started expanded.";
572           expect[42 - 1] =
573             "Line 42: Valid $URL$, started expanded.";
574           expect[75 - 1] =
575             "Line 75: Valid $URL$, started expanded.";
576         }
577     }
578 
579   /* Handle lines 48, 49, and 70 specially, as they contains two valid
580      keywords. */
581   if (rev && author)
582     {
583       if (expand)
584         {
585           expect[48 - 1] =
586             apr_pstrcat(pool, "Line 48: ",
587                         "Two keywords back to back: "
588                         "$Author: ", author, " $"
589                         "$Rev: ", rev, " $.",
590                         SVN_VA_NULL);
591           expect[49 - 1] =
592             apr_pstrcat(pool, "Line 49: ",
593                         "One keyword, one not, back to back: "
594                         "$Author: ", author, " $Rev$.",
595                         SVN_VA_NULL);
596           expect[70 - 1] =
597             apr_pstrcat(pool, "$Author: ", author, " $Rev$.", SVN_VA_NULL);
598         }
599       /* Else Lines 48, 49, and 70 remain unchanged. */
600     }
601   else if (rev && (! author))
602     {
603       if (expand)
604         {
605           expect[48 - 1] =
606             apr_pstrcat(pool, "Line 48: ",
607                         "Two keywords back to back: "
608                         "$Author$$Rev: ", rev, " $.",
609                         SVN_VA_NULL);
610           expect[49 - 1] =
611             apr_pstrcat(pool, "Line 49: ",
612                         "One keyword, one not, back to back: "
613                         "$Author$Rev: ", rev, " $.",
614                         SVN_VA_NULL);
615           expect[70 - 1] =
616             apr_pstrcat(pool, "$Author$Rev: ", rev, " $.", SVN_VA_NULL);
617         }
618       /* Else Lines 48, 49, and 70 remain unchanged. */
619     }
620   else if ((! rev) && author)
621     {
622       if (expand)
623         {
624           expect[48 - 1] =
625             apr_pstrcat(pool, "Line 48: ",
626                         "Two keywords back to back: "
627                         "$Author: ", author, " $$Rev$.",
628                         SVN_VA_NULL);
629           expect[49 - 1] =
630             apr_pstrcat(pool, "Line 49: ",
631                         "One keyword, one not, back to back: "
632                         "$Author: ", author, " $Rev$.",
633                         SVN_VA_NULL);
634           expect[70 - 1] =
635             apr_pstrcat(pool, "$Author: ", author, " $Rev$.", SVN_VA_NULL);
636         }
637       /* Else Lines 48, 49, and 70 remain unchanged. */
638     }
639   /* Else neither rev nor author, so Lines 48, 49, and 70 remain
640      unchanged. */
641 
642   /* Handle line 24 specially, as it contains two valid keywords. */
643   if (date && author)
644     {
645       if (expand)
646         {
647           expect[24 - 1] =
648             apr_pstrcat(pool, "Line 24: ",
649                         "keyword in a keyword: $Author: ",
650                         author,
651                         " $Date$ $",
652                         SVN_VA_NULL);
653         }
654       else  /* unexpand */
655         {
656           expect[24 - 1] =
657             apr_pstrcat(pool, "Line 24: ",
658                         "keyword in a keyword: $Author$Date$ $",
659                         SVN_VA_NULL);
660         }
661     }
662   else if (date && (! author))
663     {
664       if (expand)
665         {
666           expect[24 - 1] =
667             apr_pstrcat(pool, "Line 24: ",
668                         "keyword in a keyword: $Author: $Date: ",
669                         date,
670                         " $ $",
671                         SVN_VA_NULL);
672         }
673       /* Else Line 24 remains unchanged. */
674     }
675   else if ((! date) && author)
676     {
677       if (expand)
678         {
679           expect[24 - 1] =
680             apr_pstrcat(pool, "Line 24: ",
681                         "keyword in a keyword: $Author: ",
682                         author,
683                         " $Date$ $",
684                         SVN_VA_NULL);
685         }
686       else  /* unexpand */
687         {
688           expect[24 - 1] =
689             apr_pstrcat(pool, "Line 24: ",
690                         "keyword in a keyword: $Author$Date$ $",
691                         SVN_VA_NULL);
692         }
693     }
694   /* Else neither author nor date, so Line 24 remains unchanged. */
695 
696   /** Ready to verify. **/
697 
698   SVN_ERR(svn_stringbuf_from_file(&contents, dst_fname, pool));
699 
700   for (i = 0; i < (sizeof(expect) / sizeof(*expect)); i++)
701     {
702       if (contents->len < idx)
703         return svn_error_createf
704           (SVN_ERR_MALFORMED_FILE, NULL,
705            "'%s' has short contents at line %" APR_SIZE_T_FMT,
706            dst_fname, i + 1);
707 
708       if (strncmp(contents->data + idx, expect[i], strlen(expect[i])) != 0)
709         return svn_error_createf
710           (SVN_ERR_MALFORMED_FILE, NULL,
711            "'%s' has wrong contents at line %" APR_SIZE_T_FMT,
712            dst_fname, i + 1);
713 
714       /* Else, the data is correct, at least up to the next eol. */
715 
716       idx += strlen(expect[i]);
717 
718       if (dst_eol)  /* verify the promised consistent eol style */
719         {
720           if (strncmp(contents->data + idx, dst_eol, strlen(dst_eol)) != 0)
721             return svn_error_createf
722               (SVN_ERR_IO_UNKNOWN_EOL, NULL,
723                "'%s' has wrong eol style at line %" APR_SIZE_T_FMT, dst_fname,
724                i + 1);
725           else
726             idx += strlen(dst_eol);
727         }
728       else  /* allow any eol style, even inconsistent ones, loosely */
729         {
730           while ((*(contents->data + idx) == '\r')
731                  || (*(contents->data + idx) == '\n'))
732             idx++;
733         }
734     }
735 
736   /* Clean up this test, since successful. */
737   SVN_ERR(svn_io_remove_file2(src_fname, FALSE, pool));
738   SVN_ERR(svn_io_remove_file2(dst_fname, FALSE, pool));
739 
740   return SVN_NO_ERROR;
741 }
742 
743 
744 
745 static svn_error_t *
noop(apr_pool_t * pool)746 noop(apr_pool_t *pool)
747 {
748   SVN_ERR(substitute_and_verify
749           ("noop", NULL, NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
750 
751   SVN_ERR(substitute_and_verify
752           ("noop", "\r", NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
753 
754   SVN_ERR(substitute_and_verify
755           ("noop", "\n", NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
756 
757   SVN_ERR(substitute_and_verify
758           ("noop", "\r\n", NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
759 
760   return SVN_NO_ERROR;
761 }
762 
763 
764 
765 
766 /** EOL conversion alone. **/
767 
768 static svn_error_t *
crlf_to_crlf(apr_pool_t * pool)769 crlf_to_crlf(apr_pool_t *pool)
770 {
771   return substitute_and_verify
772           ("crlf_to_crlf", "\r\n", "\r\n", 0,
773            NULL, NULL, NULL, NULL, 1, pool);
774 }
775 
776 
777 static svn_error_t *
lf_to_crlf(apr_pool_t * pool)778 lf_to_crlf(apr_pool_t *pool)
779 {
780   return substitute_and_verify
781           ("lf_to_crlf", "\n", "\r\n", 0, NULL, NULL, NULL, NULL, 1, pool);
782 }
783 
784 
785 static svn_error_t *
cr_to_crlf(apr_pool_t * pool)786 cr_to_crlf(apr_pool_t *pool)
787 {
788   return substitute_and_verify
789           ("cr_to_crlf", "\r", "\r\n", 0, NULL, NULL, NULL, NULL, 1, pool);
790 }
791 
792 
793 static svn_error_t *
mixed_to_crlf(apr_pool_t * pool)794 mixed_to_crlf(apr_pool_t *pool)
795 {
796   return substitute_and_verify
797           ("mixed_to_crlf", NULL, "\r\n", 1,
798            NULL, NULL, NULL, NULL, 1, pool);
799 }
800 
801 
802 static svn_error_t *
lf_to_lf(apr_pool_t * pool)803 lf_to_lf(apr_pool_t *pool)
804 {
805   return substitute_and_verify
806           ("lf_to_lf", "\n", "\n", 0, NULL, NULL, NULL, NULL, 1, pool);
807 }
808 
809 
810 static svn_error_t *
crlf_to_lf(apr_pool_t * pool)811 crlf_to_lf(apr_pool_t *pool)
812 {
813   return substitute_and_verify
814           ("crlf_to_lf", "\r\n", "\n", 0, NULL, NULL, NULL, NULL, 1, pool);
815 }
816 
817 
818 static svn_error_t *
cr_to_lf(apr_pool_t * pool)819 cr_to_lf(apr_pool_t *pool)
820 {
821   return substitute_and_verify
822           ("cr_to_lf", "\r", "\n", 0, NULL, NULL, NULL, NULL, 1, pool);
823 }
824 
825 
826 static svn_error_t *
mixed_to_lf(apr_pool_t * pool)827 mixed_to_lf(apr_pool_t *pool)
828 {
829   return substitute_and_verify
830           ("mixed_to_lf", NULL, "\n", 1, NULL, NULL, NULL, NULL, 1, pool);
831 }
832 
833 
834 static svn_error_t *
crlf_to_cr(apr_pool_t * pool)835 crlf_to_cr(apr_pool_t *pool)
836 {
837   return substitute_and_verify
838           ("crlf_to_cr", "\r\n", "\r", 0, NULL, NULL, NULL, NULL, 1, pool);
839 }
840 
841 
842 static svn_error_t *
lf_to_cr(apr_pool_t * pool)843 lf_to_cr(apr_pool_t *pool)
844 {
845   return substitute_and_verify
846           ("lf_to_cr", "\n", "\r", 0, NULL, NULL, NULL, NULL, 1, pool);
847 }
848 
849 
850 static svn_error_t *
cr_to_cr(apr_pool_t * pool)851 cr_to_cr(apr_pool_t *pool)
852 {
853   return substitute_and_verify
854           ("cr_to_cr", "\r", "\r", 0, NULL, NULL, NULL, NULL, 1, pool);
855 }
856 
857 
858 static svn_error_t *
mixed_to_cr(apr_pool_t * pool)859 mixed_to_cr(apr_pool_t *pool)
860 {
861   return substitute_and_verify
862           ("mixed_to_cr", NULL, "\r", 1, NULL, NULL, NULL, NULL, 1, pool);
863 }
864 
865 
866 static svn_error_t *
mixed_no_repair(apr_pool_t * pool)867 mixed_no_repair(apr_pool_t *pool)
868 {
869   SVN_ERR(substitute_and_verify
870           ("mixed_no_repair", NULL, "\n", 0,
871            NULL, NULL, NULL, NULL, 1, pool));
872 
873   SVN_ERR(substitute_and_verify
874           ("mixed_no_repair", NULL, "\r\n", 0,
875            NULL, NULL, NULL, NULL, 1, pool));
876 
877   return SVN_NO_ERROR;
878 }
879 
880 
881 
882 /** Keyword expansion alone. **/
883 
884 static svn_error_t *
expand_author(apr_pool_t * pool)885 expand_author(apr_pool_t *pool)
886 {
887   SVN_ERR(substitute_and_verify
888           ("author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 1, pool));
889 
890   SVN_ERR(substitute_and_verify
891           ("author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 1, pool));
892 
893   return SVN_NO_ERROR;
894 }
895 
896 
897 static svn_error_t *
expand_date(apr_pool_t * pool)898 expand_date(apr_pool_t *pool)
899 {
900   SVN_ERR(substitute_and_verify
901           ("date", "\n", NULL, 0,
902            NULL, "Wed Jan  9 07:49:05 2002", NULL, NULL, 1, pool));
903 
904   SVN_ERR(substitute_and_verify
905           ("date", "\r\n", NULL, 0,
906            NULL, "Wed Jan  9 07:49:05 2002", NULL, NULL, 1, pool));
907 
908   return SVN_NO_ERROR;
909 }
910 
911 
912 static svn_error_t *
expand_author_date(apr_pool_t * pool)913 expand_author_date(apr_pool_t *pool)
914 {
915   SVN_ERR(substitute_and_verify
916           ("author_date", "\n", NULL, 0,
917            NULL, "Wed Jan  9 07:49:05 2002", "jrandom", NULL, 1, pool));
918 
919   SVN_ERR(substitute_and_verify
920           ("author_date", "\r\n", NULL, 0,
921            NULL, "Wed Jan  9 07:49:05 2002", "jrandom", NULL, 1, pool));
922 
923   return SVN_NO_ERROR;
924 }
925 
926 
927 static svn_error_t *
expand_author_rev(apr_pool_t * pool)928 expand_author_rev(apr_pool_t *pool)
929 {
930   SVN_ERR(substitute_and_verify
931           ("author_rev", "\n", NULL, 0,
932            "1729", NULL, "jrandom", NULL, 1, pool));
933 
934   SVN_ERR(substitute_and_verify
935           ("author_rev", "\r\n", NULL, 0,
936            "1729", NULL, "jrandom", NULL, 1, pool));
937 
938   return SVN_NO_ERROR;
939 }
940 
941 
942 static svn_error_t *
expand_rev(apr_pool_t * pool)943 expand_rev(apr_pool_t *pool)
944 {
945   SVN_ERR(substitute_and_verify
946           ("rev", "\n", NULL, 0,
947            "1729", NULL, NULL, NULL, 1, pool));
948 
949   SVN_ERR(substitute_and_verify
950           ("rev", "\r\n", NULL, 0,
951            "1729", NULL, NULL, NULL, 1, pool));
952 
953   return SVN_NO_ERROR;
954 }
955 
956 
957 static svn_error_t *
expand_rev_url(apr_pool_t * pool)958 expand_rev_url(apr_pool_t *pool)
959 {
960   SVN_ERR(substitute_and_verify
961           ("rev_url", "\n", NULL, 0,
962            "1729", NULL, NULL, "http://subversion.tigris.org", 1, pool));
963 
964   SVN_ERR(substitute_and_verify
965           ("rev_url", "\r\n", NULL, 0,
966            "1729", NULL, NULL, "http://subversion.tigris.org", 1, pool));
967 
968   return SVN_NO_ERROR;
969 }
970 
971 
972 static svn_error_t *
expand_author_date_rev_url(apr_pool_t * pool)973 expand_author_date_rev_url(apr_pool_t *pool)
974 {
975   SVN_ERR(substitute_and_verify
976           ("author_date_rev_url", "\n", NULL, 0,
977            "1729",
978            "Wed Jan  9 07:49:05 2002",
979            "jrandom",
980            "http://subversion.tigris.org",
981            1, pool));
982 
983   SVN_ERR(substitute_and_verify
984           ("author_date_rev_url", "\r\n", NULL, 0,
985            "1729",
986            "Wed Jan  9 07:49:05 2002",
987            "jrandom",
988            "http://subversion.tigris.org",
989            1, pool));
990 
991   return SVN_NO_ERROR;
992 }
993 
994 
995 
996 /** Keyword expansion and EOL conversion together. **/
997 
998 static svn_error_t *
lf_to_crlf_expand_author(apr_pool_t * pool)999 lf_to_crlf_expand_author(apr_pool_t *pool)
1000 {
1001   return substitute_and_verify
1002           ("lf_to_crlf_author", "\n", "\r\n", 0,
1003            NULL, NULL, "jrandom", NULL, 1, pool);
1004 }
1005 
1006 
1007 static svn_error_t *
mixed_to_lf_expand_author_date(apr_pool_t * pool)1008 mixed_to_lf_expand_author_date(apr_pool_t *pool)
1009 {
1010   return substitute_and_verify
1011           ("mixed_to_lf_author_date", NULL, "\n", 1,
1012            NULL, "Wed Jan  9 07:49:05 2002", "jrandom", NULL, 1, pool);
1013 }
1014 
1015 
1016 static svn_error_t *
crlf_to_cr_expand_author_rev(apr_pool_t * pool)1017 crlf_to_cr_expand_author_rev(apr_pool_t *pool)
1018 {
1019   return substitute_and_verify
1020           ("crlf_to_cr_author_rev", "\r\n", "\r", 0,
1021            "1729", NULL, "jrandom", NULL, 1, pool);
1022 }
1023 
1024 
1025 static svn_error_t *
cr_to_crlf_expand_rev(apr_pool_t * pool)1026 cr_to_crlf_expand_rev(apr_pool_t *pool)
1027 {
1028   return substitute_and_verify
1029           ("cr_to_crlf_rev", "\r", "\r\n", 0,
1030            "1729", NULL, NULL, NULL, 1, pool);
1031 }
1032 
1033 
1034 static svn_error_t *
cr_to_crlf_expand_rev_url(apr_pool_t * pool)1035 cr_to_crlf_expand_rev_url(apr_pool_t *pool)
1036 {
1037   return substitute_and_verify
1038           ("cr_to_crlf_rev_url", "\r", "\r\n", 0,
1039            "1729", NULL, NULL, "http://subversion.tigris.org", 1, pool);
1040 }
1041 
1042 
1043 static svn_error_t *
mixed_to_crlf_expand_author_date_rev_url(apr_pool_t * pool)1044 mixed_to_crlf_expand_author_date_rev_url(apr_pool_t *pool)
1045 {
1046   return substitute_and_verify
1047           ("mixed_to_crlf_author_date_rev_url", NULL, "\r\n", 1,
1048            "1729",
1049            "Wed Jan  9 07:49:05 2002",
1050            "jrandom",
1051            "http://subversion.tigris.org",
1052            1,
1053            pool);
1054 }
1055 
1056 
1057 
1058 /** Keyword unexpansion alone. **/
1059 
1060 static svn_error_t *
unexpand_author(apr_pool_t * pool)1061 unexpand_author(apr_pool_t *pool)
1062 {
1063   SVN_ERR(substitute_and_verify
1064           ("unexpand_author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
1065 
1066   SVN_ERR(substitute_and_verify
1067           ("unexpand_author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
1068 
1069   return SVN_NO_ERROR;
1070 }
1071 
1072 
1073 static svn_error_t *
unexpand_date(apr_pool_t * pool)1074 unexpand_date(apr_pool_t *pool)
1075 {
1076   SVN_ERR(substitute_and_verify
1077           ("unexpand_date", "\n", NULL, 0,
1078            NULL, "Wed Jan  9 07:49:05 2002", NULL, NULL, 0, pool));
1079 
1080   SVN_ERR(substitute_and_verify
1081           ("unexpand_date", "\r\n", NULL, 0,
1082            NULL, "Wed Jan  9 07:49:05 2002", NULL, NULL, 0, pool));
1083 
1084   return SVN_NO_ERROR;
1085 }
1086 
1087 
1088 static svn_error_t *
unexpand_author_date(apr_pool_t * pool)1089 unexpand_author_date(apr_pool_t *pool)
1090 {
1091   SVN_ERR(substitute_and_verify
1092           ("unexpand_author_date", "\n", NULL, 0,
1093            NULL, "Wed Jan  9 07:49:05 2002", "jrandom", NULL, 0, pool));
1094 
1095   SVN_ERR(substitute_and_verify
1096           ("unexpand_author_date", "\r\n", NULL, 0,
1097            NULL, "Wed Jan  9 07:49:05 2002", "jrandom", NULL, 0, pool));
1098 
1099   return SVN_NO_ERROR;
1100 }
1101 
1102 
1103 static svn_error_t *
unexpand_author_rev(apr_pool_t * pool)1104 unexpand_author_rev(apr_pool_t *pool)
1105 {
1106   SVN_ERR(substitute_and_verify
1107           ("unexpand_author_rev", "\n", NULL, 0,
1108            "1729", NULL, "jrandom", NULL, 0, pool));
1109 
1110   SVN_ERR(substitute_and_verify
1111           ("unexpand_author_rev", "\r\n", NULL, 0,
1112            "1729", NULL, "jrandom", NULL, 0, pool));
1113 
1114   return SVN_NO_ERROR;
1115 }
1116 
1117 
1118 static svn_error_t *
unexpand_rev(apr_pool_t * pool)1119 unexpand_rev(apr_pool_t *pool)
1120 {
1121   SVN_ERR(substitute_and_verify
1122           ("unexpand_rev", "\n", NULL, 0,
1123            "1729", NULL, NULL, NULL, 0, pool));
1124 
1125   SVN_ERR(substitute_and_verify
1126           ("unexpand_rev", "\r\n", NULL, 0,
1127            "1729", NULL, NULL, NULL, 0, pool));
1128 
1129   return SVN_NO_ERROR;
1130 }
1131 
1132 
1133 static svn_error_t *
unexpand_rev_url(apr_pool_t * pool)1134 unexpand_rev_url(apr_pool_t *pool)
1135 {
1136   SVN_ERR(substitute_and_verify
1137           ("unexpand_rev_url", "\n", NULL, 0,
1138            "1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
1139 
1140   SVN_ERR(substitute_and_verify
1141           ("unexpand_rev_url", "\r\n", NULL, 0,
1142            "1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
1143 
1144   return SVN_NO_ERROR;
1145 }
1146 
1147 
1148 static svn_error_t *
unexpand_author_date_rev_url(apr_pool_t * pool)1149 unexpand_author_date_rev_url(apr_pool_t *pool)
1150 {
1151   SVN_ERR(substitute_and_verify
1152           ("unexpand_author_date_rev_url", "\n", NULL, 0,
1153            "1729",
1154            "Wed Jan  9 07:49:05 2002",
1155            "jrandom",
1156            "http://subversion.tigris.org",
1157            1, pool));
1158 
1159   SVN_ERR(substitute_and_verify
1160           ("unexpand_author_date_rev_url", "\r\n", NULL, 0,
1161            "1729",
1162            "Wed Jan  9 07:49:05 2002",
1163            "jrandom",
1164            "http://subversion.tigris.org",
1165            1, pool));
1166 
1167   return SVN_NO_ERROR;
1168 }
1169 
1170 
1171 
1172 /** Keyword unexpansion and EOL conversion together. **/
1173 
1174 static svn_error_t *
lf_to_crlf_unexpand_author(apr_pool_t * pool)1175 lf_to_crlf_unexpand_author(apr_pool_t *pool)
1176 {
1177   return substitute_and_verify
1178           ("lf_to_crlf_unexpand_author", "\n", "\r\n", 0,
1179            NULL, NULL, "jrandom", NULL, 0, pool);
1180 }
1181 
1182 
1183 static svn_error_t *
mixed_to_lf_unexpand_author_date(apr_pool_t * pool)1184 mixed_to_lf_unexpand_author_date(apr_pool_t *pool)
1185 {
1186   return substitute_and_verify
1187           ("mixed_to_lf_unexpand_author_date", NULL, "\n", 1,
1188            NULL, "Wed Jan  9 07:49:05 2002", "jrandom", NULL, 0, pool);
1189 }
1190 
1191 
1192 static svn_error_t *
crlf_to_cr_unexpand_author_rev(apr_pool_t * pool)1193 crlf_to_cr_unexpand_author_rev(apr_pool_t *pool)
1194 {
1195   return substitute_and_verify
1196           ("crlf_to_cr_unexpand_author_rev", "\r\n", "\r", 0,
1197            "1729", NULL, "jrandom", NULL, 0, pool);
1198 }
1199 
1200 
1201 static svn_error_t *
cr_to_crlf_unexpand_rev(apr_pool_t * pool)1202 cr_to_crlf_unexpand_rev(apr_pool_t *pool)
1203 {
1204   return substitute_and_verify
1205           ("cr_to_crlf_unexpand_rev", "\r", "\r\n", 0,
1206            "1729", NULL, NULL, NULL, 0, pool);
1207 }
1208 
1209 
1210 static svn_error_t *
cr_to_crlf_unexpand_rev_url(apr_pool_t * pool)1211 cr_to_crlf_unexpand_rev_url(apr_pool_t *pool)
1212 {
1213   return substitute_and_verify
1214           ("cr_to_crlf_unexpand_rev_url", "\r", "\r\n", 0,
1215            "1729", NULL, NULL, "http://subversion.tigris.org", 0, pool);
1216 }
1217 
1218 
1219 static svn_error_t *
mixed_to_crlf_unexpand_author_date_rev_url(apr_pool_t * pool)1220 mixed_to_crlf_unexpand_author_date_rev_url(apr_pool_t *pool)
1221 {
1222   return substitute_and_verify
1223           ("mixed_to_crlf_unexpand_author_date_rev_url", NULL, "\r\n", 1,
1224            "1729",
1225            "Wed Jan  9 07:49:05 2002",
1226            "jrandom",
1227            "http://subversion.tigris.org",
1228            0,
1229            pool);
1230 }
1231 
1232 
1233 
1234 /* The test table.  */
1235 
1236 static int max_threads = 7;
1237 
1238 static struct svn_test_descriptor_t test_funcs[] =
1239   {
1240     SVN_TEST_NULL,
1241   /* The no-op conversion. */
1242     SVN_TEST_PASS2(noop,
1243                    "no conversions"),
1244     /* Conversions resulting in crlf, no keywords involved. */
1245     SVN_TEST_PASS2(crlf_to_crlf,
1246                    "convert CRLF to CRLF"),
1247     SVN_TEST_PASS2(lf_to_crlf,
1248                    "convert LF to CRLF"),
1249     SVN_TEST_PASS2(cr_to_crlf,
1250                    "convert CR to CRLF"),
1251     SVN_TEST_PASS2(mixed_to_crlf,
1252                    "convert mixed line endings to CRLF"),
1253     /* Conversions resulting in lf, no keywords involved. */
1254     SVN_TEST_PASS2(lf_to_lf,
1255                    "convert LF to LF"),
1256     SVN_TEST_PASS2(crlf_to_lf,
1257                    "convert CRLF to LF"),
1258     SVN_TEST_PASS2(cr_to_lf,
1259                    "convert CR to LF"),
1260     SVN_TEST_PASS2(mixed_to_lf,
1261                    "convert mixed line endings to LF"),
1262     /* Conversions resulting in cr, no keywords involved. */
1263     SVN_TEST_PASS2(crlf_to_cr,
1264                    "convert CRLF to CR"),
1265     SVN_TEST_PASS2(lf_to_cr,
1266                    "convert LF to CR"),
1267     SVN_TEST_PASS2(cr_to_cr,
1268                    "convert CR to CR"),
1269     SVN_TEST_PASS2(mixed_to_cr,
1270                    "convert mixed line endings to CR"),
1271     /* Random eol stuff. */
1272     SVN_TEST_PASS2(mixed_no_repair,
1273                    "keep mixed line endings without repair flag"),
1274     /* Keyword expansion alone, no eol conversion involved. */
1275     SVN_TEST_PASS2(expand_author,
1276                    "expand author"),
1277     SVN_TEST_PASS2(expand_date,
1278                    "expand date"),
1279     SVN_TEST_PASS2(expand_author_date,
1280                    "expand author and date"),
1281     SVN_TEST_PASS2(expand_author_rev,
1282                    "expand author and rev"),
1283     SVN_TEST_PASS2(expand_rev,
1284                    "expand rev"),
1285     SVN_TEST_PASS2(expand_rev_url,
1286                    "expand rev and url"),
1287     SVN_TEST_PASS2(expand_author_date_rev_url,
1288                    "expand author, date, rev, and url"),
1289     /* Keyword expansion and eol conversion together. */
1290     SVN_TEST_PASS2(lf_to_crlf_expand_author,
1291                    "lf_to_crlf; expand author"),
1292     SVN_TEST_PASS2(mixed_to_lf_expand_author_date,
1293                    "mixed_to_lf; expand author and date"),
1294     SVN_TEST_PASS2(crlf_to_cr_expand_author_rev,
1295                    "crlf_to_cr; expand author and rev"),
1296     SVN_TEST_PASS2(cr_to_crlf_expand_rev,
1297                    "cr_to_crlf; expand rev"),
1298     SVN_TEST_PASS2(cr_to_crlf_expand_rev_url,
1299                    "cr_to_crlf; expand rev and url"),
1300     SVN_TEST_PASS2(mixed_to_crlf_expand_author_date_rev_url,
1301                    "mixed_to_crlf; expand author, date, rev, and url"),
1302     /* Keyword unexpansion alone, no eol conversion involved. */
1303     SVN_TEST_PASS2(unexpand_author,
1304                    "unexpand author"),
1305     SVN_TEST_PASS2(unexpand_date,
1306                    "unexpand date"),
1307     SVN_TEST_PASS2(unexpand_author_date,
1308                    "unexpand author and date"),
1309     SVN_TEST_PASS2(unexpand_author_rev,
1310                    "unexpand author and rev"),
1311     SVN_TEST_PASS2(unexpand_rev,
1312                    "unexpand rev"),
1313     SVN_TEST_PASS2(unexpand_rev_url,
1314                    "unexpand rev and url"),
1315     SVN_TEST_PASS2(unexpand_author_date_rev_url,
1316                    "unexpand author, date, rev, and url"),
1317     /* Keyword unexpansion and eol conversion together. */
1318     SVN_TEST_PASS2(lf_to_crlf_unexpand_author,
1319                    "lf_to_crlf; unexpand author"),
1320     SVN_TEST_PASS2(mixed_to_lf_unexpand_author_date,
1321                    "mixed_to_lf; unexpand author and date"),
1322     SVN_TEST_PASS2(crlf_to_cr_unexpand_author_rev,
1323                    "crlf_to_cr; unexpand author and rev"),
1324     SVN_TEST_PASS2(cr_to_crlf_unexpand_rev,
1325                    "cr_to_crlf; unexpand rev"),
1326     SVN_TEST_PASS2(cr_to_crlf_unexpand_rev_url,
1327                    "cr_to_crlf; unexpand rev and url"),
1328     SVN_TEST_PASS2(mixed_to_crlf_unexpand_author_date_rev_url,
1329                    "mixed_to_crlf; unexpand author, date, rev, url"),
1330     SVN_TEST_NULL
1331   };
1332 
1333 SVN_TEST_MAIN
1334