1 /**
2  * @copyright
3  * ====================================================================
4  *    Licensed to the Apache Software Foundation (ASF) under one
5  *    or more contributor license agreements.  See the NOTICE file
6  *    distributed with this work for additional information
7  *    regarding copyright ownership.  The ASF licenses this file
8  *    to you under the Apache License, Version 2.0 (the
9  *    "License"); you may not use this file except in compliance
10  *    with the License.  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *    Unless required by applicable law or agreed to in writing,
15  *    software distributed under the License is distributed on an
16  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  *    KIND, either express or implied.  See the License for the
18  *    specific language governing permissions and limitations
19  *    under the License.
20  * ====================================================================
21  * @endcopyright
22  */
23 
24 package org.apache.subversion.javahl;
25 
26 import org.apache.subversion.javahl.types.ExternalItem;
27 import org.apache.subversion.javahl.types.NodeKind;
28 import org.apache.subversion.javahl.types.Revision;
29 
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.FileOutputStream;
33 import java.io.FileWriter;
34 import java.io.ByteArrayInputStream;
35 import java.io.ByteArrayOutputStream;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38 import java.util.Arrays;
39 import java.util.ArrayList;
40 import java.util.Date;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.HashMap;
44 
45 /**
46  * Tests the JavaHL SVNUtil APIs.
47  */
48 public class UtilTests extends SVNTests
49 {
50     private final static String NL = System.getProperty("line.separator");
51 
52     /**
53      * Base name of all our tests.
54      */
55     public final static String testName = "util_test";
56 
UtilTests()57     public UtilTests()
58     {
59         init();
60     }
61 
UtilTests(String name)62     public UtilTests(String name)
63     {
64         super(name);
65         init();
66     }
67 
68     /**
69      * Initialize the testBaseName and the testCounter, if this is the
70      * first test of this class.
71      */
init()72     private void init()
73     {
74         if (!testName.equals(testBaseName))
75         {
76             testCounter = 0;
77             testBaseName = testName;
78         }
79     }
80 
81     private final byte[] fileContentsPrefix = "1\n2\n3\n4\n".getBytes();
82     private final byte[] fileContentsSuffix = "N-3\nN-2\nN-1\nN\n".getBytes();
83 
writeFileContents(File file, String contents)84     private void writeFileContents(File file, String contents) throws Throwable
85     {
86         FileOutputStream out = new FileOutputStream(file);
87         out.write(fileContentsPrefix);
88         out.write(contents.getBytes());
89         out.write(fileContentsSuffix);
90         out.close();
91     }
92 
testFileDiff()93     public void testFileDiff() throws Throwable
94     {
95         File original = File.createTempFile("merge", ".original", localTmp);
96         File modified = File.createTempFile("merge", ".modified", localTmp);
97 
98         writeFileContents(original, "\noriginal\n\n");
99         writeFileContents(modified, "\nmodified\n\n");
100 
101         ByteArrayOutputStream result = new ByteArrayOutputStream();
102         boolean diffs =  SVNUtil.fileDiff(original.getAbsolutePath(),
103                                           modified.getAbsolutePath(),
104                                           null, "original", "modified", "UTF-8",
105                                           null, result);
106         assertTrue(diffs);
107 
108         final byte[] expected = ("--- original" + NL +
109                                  "+++ modified" + NL +
110                                  "@@ -3,7 +3,7 @@" + NL +
111                                  " 3\n 4\n \n" +
112                                  "-original\n" +
113                                  "+modified\n" +
114                                  " \n N-3\n N-2\n").getBytes();
115         assertTrue(Arrays.equals(expected, result.toByteArray()));
116     }
117 
testFileMerge()118     public void testFileMerge() throws Throwable
119     {
120         File original = File.createTempFile("merge", ".original", localTmp);
121         File modified = File.createTempFile("merge", ".modified", localTmp);
122         File latest = File.createTempFile("merge", ".latest", localTmp);
123 
124         writeFileContents(original, "\noriginal\n\n");
125         writeFileContents(modified, "\nmodified\n\n");
126         writeFileContents(latest, "\nlatest\n\n");
127 
128         ByteArrayOutputStream result = new ByteArrayOutputStream();
129         boolean conflicts = SVNUtil.fileMerge(original.getAbsolutePath(),
130                                               modified.getAbsolutePath(),
131                                               latest.getAbsolutePath(),
132                                               null,
133                                               "||||||| base",
134                                               "<<<<<<< branch",
135                                               ">>>>>>> local",
136                                               "=======",
137                                               SVNUtil.ConflictDisplayStyle.modified_original_latest,
138                                               result);
139         assertTrue(conflicts);
140 
141         final byte[] expected = ("1\n2\n3\n4\n\n" +
142                                  "<<<<<<< branch\n" +
143                                  "modified\n" +
144                                  "||||||| base\n" +
145                                  "original\n" +
146                                  "=======\n" +
147                                  "latest\n" +
148                                  ">>>>>>> local\n" +
149                                  "\nN-3\nN-2\nN-1\nN\n").getBytes();
150         assertTrue(Arrays.equals(expected, result.toByteArray()));
151     }
152 
testValidateProp()153     public void testValidateProp() throws Throwable
154     {
155         File temp = File.createTempFile("propcheck", ".file", localTmp);
156         FileOutputStream out = new FileOutputStream(temp);
157         out.write("normal text\n".getBytes());
158         out.close();
159 
160         byte[] prop = SVNUtil.canonicalizeNodeProperty(
161                            "svn:eol-style", "  native".getBytes(),
162                            "propcheck.file", NodeKind.file,
163                            "text/plain");
164         assertEquals("native", new String(prop));
165 
166         prop = SVNUtil.canonicalizeNodeProperty(
167                     "svn:eol-style", " native  ".getBytes(),
168                     "propcheck.file", NodeKind.file,
169                     "text/plain", new FileInputStream(temp));
170         assertEquals("native", new String(prop));
171 
172         boolean caught_exception = false;
173         try {
174             prop = SVNUtil.canonicalizeNodeProperty(
175                         "svn:eol-style", " weird  ".getBytes(),
176                         "propcheck.file", NodeKind.file,
177                         "text/plain");
178         } catch (ClientException ex) {
179             assertEquals("Unrecognized line ending style",
180                          ex.getAllMessages().get(0).getMessage());
181             caught_exception = true;
182         }
183         assertTrue(caught_exception);
184 
185         out = new FileOutputStream(temp);
186         out.write("inconsistent\r\ntext\n".getBytes());
187         out.close();
188 
189         caught_exception = false;
190         try {
191             prop = SVNUtil.canonicalizeNodeProperty(
192                         "svn:eol-style", " native  ".getBytes(),
193                         "propcheck.file", NodeKind.file,
194                         "text/plain", new FileInputStream(temp));
195         } catch (ClientException ex) {
196             assertEquals("Inconsistent line ending style",
197                          ex.getAllMessages().get(2).getMessage());
198             caught_exception = true;
199         }
200         assertTrue(caught_exception);
201     }
202 
203 
204     private static List<ExternalItem> externals = null;
205     static {
206         try {
207             externals = new ArrayList<ExternalItem>(25);
externals.add(new ExternalItem(R, R, null, null))208             externals.add(new ExternalItem("a", "http://server/repo/path",
209                                            null, null));
externals.add(new ExternalItem(R, R, null, null))210             externals.add(new ExternalItem("b", "//server/repo/path",
211                                            null, null));
externals.add(new ExternalItem(R, R, null, null))212             externals.add(new ExternalItem("c", "/repo/path",
213                                            null, null));
externals.add(new ExternalItem(R, R, null, null))214             externals.add(new ExternalItem("d", "^/path",
215                                            null, null));
externals.add(new ExternalItem(R, R, null, null))216             externals.add(new ExternalItem("e", "^/../oper/path",
217                                            null, null));
218 
externals.add(new ExternalItem(R, R, Revision.getInstance(42), null))219             externals.add(new ExternalItem("f", "http://server/repo/path",
220                                            Revision.getInstance(42), null));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), null))221             externals.add(new ExternalItem("g", "//server/repo/path",
222                                            Revision.getInstance(42), null));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), null))223             externals.add(new ExternalItem("h", "/repo/path",
224                                            Revision.getInstance(42), null));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), null))225             externals.add(new ExternalItem("j", "^/path",
226                                            Revision.getInstance(42), null));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), null))227             externals.add(new ExternalItem("j", "^/../oper/path",
228                                            Revision.getInstance(42), null));
229 
externals.add(new ExternalItem(R, R, null, Revision.getInstance(42)))230             externals.add(new ExternalItem("k", "http://server/repo/path",
231                                            null, Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, null, Revision.getInstance(42)))232             externals.add(new ExternalItem("l", "//server/repo/path",
233                                            null, Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, null, Revision.getInstance(42)))234             externals.add(new ExternalItem("m", "/repo/path",
235                                            null, Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, null, Revision.getInstance(42)))236             externals.add(new ExternalItem("n", "^/path",
237                                            null, Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, null, Revision.getInstance(42)))238             externals.add(new ExternalItem("o", "^/../oper/path",
239                                            null, Revision.getInstance(42)));
240 
externals.add(new ExternalItem(R, R, Revision.getInstance(69), Revision.getInstance(71)))241             externals.add(new ExternalItem("p", "http://server/repo/path",
242                                            Revision.getInstance(69),
243                                            Revision.getInstance(71)));
externals.add(new ExternalItem(R, R, Revision.getInstance(69), Revision.getInstance(71)))244             externals.add(new ExternalItem("q", "//server/repo/path",
245                                            Revision.getInstance(69),
246                                            Revision.getInstance(71)));
externals.add(new ExternalItem(R, R, Revision.getInstance(69), Revision.getInstance(71)))247             externals.add(new ExternalItem("r", "/repo/path",
248                                            Revision.getInstance(69),
249                                            Revision.getInstance(71)));
externals.add(new ExternalItem(R, R, Revision.getInstance(69), Revision.getInstance(71)))250             externals.add(new ExternalItem("s", "^/path",
251                                            Revision.getInstance(69),
252                                            Revision.getInstance(71)));
externals.add(new ExternalItem(R, R, Revision.getInstance(69), Revision.getInstance(71)))253             externals.add(new ExternalItem("t", "^/../oper/path",
254                                            Revision.getInstance(69),
255                                            Revision.getInstance(71)));
256 
externals.add(new ExternalItem(R, R, Revision.getInstance(42), Revision.getInstance(42)))257             externals.add(new ExternalItem("u", "http://server/repo/path",
258                                            Revision.getInstance(42),
259                                            Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), Revision.getInstance(42)))260             externals.add(new ExternalItem("v", "//server/repo/path",
261                                            Revision.getInstance(42),
262                                            Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), Revision.getInstance(42)))263             externals.add(new ExternalItem("w", "/repo/path",
264                                            Revision.getInstance(42),
265                                            Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), Revision.getInstance(42)))266             externals.add(new ExternalItem("x", "^/path",
267                                            Revision.getInstance(42),
268                                            Revision.getInstance(42)));
externals.add(new ExternalItem(R, R, Revision.getInstance(42), Revision.getInstance(42)))269             externals.add(new ExternalItem("y", "^/../oper/path",
270                                            Revision.getInstance(42),
271                                            Revision.getInstance(42)));
272         } catch (SubversionException ex) {
273             externals = null;
274             throw new RuntimeException(ex);
275         }
276     }
277 
278     private static final byte[] externals_propval =
279         ("http://server/repo/path a\n" +
280          "//server/repo/path b\n" +
281          "/repo/path c\n" +
282          "^/path d\n" +
283          "^/../oper/path e\n" +
284          "-r42 http://server/repo/path f\n" +
285          "-r42 //server/repo/path g\n" +
286          "-r42 /repo/path h\n" +
287          "-r42 ^/path j\n" +
288          "-r42 ^/../oper/path j\n" +
289          "http://server/repo/path@42 k\n" +
290          "//server/repo/path@42 l\n" +
291          "/repo/path@42 m\n" +
292          "^/path@42 n\n" +
293          "^/../oper/path@42 o\n" +
294          "-r69 http://server/repo/path@71 p\n" +
295          "-r69 //server/repo/path@71 q\n" +
296          "-r69 /repo/path@71 r\n" +
297          "-r69 ^/path@71 s\n" +
298          "-r69 ^/../oper/path@71 t\n" +
299          "http://server/repo/path@42 u\n" +
300          "//server/repo/path@42 v\n" +
301          "/repo/path@42 w\n" +
302          "^/path@42 x\n" +
303          "^/../oper/path@42 y\n").getBytes();
304 
305     private static List<ExternalItem> old_externals = null;
306     static {
307         try {
308             old_externals = new ArrayList<ExternalItem>(3);
old_externals.add(new ExternalItem(R, R, null, null))309             old_externals.add(new ExternalItem("X", "http://server/repo/path",
310                                                null, null));
old_externals.add(new ExternalItem(R, R, null, Revision.getInstance(42)))311             old_externals.add(new ExternalItem("Y", "http://server/repo/path",
312                                                null, Revision.getInstance(42)));
313 
old_externals.add(new ExternalItem(R, R, null, Revision.getInstance(new Date(0L))))314             old_externals.add(new ExternalItem("Z", "http://server/repo/path",
315                                                null, Revision.getInstance(new Date(0L))));
316         } catch (SubversionException ex) {
317             old_externals = null;
318             throw new RuntimeException(ex);
319         }
320     }
321 
322     private static final byte[] old_externals_propval =
323         ("X http://server/repo/path\n" +
324          "Y -r42 http://server/repo/path\n" +
325          "Z -r{1970-01-01T00:00:00.000000Z} http://server/repo/path\n").getBytes();
326 
compare_item_lists(List<ExternalItem> a, List<ExternalItem> b, String list_name)327     private static void compare_item_lists(List<ExternalItem> a,
328                                            List<ExternalItem> b,
329                                            String list_name)
330     {
331         final int length = a.size();
332         assertEquals(length, b.size());
333         for (int i = 0; i < length; ++i)
334             assertTrue("Items in " + list_name + " at index " + i + " differ",
335                        a.get(i).equals(b.get(i)));
336     }
337 
testParseExternals()338     public void testParseExternals() throws Throwable
339     {
340         List<ExternalItem> items;
341 
342         items = SVNUtil.parseExternals(externals_propval, "dirname", false);
343         compare_item_lists(items, externals, "externals");
344 
345         items = SVNUtil.parseExternals(old_externals_propval, "dirname", false);
346         compare_item_lists(items, old_externals, "old_externals");
347     }
348 
testUnparseExternals()349     public void testUnparseExternals() throws Throwable
350     {
351         byte[] props = SVNUtil.unparseExternals(externals, "dirname");
352         assertTrue(Arrays.equals(externals_propval, props));
353     }
354 
testUnparseExternalsOldstyle()355     public void testUnparseExternalsOldstyle() throws Throwable
356     {
357         byte[] props;
358 
359         props = SVNUtil.unparseExternalsForAncientUnsupportedClients(
360                      old_externals, "dirname");
361         assertTrue(Arrays.equals(old_externals_propval, props));
362 
363         // The fancy new features are not supported in the old format
364         boolean caught_exception = false;
365         try {
366             props = SVNUtil.unparseExternalsForAncientUnsupportedClients(
367                          externals, "dirname");
368         } catch (SubversionException ex) {
369             caught_exception = true;
370         }
371         assertTrue(caught_exception);
372     }
373 
testResolveExternalsUrl()374     public void testResolveExternalsUrl() throws Throwable
375     {
376         assertEquals("http://a/b/c",
377                      SVNUtil.resolveExternalsUrl(
378                          new ExternalItem("x", "http://a/b/c/", null, null),
379                          "http://a", "http://a/b"));
380 
381         assertEquals("http://a/b/c",
382                      SVNUtil.resolveExternalsUrl(
383                          new ExternalItem("x", "^/b/c", null, null),
384                          "http://a", "http://a/b"));
385 
386         assertEquals("http://a/b/c",
387                      SVNUtil.resolveExternalsUrl(
388                          new ExternalItem("x", "../b/c", null, null),
389                          "http://a", "http://a/b"));
390 
391         assertEquals("http://a/b/c",
392                      SVNUtil.resolveExternalsUrl(
393                          new ExternalItem("x", "/b/c", null, null),
394                          "http://a", "http://a/b"));
395 
396         assertEquals("http://a/b/c",
397                      SVNUtil.resolveExternalsUrl(
398                          new ExternalItem("x", "//a/b/c", null, null),
399                          "http://a", "http://a/b"));
400     }
401 
testBuildKeywords()402     public void testBuildKeywords() throws Throwable
403     {
404         final byte[] kwval = "Id TEST=%H%_%b%_%u".getBytes();
405 
406         Map<String, byte[]> result;
407 
408         result = SVNUtil.buildKeywords(kwval, Revision.SVN_INVALID_REVNUM,
409                                        null, null, null, null);
410         assertEquals("   ", new String(result.get("Id")));
411         assertEquals("     ", new String(result.get("TEST")));
412 
413         result = SVNUtil.buildKeywords(kwval, 42, "http://a/b/c",
414                                        "http://a", new Date(1), "X");
415         assertEquals("c 42 1970-01-01 00:00:00Z X",
416                      new String(result.get("Id")));
417         assertEquals("b/c 42 1970-01-01 00:00:00Z X c http://a/b/c",
418                      new String(result.get("TEST")));
419     }
420 
testTranslateStream()421     public void testTranslateStream() throws Throwable
422     {
423         final byte[] keywordsValue = "Id TEST=%H%_%b%_%u".getBytes();
424         final byte[] contentsContracted = "$Id$\n$TEST$\n".getBytes();
425         final byte[] contentsExpanded =
426             ("$Id: c 42 1970-01-01 00:00:00Z X $\r" +
427              "$TEST: b/c 42 1970-01-01 00:00:00Z X c http://a/b/c $\r"
428              ) .getBytes();
429         final Map<String, byte[]> keywords =
430             SVNUtil.buildKeywords(keywordsValue, 42, "http://a/b/c",
431                                   "http://a", new Date(1), "X");
432         final Map<String, byte[]> null_keywords = new HashMap<String, byte[]>();
433         byte[] buffer = new byte[1024];
434 
435         for (Map.Entry<String, byte[]> e : keywords.entrySet())
436             null_keywords.put(e.getKey(), null);
437 
438         // InputStream; expand
439         InputStream testin = null;
440         try {
441             testin = SVNUtil.translateStream(
442                          new ByteArrayInputStream(contentsContracted),
443                          SVNUtil.EOL_CR, true, keywords, true);
444             final int size = testin.read(buffer);
445             testin.close();
446             testin = null;
447 
448             assertEquals("expand InputStream with concrete keywords",
449                          new String(contentsExpanded),
450                          new String(buffer, 0, size));
451         } finally {
452             if (testin != null) {
453                 testin.close();
454                 testin = null;
455             }
456         }
457 
458         try {
459             testin = SVNUtil.translateStream(
460                          new ByteArrayInputStream(contentsContracted),
461                          SVNUtil.EOL_CR, true, true,
462                          keywordsValue, 42, "http://a/b/c",
463                          "http://a", new Date(1), "X");
464             final int size = testin.read(buffer);
465             testin.close();
466             testin = null;
467 
468             assertEquals("expand InputStream with implied keywords",
469                          new String(contentsExpanded),
470                          new String(buffer, 0, size));
471         } finally {
472             if (testin != null) {
473                 testin.close();
474                 testin = null;
475             }
476         }
477 
478         // InputStream; contract
479         try {
480             testin = SVNUtil.translateStream(
481                          new ByteArrayInputStream(contentsExpanded),
482                          SVNUtil.EOL_LF, true, null_keywords, false);
483             final int size = testin.read(buffer);
484             testin.close();
485             testin = null;
486 
487             assertEquals("contract InputStream with concrete keywords",
488                          new String(contentsContracted),
489                          new String(buffer, 0, size));
490         } finally {
491             if (testin != null) {
492                 testin.close();
493                 testin = null;
494             }
495         }
496 
497         try {
498             testin = SVNUtil.translateStream(
499                          new ByteArrayInputStream(contentsExpanded),
500                          SVNUtil.EOL_LF, true, false,
501                          keywordsValue, 0, "", "", new Date(1), "");
502             final int size = testin.read(buffer);
503             testin.close();
504             testin = null;
505 
506             assertEquals("contract InputStream with implied keywords",
507                          new String(contentsContracted),
508                          new String(buffer, 0, size));
509         } finally {
510             if (testin != null) {
511                 testin.close();
512                 testin = null;
513             }
514         }
515 
516 
517         // OutputStream; expand
518         OutputStream testout = null;
519         try {
520             ByteArrayOutputStream result = new ByteArrayOutputStream();
521             testout = SVNUtil.translateStream(
522                          result, SVNUtil.EOL_CR, true, keywords, true);
523             testout.write(contentsContracted);
524             testout.close();
525             testout = null;
526 
527             assertEquals("expand OutputStream with concrete keywords",
528                          new String(contentsExpanded), result.toString());
529         } finally {
530             if (testout != null) {
531                 testout.close();
532                 testout = null;
533             }
534         }
535 
536         try {
537             ByteArrayOutputStream result = new ByteArrayOutputStream();
538             testout = SVNUtil.translateStream(
539                          result, SVNUtil.EOL_CR, true, true,
540                          keywordsValue, 42, "http://a/b/c",
541                          "http://a", new Date(1), "X");
542             testout.write(contentsContracted);
543             testout.close();
544             testout = null;
545 
546             assertEquals("expand OutputStream with implied keywords",
547                          new String(contentsExpanded), result.toString());
548         } finally {
549             if (testout != null) {
550                 testout.close();
551                 testout = null;
552             }
553         }
554 
555         // OutputStream; contract
556         try {
557             ByteArrayOutputStream result = new ByteArrayOutputStream();
558             testout = SVNUtil.translateStream(
559                          result, SVNUtil.EOL_LF, true, null_keywords, false);
560             testout.write(contentsExpanded);
561             testout.close();
562             testout = null;
563 
564             assertEquals("contract OutputStream with concrete keywords",
565                          new String(contentsContracted), result.toString());
566         } finally {
567             if (testout != null) {
568                 testout.close();
569                 testout = null;
570             }
571         }
572 
573         try {
574             ByteArrayOutputStream result = new ByteArrayOutputStream();
575             testout = SVNUtil.translateStream(
576                          result, SVNUtil.EOL_LF, true, false,
577                          keywordsValue, 0, "", "", new Date(1), "");
578             testout.write(contentsExpanded);
579             testout.close();
580             testout = null;
581 
582             assertEquals("contract OutputStream with implied keywords",
583                          new String(contentsContracted), result.toString());
584         } finally {
585             if (testout != null) {
586                 testout.close();
587                 testout = null;
588             }
589         }
590     }
591 
592 
593     // Credentials definitions for testing the credentials utilities
594     private static final String util_cred_hash =
595         "4d7de6b1e103fbfc5e61565223ca23be";
596 
597     private static final String util_cred_username =
598         "K 8\n" +
599         "username\n" +
600         "V 5\n" +
601         "mungo\n" +
602         "K 15\n" +
603         "svn:realmstring\n" +
604         "V 27\n" +
605         "https://svn.example.com:443\n" +
606         "END\n";
607 
608     private static final String util_cred_simple =
609         "K 8\n" +
610         "passtype\n" +
611         "V 10\n" +
612         "javahltest\n" +
613         "K 8\n" +
614         "username\n" +
615         "V 5\n" +
616         "mungo\n" +
617         "K 8\n" +
618         "password\n" +
619         "V 6\n" +
620         "secret\n" +
621         "K 15\n" +
622         "svn:realmstring\n" +
623         "V 27\n" +
624         "https://svn.example.com:443\n" +
625         "END\n";
626 
627     private static final String util_cred_ssl_server =
628         "K 10\n" +
629         "ascii_cert\n" +
630         "V 1616\n" +
631         "MIIEtzCCA5+gAwIBAgIQWGBOrapkezd+BWVsAtmtmTANBgkqhkiG9w0BAQsFADA8" +
632         "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMVGhhd3RlLCBJbmMuMRYwFAYDVQQDEw1U" +
633         "aGF3dGUgU1NMIENBMB4XDTE0MDQxMTAwMDAwMFoXDTE2MDQwNzIzNTk1OVowgYsx" +
634         "CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxQLRm9yZXN0" +
635         "IEhpbGwxIzAhBgNVBAoUGkFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRcwFQYD" +
636         "VQQLFA5JbmZyYXN0cnVjdHVyZTEVMBMGA1UEAxQMKi5hcGFjaGUub3JnMIIBIjAN" +
637         "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Tq4mH+stRoxe4xth8tUCgLt+P4L" +
638         "D/JWZz4a2IecaaAk57vIlTxEyP16fUShUfxVJnD0KV11zv2qaEUXNaA6hKd4H/oB" +
639         "u2OyGev+quRM+aFCjWqASkXt7fLGsIkHAwP3XwBVBpARbcXJeCjCBxqaYrQqS8LT" +
640         "wfPUD9eYncGlQ+ixb3Bosy7TmkWKeLsRdS90cAO/rdgQ8OI7kLT/1tr5GpF9RmXo" +
641         "RnVqMP+U0zGd/BNNSneg7emb7TxLzxeMKZ7QbF4MZi8RRN11spvx8/f92CiYrGGu" +
642         "y67VdOGPaomYc+VZ2syLwduHGK40ADrEK3+MQpsRFB0dM08j9bhpr5A44wIDAQAB" +
643         "o4IBYzCCAV8wFwYDVR0RBBAwDoIMKi5hcGFjaGUub3JnMAkGA1UdEwQCMAAwQgYD" +
644         "VR0gBDswOTA3BgpghkgBhvhFAQc2MCkwJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3" +
645         "LnRoYXd0ZS5jb20vY3BzLzAOBgNVHQ8BAf8EBAMCBaAwHwYDVR0jBBgwFoAUp6KD" +
646         "uzRFQD381TBPErk+oQGf9tswOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL3N2ci1v" +
647         "di1jcmwudGhhd3RlLmNvbS9UaGF3dGVPVi5jcmwwHQYDVR0lBBYwFAYIKwYBBQUH" +
648         "AwEGCCsGAQUFBwMCMGkGCCsGAQUFBwEBBF0wWzAiBggrBgEFBQcwAYYWaHR0cDov" +
649         "L29jc3AudGhhd3RlLmNvbTA1BggrBgEFBQcwAoYpaHR0cDovL3N2ci1vdi1haWEu" +
650         "dGhhd3RlLmNvbS9UaGF3dGVPVi5jZXIwDQYJKoZIhvcNAQELBQADggEBAF52BLvl" +
651         "x5or9/aO7+cPhxuPxwiNRgbvHdCakD7n8vzjNyct9fKp6/XxB6GQiTZ0nZPJOyIu" +
652         "Pi1QDLKOXvaPeLKDBilL/+mrn/ev3s/aRQSrUsieKDoQnqtmlxEHc/T3+Ni/RZob" +
653         "PD4GzPuNKpK3BIc0fk/95T8R1DjBSQ5/clvkzOKtcl3VffAwnHiE9TZx9js7kZwO" +
654         "b9nOKX8DFao3EpQcS7qn63Ibzbq5A6ry8ZNRQSIJK/xlCAWoyUd1uxnqGFnus8wb" +
655         "9RVZJQe8YvyytBjgbE3QjnfPOxoEJA3twupnPmH+OCTM6V3TZqpRZj/sZ5rtIQ++" +
656         "hI5FdJWUWVSgnSw=\n" +
657         "K 8\n" +
658         "failures\n" +
659         "V 1\n" +
660         "8\n" +
661         "K 15\n" +
662         "svn:realmstring\n" +
663         "V 26\n" +
664         "https://svn.apache.org:443\n" +
665         "END\n";
666 
667     private static final String util_cred_ssl_client_passphrase =
668         "K 8\n" +
669         "passtype\n" +
670         "V 10\n" +
671         "javahltest\n" +
672         "K 10\n" +
673         "passphrase\n" +
674         "V 24\n" +
675         "secret with spaces in it\n" +
676         "K 15\n" +
677         "svn:realmstring\n" +
678         "V 27\n" +
679         "https://svn.example.com:443\n" +
680         "END\n";
681 
682     // Initialize credentials used for testing credentials utilities
initCredentials()683     private void initCredentials() throws Throwable
684     {
685         File auth = new File(this.conf, "auth");
686         if (auth.exists())
687             removeDirOrFile(auth);
688         auth.mkdirs();
689 
690         File store = new File(auth, "svn.username");
691         store.mkdir();
692         FileWriter cred = new FileWriter(new File(store, util_cred_hash));
693         cred.write(util_cred_username);
694         cred.close();
695 
696         store = new File(auth, "svn.simple");
697         store.mkdir();
698         cred = new FileWriter(new File(store, util_cred_hash));
699         cred.write(util_cred_simple);
700         cred.close();
701 
702         store = new File(auth, "svn.ssl.server");
703         store.mkdir();
704         cred = new FileWriter(new File(store, util_cred_hash));
705         cred.write(util_cred_ssl_server);
706         cred.close();
707 
708         store = new File(auth, "svn.ssl.client-passphrase");
709         store.mkdir();
710         cred = new FileWriter(new File(store, util_cred_hash));
711         cred.write(util_cred_ssl_client_passphrase);
712         cred.close();
713     }
714 
715     /**
716      * Test credentials search.
717      */
testCredentials()718     public void testCredentials() throws Throwable
719     {
720         initCredentials();
721 
722         final String configDir = this.conf.getAbsolutePath();
723         SVNUtil.Credential cred;
724         List<SVNUtil.Credential> creds;
725 
726         /* one username credential */
727         cred = SVNUtil.getCredential(configDir,
728                                      SVNUtil.Credential.Kind.username,
729                                      "https://svn.example.com:443");
730         assertNotNull(cred);
731         assertEquals(cred.getUsername(), "mungo");
732 
733         /* one simple credential */
734         cred = SVNUtil.getCredential(configDir,
735                                      SVNUtil.Credential.Kind.simple,
736                                      "https://svn.example.com:443");
737         assertNotNull(cred);
738         assertEquals(cred.getUsername(), "mungo");
739         assertEquals(cred.getPassword(), "secret");
740         assertEquals(cred.getSecureStore(), "javahltest");
741 
742         /* one SSL server trust credential */
743         cred = SVNUtil.getCredential(configDir,
744                                      SVNUtil.Credential.Kind.sslServer,
745                                      "https://svn.apache.org:443");
746         assertNotNull(cred);
747         assertEquals(cred.getServerCertInfo().getSubject(),
748                      "C=US, ST=Maryland, L=Forest Hill, " +
749                      "O=Apache Software Foundation, OU=Infrastructure, " +
750                      "CN=*.apache.org");
751 
752         /* one SSL client passphrase credential */
753         cred = SVNUtil.getCredential(configDir,
754                                      SVNUtil.Credential.Kind.sslClientPassphrase,
755                                      "https://svn.example.com:443");
756         assertNotNull(cred);
757         assertEquals(cred.getClientCertPassphrase(), "secret with spaces in it");
758         assertEquals(cred.getSecureStore(), "javahltest");
759 
760         /* search with no parameters (empty return) */
761         creds = SVNUtil.searchCredentials(configDir, null,
762                                           null, null, null, null);
763         assertNull(creds);
764 
765         /* search with unmatched parameters */
766         creds = SVNUtil.searchCredentials(configDir,
767                                           SVNUtil.Credential.Kind.sslServer,
768                                           null, null, null, "*java*");
769         assertNull(creds);
770 
771         /* search with unmatched parameters */
772         creds = SVNUtil.searchCredentials(configDir, null,
773                                           null, "*java*", null, null);
774         assertNull(creds);
775 
776         /* search with match on kind */
777         creds = SVNUtil.searchCredentials(configDir,
778                                           SVNUtil.Credential.Kind.sslServer,
779                                           "*", null, null, null);
780         assertNotNull(creds);
781         assertEquals(creds.size(), 1);
782 
783         /* search with match on passtype */
784         creds = SVNUtil.searchCredentials(configDir, null,
785                                           null, null, null, "*java*");
786         assertNotNull(creds);
787         assertEquals(creds.size(), 2);
788 
789         /* search with match on username */
790         creds = SVNUtil.searchCredentials(configDir, null,
791                                           null, "mungo", null, null);
792         assertNotNull(creds);
793         assertEquals(creds.size(), 2);
794 
795         /* search with match on subvject */
796         creds = SVNUtil.searchCredentials(configDir, null,
797                                           null, null, "\\*.apache.org", null);
798         assertNotNull(creds);
799         assertEquals(creds.size(), 1);
800 
801         /* search with match on realm */
802         creds = SVNUtil.searchCredentials(configDir, null,
803                                           "*example*", null, null, null);
804         assertNotNull(creds);
805         assertEquals(creds.size(), 3);
806     }
807 }
808