View Javadoc

1   /*
2    * JCaptcha, the open source java framework for captcha definition and integration
3    * Copyright (c)  2007 jcaptcha.net. All Rights Reserved.
4    * See the LICENSE.txt file distributed with this package.
5    */
6   
7   package com.octo.captcha.service;
8   
9   import com.octo.captcha.Captcha;
10  import com.octo.captcha.engine.MockCaptchaEngine;
11  import com.octo.captcha.service.captchastore.CaptchaStore;
12  import com.octo.captcha.service.captchastore.MapCaptchaStore;
13  
14  import java.util.Locale;
15  
16  public class RunableAbstractManageableCaptchaServiceTest extends RunableAbstractCaptchaServiceTest {
17      public static int MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS = 3;
18      public static int CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION = 2 * SIZE;
19      public static int MAX_CAPTCHA_STORE_SIZE = 3 * SIZE;
20  
21  
22      protected void setUp() throws Exception {
23          super.setUp();
24          //redefines service
25          this.service = new MockedManageableCaptchaService(new MapCaptchaStore(), new MockCaptchaEngine(),
26                  MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS,
27                  MAX_CAPTCHA_STORE_SIZE, CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
28      }
29  
30      //down casts
31      protected ManageableCaptchaService getMService() {
32          return (ManageableCaptchaService) service;
33      }
34  
35      public void testIsCaptchaStoreFull() {
36          
37          AbstractManageableCaptchaService mockedService = new MockedManageableCaptchaService(
38                  new MapCaptchaStore(), new MockCaptchaEngine(),
39                  MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, 0, 0);
40  
41          assertFalse(mockedService.isCaptchaStoreFull());
42      }
43  
44  
45      public void testAbstractManageableCaptchaService() throws Exception {
46          try {
47              new MockedManageableCaptchaService(new MapCaptchaStore(), new MockCaptchaEngine(), 0, 10, 100);
48              fail("should have thrown an exception");
49          } catch (Exception e) {
50              assertTrue("IllegalArgumentException attended", e instanceof IllegalArgumentException);
51          }
52      }
53  
54      public void testGetCaptchaEngineClass() throws Exception {
55          assertEquals("Sould be the mockEngine...", MockCaptchaEngine.class.getName(),
56                  getMService().getCaptchaEngineClass());
57      }
58  
59      public void testSetCaptchaEngineClass() throws Exception {
60          try {
61              getMService().setCaptchaEngineClass("unknown");
62              fail("shoul have thown an exception");
63          } catch (IllegalArgumentException e) {
64              assertEquals("Sould still be the mockEngine...",
65                      MockCaptchaEngine.class.getName(),
66                      getMService().getCaptchaEngineClass());
67          }
68          
69          try {
70              getMService().setCaptchaEngineClass("java.lang.String");
71              fail("shoul have thown an exception");
72          } catch (IllegalArgumentException e) {
73              assertEquals("Sould still be the mockEngine...",
74                      MockCaptchaEngine.class.getName(),
75                      getMService().getCaptchaEngineClass());
76          }
77          
78          assertEquals("Sould still be the mockEngine...", MockCaptchaEngine.class.getName(),
79                  getMService().getCaptchaEngineClass());
80  
81          try {
82              getMService().setCaptchaEngineClass(SecondMockCaptchaEngine.class.getName());
83              assertEquals("Sould be the SecondmockEngine...", SecondMockCaptchaEngine.class.getName(),
84                      getMService().getCaptchaEngineClass());
85          } catch (IllegalArgumentException e) {
86              fail("should be ok " + e);
87              assertEquals("Sould be the mockEngine...",
88                      MockCaptchaEngine.class.getName(),
89                      getMService().getCaptchaEngineClass());
90          }
91      }
92  
93      public void testEmptyCaptchaStore() throws Exception {
94          for (int i = 0; i < SIZE; i++) {
95              String id = String.valueOf(myRandom.nextInt());
96              service.generateAndStoreCaptcha(Locale.getDefault(), id);
97          }
98          getMService().emptyCaptchaStore();
99          assertTrue("it shoud be emtpy", getMService().getCaptchaStoreSize() == 0);
100     }
101 
102     public void testGarbageCollectCaptchaStore() throws Exception {
103         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
104             String id = String.valueOf(myRandom.nextInt());
105             service.generateAndStoreCaptcha(Locale.getDefault(), id);
106         }
107 
108         getMService().garbageCollectCaptchaStore();
109         assertTrue("store size should be the same(this test may fail if time to load the store is > min guaranted...)",
110                 getMService().getCaptchaStoreSize() == CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
111         //wait,  and collect
112         Thread.sleep(MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS * 1000 + 100);
113         getMService().garbageCollectCaptchaStore();
114         assertTrue("store should be empty",
115                 getMService().getCaptchaStoreSize() == 0);
116     }
117 
118     public void testGetCaptchaStoreMaxSize() throws Exception {
119         assertEquals("initial size", MAX_CAPTCHA_STORE_SIZE, getMService().getCaptchaStoreMaxSize());
120     }
121 
122     public void testSetCaptchaStoreMaxSize() throws Exception {
123         try {
124             getMService().setCaptchaStoreMaxSize(CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1);
125             fail("should have thrown an exception");
126         } catch (Exception e) {
127             assertTrue("IllegalArgumentException attended", e instanceof IllegalArgumentException);
128         }
129         getMService().setCaptchaStoreMaxSize(CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
130         assertEquals("modified size",
131                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION, getMService().getCaptchaStoreMaxSize());
132     }
133 
134     public void testSetCaptchaStoreSizeBeforeGarbageCollection() throws Exception {
135         try {
136             getMService().setCaptchaStoreSizeBeforeGarbageCollection(MAX_CAPTCHA_STORE_SIZE + 1);
137             fail("should have thrown an exception");
138         } catch (Exception e) {
139             assertTrue("IllegalArgumentException attended", e instanceof IllegalArgumentException);
140         }
141         getMService().setCaptchaStoreSizeBeforeGarbageCollection(MAX_CAPTCHA_STORE_SIZE);
142         assertEquals("modified size",
143                 MAX_CAPTCHA_STORE_SIZE, getMService().getCaptchaStoreSizeBeforeGarbageCollection());
144     }
145 
146     public void testGetCaptchaStoreSizeBeforeGarbageCollection() throws Exception {
147         assertEquals("initial value", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
148                 getMService().getCaptchaStoreSizeBeforeGarbageCollection());
149     }
150 
151     public void testGetNumberOfGarbageCollectedCaptcha() throws Exception {
152         assertEquals("inital value", 0, getMService().getNumberOfGarbageCollectedCaptcha());
153         loadAndWait();
154         getMService().garbageCollectCaptchaStore();
155         assertEquals("all should have been collected",
156                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
157                 getMService().getNumberOfGarbageCollectedCaptcha());
158         //try with empty
159         loadAndWait();
160         getMService().emptyCaptchaStore();
161         getMService().garbageCollectCaptchaStore();
162         assertEquals("none have been collected",
163                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
164                 getMService().getNumberOfGarbageCollectedCaptcha());
165 
166         loadAndWait();
167         getMService().validateResponseForID(String.valueOf(0), "true");
168         getMService().garbageCollectCaptchaStore();
169         assertEquals("all but one should have been collected",
170                 2 * CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1,
171                 getMService().getNumberOfGarbageCollectedCaptcha());
172     }
173 
174 
175     public void testGetNumberOfGarbageCollectableCaptchas() throws Exception {
176         assertEquals("inital value", 0, getMService().getNumberOfGarbageCollectableCaptchas());
177         loadAndWait();
178 
179         assertEquals("all should be collectable",
180                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
181                 getMService().getNumberOfGarbageCollectableCaptchas());
182         getMService().garbageCollectCaptchaStore();
183         
184         //try with empty
185         assertEquals("none should be collectable", 0, getMService().getNumberOfGarbageCollectableCaptchas());
186         loadAndWait();
187         assertEquals("all should be collectable",
188                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
189                 getMService().getNumberOfGarbageCollectableCaptchas());
190         getMService().emptyCaptchaStore();
191         assertEquals("none should be collectable", 0, getMService().getNumberOfGarbageCollectableCaptchas());
192         //try with validate
193         loadAndWait();
194         getMService().validateResponseForID(String.valueOf(0), "true");
195         assertEquals("all but one should be collectable",
196                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1,
197                 getMService().getNumberOfGarbageCollectableCaptchas());
198 
199         getMService().getChallengeForID("newCaptcha");
200         assertEquals("all but one should be collectable",
201                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1,
202                 getMService().getNumberOfGarbageCollectableCaptchas());
203 
204         Thread.sleep(MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS * 1000 + 100);
205         assertEquals("all should be collectable",
206                 CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
207                 getMService().getNumberOfGarbageCollectableCaptchas());
208 
209     }
210 
211     public void testGetCaptchaStoreSize() throws Exception {
212         assertEquals("initial size", 0, getMService().getCaptchaStoreSize());
213         for (int i = 0; i < SIZE; i++) {
214             String id = String.valueOf(i);
215             service.generateAndStoreCaptcha(Locale.getDefault(), id);
216             assertEquals("size", i + 1, getMService().getCaptchaStoreSize());
217         }
218         getMService().validateResponseForID(String.valueOf(0), "true");
219         assertEquals("size", SIZE - 1,
220                 getMService().getCaptchaStoreSize());
221         getMService().getChallengeForID("newCaptcha");
222         assertEquals("size", SIZE
223                 , getMService().getCaptchaStoreSize());
224         getMService().getChallengeForID("newCaptcha");
225         assertEquals("size", SIZE
226                 , getMService().getCaptchaStoreSize());
227         getMService().getQuestionForID("newCaptcha");
228         assertEquals("size", SIZE
229                 , getMService().getCaptchaStoreSize());
230         getMService().getQuestionForID("newCaptcha", Locale.getDefault());
231         assertEquals("size", SIZE
232                 , getMService().getCaptchaStoreSize());
233         getMService().getChallengeForID("newCaptcha", Locale.getDefault());
234         assertEquals("size", SIZE
235                 , getMService().getCaptchaStoreSize());
236 
237     }
238 
239     public void testGetNumberOfUncorrectResponses() throws Exception {
240         assertEquals("initial size", 0, getMService().getNumberOfUncorrectResponses());
241 
242         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
243             String id = String.valueOf(i);
244             service.generateAndStoreCaptcha(Locale.getDefault(), id);
245             service.validateResponseForID(id, "false");
246             assertEquals("size", i + 1, getMService().getNumberOfUncorrectResponses());
247         }
248 
249         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
250             String id = String.valueOf(i);
251             service.generateAndStoreCaptcha(Locale.getDefault(), id);
252             service.validateResponseForID(id, "true");
253             assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
254                     getMService().getNumberOfUncorrectResponses());
255         }
256 
257         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
258             String id = String.valueOf(i);
259             service.generateAndStoreCaptcha(Locale.getDefault(), id);
260             try {
261                 service.validateResponseForID("unknown", "false");
262                 fail("should have thrown an exception");
263             } catch (CaptchaServiceException e) {
264             	assertNotNull(e.getMessage());
265             }
266             assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
267                     getMService().getNumberOfUncorrectResponses());
268         }
269 
270 
271     }
272 
273     public void testGetNumberOfCorrectResponses() throws Exception {
274         assertEquals("initial size", 0, getMService().getNumberOfCorrectResponses());
275 
276         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
277             String id = String.valueOf(i);
278             service.generateAndStoreCaptcha(Locale.getDefault(), id);
279             service.validateResponseForID(id, "true");
280             assertEquals("size", i + 1, getMService().getNumberOfCorrectResponses());
281         }
282 
283         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
284             String id = String.valueOf(i);
285             service.generateAndStoreCaptcha(Locale.getDefault(), id);
286             service.validateResponseForID(id, "false");
287             assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
288                     getMService().getNumberOfCorrectResponses());
289         }
290 
291         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
292             String id = String.valueOf(i);
293             service.generateAndStoreCaptcha(Locale.getDefault(), id);
294             try {
295                 service.validateResponseForID("unknown", "false");
296                 fail("should have thrown an exception");
297             } catch (CaptchaServiceException e) {
298             	assertNotNull(e.getMessage());
299             }
300             assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
301                     getMService().getNumberOfCorrectResponses());
302         }
303     }
304 
305     public void testGetNumberOfGeneratedCaptchas() throws Exception {
306         assertEquals("initial size", 0, getMService().getNumberOfGeneratedCaptchas());
307 
308         for (int i = 0; i < SIZE; i++) {
309             String id = String.valueOf(i);
310             service.getChallengeForID(id);
311             assertEquals("size", 4 * i + 1, getMService().getNumberOfGeneratedCaptchas());
312             service.getChallengeForID(id);
313             assertEquals("size", 4 * i + 2, getMService().getNumberOfGeneratedCaptchas());
314             service.getQuestionForID(id);
315             assertEquals("size", 4 * i + 2, getMService().getNumberOfGeneratedCaptchas());
316             service.getQuestionForID(id);
317             assertEquals("size", 4 * i + 2, getMService().getNumberOfGeneratedCaptchas());
318             service.getChallengeForID(id);
319             assertEquals("size", 4 * i + 3, getMService().getNumberOfGeneratedCaptchas());
320             service.getChallengeForID(id);
321             assertEquals("size", 4 * i + 4, getMService().getNumberOfGeneratedCaptchas());
322         }
323         long generatedBefore = getMService().getNumberOfGeneratedCaptchas();
324         getMService().emptyCaptchaStore();
325         for (int i = 0; i < SIZE; i++) {
326             String id = String.valueOf(i);
327             service.getQuestionForID(id);
328             assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
329             service.getChallengeForID(id);
330             assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
331             service.getQuestionForID(id);
332             assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
333             service.getQuestionForID(id);
334             assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
335             service.getChallengeForID(id);
336             assertEquals("size", 3 * i + 2 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
337             service.getChallengeForID(id);
338             assertEquals("size", 3 * i + 3 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
339         }
340 
341 
342     }
343 
344     public void testSetMinGuarantedStorageDelayInSeconds() throws Exception {
345         assertEquals("initial", MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, getMService().getMinGuarantedStorageDelayInSeconds());
346         getMService().setMinGuarantedStorageDelayInSeconds(80);
347         assertEquals("changed", 80, getMService().getMinGuarantedStorageDelayInSeconds());
348 
349         getMService().setMinGuarantedStorageDelayInSeconds(100);
350         fullLoad();
351 
352         assertEquals("none should be collected", 0, getMService().getNumberOfGarbageCollectedCaptcha());
353 
354     }
355 
356     public void testGetMinGuarantedStorageDelayInSeconds() throws Exception {
357         assertEquals("initial", MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, getMService().getMinGuarantedStorageDelayInSeconds());
358     }
359 
360 
361     public void testAutomaticGarbaging() throws Exception {
362         loadAndWait();
363         assertEquals("none should have been collected yet", 0, getMService().getNumberOfGarbageCollectedCaptcha());
364         getMService().getChallengeForID("new");
365         assertEquals("all should have been collected", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
366                 getMService().getNumberOfGarbageCollectedCaptcha());
367         getMService().emptyCaptchaStore();
368         assertEquals("we should not been able to garbage collect",
369                 0,
370                 getMService().getNumberOfGarbageCollectableCaptchas());
371         getMService().setMinGuarantedStorageDelayInSeconds(5);
372         assertEquals("we should not been able to garbage collect",
373                 0,
374                 getMService().getNumberOfGarbageCollectableCaptchas());
375 //        System.out.println("before "+System.currentTimeMillis());
376         fullLoad();
377 //        System.out.println(System.currentTimeMillis());
378         
379         assertEquals("to be valid we should not been able to garbage collect",
380                 0,
381                 getMService().getNumberOfGarbageCollectableCaptchas());
382         assertEquals("store size should be full",
383                 MAX_CAPTCHA_STORE_SIZE,
384                 getMService().getCaptchaStoreSize());
385         Thread.sleep(5 * 1000 + 100);
386         assertEquals("all should be collectable",
387                 MAX_CAPTCHA_STORE_SIZE,
388                 getMService().getNumberOfGarbageCollectableCaptchas());
389 
390 
391     }
392 
393 
394     public void testMaxStoreSizeConstraint() throws Exception {
395         //getMService().setMinGuarantedStorageDelayInSeconds(10000);
396         fullLoad();
397         for (int i = 0; i < 100; i++) {
398             try {
399                 getMService().getChallengeForID("new" + String.valueOf(i));
400                 fail("should have thrown a captcha store full exception");
401             } catch (CaptchaServiceException e) {
402                 assertEquals("store should be of max size", MAX_CAPTCHA_STORE_SIZE, getMService().getCaptchaStoreSize());
403             }
404         }
405 
406         Thread.sleep(1000);
407         getMService().setMinGuarantedStorageDelayInSeconds(1);
408         Thread.sleep(1000);
409         try {
410             fullLoad();
411 
412         } catch (CaptchaServiceException e) {
413             fail("should not have thrown a captcha store full exception");
414         }
415 
416     }
417 
418     private void fullLoad() {
419         int i = 0;
420         try {
421             for (i = 0; i < MAX_CAPTCHA_STORE_SIZE; i++) {
422                 String id = String.valueOf(i);
423                 service.generateAndStoreCaptcha(Locale.getDefault(), id);
424             }
425         } catch (CaptchaServiceException e) {
426             System.out.println("i = " + i);
427             e.printStackTrace();
428             throw e;
429         }
430     }
431 
432     private void loadAndWait() throws InterruptedException {
433         for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
434             String id = String.valueOf(i);
435             service.generateAndStoreCaptcha(Locale.getDefault(), id);
436         }
437         Thread.sleep(MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS * 1000 + 100);
438     }
439 
440 
441     protected class MockedManageableCaptchaService extends AbstractManageableCaptchaService {
442 
443         protected MockedManageableCaptchaService(CaptchaStore captchaStore, com.octo.captcha.engine.CaptchaEngine captchaEngine,
444                                                  int minGuarantedStorageDelayInSeconds,
445                                                  int maxCaptchaStoreSize,
446                                                  int captchaStoreLoadBeforeGarbageCollection) {
447             super(captchaStore, captchaEngine, minGuarantedStorageDelayInSeconds, maxCaptchaStoreSize,
448                     captchaStoreLoadBeforeGarbageCollection);
449         }
450 
451         /***
452          * This method must be implemented by sublcasses and : Retrieve the challenge from the captcha Make and return a
453          * clone of the challenge Return the clone It has be design in order to let the service dipose the challenge of
454          * the captcha after rendering. It should be implemented for all captcha type (@see ImageCaptchaService
455          * implementations for exemple)
456          *
457          * @return a Challenge Clone
458          */
459         protected Object getChallengeClone(Captcha captcha) {
460             return new String(captcha.getChallenge().toString()) + MockedCaptchaService.CLONE_CHALLENGE;
461         }
462 
463     }
464 
465 
466 }