SVN: svn authentication test to work on Unix as well (different defaults on different...
[idea/community.git] / plugins / svn4idea / testSource / org / jetbrains / idea / svn / SvnAuthenticationTest.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.idea.svn;
17
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.util.Pair;
20 import com.intellij.openapi.util.SystemInfo;
21 import com.intellij.openapi.util.Trinity;
22 import com.intellij.openapi.util.io.FileUtil;
23 import com.intellij.testFramework.PlatformTestCase;
24 import com.intellij.util.concurrency.Semaphore;
25 import junit.framework.Assert;
26 import org.jetbrains.idea.svn.auth.ProviderType;
27 import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction;
28 import org.jetbrains.idea.svn.auth.SvnAuthenticationListener;
29 import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider;
30 import org.tmatesoft.svn.core.SVNErrorMessage;
31 import org.tmatesoft.svn.core.SVNException;
32 import org.tmatesoft.svn.core.SVNURL;
33 import org.tmatesoft.svn.core.auth.*;
34 import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
35 import org.tmatesoft.svn.core.internal.wc.SVNConfigFile;
36
37 import java.io.File;
38 import java.util.ArrayList;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Set;
42
43 public class SvnAuthenticationTest extends PlatformTestCase {
44   private SvnAuthenticationManager myAuthenticationManager;
45   private TestInteraction myTestInteraction;
46   private SvnVcs myVcs;
47   private final Object mySynchObject = new Object();
48   private SvnTestInteractiveAuthentication myInteractiveProvider;
49   private SvnConfiguration myConfiguration;
50
51   @Override
52   protected void setUp() throws Exception {
53     super.setUp();
54
55     myConfiguration = SvnConfiguration.getInstance(myProject);
56     final String configPath = myProject.getBaseDir().getPath() + File.separator + "Subversion";
57     myConfiguration.setConfigurationDirectory(configPath);
58
59     final File configFile = new File(configPath);
60     myFilesToDelete.add(configFile);
61
62     myVcs = SvnVcs.getInstance(myProject);
63
64     myAuthenticationManager = new SvnAuthenticationManager(myProject, configFile);
65
66     myInteractiveProvider = new SvnTestInteractiveAuthentication(myAuthenticationManager);
67     myAuthenticationManager.setAuthenticationProvider(new SvnAuthenticationProvider(myVcs, myInteractiveProvider));
68     myAuthenticationManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE);
69
70     myTestInteraction = new TestInteraction();
71     myAuthenticationManager.setInteraction(myTestInteraction);
72
73     SVNConfigFile.createDefaultConfiguration(configFile);
74   }
75
76   @Override
77   protected void tearDown() throws Exception {
78     super.tearDown();
79     FileUtil.delete(new File(myConfiguration.getConfigurationDirectory()));
80   }
81
82   public void testSavedAndRead() throws Exception {
83     final TestListener listener = new TestListener(mySynchObject);
84     myAuthenticationManager.addListener(listener);
85     final SavedOnceListener savedOnceListener = new SavedOnceListener();
86     myAuthenticationManager.addListener(savedOnceListener);
87
88     final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
89
90     final SVNException[] exception = new SVNException[1];
91     final Boolean[] result = new Boolean[1];
92     synchronousBackground(new Runnable() {
93       @Override
94       public void run() {
95         try {
96
97           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
98           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
99           if (SystemInfo.isWindows) {
100             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.save));
101           } else {
102             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
103           }
104
105           commonScheme(url, false, null);
106           Assert.assertEquals(3, listener.getCnt());
107           //long start = System.currentTimeMillis();
108           //waitListenerStep(start, listener, 3);
109
110           listener.reset();
111           SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
112           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
113           if (! SystemInfo.isWindows) {
114             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
115             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
116           }
117           commonScheme(url, false, null);
118           //start = System.currentTimeMillis();
119           //waitListenerStep(start, listener, 4);
120           Assert.assertEquals((SystemInfo.isWindows ? 1 : 3), listener.getCnt());
121         }
122         catch (SVNException e) {
123           exception[0] = e;
124         }
125         result[0] = true;
126       }
127     });
128
129     Assert.assertTrue(result[0]);
130     Assert.assertEquals(SystemInfo.isWindows ? 0 : 2, myTestInteraction.getNumPlaintextPrompt());
131     Assert.assertEquals(0, myTestInteraction.getNumAuthWarn());
132     Assert.assertEquals(0, myTestInteraction.getNumPasswordsWarn());
133     Assert.assertEquals(0, myTestInteraction.getNumSSLPlaintextPrompt());
134     Assert.assertEquals(0, myTestInteraction.getNumSSLWarn());
135     Assert.assertEquals((SystemInfo.isWindows ? 1 : 3), listener.getCnt());
136     listener.assertForAwt();
137     savedOnceListener.assertForAwt();
138
139     savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
140
141     if (exception[0] != null) {
142       throw exception[0];
143     }
144   }
145
146   public void testSavedAndReadUnix() throws Exception {
147     if (SystemInfo.isWindows) return;
148
149     final TestListener listener = new TestListener(mySynchObject);
150     myAuthenticationManager.addListener(listener);
151     final SavedOnceListener savedOnceListener = new SavedOnceListener();
152     myAuthenticationManager.addListener(savedOnceListener);
153
154     final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
155
156     final SVNException[] exception = new SVNException[1];
157     final Boolean[] result = new Boolean[1];
158
159     final File servers = new File(myConfiguration.getConfigurationDirectory(), "servers");
160     final File oldServers = new File(myConfiguration.getConfigurationDirectory(), "config_old");
161     FileUtil.copy(servers, oldServers);
162     try {
163       FileUtil.appendToFile(servers, "\nstore-plaintext-passwords=yes\n");
164
165       synchronousBackground(new Runnable() {
166         @Override
167         public void run() {
168           try {
169             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
170             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
171             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.save));
172
173             commonScheme(url, false, null);
174             Assert.assertEquals(3, listener.getCnt());
175             //long start = System.currentTimeMillis();
176             //waitListenerStep(start, listener, 3);
177
178             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
179             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
180             commonScheme(url, false, null);
181             //start = System.currentTimeMillis();
182             //waitListenerStep(start, listener, 4);
183             Assert.assertEquals(4, listener.getCnt());
184           }
185           catch (SVNException e) {
186             exception[0] = e;
187           }
188           result[0] = true;
189         }
190       });
191     } finally {
192       FileUtil.delete(servers);
193       FileUtil.rename(oldServers, servers);
194     }
195
196     Assert.assertTrue(result[0]);
197     myTestInteraction.assertNothing();
198     Assert.assertEquals(4, listener.getCnt());
199     listener.assertForAwt();
200     savedOnceListener.assertForAwt();
201
202     savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
203
204     if (exception[0] != null) {
205       throw exception[0];
206     }
207   }
208
209   private void waitListenerStep(long start, TestListener listener, final int stepNoNext) {
210     while ((listener.getCnt() < stepNoNext) && ((System.currentTimeMillis() - start) < 10000)) {
211       synchronized (mySynchObject) {
212         try {
213           mySynchObject.wait(50);
214         }
215         catch (InterruptedException e) {
216           //
217         }
218       }
219     }
220     Assert.assertEquals(stepNoNext, listener.getCnt());
221   }
222
223   public void testWhenNotSaved() throws Exception {
224     final TestListener listener = new TestListener(mySynchObject);
225     myAuthenticationManager.addListener(listener);
226     final SavedOnceListener savedOnceListener = new SavedOnceListener();
227     myAuthenticationManager.addListener(savedOnceListener);
228
229     myInteractiveProvider.setSaveData(false);
230
231     final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
232
233     final SVNException[] exception = new SVNException[1];
234     final Boolean[] result = new Boolean[1];
235     synchronousBackground(new Runnable() {
236       @Override
237       public void run() {
238         try {
239           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
240           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
241
242           commonScheme(url, false, null);
243           //long start = System.currentTimeMillis();
244           //waitListenerStep(start, listener, 2);
245           Assert.assertEquals(2, listener.getCnt());
246
247           savedOnceListener.assertNotSaved(url, ISVNAuthenticationManager.PASSWORD);
248           // cause is not cleared though
249           savedOnceListener.reset();
250
251           SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
252           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
253           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
254           commonScheme(url, false, null);
255           Assert.assertEquals(4, listener.getCnt());
256           //start = System.currentTimeMillis();
257           //waitListenerStep(start, listener, 4);
258         }
259         catch (SVNException e) {
260           exception[0] = e;
261         }
262         result[0] = true;
263       }
264     });
265
266     Assert.assertTrue(result[0]);
267     myTestInteraction.assertNothing();
268     Assert.assertEquals(4, listener.getCnt());
269     listener.assertForAwt();
270     savedOnceListener.assertForAwt();
271     savedOnceListener.assertNotSaved(url, ISVNAuthenticationManager.PASSWORD);
272
273     if (exception[0] != null) {
274       throw exception[0];
275     }
276   }
277
278   public void testWhenAuthCredsNoInConfig() throws Exception {
279     final TestListener listener = new TestListener(mySynchObject);
280     myAuthenticationManager.addListener(listener);
281     final SavedOnceListener savedOnceListener = new SavedOnceListener();
282     myAuthenticationManager.addListener(savedOnceListener);
283
284     final File config = new File(myConfiguration.getConfigurationDirectory(), "config");
285     final char[] chars = FileUtil.loadFileText(config);
286     final String contents = String.valueOf(chars);
287     final String auth = "[auth]";
288     final int idx = contents.indexOf(auth);
289     Assert.assertTrue(idx != -1);
290     final String newContents = contents.substring(0, idx + auth.length()) + "\nstore-auth-creds=no\n" + contents.substring(idx + auth.length());
291
292     final File oldConfig = new File(myConfiguration.getConfigurationDirectory(), "config_old");
293     FileUtil.rename(config, oldConfig);
294     try {
295       config.createNewFile();
296       FileUtil.appendToFile(config, newContents);
297
298       final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
299
300       final SVNException[] exception = new SVNException[1];
301       final Boolean[] result = new Boolean[1];
302       synchronousBackground(new Runnable() {
303         @Override
304         public void run() {
305           try {
306             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
307             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
308
309             commonScheme(url, false, null);
310             Assert.assertEquals(2, listener.getCnt());
311             Assert.assertEquals(1, myTestInteraction.getNumAuthWarn());
312             myTestInteraction.reset();
313             savedOnceListener.assertForAwt();
314             savedOnceListener.reset();
315
316             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
317             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
318             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
319             commonScheme(url, false, null);
320             Assert.assertEquals(4, listener.getCnt());
321             Assert.assertEquals(1, myTestInteraction.getNumAuthWarn());
322           }
323           catch (SVNException e) {
324             exception[0] = e;
325           }
326           result[0] = true;
327         }
328       });
329
330       Assert.assertTrue(result[0]);
331       Assert.assertEquals(1, myTestInteraction.getNumAuthWarn());
332       Assert.assertEquals(4, listener.getCnt());
333       listener.assertForAwt();
334       savedOnceListener.assertForAwt();
335       savedOnceListener.assertNotSaved(url, ISVNAuthenticationManager.PASSWORD);
336
337       if (exception[0] != null) {
338         throw exception[0];
339       }
340     } finally {
341       FileUtil.delete(config);
342       FileUtil.rename(oldConfig, config);
343     }
344   }
345
346   public void testWhenAuthCredsNoInServers() throws Exception {
347     final TestListener listener = new TestListener(mySynchObject);
348     myAuthenticationManager.addListener(listener);
349     final SavedOnceListener savedOnceListener = new SavedOnceListener();
350     myAuthenticationManager.addListener(savedOnceListener);
351
352     final File servers = new File(myConfiguration.getConfigurationDirectory(), "servers");
353
354     final File oldServers = new File(myConfiguration.getConfigurationDirectory(), "config_old");
355     FileUtil.copy(servers, oldServers);
356     try {
357       FileUtil.appendToFile(servers, "\nstore-auth-creds=no\n");
358
359       final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
360
361       final SVNException[] exception = new SVNException[1];
362       final Boolean[] result = new Boolean[1];
363       synchronousBackground(new Runnable() {
364         @Override
365         public void run() {
366           try {
367             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
368             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
369
370             commonScheme(url, false, null);
371             Assert.assertEquals(2, listener.getCnt());
372             Assert.assertEquals(1, myTestInteraction.getNumAuthWarn());
373             myTestInteraction.reset();
374             savedOnceListener.assertForAwt();
375             savedOnceListener.reset();
376
377             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
378             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
379             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
380             commonScheme(url, false, null);
381             Assert.assertEquals(4, listener.getCnt());
382             Assert.assertEquals(1, myTestInteraction.getNumAuthWarn());
383           }
384           catch (SVNException e) {
385             exception[0] = e;
386           }
387           result[0] = true;
388         }
389       });
390
391       Assert.assertTrue(result[0]);
392       Assert.assertEquals(1, myTestInteraction.getNumAuthWarn());
393       Assert.assertEquals(4, listener.getCnt());
394       listener.assertForAwt();
395       savedOnceListener.assertForAwt();
396       savedOnceListener.assertNotSaved(url, ISVNAuthenticationManager.PASSWORD);
397
398       if (exception[0] != null) {
399         throw exception[0];
400       }
401     } finally {
402       FileUtil.delete(servers);
403       FileUtil.rename(oldServers, servers);
404     }
405   }
406
407   public void testWhenPassSaveNoInConfig() throws Exception {
408     final TestListener listener = new TestListener(mySynchObject);
409     myAuthenticationManager.addListener(listener);
410     final SavedOnceListener savedOnceListener = new SavedOnceListener();
411     myAuthenticationManager.addListener(savedOnceListener);
412
413     final File config = new File(myConfiguration.getConfigurationDirectory(), "config");
414     final char[] chars = FileUtil.loadFileText(config);
415     final String contents = String.valueOf(chars);
416     final String auth = "[auth]";
417     final int idx = contents.indexOf(auth);
418     Assert.assertTrue(idx != -1);
419     final String newContents = contents.substring(0, idx + auth.length()) + "\nstore-passwords=no\n" + contents.substring(idx + auth.length());
420
421     final File oldConfig = new File(myConfiguration.getConfigurationDirectory(), "config_old");
422     FileUtil.rename(config, oldConfig);
423     try {
424       config.createNewFile();
425       FileUtil.appendToFile(config, newContents);
426
427       final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
428
429       final SVNException[] exception = new SVNException[1];
430       final Boolean[] result = new Boolean[1];
431       synchronousBackground(new Runnable() {
432         @Override
433         public void run() {
434           try {
435             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
436             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
437             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
438
439             commonScheme(url, false, null);
440             Assert.assertEquals(3, listener.getCnt());
441             Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
442             myTestInteraction.reset();
443             savedOnceListener.assertForAwt();
444             savedOnceListener.reset();
445
446             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
447             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
448             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
449             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
450             commonScheme(url, false, null);
451             Assert.assertEquals(6, listener.getCnt());
452             Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
453           }
454           catch (SVNException e) {
455             exception[0] = e;
456           }
457           result[0] = true;
458         }
459       });
460
461       Assert.assertTrue(result[0]);
462       Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
463       Assert.assertEquals(6, listener.getCnt());
464       listener.assertForAwt();
465       savedOnceListener.assertForAwt();
466       savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
467
468       if (exception[0] != null) {
469         throw exception[0];
470       }
471     } finally {
472       FileUtil.delete(config);
473       FileUtil.rename(oldConfig, config);
474     }
475   }
476
477   public void testWhenPassSaveNoInServers() throws Exception {
478     final TestListener listener = new TestListener(mySynchObject);
479     myAuthenticationManager.addListener(listener);
480     final SavedOnceListener savedOnceListener = new SavedOnceListener();
481     myAuthenticationManager.addListener(savedOnceListener);
482
483     final File servers = new File(myConfiguration.getConfigurationDirectory(), "servers");
484
485     final File oldServers = new File(myConfiguration.getConfigurationDirectory(), "config_old");
486     FileUtil.copy(servers, oldServers);
487     try {
488       FileUtil.appendToFile(servers, "\nstore-passwords=no\n");
489
490       final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
491
492       final SVNException[] exception = new SVNException[1];
493       final Boolean[] result = new Boolean[1];
494       synchronousBackground(new Runnable() {
495         @Override
496         public void run() {
497           try {
498             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
499             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
500             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
501
502             commonScheme(url, false, null);
503             Assert.assertEquals(3, listener.getCnt());
504             Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
505             myTestInteraction.reset();
506             savedOnceListener.assertForAwt();
507             savedOnceListener.reset();
508
509             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
510             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
511             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
512             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
513             commonScheme(url, false, null);
514             Assert.assertEquals(6, listener.getCnt());
515             Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
516           }
517           catch (SVNException e) {
518             exception[0] = e;
519           }
520           result[0] = true;
521         }
522       });
523
524       Assert.assertTrue(result[0]);
525       Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
526       Assert.assertEquals(6, listener.getCnt());
527       listener.assertForAwt();
528       savedOnceListener.assertForAwt();
529       savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
530
531       if (exception[0] != null) {
532         throw exception[0];
533       }
534     } finally {
535       FileUtil.delete(servers);
536       FileUtil.rename(oldServers, servers);
537     }
538   }
539
540   public void testWhenPassSaveNoForGroup() throws Exception {
541     final TestListener listener = new TestListener(mySynchObject);
542     myAuthenticationManager.addListener(listener);
543     final SavedOnceListener savedOnceListener = new SavedOnceListener();
544     myAuthenticationManager.addListener(savedOnceListener);
545
546     final File servers = new File(myConfiguration.getConfigurationDirectory(), "servers");
547     final char[] chars = FileUtil.loadFileText(servers);
548     final String contents = String.valueOf(chars);
549     final String groups = "[groups]";
550     final int idx = contents.indexOf(groups);
551     Assert.assertTrue(idx != -1);
552     final String newContents = contents.substring(0, idx + groups.length()) + "\nsomegroup=some*\n" + contents.substring(idx + groups.length()) +
553       "\n[somegroup]\nstore-passwords=no\n";
554
555     final File oldServers = new File(myConfiguration.getConfigurationDirectory(), "config_old");
556     FileUtil.rename(servers, oldServers);
557     try {
558       servers.createNewFile();
559       FileUtil.appendToFile(servers, newContents);
560
561       final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
562
563       final SVNException[] exception = new SVNException[1];
564       final Boolean[] result = new Boolean[1];
565       synchronousBackground(new Runnable() {
566         @Override
567         public void run() {
568           try {
569             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
570             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
571             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
572
573             commonScheme(url, false, null);
574             Assert.assertEquals(3, listener.getCnt());
575             Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
576             myTestInteraction.reset();
577             savedOnceListener.assertForAwt();
578             savedOnceListener.reset();
579
580             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
581             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
582             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
583             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
584             commonScheme(url, false, null);
585             Assert.assertEquals(6, listener.getCnt());
586             Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
587           }
588           catch (SVNException e) {
589             exception[0] = e;
590           }
591           result[0] = true;
592         }
593       });
594
595       Assert.assertTrue(result[0]);
596       Assert.assertEquals(1, myTestInteraction.getNumPasswordsWarn());
597       Assert.assertEquals(6, listener.getCnt());
598       listener.assertForAwt();
599       savedOnceListener.assertForAwt();
600       savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
601
602       if (exception[0] != null) {
603         throw exception[0];
604       }
605     } finally {
606       FileUtil.delete(servers);
607       FileUtil.rename(oldServers, servers);
608     }
609   }
610
611   public void testWhenPassPhraseSaveNo() throws Exception {
612     final TestListener listener = new TestListener(mySynchObject);
613     myAuthenticationManager.addListener(listener);
614     final SavedOnceListener savedOnceListener = new SavedOnceListener();
615     myAuthenticationManager.addListener(savedOnceListener);
616
617     final File servers = new File(myConfiguration.getConfigurationDirectory(), "servers");
618
619     final File oldServers = new File(myConfiguration.getConfigurationDirectory(), "config_old");
620     FileUtil.copy(servers, oldServers);
621     try {
622       FileUtil.appendToFile(servers, "\nstore-ssl-client-cert-pp=no\n");
623
624       final SVNURL url = SVNURL.parseURIEncoded("https://some.host.com/repo");
625
626       final SVNException[] exception = new SVNException[1];
627       final Boolean[] result = new Boolean[1];
628       synchronousBackground(new Runnable() {
629         @Override
630         public void run() {
631           try {
632             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
633             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
634             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
635
636             commonScheme(url, false, null);
637             Assert.assertEquals(3, listener.getCnt());
638             Assert.assertEquals(1, myTestInteraction.getNumSSLWarn());
639             myTestInteraction.reset();
640             savedOnceListener.assertForAwt();
641             savedOnceListener.reset();
642
643             SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
644             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
645             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
646             listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
647             commonScheme(url, false, null);
648             Assert.assertEquals(6, listener.getCnt());
649             Assert.assertEquals(1, myTestInteraction.getNumSSLWarn());
650           }
651           catch (SVNException e) {
652             exception[0] = e;
653           }
654           result[0] = true;
655         }
656       });
657
658       Assert.assertTrue(result[0]);
659       Assert.assertEquals(1, myTestInteraction.getNumSSLWarn());
660       Assert.assertEquals(6, listener.getCnt());
661       listener.assertForAwt();
662       savedOnceListener.assertForAwt();
663       savedOnceListener.assertSaved(url, ISVNAuthenticationManager.SSL);
664
665       if (exception[0] != null) {
666         throw exception[0];
667       }
668     } finally {
669       FileUtil.delete(servers);
670       FileUtil.rename(oldServers, servers);
671     }
672   }
673
674   public void testPlaintextPrompt() throws Exception {
675     SVNJNAUtil.setJNAEnabled(false);
676
677     // yes, no
678     final TestListener listener = new TestListener(mySynchObject);
679     myAuthenticationManager.addListener(listener);
680     final SavedOnceListener savedOnceListener = new SavedOnceListener();
681     myAuthenticationManager.addListener(savedOnceListener);
682     myTestInteraction.setPlaintextAnswer(true);
683
684     final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
685
686     final SVNException[] exception = new SVNException[1];
687     final Boolean[] result = new Boolean[1];
688     synchronousBackground(new Runnable() {
689       @Override
690       public void run() {
691         try {
692           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
693           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
694           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.save));
695
696           commonScheme(url, false, null);
697           long start = System.currentTimeMillis();
698           waitListenerStep(start, listener, 3);
699           Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
700           savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
701           savedOnceListener.reset();
702           myTestInteraction.reset();
703
704           myConfiguration.clearAuthenticationDirectory();
705           myTestInteraction.setPlaintextAnswer(false);
706           SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
707
708           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
709           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
710           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
711           commonScheme(url, false, null);
712           start = System.currentTimeMillis();
713           waitListenerStep(start, listener, 6);
714           Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
715
716           savedOnceListener.reset();
717           myTestInteraction.reset();
718           SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
719           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
720           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
721           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
722           commonScheme(url, false, null);
723           start = System.currentTimeMillis();
724           waitListenerStep(start, listener, 9);
725           Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
726         }
727         catch (SVNException e) {
728           exception[0] = e;
729         }
730         result[0] = true;
731       }
732     });
733
734     Assert.assertTrue(result[0]);
735     Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
736     Assert.assertEquals(9, listener.getCnt());
737     listener.assertForAwt();
738     savedOnceListener.assertForAwt();
739     savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
740
741     if (exception[0] != null) {
742       throw exception[0];
743     }
744     SVNJNAUtil.setJNAEnabled(true);
745   }
746
747   public void testPlaintextPromptAndSecondPrompt() throws Exception {
748     SVNJNAUtil.setJNAEnabled(false);
749
750     // yes, no
751     final TestListener listener = new TestListener(mySynchObject);
752     myAuthenticationManager.addListener(listener);
753     final SavedOnceListener savedOnceListener = new SavedOnceListener();
754     myAuthenticationManager.addListener(savedOnceListener);
755     myTestInteraction.setPlaintextAnswer(false);
756
757     final SVNURL url = SVNURL.parseURIEncoded("http://some.host.com/repo");
758     final SVNURL url2 = SVNURL.parseURIEncoded("http://some.other.host.com/repo");
759
760     final SVNException[] exception = new SVNException[1];
761     final Boolean[] result = new Boolean[1];
762     synchronousBackground(new Runnable() {
763       @Override
764       public void run() {
765         try {
766           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
767           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
768           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
769
770           commonScheme(url, false, null);
771           long start = System.currentTimeMillis();
772           waitListenerStep(start, listener, 3);
773           Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
774           // actually password not saved, but save was called
775           savedOnceListener.assertSaved(url, ISVNAuthenticationManager.PASSWORD);
776           savedOnceListener.reset();
777           myTestInteraction.reset();
778
779           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url2, Type.request));
780           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url2, Type.request));
781           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url2, Type.without_pasword_save));
782           commonScheme(url2, false, "anotherRealm");
783           start = System.currentTimeMillis();
784           waitListenerStep(start, listener, 6);
785           Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
786         }
787         catch (SVNException e) {
788           exception[0] = e;
789         }
790         result[0] = true;
791       }
792     });
793
794     Assert.assertTrue(result[0]);
795     Assert.assertEquals(1, myTestInteraction.getNumPlaintextPrompt());
796     Assert.assertEquals(6, listener.getCnt());
797     listener.assertForAwt();
798     savedOnceListener.assertForAwt();
799     // didn't called to save for 2nd time
800     savedOnceListener.assertNotSaved(url, ISVNAuthenticationManager.PASSWORD);
801
802     if (exception[0] != null) {
803       throw exception[0];
804     }
805     SVNJNAUtil.setJNAEnabled(true);
806   }
807
808   public void testPlaintextSSLPrompt() throws Exception {
809     SVNJNAUtil.setJNAEnabled(false);
810
811     // yes, no
812     final TestListener listener = new TestListener(mySynchObject);
813     myAuthenticationManager.addListener(listener);
814     final SavedOnceListener savedOnceListener = new SavedOnceListener();
815     myAuthenticationManager.addListener(savedOnceListener);
816     myTestInteraction.setSSLPlaintextAnswer(true);
817
818     final SVNURL url = SVNURL.parseURIEncoded("https://some.host.com/repo");
819
820     final SVNException[] exception = new SVNException[1];
821     final Boolean[] result = new Boolean[1];
822     synchronousBackground(new Runnable() {
823       @Override
824       public void run() {
825         try {
826           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
827           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
828           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.save));
829
830           commonScheme(url, false, null);
831           long start = System.currentTimeMillis();
832           waitListenerStep(start, listener, 3);
833           Assert.assertEquals(1, myTestInteraction.getNumSSLPlaintextPrompt());
834           savedOnceListener.assertSaved(url, ISVNAuthenticationManager.SSL);
835           savedOnceListener.reset();
836           myTestInteraction.reset();
837
838           myConfiguration.clearAuthenticationDirectory();
839           myTestInteraction.setSSLPlaintextAnswer(false);
840           SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
841
842           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
843           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
844           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
845           commonScheme(url, false, null);
846           start = System.currentTimeMillis();
847           waitListenerStep(start, listener, 6);
848           Assert.assertEquals(1, myTestInteraction.getNumSSLPlaintextPrompt());
849
850           SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
851           myTestInteraction.reset();
852           savedOnceListener.reset();
853
854           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.request));
855           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.interactive, url, Type.request));
856           listener.addStep(new Trinity<ProviderType, SVNURL, Type>(ProviderType.persistent, url, Type.without_pasword_save));
857           commonScheme(url, false, null);
858           start = System.currentTimeMillis();
859           waitListenerStep(start, listener, 9);
860           Assert.assertEquals(1, myTestInteraction.getNumSSLPlaintextPrompt());
861         }
862         catch (SVNException e) {
863           exception[0] = e;
864         }
865         result[0] = true;
866       }
867     });
868
869     Assert.assertTrue(result[0]);
870     Assert.assertEquals(1, myTestInteraction.getNumSSLPlaintextPrompt());
871     Assert.assertEquals(9, listener.getCnt());
872     listener.assertForAwt();
873     savedOnceListener.assertForAwt();
874     savedOnceListener.assertSaved(url, ISVNAuthenticationManager.SSL);
875
876     if (exception[0] != null) {
877       throw exception[0];
878     }
879     SVNJNAUtil.setJNAEnabled(true);
880   }
881
882   private void synchronousBackground(final Runnable runnable) throws InterruptedException {
883     final Semaphore semaphore = new Semaphore();
884     semaphore.down();
885     ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
886       @Override
887       public void run() {
888         try {
889           runnable.run();
890         } finally {
891           semaphore.up();
892         }
893       }
894     });
895     semaphore.waitFor();
896   }
897
898   private void commonScheme(final SVNURL url, final boolean username, final String realm) throws SVNException {
899     String kind = null;
900
901     final String actualRealm = realm == null ? "realm" : realm;
902     final String protocol = url.getProtocol();
903     if (username) {
904       kind = ISVNAuthenticationManager.USERNAME;
905     } else if ("svn+ssh".equals(protocol)) {
906       kind = ISVNAuthenticationManager.SSH;
907     } else if ("http".equals(protocol)) {
908       kind = ISVNAuthenticationManager.PASSWORD;
909     } else if ("https".equals(protocol)) {
910       kind = ISVNAuthenticationManager.SSL;
911     } else if ("file".equals(protocol)) {
912       kind = ISVNAuthenticationManager.USERNAME;
913     }
914     SVNAuthentication authentication = null;
915     try {
916       authentication = myAuthenticationManager.getFirstAuthentication(kind, actualRealm, url);
917       while (! passwordSpecified(authentication)) {
918         authentication = myAuthenticationManager.getNextAuthentication(kind, actualRealm, url);
919       }
920     } finally {
921       myAuthenticationManager.acknowledgeAuthentication(authentication != null, kind, actualRealm, null, authentication);
922     }
923   }
924
925   private static class SvnTestInteractiveAuthentication implements ISVNAuthenticationProvider {
926     private final SvnAuthenticationManager myManager;
927     private boolean mySaveData;
928
929     public SvnTestInteractiveAuthentication(SvnAuthenticationManager manager) {
930       myManager = manager;
931       mySaveData = true;
932     }
933
934     public void setSaveData(boolean saveData) {
935       mySaveData = saveData;
936     }
937
938     @Override
939     public int acceptServerAuthentication(SVNURL url, String realm, Object certificate, boolean resultMayBeStored) {
940       return ISVNAuthenticationProvider.REJECTED;
941     }
942
943     @Override
944     public SVNAuthentication requestClientAuthentication(String kind,
945                                                          SVNURL url,
946                                                          String realm,
947                                                          SVNErrorMessage errorMessage,
948                                                          SVNAuthentication previousAuth,
949                                                          boolean authMayBeStored) {
950       authMayBeStored = authMayBeStored & mySaveData;
951       SVNAuthentication result = null;
952       if (ISVNAuthenticationManager.USERNAME.equals(kind)) {
953         result = new SVNUserNameAuthentication("username", authMayBeStored);
954       } else if (ISVNAuthenticationManager.PASSWORD.equals(kind)) {
955         result = new SVNPasswordAuthentication("username", "abc", authMayBeStored, url, false);
956       } else if (ISVNAuthenticationManager.SSH.equals(kind)) {
957         result = new SVNSSHAuthentication("username", "abc", -1, authMayBeStored, url, false);
958       } else if (ISVNAuthenticationManager.SSL.equals(kind)) {
959         result = new SVNSSLAuthentication(new File("aaa"), "abc", authMayBeStored, url, false);
960       }
961       if (! ISVNAuthenticationManager.USERNAME.equals(kind)) {
962         myManager.requested(ProviderType.interactive, url, realm, kind, result == null);
963       }
964       return result;
965     }
966   }
967
968   private static boolean passwordSpecified(final SVNAuthentication authentication) {
969     final String kind = authentication.getKind();
970     if (ISVNAuthenticationManager.SSH.equals(kind)) {
971       if (((SVNSSHAuthentication) authentication).hasPrivateKey()) {
972         return ((SVNSSHAuthentication) authentication).getPassphrase() != null &&
973                ((((SVNSSHAuthentication) authentication).getPrivateKey() != null) || (((SVNSSHAuthentication) authentication).getPrivateKeyFile() != null));
974       } else {
975         return ((SVNSSHAuthentication) authentication).getPassword() != null;
976       }
977     } else if (ISVNAuthenticationManager.PASSWORD.equals(kind)) {
978       return ((SVNPasswordAuthentication) authentication).getPassword() != null;
979     } else if (ISVNAuthenticationManager.SSL.equals(kind)) {
980       return ((SVNSSLAuthentication) authentication).getPassword() != null;
981     } else if (ISVNAuthenticationManager.USERNAME.equals(kind)) {
982       return true;
983     }
984     return true;
985   }
986
987   private static class TestListener implements SvnAuthenticationListener {
988     private List<Trinity<ProviderType, SVNURL, Type>> myExpectedSequence;
989     private int myCnt;
990     private final Object mySynchObject;
991     private boolean mySuccess;
992
993     private TestListener(final Object synchObject) {
994       mySynchObject = synchObject;
995       myExpectedSequence = new ArrayList<Trinity<ProviderType, SVNURL, Type>>();
996       myCnt = 0;
997       mySuccess = true;
998     }
999
1000     public void addStep(Trinity<ProviderType, SVNURL, Type> step) {
1001       myExpectedSequence.add(step);
1002     }
1003
1004     public int getCnt() {
1005       return myCnt;
1006     }
1007
1008     @Override
1009     public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind, boolean withCredentials) {
1010       if (! mySuccess) return;
1011       
1012       mySuccess = myExpectedSequence.get(myCnt).equals(new Trinity<ProviderType, SVNURL, Type>(type, url, withCredentials ? Type.save : Type.without_pasword_save));
1013       if (mySuccess) {
1014         ++ myCnt;
1015       }
1016       synchronized (mySynchObject) {
1017         mySynchObject.notifyAll();
1018       }
1019     }
1020
1021     public void reset() {
1022       myExpectedSequence.clear();
1023       myCnt = 0;
1024       mySuccess = true;
1025     }
1026
1027     @Override
1028     public void requested(ProviderType type, SVNURL url, String realm, String kind, boolean canceled) {
1029       if (! mySuccess) return;
1030
1031       mySuccess = myExpectedSequence.get(myCnt).equals(new Trinity<ProviderType, SVNURL, Type>(type, url, Type.request));
1032       if (mySuccess) {
1033         ++ myCnt;
1034       }
1035       synchronized (mySynchObject) {
1036         mySynchObject.notifyAll();
1037       }
1038     }
1039
1040     public void assertForAwt() {
1041       Assert.assertTrue("last cnt = " + myCnt, mySuccess);
1042     }
1043   }
1044
1045   private static class SavedOnceListener implements SvnAuthenticationListener {
1046     private final Set<Pair<SVNURL, String>> myClientRequested;
1047     private final Set<Pair<SVNURL, String>> mySaved;
1048     private String myCause;
1049
1050     private SavedOnceListener() {
1051       myClientRequested = new HashSet<Pair<SVNURL, String>>();
1052       mySaved = new HashSet<Pair<SVNURL, String>>();
1053     }
1054
1055     public void reset() {
1056       mySaved.clear();
1057       myClientRequested.clear();
1058     }
1059
1060     @Override
1061     public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind, boolean withCredentials) {
1062       final Pair<SVNURL, String> pair = new Pair<SVNURL, String>(url, kind);
1063       if (mySaved.contains(pair)) {
1064         myCause = "saved twice";
1065       }
1066       mySaved.add(pair);
1067     }
1068
1069     public boolean isSaved(final SVNURL url, final String kind) {
1070       return mySaved.contains(new Pair<SVNURL, String>(url, kind));
1071     }
1072
1073     @Override
1074     public void requested(ProviderType type, SVNURL url, String realm, String kind, boolean canceled) {
1075       if (ProviderType.interactive.equals(type)) {
1076         final Pair<SVNURL, String> pair = new Pair<SVNURL, String>(url, kind);
1077         if (myClientRequested.contains(pair)) {
1078           myCause = "client requested twice";
1079         }
1080         myClientRequested.add(pair);
1081       }
1082     }
1083
1084     public void assertForAwt() {
1085       Assert.assertTrue(myCause, myCause == null);
1086     }
1087
1088     public void assertSaved(final SVNURL url, final String kind) {
1089       Assert.assertTrue("not saved", mySaved.contains(new Pair<SVNURL, String>(url, kind)));
1090     }
1091
1092     public void assertNotSaved(final SVNURL url, final String kind) {
1093       Assert.assertTrue("saved", ! mySaved.contains(new Pair<SVNURL, String>(url, kind)));
1094     }
1095   }
1096
1097   private static enum Type {
1098     request,
1099     save,
1100     without_pasword_save
1101   }
1102
1103   private static class TestInteraction implements SvnAuthenticationInteraction {
1104     private int myNumAuthWarn;
1105     private int myNumPasswordsWarn;
1106     private int myNumSSLWarn;
1107     private int myNumPlaintextPrompt;
1108     private int myNumSSLPlaintextPrompt;
1109
1110     private boolean myPlaintextAnswer;
1111     private boolean mySSLPlaintextAnswer;
1112
1113     public void setPlaintextAnswer(boolean plaintextAnswer) {
1114       myPlaintextAnswer = plaintextAnswer;
1115     }
1116
1117     public void setSSLPlaintextAnswer(boolean SSLPlaintextAnswer) {
1118       mySSLPlaintextAnswer = SSLPlaintextAnswer;
1119     }
1120
1121     public void assertNothing() {
1122       Assert.assertEquals("myNumAuthWarn", myNumAuthWarn, 0);
1123       Assert.assertEquals("myNumPasswordsWarn", myNumPasswordsWarn, 0);
1124       Assert.assertEquals("myNumSSLWarn", myNumSSLWarn, 0);
1125       Assert.assertEquals("myNumPlaintextPrompt", myNumPlaintextPrompt, 0);
1126       Assert.assertEquals("myNumSSLPlaintextPrompt", myNumSSLPlaintextPrompt, 0);
1127     }
1128
1129     public void reset() {
1130       myNumAuthWarn = 0;
1131       myNumPasswordsWarn = 0;
1132       myNumSSLWarn = 0;
1133       myNumPlaintextPrompt = 0;
1134       myNumSSLPlaintextPrompt = 0;
1135     }
1136
1137     @Override
1138     public boolean promptForPlaintextPasswordSaving(SVNURL url, String realm) {
1139       ++ myNumPlaintextPrompt;
1140       return myPlaintextAnswer;
1141     }
1142
1143     @Override
1144     public boolean promptInAwt() {
1145       return false;
1146     }
1147
1148     @Override
1149     public void warnOnAuthStorageDisabled(SVNURL url) {
1150       ++ myNumAuthWarn;
1151     }
1152
1153     @Override
1154     public void warnOnPasswordStorageDisabled(SVNURL url) {
1155       ++ myNumPasswordsWarn;
1156     }
1157
1158     @Override
1159     public void warnOnSSLPassphraseStorageDisabled(SVNURL url) {
1160       ++ myNumSSLWarn;
1161     }
1162
1163     @Override
1164     public boolean promptForSSLPlaintextPassphraseSaving(SVNURL url, String realm, File certificateFile) {
1165       ++ myNumSSLPlaintextPrompt;
1166       return mySSLPlaintextAnswer;
1167     }
1168
1169     public int getNumAuthWarn() {
1170       return myNumAuthWarn;
1171     }
1172
1173     public int getNumPasswordsWarn() {
1174       return myNumPasswordsWarn;
1175     }
1176
1177     public int getNumPlaintextPrompt() {
1178       return myNumPlaintextPrompt;
1179     }
1180
1181     public int getNumSSLPlaintextPrompt() {
1182       return myNumSSLPlaintextPrompt;
1183     }
1184
1185     public int getNumSSLWarn() {
1186       return myNumSSLWarn;
1187     }
1188   }
1189 }