/*
* JCaptcha, the open source java framework for captcha definition and integration
* Copyright (c) 2007 jcaptcha.net. All Rights Reserved.
* See the LICENSE.txt file distributed with this package.
*/
package com.octo.captcha.service;
import com.octo.captcha.Captcha;
import com.octo.captcha.engine.MockCaptchaEngine;
import com.octo.captcha.service.captchastore.CaptchaStore;
import com.octo.captcha.service.captchastore.MapCaptchaStore;
import java.util.Locale;
public class RunableAbstractManageableCaptchaServiceTest extends RunableAbstractCaptchaServiceTest {
public static int MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS = 3;
public static int CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION = 2 * SIZE;
public static int MAX_CAPTCHA_STORE_SIZE = 3 * SIZE;
protected void setUp() throws Exception {
super.setUp();
//redefines service
this.service = new MockedManageableCaptchaService(new MapCaptchaStore(), new MockCaptchaEngine(),
MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS,
MAX_CAPTCHA_STORE_SIZE, CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
}
//down casts
protected ManageableCaptchaService getMService() {
return (ManageableCaptchaService) service;
}
public void testIsCaptchaStoreFull() {
AbstractManageableCaptchaService mockedService = new MockedManageableCaptchaService(
new MapCaptchaStore(), new MockCaptchaEngine(),
MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, 0, 0);
assertFalse(mockedService.isCaptchaStoreFull());
}
public void testAbstractManageableCaptchaService() throws Exception {
try {
new MockedManageableCaptchaService(new MapCaptchaStore(), new MockCaptchaEngine(), 0, 10, 100);
fail("should have thrown an exception");
} catch (Exception e) {
assertTrue("IllegalArgumentException attended", e instanceof IllegalArgumentException);
}
}
public void testGetCaptchaEngineClass() throws Exception {
assertEquals("Sould be the mockEngine...", MockCaptchaEngine.class.getName(),
getMService().getCaptchaEngineClass());
}
public void testSetCaptchaEngineClass() throws Exception {
try {
getMService().setCaptchaEngineClass("unknown");
fail("shoul have thown an exception");
} catch (IllegalArgumentException e) {
assertEquals("Sould still be the mockEngine...",
MockCaptchaEngine.class.getName(),
getMService().getCaptchaEngineClass());
}
try {
getMService().setCaptchaEngineClass("java.lang.String");
fail("shoul have thown an exception");
} catch (IllegalArgumentException e) {
assertEquals("Sould still be the mockEngine...",
MockCaptchaEngine.class.getName(),
getMService().getCaptchaEngineClass());
}
assertEquals("Sould still be the mockEngine...", MockCaptchaEngine.class.getName(),
getMService().getCaptchaEngineClass());
try {
getMService().setCaptchaEngineClass(SecondMockCaptchaEngine.class.getName());
assertEquals("Sould be the SecondmockEngine...", SecondMockCaptchaEngine.class.getName(),
getMService().getCaptchaEngineClass());
} catch (IllegalArgumentException e) {
fail("should be ok " + e);
assertEquals("Sould be the mockEngine...",
MockCaptchaEngine.class.getName(),
getMService().getCaptchaEngineClass());
}
}
public void testEmptyCaptchaStore() throws Exception {
for (int i = 0; i < SIZE; i++) {
String id = String.valueOf(myRandom.nextInt());
service.generateAndStoreCaptcha(Locale.getDefault(), id);
}
getMService().emptyCaptchaStore();
assertTrue("it shoud be emtpy", getMService().getCaptchaStoreSize() == 0);
}
public void testGarbageCollectCaptchaStore() throws Exception {
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(myRandom.nextInt());
service.generateAndStoreCaptcha(Locale.getDefault(), id);
}
getMService().garbageCollectCaptchaStore();
assertTrue("store size should be the same(this test may fail if time to load the store is > min guaranted...)",
getMService().getCaptchaStoreSize() == CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
//wait, and collect
Thread.sleep(MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS * 1000 + 100);
getMService().garbageCollectCaptchaStore();
assertTrue("store should be empty",
getMService().getCaptchaStoreSize() == 0);
}
public void testGetCaptchaStoreMaxSize() throws Exception {
assertEquals("initial size", MAX_CAPTCHA_STORE_SIZE, getMService().getCaptchaStoreMaxSize());
}
public void testSetCaptchaStoreMaxSize() throws Exception {
try {
getMService().setCaptchaStoreMaxSize(CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1);
fail("should have thrown an exception");
} catch (Exception e) {
assertTrue("IllegalArgumentException attended", e instanceof IllegalArgumentException);
}
getMService().setCaptchaStoreMaxSize(CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
assertEquals("modified size",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION, getMService().getCaptchaStoreMaxSize());
}
public void testSetCaptchaStoreSizeBeforeGarbageCollection() throws Exception {
try {
getMService().setCaptchaStoreSizeBeforeGarbageCollection(MAX_CAPTCHA_STORE_SIZE + 1);
fail("should have thrown an exception");
} catch (Exception e) {
assertTrue("IllegalArgumentException attended", e instanceof IllegalArgumentException);
}
getMService().setCaptchaStoreSizeBeforeGarbageCollection(MAX_CAPTCHA_STORE_SIZE);
assertEquals("modified size",
MAX_CAPTCHA_STORE_SIZE, getMService().getCaptchaStoreSizeBeforeGarbageCollection());
}
public void testGetCaptchaStoreSizeBeforeGarbageCollection() throws Exception {
assertEquals("initial value", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getCaptchaStoreSizeBeforeGarbageCollection());
}
public void testGetNumberOfGarbageCollectedCaptcha() throws Exception {
assertEquals("inital value", 0, getMService().getNumberOfGarbageCollectedCaptcha());
loadAndWait();
getMService().garbageCollectCaptchaStore();
assertEquals("all should have been collected",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfGarbageCollectedCaptcha());
//try with empty
loadAndWait();
getMService().emptyCaptchaStore();
getMService().garbageCollectCaptchaStore();
assertEquals("none have been collected",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfGarbageCollectedCaptcha());
loadAndWait();
getMService().validateResponseForID(String.valueOf(0), "true");
getMService().garbageCollectCaptchaStore();
assertEquals("all but one should have been collected",
2 * CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1,
getMService().getNumberOfGarbageCollectedCaptcha());
}
public void testGetNumberOfGarbageCollectableCaptchas() throws Exception {
assertEquals("inital value", 0, getMService().getNumberOfGarbageCollectableCaptchas());
loadAndWait();
assertEquals("all should be collectable",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfGarbageCollectableCaptchas());
getMService().garbageCollectCaptchaStore();
//try with empty
assertEquals("none should be collectable", 0, getMService().getNumberOfGarbageCollectableCaptchas());
loadAndWait();
assertEquals("all should be collectable",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfGarbageCollectableCaptchas());
getMService().emptyCaptchaStore();
assertEquals("none should be collectable", 0, getMService().getNumberOfGarbageCollectableCaptchas());
//try with validate
loadAndWait();
getMService().validateResponseForID(String.valueOf(0), "true");
assertEquals("all but one should be collectable",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1,
getMService().getNumberOfGarbageCollectableCaptchas());
getMService().getChallengeForID("newCaptcha");
assertEquals("all but one should be collectable",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION - 1,
getMService().getNumberOfGarbageCollectableCaptchas());
Thread.sleep(MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS * 1000 + 100);
assertEquals("all should be collectable",
CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfGarbageCollectableCaptchas());
}
public void testGetCaptchaStoreSize() throws Exception {
assertEquals("initial size", 0, getMService().getCaptchaStoreSize());
for (int i = 0; i < SIZE; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
assertEquals("size", i + 1, getMService().getCaptchaStoreSize());
}
getMService().validateResponseForID(String.valueOf(0), "true");
assertEquals("size", SIZE - 1,
getMService().getCaptchaStoreSize());
getMService().getChallengeForID("newCaptcha");
assertEquals("size", SIZE
, getMService().getCaptchaStoreSize());
getMService().getChallengeForID("newCaptcha");
assertEquals("size", SIZE
, getMService().getCaptchaStoreSize());
getMService().getQuestionForID("newCaptcha");
assertEquals("size", SIZE
, getMService().getCaptchaStoreSize());
getMService().getQuestionForID("newCaptcha", Locale.getDefault());
assertEquals("size", SIZE
, getMService().getCaptchaStoreSize());
getMService().getChallengeForID("newCaptcha", Locale.getDefault());
assertEquals("size", SIZE
, getMService().getCaptchaStoreSize());
}
public void testGetNumberOfUncorrectResponses() throws Exception {
assertEquals("initial size", 0, getMService().getNumberOfUncorrectResponses());
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
service.validateResponseForID(id, "false");
assertEquals("size", i + 1, getMService().getNumberOfUncorrectResponses());
}
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
service.validateResponseForID(id, "true");
assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfUncorrectResponses());
}
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
try {
service.validateResponseForID("unknown", "false");
fail("should have thrown an exception");
} catch (CaptchaServiceException e) {
assertNotNull(e.getMessage());
}
assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfUncorrectResponses());
}
}
public void testGetNumberOfCorrectResponses() throws Exception {
assertEquals("initial size", 0, getMService().getNumberOfCorrectResponses());
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
service.validateResponseForID(id, "true");
assertEquals("size", i + 1, getMService().getNumberOfCorrectResponses());
}
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
service.validateResponseForID(id, "false");
assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfCorrectResponses());
}
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
try {
service.validateResponseForID("unknown", "false");
fail("should have thrown an exception");
} catch (CaptchaServiceException e) {
assertNotNull(e.getMessage());
}
assertEquals("should not have been incremented", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfCorrectResponses());
}
}
public void testGetNumberOfGeneratedCaptchas() throws Exception {
assertEquals("initial size", 0, getMService().getNumberOfGeneratedCaptchas());
for (int i = 0; i < SIZE; i++) {
String id = String.valueOf(i);
service.getChallengeForID(id);
assertEquals("size", 4 * i + 1, getMService().getNumberOfGeneratedCaptchas());
service.getChallengeForID(id);
assertEquals("size", 4 * i + 2, getMService().getNumberOfGeneratedCaptchas());
service.getQuestionForID(id);
assertEquals("size", 4 * i + 2, getMService().getNumberOfGeneratedCaptchas());
service.getQuestionForID(id);
assertEquals("size", 4 * i + 2, getMService().getNumberOfGeneratedCaptchas());
service.getChallengeForID(id);
assertEquals("size", 4 * i + 3, getMService().getNumberOfGeneratedCaptchas());
service.getChallengeForID(id);
assertEquals("size", 4 * i + 4, getMService().getNumberOfGeneratedCaptchas());
}
long generatedBefore = getMService().getNumberOfGeneratedCaptchas();
getMService().emptyCaptchaStore();
for (int i = 0; i < SIZE; i++) {
String id = String.valueOf(i);
service.getQuestionForID(id);
assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
service.getChallengeForID(id);
assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
service.getQuestionForID(id);
assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
service.getQuestionForID(id);
assertEquals("size", 3 * i + 1 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
service.getChallengeForID(id);
assertEquals("size", 3 * i + 2 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
service.getChallengeForID(id);
assertEquals("size", 3 * i + 3 + generatedBefore, getMService().getNumberOfGeneratedCaptchas());
}
}
public void testSetMinGuarantedStorageDelayInSeconds() throws Exception {
assertEquals("initial", MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, getMService().getMinGuarantedStorageDelayInSeconds());
getMService().setMinGuarantedStorageDelayInSeconds(80);
assertEquals("changed", 80, getMService().getMinGuarantedStorageDelayInSeconds());
getMService().setMinGuarantedStorageDelayInSeconds(100);
fullLoad();
assertEquals("none should be collected", 0, getMService().getNumberOfGarbageCollectedCaptcha());
}
public void testGetMinGuarantedStorageDelayInSeconds() throws Exception {
assertEquals("initial", MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, getMService().getMinGuarantedStorageDelayInSeconds());
}
public void testAutomaticGarbaging() throws Exception {
loadAndWait();
assertEquals("none should have been collected yet", 0, getMService().getNumberOfGarbageCollectedCaptcha());
getMService().getChallengeForID("new");
assertEquals("all should have been collected", CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION,
getMService().getNumberOfGarbageCollectedCaptcha());
getMService().emptyCaptchaStore();
assertEquals("we should not been able to garbage collect",
0,
getMService().getNumberOfGarbageCollectableCaptchas());
getMService().setMinGuarantedStorageDelayInSeconds(5);
assertEquals("we should not been able to garbage collect",
0,
getMService().getNumberOfGarbageCollectableCaptchas());
// System.out.println("before "+System.currentTimeMillis());
fullLoad();
// System.out.println(System.currentTimeMillis());
assertEquals("to be valid we should not been able to garbage collect",
0,
getMService().getNumberOfGarbageCollectableCaptchas());
assertEquals("store size should be full",
MAX_CAPTCHA_STORE_SIZE,
getMService().getCaptchaStoreSize());
Thread.sleep(5 * 1000 + 100);
assertEquals("all should be collectable",
MAX_CAPTCHA_STORE_SIZE,
getMService().getNumberOfGarbageCollectableCaptchas());
}
public void testMaxStoreSizeConstraint() throws Exception {
//getMService().setMinGuarantedStorageDelayInSeconds(10000);
fullLoad();
for (int i = 0; i < 100; i++) {
try {
getMService().getChallengeForID("new" + String.valueOf(i));
fail("should have thrown a captcha store full exception");
} catch (CaptchaServiceException e) {
assertEquals("store should be of max size", MAX_CAPTCHA_STORE_SIZE, getMService().getCaptchaStoreSize());
}
}
Thread.sleep(1000);
getMService().setMinGuarantedStorageDelayInSeconds(1);
Thread.sleep(1000);
try {
fullLoad();
} catch (CaptchaServiceException e) {
fail("should not have thrown a captcha store full exception");
}
}
private void fullLoad() {
int i = 0;
try {
for (i = 0; i < MAX_CAPTCHA_STORE_SIZE; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
}
} catch (CaptchaServiceException e) {
System.out.println("i = " + i);
e.printStackTrace();
throw e;
}
}
private void loadAndWait() throws InterruptedException {
for (int i = 0; i < CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION; i++) {
String id = String.valueOf(i);
service.generateAndStoreCaptcha(Locale.getDefault(), id);
}
Thread.sleep(MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS * 1000 + 100);
}
protected class MockedManageableCaptchaService extends AbstractManageableCaptchaService {
protected MockedManageableCaptchaService(CaptchaStore captchaStore, com.octo.captcha.engine.CaptchaEngine captchaEngine,
int minGuarantedStorageDelayInSeconds,
int maxCaptchaStoreSize,
int captchaStoreLoadBeforeGarbageCollection) {
super(captchaStore, captchaEngine, minGuarantedStorageDelayInSeconds, maxCaptchaStoreSize,
captchaStoreLoadBeforeGarbageCollection);
}
/**
* This method must be implemented by sublcasses and : Retrieve the challenge from the captcha Make and return a
* clone of the challenge Return the clone It has be design in order to let the service dipose the challenge of
* the captcha after rendering. It should be implemented for all captcha type (@see ImageCaptchaService
* implementations for exemple)
*
* @return a Challenge Clone
*/
protected Object getChallengeClone(Captcha captcha) {
return new String(captcha.getChallenge().toString()) + MockedCaptchaService.CLONE_CHALLENGE;
}
}
}