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 package org.apache.subversion.javahl;
24 
25 import org.apache.subversion.javahl.callback.*;
26 import org.apache.subversion.javahl.types.*;
27 
28 import java.io.File;
29 import java.io.FileOutputStream;
30 import java.io.FileNotFoundException;
31 import java.io.FileReader;
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.io.ByteArrayOutputStream;
35 import java.io.UnsupportedEncodingException;
36 import java.nio.ByteBuffer;
37 import java.nio.channels.ReadableByteChannel;
38 import java.nio.channels.WritableByteChannel;
39 import java.text.ParseException;
40 import java.util.Collection;
41 import java.util.Arrays;
42 import java.util.ArrayList;
43 import java.util.Date;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Set;
48 import java.util.Map;
49 import java.text.DateFormat;
50 import java.text.SimpleDateFormat;
51 
52 
53 /**
54  * Tests the basic functionality of javahl binding (inspired by the
55  * tests in subversion/tests/cmdline/basic_tests.py).
56  */
57 public class ExceptionTests extends SVNTests
58 {
59     /**
60      * Base name of all our tests.
61      */
62     public final static String testName = "exception_test";
63 
ExceptionTests()64     public ExceptionTests()
65     {
66         init();
67     }
68 
ExceptionTests(String name)69     public ExceptionTests(String name)
70     {
71         super(name);
72         init();
73     }
74 
75     /**
76      * Initialize the testBaseName and the testCounter, if this is the
77      * first test of this class.
78      */
init()79     private void init()
80     {
81         if (!testName.equals(testBaseName))
82         {
83             testCounter = 0;
84             testBaseName = testName;
85         }
86     }
87 
88     /**
89      * Specific exception class to verify if the marshalling of errors
90      * through Subversion is handled properly.
91      */
92     final class TestException extends RuntimeException
93     {
94         private static final long serialVersionUID = 1L;
95 
TestException(String message)96         public TestException(String message)
97         {
98             super(message);
99         }
100 
TestException(String message, Throwable cause)101         public TestException(String message, Throwable cause)
102         {
103             super(message, cause);
104         }
105     }
106 
testStatusCallback()107     public void testStatusCallback() throws Exception
108     {
109         // build the test setup
110         OneTest thisTest = new OneTest();
111 
112         final TestException theException = new TestException("The Exception");
113         boolean handled = false;
114         // Test status of non-existent file
115         try
116         {
117             client.status(thisTest.getWorkingCopy() + "/A", Depth.immediates,
118                           false, true, true, false, false, false, null,
119                           new StatusCallback()
120                           {
121                             public void doStatus(String path, Status status)
122                             {
123                                 throw new TestException("inner", theException);
124                             }
125                           });
126         }
127         catch (ClientException e)
128         {
129             if (VerifyCause(e, theException))
130                 handled = true;
131             else
132                 throw e;
133         }
134         assertTrue(handled);
135     }
136 
testInfoCallback()137     public void testInfoCallback() throws Exception
138     {
139         // build the test setup
140         OneTest thisTest = new OneTest();
141 
142         final TestException theException = new TestException("The Exception");
143         boolean handled = false;
144         // Test status of non-existent file
145         try
146         {
147             client.info(thisTest.getWorkingCopy() + "/A", null, null, Depth.immediates,
148                         true, true, false, null,
149                           new InfoCallback()
150                           {
151                             public void singleInfo(Info info)
152                             {
153                                 throw new TestException("inner", theException);
154                             }
155                           });
156         }
157         catch (ClientException e)
158         {
159             if (VerifyCause(e, theException))
160                 handled = true;
161             else
162                 throw e;
163         }
164         assertTrue(handled);
165     }
166 
testListCallback()167     public void testListCallback() throws Exception
168     {
169         // build the test setup
170         OneTest thisTest = new OneTest();
171 
172         final TestException theException = new TestException("The Exception");
173         boolean handled = false;
174         // Test status of non-existent file
175         try
176         {
177             client.list(thisTest.getWorkingCopy() + "/A", null, null, Depth.immediates,
178                         7, false,
179                         new ListCallback()
180                           {
181                             public void doEntry(DirEntry dirent, Lock lock)
182                             {
183                                 throw new TestException("inner", theException);
184                             }
185                           });
186         }
187         catch (ClientException e)
188         {
189             if (VerifyCause(e, theException))
190                 handled = true;
191             else
192                 throw e;
193         }
194         assertTrue(handled);
195     }
196 
testBlameCallback()197     public void testBlameCallback() throws Exception
198     {
199         // build the test setup
200         OneTest thisTest = new OneTest();
201 
202         final TestException theException = new TestException("The Exception");
203         boolean handled = false;
204         // Test status of non-existent file
205         try
206         {
207             client.blame(thisTest.getWorkingCopy() + "/iota",
208                          Revision.getInstance(1), Revision.getInstance(1),
209                          Revision.getInstance(1), false, false, null, null,
210                          new BlameLineCallback() {
211                              public void singleLine(long lineNum, long revision,
212                                                     Map<String, byte[]> revProps, long mergedRevision,
213                                                     Map<String, byte[]> mergedRevProps,
214                                                     String mergedPath, boolean localChange,
215                                                     byte[] line)
216                              {
217                                  throw new TestException("inner", theException);
218                              }
219                          });
220         }
221         catch (ClientException e)
222         {
223             if (VerifyCause(e, theException))
224                 handled = true;
225             else
226                 throw e;
227         }
228         assertTrue(handled);
229     }
230 
testLogMessageCallback()231     public void testLogMessageCallback() throws Exception
232     {
233         // build the test setup
234         OneTest thisTest = new OneTest();
235 
236         final TestException theException = new TestException("The Exception");
237         boolean handled = false;
238         // Test status of non-existent file
239         try
240         {
241             List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
242             ranges.add(new RevisionRange(null, null));
243             // Testing variant with allRevProps = false
244             client.logMessages(thisTest.getWorkingCopy() + "/iota",
245                                Revision.getInstance(1), ranges,
246                                false, false, false,
247                                null, false, 2,
248                                new LogMessageCallback()
249                                {
250                                     public void singleMessage(
251                                                   Set<ChangePath> changedPaths,
252                                                   long revision,
253                                                   Map<String, byte[]> revprops,
254                                                   boolean hasChildren)
255                                     {
256                                         throw new TestException("inner",
257                                                                 theException);
258                                     }
259                                });
260         }
261         catch (ClientException e)
262         {
263             if (VerifyCause(e, theException))
264                 handled = true;
265             else
266                 throw e;
267         }
268         assertTrue(handled);
269     }
270 
testDiffSummaryReceiver()271     public void testDiffSummaryReceiver() throws Exception
272     {
273         // build the test setup
274         OneTest thisTest = new OneTest();
275 
276         final TestException theException = new TestException("The Exception");
277         boolean handled = false;
278         // Test status of non-existent file
279         try
280         {
281             List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
282             ranges.add(new RevisionRange(null, null));
283             client.diffSummarize(thisTest.getUrl() + "/A",
284                                  Revision.getInstance(1),
285                                  thisTest.getUrl() + "/A",
286                                  Revision.getInstance(0),
287                                  Depth.infinity, null, true,
288                                  new DiffSummaryCallback()
289                                  {
290                                     public void onSummary(
291                                                   DiffSummary descriptor)
292                                     {
293                                         throw new TestException("inner",
294                                                                 theException);
295                                     }
296                                });
297         }
298         catch (ClientException e)
299         {
300             if (VerifyCause(e, theException))
301                 handled = true;
302             else
303                 throw e;
304         }
305         assertTrue(handled);
306     }
307 
testNotify()308     public void testNotify() throws Exception
309     {
310         // build the test setup
311         OneTest thisTest = new OneTest();
312 
313         final TestException theException = new TestException("The Exception");
314         boolean handled = false;
315         // Test status of non-existent file
316         try
317         {
318             client.notification2(new ClientNotifyCallback()
319                                  {
320                                     public void onNotify(ClientNotifyInformation info)
321                                     {
322                                         throw new TestException("inner",
323                                                                 theException);
324                                     }
325                                 });
326 
327             client.remove(thisTest.getWCPathSet("/A"), false, false,
328                           null, null, null);
329         }
330         catch (ClientException e)
331         {
332             if (VerifyCause(e, theException))
333                 handled = true;
334             else
335                 throw e;
336         }
337         assertTrue(handled);
338     }
339 
340     /**
341      * Verifies if a specific throwable instance is recorded in the exception chain
342      */
VerifyCause(Throwable caught, Throwable needle)343     private boolean VerifyCause(Throwable caught, Throwable needle)
344     {
345         if (caught == needle)
346             return true;
347 
348         Throwable cause = caught.getCause();
349         if (cause == null)
350             return false;
351 
352         return VerifyCause(cause, needle);
353     }
354 }
355