token = CompletableFuture.supplyAsync(() -> makeToken(captchaText, saltSource));
- captcha = new TextCaptcha(imgData, token.get() + selfreference.get());
- } catch (InterruptedException e) {
- log.fatal("Thread interruption during captcha generation: " + e.getLocalizedMessage());
-
- } catch (ExecutionException e) {
- log.fatal("Fatal error during captcha generation: " + e.getLocalizedMessage());
- }
- return captcha;
- }
-
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/TextImageRenderer.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/TextImageRenderer.java
deleted file mode 100644
index 0dd3258..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/TextImageRenderer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * Describes the logic required to render
- *
- * @author Yannick Forster
- */
-public interface TextImageRenderer {
-
- /**
- * Creates a {@link BufferedImage} based on the input string, the pixel height
- * and pixel width
- *
- * @param captchaTextInput String the image will show
- * @param height the height of the image to be generated
- * @param width the width of the image to be generated
- * @return the generated image as {@link BufferedImage}
- */
- BufferedImage render(final String captchaTextInput, int height, int width);
-
- /**
- * Picks a random color from the array of possible text colors
- *
- * @param colors Color array from which to pick a random element.
- * @return Color object, picked randomly out of the textCols-Field array
- */
- default Color pickRandomColor(Color[] colors) {
- if (colors.length == 1) {
- return colors[0];
- }
- ThreadLocalRandom r = ThreadLocalRandom.current();
- int i = r.nextInt(colors.length);
- return colors[i];
- }
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/BackgroundPictureTextImageRenderer.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/BackgroundPictureTextImageRenderer.java
deleted file mode 100644
index 7c596ef..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/BackgroundPictureTextImageRenderer.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRenderer;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import org.apache.commons.lang3.StringUtils;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-
-/**
- * @author Yannick Forster
- */
-@RequiredArgsConstructor
-public class BackgroundPictureTextImageRenderer extends SimpleTextImageRenderer implements TextImageRenderer {
-
- @NonNull
- private BufferedImage backgroundimg;
-
- @Override
- public final BufferedImage render(final String captchaTextInput, int height, int width) {
- if (StringUtils.isEmpty(captchaTextInput)) {
- throw new IllegalArgumentException("The specified captcha string is empty.");
- }
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- Graphics2D graphic = image.createGraphics();
- graphic.setColor(getBackgrndCol());
- graphic.drawImage(backgroundimg, null, 0, 0);
- drawDistortions(height, width, graphic);
- drawText(captchaTextInput, image);
- graphic.dispose();
- return image;
- }
-
-
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/CleanTextImageRenderer.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/CleanTextImageRenderer.java
deleted file mode 100644
index 2b8ab53..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/CleanTextImageRenderer.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRenderer;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.experimental.Accessors;
-import org.apache.commons.lang3.StringUtils;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.util.stream.IntStream;
-
-/**
- * Example implementation.
- *
- * Renders a text captcha image without visual distortions in the finished
- * image.
- *
- * @author Yannick Forster
- */
-@SuppressWarnings("DuplicatedCode")
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-@Accessors(chain = true)
-public class CleanTextImageRenderer implements TextImageRenderer {
-
- /**
- * Color of the Captcha Background
- */
- private Color backgrndCol = Color.white;
- /**
- * Set of possible colors of the letters in the captcha image
- */
- private Color[] textCols = new Color[]{Color.blue};
-
- /**
- * The name of the font used to draw the letters
- */
- private String fontName = "Verdana";
-
- /**
- * Renders a captcha image of specified height and widght of the given string
- */
- @Override
- public BufferedImage render(final String captchaTextInput, int height, int width) {
- if (StringUtils.isEmpty(captchaTextInput)) {
- throw new IllegalArgumentException("The specified captcha string is empty.");
- }
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- Graphics2D graphic = image.createGraphics();
- graphic.setColor(backgrndCol);
- graphic.fillRect(0, 0, width, height);
- drawText(captchaTextInput, image);
- graphic.dispose();
- return image;
- }
-
- /**
- * prepares the writing of the given captcha text onto the specified Graphics2d
- * object
- *
- * @param captchaTextInput string containing the text to write
- * @param image the image on which to draw
- */
- private void drawText(String captchaTextInput, BufferedImage image) {
- Graphics2D graphic = image.createGraphics();
- Font textFont = new Font(fontName, Font.BOLD, (int) (image.getHeight() / 2.5));
- graphic.setColor(pickRandomColor(textCols));
- graphic.setFont(textFont);
- FontMetrics fontMetrics = graphic.getFontMetrics();
- int margin = image.getWidth() / 16;
- int chars = captchaTextInput.length();
- float spaceForLetters = (-margin << 1) + image.getWidth();
- float spacePerChar = spaceForLetters / (chars - 1.0f);
- IntStream.range(0, chars).boxed().forEachOrdered(i -> {
- char charToDraw = captchaTextInput.charAt(i);
- drawCharacter(image, textFont, fontMetrics, margin, spacePerChar, i, charToDraw);
- });
- }
-
- /**
- * Measures the font and draws each character of the given string to the
- * Graphics2D object at a randomized angle.
- *
- * @param image the Graphics2D object containing the graphic in which the
- * image is constructed
- * @param textFont Font object containing the font in which the characters
- * are to be drawn
- * @param fontMetrics fontmetrics object used to measure the characters in the
- * string
- * @param margin calculated based on the width to define an approximate
- * margin between each letter
- * @param spacePerChar the space that the entire string will approximately
- * require
- * @param index running index of the character in the source string
- * @param charToDraw the character to draw
- */
- private void drawCharacter(BufferedImage image, Font textFont, FontMetrics fontMetrics, int margin,
- float spacePerChar, Integer index, char charToDraw) {
- int maxAdvance = fontMetrics.getMaxAdvance();
- int fontHeight = fontMetrics.getHeight();
- int charWidth = fontMetrics.charWidth(charToDraw);
- int charDim = Math.max(maxAdvance, fontHeight);
- BufferedImage charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);
- Graphics2D charGraphics = charImage.createGraphics();
- charGraphics.setColor(pickRandomColor(textCols));
- charGraphics.setFont(textFont);
- int charX = (int) (0.5 * charDim - 0.5 * charWidth);
- charGraphics.drawString(String.valueOf(charToDraw), charX,
- (charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent());
- float x = margin + spacePerChar * (index.floatValue()) - charDim / 2.0f;
- int y = (image.getHeight() - charDim) / 2;
- image.createGraphics().drawImage(charImage, (int) x, y, charDim, charDim, null, null);
- charGraphics.dispose();
- }
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/EffectChainTextImageRenderer.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/EffectChainTextImageRenderer.java
deleted file mode 100644
index 4f8e909..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/EffectChainTextImageRenderer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import com.jhlabs.image.AbstractBufferedImageOp;
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRenderer;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.experimental.Accessors;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Text Captcha rendering using a chain of Filters that will be applied to the generated image.
- *
- * @author Yannick Forster
- */
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-@Accessors(chain = true)
-public class EffectChainTextImageRenderer implements TextImageRenderer {
-
- /**
- * Set of possible colors of the letters in the captcha image
- */
- private Color[] textCols = new Color[]{Color.blue, Color.red, Color.darkGray, Color.magenta, Color.black};
-
- /**
- * List of operations that will be applied to the image during rendering.
- */
- private List bufferedOps = new ArrayList<>(0);
-
- @Override
- public BufferedImage render(final String captchaTextInput, int height, int width) {
- BufferedImage image = new SimpleTextImageRenderer().render(captchaTextInput, height, width);
- if (!bufferedOps.isEmpty()) {
- applyFilters(image);
- }
- return image;
- }
-
- private void applyFilters(BufferedImage image) {
- bufferedOps.forEach(op -> op.filter(image, image));
- }
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/SimpleTextImageRenderer.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/SimpleTextImageRenderer.java
deleted file mode 100644
index f60f983..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/SimpleTextImageRenderer.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRenderer;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.experimental.Accessors;
-import org.apache.commons.lang3.StringUtils;
-
-import java.awt.*;
-import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.security.SecureRandom;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.stream.IntStream;
-
-/**
- * Example implementation.
- *
- * Implements a rendering logic taking in an input string to generate a
- * visualization of said string and return it in a base64 string representation
- * for easier transportation
- *
- * @author Yannick Forster
- */
-@SuppressWarnings("DuplicatedCode")
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-@Accessors(chain = true)
-public class SimpleTextImageRenderer implements TextImageRenderer {
-
- /**
- * Color of the Captcha Background
- */
- private Color backgrndCol = Color.white;
- /**
- * Set of possible colors of the letters in the captcha image
- */
- private Color[] textCols = new Color[]{Color.blue};
- /**
- * Color of distortions in the image
- */
- private Color distortCol = Color.white;
- /**
- * Defines the maximum angle that can be used to rotate a single character in
- * the captcha
- */
- private double maxrotateAngle = 0.45;
- /**
- * String name of the font to be used when writing characters to the image
- */
- private String fontName = "Verdana";
-
- /**
- * Renders a captcha image of specified height and widght of the given string
- */
- @Override
- public BufferedImage render(final String captchaTextInput, int height, int width) {
- if (StringUtils.isEmpty(captchaTextInput)) {
- throw new IllegalArgumentException("The specified captcha string is empty.");
- }
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- Graphics2D graphic = image.createGraphics();
- graphic.setColor(backgrndCol);
- graphic.fillRect(0, 0, width, height);
- drawDistortions(height, width, graphic);
- drawText(captchaTextInput, image);
- graphic.dispose();
- return image;
- }
-
- /**
- * Draws distortions onto the given Graphics2D object in the shape of randomly
- * generated rectangles and dots to help obscure the text in the captcha image
- *
- * @param height pixel height of the image inside the graphics object
- * @param width pixel width of the image inside the graphics object
- * @param graphic the Graphics2D object onto which the distortions are to be
- * drawn
- */
- protected void drawDistortions(int height, int width, Graphics2D graphic) {
- graphic.setColor(distortCol);
- SecureRandom rnd = new SecureRandom();
- for (int i = 0; i < width / 64; i++) {
- int L = (int) (rnd.nextDouble() * height / 2.0);
- int X = (int) (rnd.nextDouble() * width - L);
- int Y = (int) (rnd.nextDouble() * height - L);
- graphic.draw3DRect(X, Y, L << 1, L << 1, true);
- }
- Color darkerBackgrnd = backgrndCol.darker();
- graphic.setColor(darkerBackgrnd);
- ThreadLocalRandom random = ThreadLocalRandom.current();
- int dotCount = height * width / 4;
- for (int j = 0; j < dotCount; j++) {
- int x = Math.abs(random.nextInt()) % width;
- int y = Math.abs(random.nextInt()) % height;
- graphic.drawLine(x, y, x, y);
- }
- }
-
- /**
- * prepares the writing of the given captcha text onto the specified Graphics2d
- * object
- *
- * @param captchaTextInput string containing the text to write
- * @param image the image on which to draw the text
- */
- protected void drawText(String captchaTextInput, BufferedImage image) {
- Graphics2D graphic = image.createGraphics();
- Font textFont = new Font(fontName, Font.BOLD, (int) (image.getHeight() / 2.5));
- graphic.setColor(pickRandomColor(textCols));
- graphic.setFont(textFont);
- FontMetrics fontMetrics = graphic.getFontMetrics();
- int margin = image.getWidth() / 16;
- int chars = captchaTextInput.length();
- float spaceForLetters = (-margin << 1) + image.getWidth();
- float spacePerChar = spaceForLetters / (chars - 1.0f);
- IntStream.range(0, chars).boxed().forEachOrdered(i -> {
- char charToDraw = captchaTextInput.charAt(i);
- drawCharacter(image, textFont, fontMetrics, margin, spacePerChar, i, charToDraw);
- });
- }
-
- /**
- * Measures the font and draws each character of the given string to the
- * Graphics2D object at a randomized angle.
- *
- * @param textFont Font object containing the font in which the characters
- * are to be drawn
- * @param fontMetrics fontmetrics object used to measure the characters in the
- * string
- * @param margin calculated based on the width to define an approximate
- * margin between each letter
- * @param spacePerChar the space that the entire string will approximately
- * require
- * @param index running index of the character in the source string
- */
- private void drawCharacter(BufferedImage image, Font textFont, FontMetrics fontMetrics, int margin,
- float spacePerChar, Integer index, char charToDraw) {
- int maxAdvance = fontMetrics.getMaxAdvance();
- int fontHeight = fontMetrics.getHeight();
- int charWidth = fontMetrics.charWidth(charToDraw);
- int charDim = Math.max(maxAdvance, fontHeight);
- int halfCharDim = charDim / 2;
- BufferedImage charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);
- Graphics2D charGraphics = charImage.createGraphics();
- charGraphics.translate(halfCharDim, halfCharDim);
- double angle = (new SecureRandom().nextDouble() - 0.5) * maxrotateAngle;
- charGraphics.transform(AffineTransform.getRotateInstance(angle));
- charGraphics.translate(-halfCharDim, -halfCharDim);
- charGraphics.setColor(pickRandomColor(textCols));
- charGraphics.setFont(textFont);
- int charX = (int) (0.5 * charDim - 0.5 * charWidth);
- charGraphics.drawString(String.valueOf(charToDraw), charX,
- (charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent());
- float x = margin + spacePerChar * (index.floatValue()) - charDim / 2.0f;
- int y = (image.getHeight() - charDim) / 2;
- image.createGraphics().drawImage(charImage, (int) x, y, charDim, charDim, null, null);
- charGraphics.dispose();
- }
-
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/TwirledTextImageRenderer.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/TwirledTextImageRenderer.java
deleted file mode 100644
index 786c9d9..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/TwirledTextImageRenderer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import com.jhlabs.image.TwirlFilter;
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRenderer;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.experimental.Accessors;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * Text image handler that adds a twirl effect to the rendered text captcha
- * image
- *
- * @author Yannick Forster
- */
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-@Accessors(chain = true)
-public class TwirledTextImageRenderer implements TextImageRenderer {
-
- /**
- * Set of possible colors of the letters in the captcha image
- */
- private Color[] textCols = new Color[]{Color.blue, Color.red, Color.darkGray, Color.magenta, Color.black};
- /**
- * Radius integer used for the twirling effect. Higher numbers result in a
- * stronger effect. 10 per default.
- */
- private float twirlStrength = -0.3f;
-
- @Override
- public BufferedImage render(final String captchaTextInput, int height, int width) {
- SimpleTextImageRenderer simpleRenderer = new SimpleTextImageRenderer();
- simpleRenderer.setTextCols(textCols);
- BufferedImage image = simpleRenderer.render(captchaTextInput, height, width);
- return applytwirl(image);
- }
-
- /**
- * Applies a twisting effect of the entire graphic originating in the center of
- * the image
- */
- private BufferedImage applytwirl(BufferedImage image) {
- TwirlFilter filter = new TwirlFilter();
- ThreadLocalRandom random = ThreadLocalRandom.current();
- float angle = twirlStrength;
- if (random.nextBoolean()) {
- angle = angle * (-1);
- }
- filter.setAngle(angle);
- return filter.filter(image, new BufferedImage(image.getWidth(), image.getHeight(), image.getType()));
- }
-
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/textgen/CaptchaTextGenerator.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/textgen/CaptchaTextGenerator.java
deleted file mode 100644
index 7c93b57..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/textgen/CaptchaTextGenerator.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.textgen;
-
-import io.github.yaforster.flexcaptcha.textbased.enums.Case;
-
-/**
- * Interface for declaring methods used for to generate randomized Strings
- *
- * @author Yannick Forster
- */
-public interface CaptchaTextGenerator {
-
- /**
- * String containing every character that is allowed for the generation of
- * Strings. Excludes some characters by default that may be confusing when
- * rotated in a certain way.
- */
- String DEFAULT_CHARACTER_BASE = "abcdefghjkmpqrstuvwxy2345689";
-
- /**
- * Generates a new randomized String of mixed case letters and numbers of the
- * given length
- *
- * @param length the generated string is supposed to have
- * @return randomized String of mixed case letters and numbers of the given
- * length
- */
- default String generate(int length) {
- return generate(length, DEFAULT_CHARACTER_BASE, Case.MIXEDCASE);
- }
-
- /**
- * Generates a new randomized String of the specified length consisting of a
- * randomly selected set of characters from the given string
- *
- * @param length the generated string is supposed to have
- * @param characterbase String consisting of the set of letters from which the
- * method will randomly pick characters
- * @return randomized String of the specified length consisting of a randomly
- * selected set of characters from the given string
- */
- default String generate(int length, String characterbase) {
- return generate(length, characterbase, Case.MIXEDCASE);
- }
-
- /**
- * Generates a new randomized String of letters and numbers of the given length
- * and specified case
- *
- * @param length the generated string is supposed to have
- * @param charCase Case enum with either lower-, upper-, or mixed case.
- * @return randomized String of letters and numbers of the given length and
- * specified case
- */
- default String generate(int length, Case charCase) {
- return generate(length, DEFAULT_CHARACTER_BASE, charCase);
- }
-
- /**
- * Generates a new randomized String of the specified length consisting of a
- * randomly selected set of characters from the given string, generated as
- * either upper-, lower- or mixed case, depending on the case specified
- *
- * @param length the generated string is supposed to have
- * @param characterbase String consisting of the set of letters from which the
- * method will randomly pick characters * @param charCase
- * @param charCase Case enum with either lower-, upper-, or mixed case.
- * @return randomized String of the specified length consisting of a randomly
- * selected set of characters from the given string
- */
- String generate(int length, String characterbase, Case charCase);
-
-}
\ No newline at end of file
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/textgen/impl/SimpleCaptchaTextGenerator.java b/src/main/java/io/github/yaforster/flexcaptcha/textbased/textgen/impl/SimpleCaptchaTextGenerator.java
deleted file mode 100644
index c4b2d28..0000000
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/textgen/impl/SimpleCaptchaTextGenerator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.textgen.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.enums.Case;
-import io.github.yaforster.flexcaptcha.textbased.textgen.CaptchaTextGenerator;
-import lombok.Getter;
-import lombok.Setter;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.stream.IntStream;
-
-/**
- * @author Yannick Forster
- *
- * This class is used to provide logic to generate or accept a String
- * representing the image content and the solution for the Captcha for
- * further processing
- */
-@Getter
-@Setter
-public class SimpleCaptchaTextGenerator implements CaptchaTextGenerator {
-
- /**
- * Checks the given Case enum and modifies the case of the character based on
- * the enum.
- *
- * @param charCase Case enum defining the character to either be lowercase,
- * uppercase or random case.
- * @param c the character
- * @return modified char
- */
- private static char setCase(Case charCase, char c) {
- switch (charCase) {
- case LOWERCASE:
- c = Character.toLowerCase(c);
- break;
- case UPPERCASE:
- c = Character.toUpperCase(c);
- break;
- default:
- ThreadLocalRandom random = ThreadLocalRandom.current();
- if (random.nextBoolean()) {
- c = Character.toUpperCase(c);
- }
- break;
- }
- return c;
- }
-
- /**
- * Returns a single character from the String at a random position in the string
- *
- * @param src source String from which the character is randomly pulled
- * @return character pulled from the String at random point
- */
- private static char pickRandomChar(String src) {
- ThreadLocalRandom random = ThreadLocalRandom.current();
- int index = random.nextInt(src.length());
- return src.charAt(index);
- }
-
- /**
- * Constructs the output String by repeatedly copying a single character from
- * the characterbase-String at a random point until the specified length is
- * reached. The case-enum controls whether the case of the letters. Mixed
- * case will randomize the case of each character every time it is picked from
- * the source string
- *
- * @param length the generated string is supposed to have
- * @param characterbase String consisting of the set of letters from which the
- * method will randomly pick characters
- * @param charCase Case enum with either lower-, upper-, or mixed case.
- * @return randomized String of the specified length consisting of a randomly
- * selected set of characters from the given string
- */
- private static String getRandomLetters(int length, String characterbase, Case charCase) {
- StringBuffer charbuf = new StringBuffer(0);
- IntStream.range(0, length).forEach(i -> {
- char c = pickRandomChar(characterbase);
- c = setCase(charCase, c);
- charbuf.append(c);
- });
- return charbuf.toString();
- }
-
- /**
- * Generates a new randomized String of the specified length consisting of a
- * randomly selected set of characters from the given string, generated as
- * either upper-, lower- or mixed case, depending on the case specified
- *
- * @param length the generated string is supposed to have
- * @param characterbase String consisting of the set of letters from which the
- * method will randomly pick characters
- * @param charCase Case enum with either lower-, upper-, or mixed case.
- * @return randomized String of the specified length consisting of a randomly
- * selected set of characters from the given string
- */
- @Override
- public String generate(int length, String characterbase, Case charCase) {
- if (StringUtils.isEmpty(characterbase)) {
- throw new IllegalArgumentException(
- "the specified character base from which to draw the captcha characters is empty.");
- }
- return getRandomLetters(length, characterbase, charCase);
- }
-
-}
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/util/AbstractTextGenerator.java b/src/main/java/io/github/yaforster/flexcaptcha/util/AbstractTextGenerator.java
new file mode 100644
index 0000000..131017d
--- /dev/null
+++ b/src/main/java/io/github/yaforster/flexcaptcha/util/AbstractTextGenerator.java
@@ -0,0 +1,61 @@
+package io.github.yaforster.flexcaptcha.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Interface for declaring methods used for to generate randomized Strings
+ *
+ * @author Yannick Forster
+ */
+public abstract class AbstractTextGenerator {
+
+ /**
+ * String containing every character that is allowed for the generation of
+ * Strings. Excludes some characters by default that may be confusing when
+ * rotated in a certain way.
+ */
+ protected final static String DEFAULT_CHARACTER_BASE = "abcdefghjkmpqrstuvwxy2345689";
+ /**
+ * String consisting of the set of letters from which the method will randomly pick characters
+ */
+ protected final String characterbase;
+
+ protected AbstractTextGenerator(String characterbase) {
+ this.characterbase = getCharCaseOrDefault(characterbase);
+ }
+
+ protected static String getCharCaseOrDefault(String characterbase) {
+ if (characterbase != null && !StringUtils.isBlank(characterbase)) {
+ return characterbase;
+ }
+ else {
+ return DEFAULT_CHARACTER_BASE;
+ }
+ }
+
+
+ /**
+ * Generates a new randomized String of the specified length consisting of a
+ * randomly selected set of characters from the given string
+ *
+ * @param length the generated string is supposed to have
+ * @return randomized String of the specified length consisting of a randomly
+ * selected set of characters from the given string
+ */
+ public final String generate(int length) {
+ return generate(length, TextCase.MIXEDCASE);
+ }
+
+ /**
+ * Generates a new randomized String of the specified length consisting of a
+ * randomly selected set of characters from the given string, generated as
+ * either upper-, lower- or mixed case, depending on the case specified
+ *
+ * @param length the generated string is supposed to have
+ * @param charTextCase Case enum with either lower-, upper-, or mixed case.
+ * @return randomized String of the specified length consisting of a randomly
+ * selected set of characters from the given string
+ */
+ abstract String generate(int length, TextCase charTextCase);
+
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/textbased/enums/Case.java b/src/main/java/io/github/yaforster/flexcaptcha/util/TextCase.java
similarity index 50%
rename from src/main/java/io/github/yaforster/flexcaptcha/textbased/enums/Case.java
rename to src/main/java/io/github/yaforster/flexcaptcha/util/TextCase.java
index f7bacc3..401527c 100644
--- a/src/main/java/io/github/yaforster/flexcaptcha/textbased/enums/Case.java
+++ b/src/main/java/io/github/yaforster/flexcaptcha/util/TextCase.java
@@ -1,4 +1,4 @@
-package io.github.yaforster.flexcaptcha.textbased.enums;
+package io.github.yaforster.flexcaptcha.util;
import lombok.Getter;
@@ -8,28 +8,19 @@
* @author Yannick Forster
*/
@Getter
-public enum Case {
+public enum TextCase {
/**
* Uppercase letters only
*/
- UPPERCASE(0),
+ UPPERCASE,
/**
* Lowercase letters only
*/
- LOWERCASE(1),
+ LOWERCASE,
/**
* Both uppercase and lowercase letters
*/
- MIXEDCASE(2);
+ MIXEDCASE
- /**
- * A number representing the available cases
- */
- private final int caseNum;
-
- Case(int caseNum) {
- this.caseNum = caseNum;
- }
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/yaforster/flexcaptcha/util/TextGenerator.java b/src/main/java/io/github/yaforster/flexcaptcha/util/TextGenerator.java
new file mode 100644
index 0000000..27c93fd
--- /dev/null
+++ b/src/main/java/io/github/yaforster/flexcaptcha/util/TextGenerator.java
@@ -0,0 +1,105 @@
+package io.github.yaforster.flexcaptcha.util;
+
+import lombok.Builder;
+
+import java.security.SecureRandom;
+import java.util.stream.IntStream;
+
+/**
+ * @author Yannick Forster
+ *
+ * This class is used to provide logic to generate or accept a String
+ * representing the image content and the solution for the Captcha for
+ * further processing
+ */
+public class TextGenerator extends AbstractTextGenerator {
+
+ @Builder
+ public TextGenerator(String characterbase) {
+ super(characterbase);
+ }
+
+ /**
+ * Checks the given Case enum and modifies the case of the character based on
+ * the enum.
+ *
+ * @param charTextCase Case enum defining the character to either be lowercase,
+ * uppercase or random case.
+ * @param c the character
+ * @return modified char
+ */
+ private static char setCase(TextCase charTextCase, char c) {
+ return switch (charTextCase) {
+ case LOWERCASE:
+ yield Character.toLowerCase(c);
+ case UPPERCASE:
+ yield Character.toUpperCase(c);
+ default:
+ SecureRandom random = new SecureRandom();
+ if (random.nextBoolean()) {
+ yield Character.toUpperCase(c);
+ }
+ else {
+ yield c;
+ }
+ };
+ }
+
+ /**
+ * Returns a single character from the String at a random position in the string
+ *
+ * @param src source String from which the character is randomly pulled
+ * @return character pulled from the String at random point
+ */
+ private static char pickRandomChar(String src) {
+ SecureRandom random = new SecureRandom();
+ int index = random.nextInt(src.length());
+ return src.charAt(index);
+ }
+
+ /**
+ * Constructs the output String by repeatedly copying a single character from
+ * the characterbase-String at a random point until the specified length is
+ * reached. The case-enum controls whether the case of the letters. Mixed
+ * case will randomize the case of each character every time it is picked from
+ * the source string
+ *
+ * @param length the generated string is supposed to have
+ * @param charTextCase Case enum with either lower-, upper-, or mixed case.
+ * @return randomized String of the specified length consisting of a randomly
+ * selected set of characters from the given string
+ */
+ private String getRandomLetters(int length, TextCase charTextCase) {
+ StringBuffer charbuf = new StringBuffer(0);
+ IntStream.range(0, length).forEach(i -> {
+ appendBufferByRandomCharOfCase(charTextCase, charbuf);
+ });
+ return charbuf.toString();
+ }
+
+ private void appendBufferByRandomCharOfCase(TextCase charTextCase, StringBuffer charbuf) {
+ char c = pickRandomCharWithCase(charTextCase);
+ charbuf.append(c);
+ }
+
+ private char pickRandomCharWithCase(TextCase charTextCase) {
+ char randomChar = pickRandomChar(characterbase);
+ return setCase(charTextCase, randomChar);
+ }
+
+ /**
+ * Generates a new randomized String of the specified length consisting of a
+ * randomly selected set of characters from the given string, generated as
+ * either upper-, lower- or mixed case, depending on the case specified
+ *
+ * @param length the generated string is supposed to have
+ * @param charTextCase Case enum with either lower-, upper-, or mixed case.
+ * @return randomized String of the specified length consisting of a randomly
+ * selected set of characters from the given string
+ */
+ @Override
+ public final String generate(int length, TextCase charTextCase) {
+ return getRandomLetters(length, charTextCase);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
index cffe811..eb50e2e 100644
--- a/src/main/resources/log4j2.xml
+++ b/src/main/resources/log4j2.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/CaptchaGeneratorTest.java b/src/test/java/io/github/yaforster/flexcaptcha/CaptchaGeneratorTest.java
new file mode 100644
index 0000000..3402de4
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/CaptchaGeneratorTest.java
@@ -0,0 +1,40 @@
+package io.github.yaforster.flexcaptcha;
+
+import io.github.yaforster.flexcaptcha.core.Captcha;
+import io.github.yaforster.flexcaptcha.core.CaptchaGenerator;
+import io.github.yaforster.flexcaptcha.impl.rendering.CaptchaRenderer;
+import io.github.yaforster.flexcaptcha.impl.token.CaptchaCipher;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CaptchaGeneratorTest {
+
+ @Test
+ void generate_with_default_should_work() {
+ CaptchaCipher cipher = CaptchaCipher.builder().build();
+ CaptchaRenderer renderer = CaptchaRenderer.getDefaultCaptchaRenderer();
+ CaptchaGenerator generator = new CaptchaGenerator(cipher, renderer);
+ assertDoesNotThrow(() -> generator.generate("abc123", "salt"));
+ }
+
+ @Test
+ void test_validation_should_work() {
+ CaptchaCipher cipher = CaptchaCipher.builder().build();
+ CaptchaRenderer renderer = CaptchaRenderer.getDefaultCaptchaRenderer();
+ CaptchaGenerator generator = new CaptchaGenerator(cipher, renderer);
+ assertTrue(generator.validate("vnBn8x3bpm3wkvJYANdy9VNRijRowlFyq72US0ja4Jo=", "aBc123", "salt"));
+ }
+
+ @Test
+ void test_can_validate_own_tokens() {
+ CaptchaCipher cipher = CaptchaCipher.builder().build();
+ CaptchaRenderer renderer = CaptchaRenderer.getDefaultCaptchaRenderer();
+ CaptchaGenerator generator = new CaptchaGenerator(cipher, renderer);
+ String solution = "aBc123";
+ String someSalt = "salt";
+ Captcha captcha = generator.generate(solution, someSalt);
+ assertTrue(generator.validate(captcha.token(), solution, someSalt));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/CaptchaHandlerTest.java b/src/test/java/io/github/yaforster/flexcaptcha/CaptchaHandlerTest.java
deleted file mode 100644
index a8f5253..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/CaptchaHandlerTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package io.github.yaforster.flexcaptcha;
-
-import org.apache.commons.lang3.NotImplementedException;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import javax.crypto.spec.IvParameterSpec;
-import java.awt.*;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-
-/**
- * Tests default methods of the {@link CaptchaHandler} interface using an
- * arbitrary implementation
- *
- *
- * @author Yannick Forster
- */
-public class CaptchaHandlerTest {
-
- private final CipherHandler cipherHandler = getCHMock();
- private final String password = "ThisIsMyPassword";
- private final Button dummyObj = new Button();
- private final CaptchaHandler captchaHandler = makeCaptchaHandler();
-
- @Test
- public void testAddSelfReference() {
- String selfReference = captchaHandler.addSelfReference(cipherHandler, dummyObj, password);
- String selfReferenceBase64 = selfReference.split(CaptchaHandler.DELIMITER)[1];
- assertEquals("AQID", selfReferenceBase64);
- }
-
- @Test
- public void testGetSaltObjectBytes() {
- try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos)) {
- oos.writeObject(dummyObj);
- baos.close();
- oos.close();
- byte[] testbytes = baos.toByteArray();
- byte[] methodTestBytes = captchaHandler.getSaltObjectBytes(dummyObj);
- assertArrayEquals(testbytes, methodTestBytes);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /*
- * === Test setup ===
- */
-
- private CipherHandler getCHMock() {
- CipherHandler cipherHandler = Mockito.mock(CipherHandler.class);
- Mockito.when(cipherHandler.generateIV())
- .thenReturn(new IvParameterSpec(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}));
- Mockito.when(cipherHandler.decryptString(any(byte[].class), anyString(), any()))
- .thenReturn(new byte[]{1, 2, 3});
- Mockito.when(cipherHandler.encryptString(any(byte[].class), anyString(), any(), any(byte[].class)))
- .thenReturn(new byte[]{1, 2, 3});
- return cipherHandler;
-
- }
-
- private CaptchaHandler makeCaptchaHandler() {
- return (answer, token, cipherHandler, saltSource, password) -> {
- throw new NotImplementedException();
- };
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/CaptchaTest.java b/src/test/java/io/github/yaforster/flexcaptcha/CaptchaTest.java
new file mode 100644
index 0000000..59ae30d
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/CaptchaTest.java
@@ -0,0 +1,16 @@
+package io.github.yaforster.flexcaptcha;
+
+import io.github.yaforster.flexcaptcha.core.Captcha;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CaptchaTest {
+
+ @Test
+ void getImgDataAsBase64() {
+ Captcha captcha = new Captcha("someToken", new byte[]{1, 2, 3, 4, 5});
+ String imgBytesBase64 = captcha.getImgDataAsBase64();
+ assertEquals("AQIDBAU=", imgBytesBase64);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/CipherHandlerTest.java b/src/test/java/io/github/yaforster/flexcaptcha/CipherHandlerTest.java
deleted file mode 100644
index 9072377..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/CipherHandlerTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package io.github.yaforster.flexcaptcha;
-
-import org.junit.Test;
-
-import java.awt.*;
-
-import static org.junit.Assert.*;
-
-public class CipherHandlerTest {
-
- private final CipherHandler ch = new CipherHandler();
- private final byte[] inputBytes = "TestString".getBytes();
- private final String password = "ThisIsMyPassword";
- private final Button dummyObj = new Button();
- private final byte[] ivBytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-
- private final byte[] encrExpected = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -32, 13, -33, -117, 18,
- 92, 6, 17, -66, -63, -118, 122, -18, 119, -57, -13};
- private final byte[] decrExpected = new byte[]{84, 101, 115, 116, 83, 116, 114, 105, 110, 103};
- private final byte[] encrNoSaltSourceExpected = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -80, -47, -48,
- 81, 125, 62, 101, 85, -9, 21, -103, -91, 94, 95, 80, 88};
- private final byte[] decrNoSaltSourceExpected = new byte[]{84, 101, 115, 116, 83, 116, 114, 105, 110, 103};
-
- @Test
- public void testEncryptString_ShouldWork() {
- byte[] encrypted = ch.encryptString(inputBytes, password, dummyObj, ivBytes);
- assertArrayEquals(encrypted, encrExpected);
- }
-
- @Test
- public void testEncryptString_NoInput_ShouldFail() {
- assertThrows(IllegalArgumentException.class, () -> ch.encryptString(null, password, dummyObj, ivBytes));
- }
-
- @Test
- public void testEncryptString_NoPassword_ShouldFail() {
- assertThrows(IllegalArgumentException.class, () -> ch.encryptString(inputBytes, null, dummyObj, ivBytes));
- }
-
- @Test
- public void testEncryptString_NoSaltSource_ShouldWork() {
- byte[] encrypted = ch.encryptString(inputBytes, password, null, ivBytes);
- assertEquals(32, encrypted.length);
- }
-
- @Test
- public void testEncryptString_EmptySaltSource_ShouldWork() {
- byte[] encrypted = ch.encryptString(inputBytes, password, "", ivBytes);
- assertEquals(32, encrypted.length);
- }
-
- @Test
- public void testEncryptString_NullIVBytes_ShouldFail() {
- assertThrows(NullPointerException.class, () -> ch.encryptString(inputBytes, password, "", null));
- }
-
- @Test
- public void testEncryptString_NoIVBytes_ShouldWork() {
- byte[] encrypted = ch.encryptString(inputBytes, password, "");
- assertEquals(32, encrypted.length);
- }
-
- @Test
- public void testDecryptString_ShouldWork() {
- byte[] decrypted = ch.decryptString(encrExpected, password, dummyObj);
- assertArrayEquals(decrypted, decrExpected);
- }
-
- @Test
- public void testDecryptString_NoInput_ShouldFail() {
- assertThrows(NullPointerException.class, () -> ch.decryptString(null, password, dummyObj));
- }
-
- @Test
- public void testDecryptString_NoPassword_ShouldFail() {
- assertThrows(IllegalArgumentException.class, () -> ch.decryptString(inputBytes, null, dummyObj));
- }
-
- @Test
- public void testDecryptString_NoSaltSource_ShouldWork() {
- byte[] decrypted = ch.decryptString(encrNoSaltSourceExpected, password, null);
- assertArrayEquals(decrypted, decrNoSaltSourceExpected);
- }
-
- @Test
- public void testDecryptString_EmptySaltSource_ShouldFail() {
- byte[] decrypted = ch.decryptString(encrNoSaltSourceExpected, password, "");
- assertNull(decrypted);
- }
-
- @Test
- public void testGenerateIV_ShouldWork() {
- byte[] iv = new CipherHandler().generateIV().getIV();
- assertEquals(16, iv.length);
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/core/AbstractCaptchaCipherTest.java b/src/test/java/io/github/yaforster/flexcaptcha/core/AbstractCaptchaCipherTest.java
new file mode 100644
index 0000000..53dbc4f
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/core/AbstractCaptchaCipherTest.java
@@ -0,0 +1,64 @@
+package io.github.yaforster.flexcaptcha.core;
+
+import io.github.yaforster.flexcaptcha.impl.token.CaptchaCipher;
+import io.github.yaforster.flexcaptcha.impl.token.CipherInstantiationException;
+import io.github.yaforster.flexcaptcha.impl.token.CipherSettings;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import java.security.NoSuchAlgorithmException;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+
+class AbstractCaptchaCipherTest {
+
+ private static final String FICTIONAL_PASSWORD = "somepassword";
+ private static final String FICTIONAL_SALT = "salt";
+ private static final byte[] FICTIONAL_IV = {-71, 11, 45, -61, 44, -22, 5, -21, -91, -80, -121, -48, 29, -31, -25,
+ 76};
+
+ @Test
+ final void getCipher_shouldWork() {
+ CaptchaCipher captchaCipher = CaptchaCipher.builder().build();
+ assertDoesNotThrow(() -> captchaCipher.getCipher(FICTIONAL_PASSWORD, FICTIONAL_SALT, Cipher.ENCRYPT_MODE,
+ FICTIONAL_IV));
+ }
+
+ @Test
+ final void getCipher_should_Throw_and_map_SuchPaddingException() {
+ try (MockedStatic cipherMockedStatic = Mockito.mockStatic(Cipher.class)) {
+ cipherMockedStatic.when(() -> Cipher.getInstance(any())).thenThrow(NoSuchPaddingException.class);
+ CaptchaCipher captchaCipher = CaptchaCipher.builder().build();
+ CipherInstantiationException exception = assertThrows(CipherInstantiationException.class,
+ () -> captchaCipher.getCipher(FICTIONAL_PASSWORD, FICTIONAL_SALT, Cipher.ENCRYPT_MODE,
+ FICTIONAL_IV));
+ assertTrue(exception.getLocalizedMessage().contains("Unknown padding specified for token encryption"));
+ }
+ }
+
+ @Test
+ final void getCipher_should_Throw_and_map_NoSuchAlgorithmException() {
+ try (MockedStatic cipherMockedStatic = Mockito.mockStatic(Cipher.class)) {
+ cipherMockedStatic.when(() -> Cipher.getInstance(any())).thenThrow(NoSuchAlgorithmException.class);
+ CaptchaCipher captchaCipher = CaptchaCipher.builder().build();
+ CipherInstantiationException exception = assertThrows(CipherInstantiationException.class,
+ () -> captchaCipher.getCipher(FICTIONAL_PASSWORD, FICTIONAL_SALT, Cipher.ENCRYPT_MODE,
+ FICTIONAL_IV));
+ assertTrue(exception.getLocalizedMessage().contains("Unknown padding specified for token encryption"));
+ }
+ }
+
+ @Test
+ final void getCipher_should_Throw_and_map_anything_else() {
+ CipherSettings invalidCipherSettings = new CipherSettings("PBKDF2WithHmacSHA256", "AES/CBC/PKCS5Padding",
+ "somethingBroken");
+ CaptchaCipher captchaCipher = CaptchaCipher.builder().cipherSettings(invalidCipherSettings).build();
+ CipherInstantiationException exception = assertThrows(CipherInstantiationException.class,
+ () -> captchaCipher.getCipher(FICTIONAL_PASSWORD, FICTIONAL_SALT, Cipher.ENCRYPT_MODE, FICTIONAL_IV));
+ assertTrue(exception.getLocalizedMessage().contains("Fatal error during token encryption"));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/core/CaptchaTest.java b/src/test/java/io/github/yaforster/flexcaptcha/core/CaptchaTest.java
deleted file mode 100644
index c2616b2..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/core/CaptchaTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.yaforster.flexcaptcha.core;
-
-import io.github.yaforster.flexcaptcha.Captcha;
-import io.github.yaforster.flexcaptcha.textbased.TextCaptcha;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Tests {@link Captcha}
- *
- * @author Yannick Forster
- */
-public class CaptchaTest {
-
- @Test
- public void testGetImgDataAsBase64() {
- TextCaptcha captcha = new TextCaptcha(new byte[]{-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72}, "ABC");
- assertEquals("iVBORw0KGgoAAAANSUg=", captcha.getImgDataAsBase64());
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/imgbased/handling/ImageCaptchaHandlerTest.java b/src/test/java/io/github/yaforster/flexcaptcha/imgbased/handling/ImageCaptchaHandlerTest.java
deleted file mode 100644
index 37f02f4..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/imgbased/handling/ImageCaptchaHandlerTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package io.github.yaforster.flexcaptcha.imgbased.handling;
-
-import io.github.yaforster.flexcaptcha.CipherHandler;
-import io.github.yaforster.flexcaptcha.imgbased.ImageCaptcha;
-import io.github.yaforster.flexcaptcha.imgbased.handling.impl.SimpleImageCaptchaHandler;
-import org.apache.commons.lang3.ArrayUtils;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import javax.crypto.spec.IvParameterSpec;
-import javax.imageio.ImageIO;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.stream.Stream;
-
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-
-/**
- * Tests the default methods of the {@link ImageCaptchaHandler} interface using
- * an arbitrary implementation
- *
- * @author Yannick Forster
- */
-@SuppressWarnings("ZeroLengthArrayAllocation")
-public class ImageCaptchaHandlerTest {
-
- private final ImageCaptchaHandler handler = new SimpleImageCaptchaHandler();
- private final BufferedImage[] dummyArr = new BufferedImage[]{new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR)};
- private final BufferedImage[] dummyArr2 = new BufferedImage[]{new BufferedImage(15, 15, BufferedImage.TYPE_4BYTE_ABGR)};
- private final Button dummySerializable = new Button();
- private final String password = "ThisIsMyPassword!";
- private final CipherHandler cipherHandler = getCHMock();
-
- @Test
- public void testWithDummyObjs_ShouldWork() {
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable, password, dummyArr, dummyArr2,
- true);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(ArrayUtils.isNotEmpty(captcha.getImgData()));
- }
-
- @Test
- public void testWithDifferentDummyObjs_ShouldWork() {
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable, password, dummyArr, dummyArr2,
- true);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Arrays.stream(captcha.getImgData()).distinct().count() > 2);
- }
-
- @Test
- public void testNullSerializable_Shouldwork() {
- ImageCaptcha captcha = handler.generate(2, cipherHandler, null, password, dummyArr, dummyArr2, true);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(ArrayUtils.isNotEmpty(captcha.getImgData()));
- }
-
- @Test
- public void testEmptySerializable_Shouldwork() {
- ImageCaptcha captcha = handler.generate(2, cipherHandler, "", password, dummyArr, dummyArr2, true);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(ArrayUtils.isNotEmpty(captcha.getImgData()));
- }
-
- @Test
- public void testNullArrays() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(2, cipherHandler, null, password, null, null, true));
- }
-
- @Test
- public void testEmptyArrays() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(2, cipherHandler, null, password, new BufferedImage[]{}, new BufferedImage[]{}, true));
- }
-
- @Test
- public void testNullSolutionArray() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(2, cipherHandler, null, password, dummyArr, null, true));
- }
-
- @Test
- public void testEmptySolutionArray() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(2, cipherHandler, null, password, new BufferedImage[]{}, null, true));
- }
-
- @Test
- public void testNullFillArray() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(2, cipherHandler, null, password, null, dummyArr, true));
- }
-
- @Test
- public void testEmptyFillArray() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(2, cipherHandler, null, password, dummyArr, new BufferedImage[]{}, true));
- }
-
- @Test
- public void autoResizeTest30x30() {
- BufferedImage smallImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage largeImage = new BufferedImage(30, 30, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage[] images = new BufferedImage[]{smallImage, largeImage};
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable, password, images, images, true);
- BufferedImage[] resizedImages = Stream.of(captcha.getImgData()).map(data -> {
- try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) {
- return ImageIO.read(stream);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }).toArray(BufferedImage[]::new);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Stream.of(resizedImages).allMatch(img -> (img.getHeight() == 30 && img.getWidth() == 30)));
- }
-
- @Test
- public void autoResizeTest30x10() {
- BufferedImage smallImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage largeImage = new BufferedImage(10, 30, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage[] images = new BufferedImage[]{smallImage, largeImage};
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable, password, images, images, true);
- BufferedImage[] resizedImages = Stream.of(captcha.getImgData()).map(data -> {
- try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) {
- return ImageIO.read(stream);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }).toArray(BufferedImage[]::new);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Stream.of(resizedImages).allMatch(img -> (img.getHeight() == 30 && img.getWidth() == 10)));
- }
-
- @Test
- public void autoResizeTest10x30() {
- BufferedImage smallImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage largeImage = new BufferedImage(30, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage[] images = new BufferedImage[]{smallImage, largeImage};
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable, password, images, images, true);
- BufferedImage[] resizedImages = Stream.of(captcha.getImgData()).map(data -> {
- try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) {
- return ImageIO.read(stream);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }).toArray(BufferedImage[]::new);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Stream.of(resizedImages).allMatch(img -> (img.getHeight() == 10 && img.getWidth() == 30)));
- }
-
- private CipherHandler getCHMock() {
- CipherHandler cipherHandler = Mockito.mock(CipherHandler.class);
- Mockito.when(cipherHandler.generateIV())
- .thenReturn(new IvParameterSpec(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}));
- Mockito.when(cipherHandler.decryptString(any(byte[].class), anyString(), any()))
- .thenReturn(new byte[]{1, 2, 3});
- Mockito.when(cipherHandler.encryptString(any(byte[].class), anyString(), any(), any(byte[].class)))
- .thenReturn(new byte[]{1, 2, 3});
- return cipherHandler;
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/imgbased/handling/impl/SimpleImageCaptchaHandlerTest.java b/src/test/java/io/github/yaforster/flexcaptcha/imgbased/handling/impl/SimpleImageCaptchaHandlerTest.java
deleted file mode 100644
index 71d1715..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/imgbased/handling/impl/SimpleImageCaptchaHandlerTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package io.github.yaforster.flexcaptcha.imgbased.handling.impl;
-
-import io.github.yaforster.flexcaptcha.CipherHandler;
-import io.github.yaforster.flexcaptcha.imgbased.ImageCaptcha;
-import io.github.yaforster.flexcaptcha.imgbased.handling.ImageCaptchaHandler;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import javax.crypto.spec.IvParameterSpec;
-import javax.imageio.ImageIO;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.stream.Stream;
-
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-
-/**
- * Tests {@link SimpleImageCaptchaHandler}
- *
- * @author Yannick Forster
- */
-public class SimpleImageCaptchaHandlerTest {
-
- private final ImageCaptchaHandler handler = new SimpleImageCaptchaHandler();
- private final BufferedImage[] dummyArr = new BufferedImage[]{new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR)};
- private final BufferedImage[] dummyArr2 = new BufferedImage[]{new BufferedImage(15, 15, BufferedImage.TYPE_4BYTE_ABGR)};
- private final Button dummySerializable = new Button();
- private final String password = "ThisIsMyPassword!";
- private final CipherHandler cipherHandler = getCHMock();
-
- @Test
- public void testAllNull() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(0, cipherHandler, null, null, null, null, 0, 0, true));
- }
-
- @Test
- public void testGridWidth0_ShouldFail() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(0, cipherHandler, dummySerializable, password,
- dummyArr, dummyArr2, true));
- }
-
- @Test
- public void testGridWidth1_ShouldFail() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, dummySerializable, password,
- dummyArr, dummyArr2, true));
- }
-
- @Test
- public void manualResizeTest30x10() {
- BufferedImage smallImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage largeImage = new BufferedImage(10, 30, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage[] images = new BufferedImage[]{smallImage, largeImage};
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable,
- password, images, images, 30, 10, true);
- BufferedImage[] resizedImages = getResizedImages(captcha);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Stream.of(resizedImages).allMatch(img -> (img.getHeight() == 30 && img.getWidth() == 10)));
- }
-
- @Test
- public void manualResizeTest30x30() {
- BufferedImage smallImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage largeImage = new BufferedImage(10, 30, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage[] images = new BufferedImage[]{smallImage, largeImage};
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable,
- password, images, images, 30, 30, true);
- BufferedImage[] resizedImages = getResizedImages(captcha);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Stream.of(resizedImages).allMatch(img -> (img.getHeight() == 30 && img.getWidth() == 30)));
- }
-
- @Test
- public void manualResizeTest10x30() {
- BufferedImage smallImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage largeImage = new BufferedImage(10, 30, BufferedImage.TYPE_3BYTE_BGR);
- BufferedImage[] images = new BufferedImage[]{smallImage, largeImage};
- ImageCaptcha captcha = handler.generate(2, cipherHandler, dummySerializable,
- password, images, images, 10, 30, true);
- BufferedImage[] resizedImages = getResizedImages(captcha);
- assertTrue(captcha.getToken().length() > 0);
- assertTrue(Stream.of(resizedImages).allMatch(img -> (img.getHeight() == 10 && img.getWidth() == 30)));
- }
-
- private BufferedImage[] getResizedImages(ImageCaptcha captcha) {
- return Stream.of(captcha.getImgData()).map(data -> {
- try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) {
- return ImageIO.read(stream);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }).toArray(BufferedImage[]::new);
- }
-
- private CipherHandler getCHMock() {
- CipherHandler cipherHandler = Mockito.mock(CipherHandler.class);
- Mockito.when(cipherHandler.generateIV())
- .thenReturn(new IvParameterSpec(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}));
- Mockito.when(cipherHandler.decryptString(any(byte[].class), anyString(), any()))
- .thenReturn(new byte[]{1, 2, 3});
- Mockito.when(cipherHandler.encryptString(any(byte[].class), anyString(), any(), any(byte[].class)))
- .thenReturn(new byte[]{1, 2, 3});
- return cipherHandler;
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/BackgroundImageTest.java b/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/BackgroundImageTest.java
new file mode 100644
index 0000000..466738d
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/BackgroundImageTest.java
@@ -0,0 +1,27 @@
+package io.github.yaforster.flexcaptcha.impl.rendering;
+
+import org.junit.jupiter.api.Test;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class BackgroundImageTest {
+
+ @Test
+ void drawBackground_test_pixels_of_image() {
+ Color testColor = Color.RED;
+ BufferedImage fictionalImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+ fictionalImage.setRGB(0, 0, testColor.getRGB());
+ BackgroundImage background = new BackgroundImage(Color.BLUE, fictionalImage);
+ BufferedImage testImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+
+ background.drawBackground(testImage);
+
+ int pixel = testImage.getRGB(0, 0);
+ Color pixelColor = new Color(pixel, true);
+
+ assertEquals(testColor, pixelColor);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/CaptchaRendererTest.java b/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/CaptchaRendererTest.java
new file mode 100644
index 0000000..bb25970
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/CaptchaRendererTest.java
@@ -0,0 +1,99 @@
+package io.github.yaforster.flexcaptcha.impl.rendering;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+
+class CaptchaRendererTest {
+
+ @Test
+ final void renderAndConvertToBytes_with_default_renderer() {
+ CaptchaRenderer renderer = CaptchaRenderer.getDefaultCaptchaRenderer();
+ assertDoesNotThrow(() -> renderer.renderAndConvertToBytes("abc123"));
+ }
+
+ @Test
+ final void renderAndConvertToBytes_with_undefined_renderer() {
+ CaptchaRenderer renderer = CaptchaRenderer.builder().build();
+ assertDoesNotThrow(() -> renderer.renderAndConvertToBytes("abc123"));
+ }
+
+ @Test
+ final void renderAndConvertToBytes_test_height() throws IOException {
+ int targetHeight = 100;
+ CaptchaRenderer renderer = CaptchaRenderer.builder().pictureHeight(targetHeight).build();
+ byte[] imageAsBytes = renderer.renderAndConvertToBytes("abc123");
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(imageAsBytes)) {
+ BufferedImage image = ImageIO.read(bis);
+ assertEquals(targetHeight, image.getHeight());
+ }
+ }
+
+ @Test
+ final void renderAndConvertToBytes_test_width() throws IOException {
+ int targetWidth = 300;
+ CaptchaRenderer renderer = CaptchaRenderer.builder().pictureWidth(targetWidth).build();
+ byte[] imageAsBytes = renderer.renderAndConvertToBytes("abc123");
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(imageAsBytes)) {
+ BufferedImage image = ImageIO.read(bis);
+ assertEquals(targetWidth, image.getWidth());
+ }
+ }
+
+ @Test
+ final void renderAndConvertToBytes_test_color_settings() throws IOException {
+ CaptchaRenderer renderer = CaptchaRenderer.builder()
+ .noiseSettings(new NoiseSettings(1, Color.GRAY))
+ .availableTextColors(Collections.singletonList(Color.BLUE))
+ .imageBackground(new FlatColorBackground(Color.BLUE))
+ .build();
+ byte[] imageAsBytes = renderer.renderAndConvertToBytes("abc123");
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(imageAsBytes)) {
+ BufferedImage image = ImageIO.read(bis);
+ int pixel = image.getRGB(0, 0);
+ Color pixelColor = new Color(pixel, true);
+ assertTrue(200 < pixelColor.getBlue());
+ }
+ }
+
+ @Test
+ final void renderAndConvertToBytes_as_png() {
+ CaptchaRenderer renderer = CaptchaRenderer.builder().imgFileFormat("png").build();
+ assertDoesNotThrow(() -> renderer.renderAndConvertToBytes("abc123"));
+ }
+
+ @Test
+ final void renderAndConvertToBytes_catch_null_in_builder() {
+ CaptchaRenderer renderer = CaptchaRenderer.builder().imgFileFormat(null).build();
+ assertDoesNotThrow(() -> renderer.renderAndConvertToBytes("abc123"));
+ }
+
+ @Test
+ final void renderAndConvertToBytes_with_multiple_colors() {
+ List colors = List.of(Color.BLUE, Color.BLACK);
+ CaptchaRenderer renderer = CaptchaRenderer.builder().availableTextColors(colors).build();
+ assertDoesNotThrow(() -> renderer.renderAndConvertToBytes("abc123"));
+ }
+
+ @Test
+ final void renderAndConvertToBytes_test_errorhandling() {
+ try (MockedStatic imageIOMock = Mockito.mockStatic(ImageIO.class)) {
+ imageIOMock.when(() -> ImageIO.write(any(), any(), Mockito.any(OutputStream.class)))
+ .thenThrow(IOException.class);
+ CaptchaRenderer renderer = CaptchaRenderer.builder().imgFileFormat(null).build();
+ assertThrows(CaptchaRenderingException.class, () -> renderer.renderAndConvertToBytes("abc123"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/FlatColorBackgroundTest.java b/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/FlatColorBackgroundTest.java
new file mode 100644
index 0000000..934b0c8
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/impl/rendering/FlatColorBackgroundTest.java
@@ -0,0 +1,25 @@
+package io.github.yaforster.flexcaptcha.impl.rendering;
+
+import org.junit.jupiter.api.Test;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class FlatColorBackgroundTest {
+
+ @Test
+ void drawBackground_test_pixels_of_background_color() {
+ Color testColor = Color.BLUE;
+ FlatColorBackground background = new FlatColorBackground(testColor);
+ BufferedImage testImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+
+ background.drawBackground(testImage);
+
+ int pixel = testImage.getRGB(0, 0);
+ Color pixelColor = new Color(pixel, true);
+
+ assertEquals(testColor, pixelColor);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/impl/token/CaptchaCipherTest.java b/src/test/java/io/github/yaforster/flexcaptcha/impl/token/CaptchaCipherTest.java
new file mode 100644
index 0000000..326cee2
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/impl/token/CaptchaCipherTest.java
@@ -0,0 +1,96 @@
+package io.github.yaforster.flexcaptcha.impl.token;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.io.Serializable;
+import java.util.Base64;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
+
+class CaptchaCipherTest {
+
+ @Test
+ void generateToken_without_expiration_time() {
+ String solution = "abc123";
+ Serializable salt = "SomeSalt";
+ CaptchaCipher cipher = CaptchaCipher.builder().build();
+
+ String generatedToken = cipher.generateToken(solution, salt);
+ byte[] decodedToken = Base64.getDecoder().decode(generatedToken);
+
+ assertEquals(32, decodedToken.length);
+ }
+
+ @Test
+ void generateToken_expiration_time() {
+ ExpirationTimeSettings mockedExpirationTime = Mockito.mock(ExpirationTimeSettings.class);
+ when(mockedExpirationTime.getTime()).thenReturn(0L);
+ when(mockedExpirationTime.expirationTimeMillisOffset()).thenReturn(1000L);
+ String solution = "abc123";
+ Serializable salt = "SomeSalt";
+ CaptchaCipher cipher = CaptchaCipher.builder().expirationTimeSettings(mockedExpirationTime).build();
+
+ String generatedToken = cipher.generateToken(solution, salt);
+ byte[] decodedToken = Base64.getDecoder().decode(generatedToken);
+
+ assertEquals(48, decodedToken.length);
+ }
+
+ @Test
+ void generate_and_validate_Token_without_expiration_time() {
+ String solution = "abc123";
+ Serializable salt = "SomeSalt";
+ CaptchaCipher cipher = CaptchaCipher.builder().build();
+
+ String generatedToken = cipher.generateToken(solution, salt);
+ boolean validationResult = cipher.validateToken(generatedToken, salt, solution);
+
+ assertTrue(validationResult);
+ }
+
+ @Test
+ void generate_and_validate_Token_with_expiration_time() {
+ ExpirationTimeSettings mockedExpirationTime = Mockito.mock(ExpirationTimeSettings.class);
+ when(mockedExpirationTime.getTime()).thenReturn(0L);
+ when(mockedExpirationTime.expirationTimeMillisOffset()).thenReturn(1000L);
+ String solution = "abc123";
+ Serializable salt = "SomeSalt";
+ CaptchaCipher cipher = CaptchaCipher.builder().expirationTimeSettings(mockedExpirationTime).build();
+
+ String generatedToken = cipher.generateToken(solution, salt);
+
+ when(mockedExpirationTime.getTime()).thenReturn(999L);
+ boolean validationResult = cipher.validateToken(generatedToken, salt, solution);
+
+ assertTrue(validationResult);
+ }
+
+ @Test
+ void generate_and_validate_Token_with_expired_token() {
+ ExpirationTimeSettings mockedExpirationTime = Mockito.mock(ExpirationTimeSettings.class);
+ when(mockedExpirationTime.getTime()).thenReturn(0L);
+ when(mockedExpirationTime.expirationTimeMillisOffset()).thenReturn(1000L);
+ String solution = "abc123";
+ Serializable salt = "SomeSalt";
+ CaptchaCipher cipher = CaptchaCipher.builder().expirationTimeSettings(mockedExpirationTime).build();
+
+ String generatedToken = cipher.generateToken(solution, salt);
+
+ when(mockedExpirationTime.getTime()).thenReturn(1001L);
+ boolean validationResult = cipher.validateToken(generatedToken, salt, solution);
+
+ assertFalse(validationResult);
+ }
+
+ @Test
+ void generateToken_test_error_handling() {
+ CaptchaCipher cipher = CaptchaCipher.builder().build();
+
+ TokengenerationException exception = assertThrows(TokengenerationException.class,
+ () -> cipher.generateToken(null, null));
+ assertTrue(exception.getLocalizedMessage().contains("Fatal error during cryptographic operation"));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/handling/impl/SecureTextCaptchaHandlerTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/handling/impl/SecureTextCaptchaHandlerTest.java
deleted file mode 100644
index ca0633d..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/handling/impl/SecureTextCaptchaHandlerTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.handling.impl;
-
-import io.github.yaforster.flexcaptcha.Captcha;
-import io.github.yaforster.flexcaptcha.CipherHandler;
-import io.github.yaforster.flexcaptcha.textbased.TextCaptcha;
-import io.github.yaforster.flexcaptcha.textbased.rendering.impl.SimpleTextImageRenderer;
-import io.github.yaforster.flexcaptcha.textbased.textgen.impl.SimpleCaptchaTextGenerator;
-import org.junit.Test;
-
-import java.awt.*;
-
-import static org.junit.Assert.*;
-
-public class SecureTextCaptchaHandlerTest {
-
- private final SecureTextCaptchaHandler handler = new SecureTextCaptchaHandler();
- private final SimpleCaptchaTextGenerator generator = new SimpleCaptchaTextGenerator();
- private final SimpleTextImageRenderer renderer = new SimpleTextImageRenderer();
- private final CipherHandler cipherHandler = new CipherHandler();
- private final Button dummySerializable = new Button();
- private final String password = "ThisIsMyPassword!";
-
- @Test
- public void testGenerateGeneric() {
- TextCaptcha captcha = handler.generate(10, cipherHandler, "ABC", password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericEmptySalt() {
- TextCaptcha captcha = handler.generate(10, cipherHandler, "", password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericNullSalt() {
- TextCaptcha captcha = handler.generate(10, cipherHandler, null, password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericAllPixelMinimum() {
- TextCaptcha captcha = handler.generate(1, cipherHandler, "", password, generator, renderer, 3, 1, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericLengthZero() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(0, cipherHandler, "", password, generator, renderer, 1, 1, true));
- }
-
- @Test
- public void testGenerateGenericLengthNegative() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(-1, cipherHandler, "", password, generator, renderer, 1, 1, true));
- }
-
- @Test
- public void testGenerateGenericIllegalHeight() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, 1, 1, true));
- }
-
- @Test
- public void testGenerateGenericNegativeHeight() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, -3, 1, true));
- }
-
- @Test
- public void testGenerateGenericIllegalWidth() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, 3, 0, true));
- }
-
- @Test
- public void testGenerateGenericNegativeWidth() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, 3, -1, true));
- }
-
- @Test
- public void testGenerateGenericNull() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(10, cipherHandler, null, password, null, null, 60, 300, true));
- }
-
- @Test
- public void testGenerateGenericShort() {
- TextCaptcha captcha = handler.generate(5, cipherHandler, "ABC", password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericWithDummyObj() {
- TextCaptcha captcha = handler.generate(5, cipherHandler, dummySerializable, password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testValidateEmptyString() {
- assertThrows(IllegalArgumentException.class, () -> handler.toCaptcha("", cipherHandler, dummySerializable, password, new SimpleTextImageRenderer(), 60, 300, true));
- }
-
- @Test
- public void testValidation() {
- String myText = "myText";
- Captcha captcha = handler.toCaptcha(myText, cipherHandler, dummySerializable, password, renderer, 100, 50, false);
- assertTrue(handler.validate(myText, captcha.getToken(), cipherHandler, dummySerializable, password));
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/handling/impl/SimpleTextCaptchaHandlerTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/handling/impl/SimpleTextCaptchaHandlerTest.java
deleted file mode 100644
index fb97e23..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/handling/impl/SimpleTextCaptchaHandlerTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.handling.impl;
-
-import io.github.yaforster.flexcaptcha.Captcha;
-import io.github.yaforster.flexcaptcha.CipherHandler;
-import io.github.yaforster.flexcaptcha.textbased.TextCaptcha;
-import io.github.yaforster.flexcaptcha.textbased.rendering.impl.SimpleTextImageRenderer;
-import io.github.yaforster.flexcaptcha.textbased.textgen.impl.SimpleCaptchaTextGenerator;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import javax.crypto.spec.IvParameterSpec;
-import java.awt.*;
-
-import static org.junit.Assert.*;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-
-/**
- * Tests {@link SimpleTextCaptchaHandler}
- *
- * @author Yannick Forster
- */
-
-public class SimpleTextCaptchaHandlerTest {
-
- private final SimpleTextCaptchaHandler handler = new SimpleTextCaptchaHandler();
- private final SimpleCaptchaTextGenerator generator = new SimpleCaptchaTextGenerator();
- private final SimpleTextImageRenderer renderer = new SimpleTextImageRenderer();
- private final CipherHandler cipherHandler = getCHMock();
- private final Button dummySerializable = new Button();
- private final String password = "ThisIsMyPassword!";
-
- @Test
- public void testGenerateGeneric() {
- TextCaptcha captcha = handler.generate(10, cipherHandler, "ABC", password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericEmptySalt() {
- TextCaptcha captcha = handler.generate(10, cipherHandler, "", password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericNullSalt() {
- TextCaptcha captcha = handler.generate(10, cipherHandler, null, password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericAllPixelMinimum() {
- TextCaptcha captcha = handler.generate(1, cipherHandler, "", password, generator, renderer, 3, 1, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericLengthZero() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(0, cipherHandler, "", password, generator, renderer, 1, 1, true));
- }
-
- @Test
- public void testGenerateGenericLengthNegative() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(-1, cipherHandler, "", password, generator, renderer, 1, 1, true));
- }
-
- @Test
- public void testGenerateGenericIllegalHeight() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, 1, 1, true));
- }
-
- @Test
- public void testGenerateGenericNegativeHeight() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, -3, 1, true));
- }
-
- @Test
- public void testGenerateGenericIllegalWidth() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, 3, 0, true));
- }
-
- @Test
- public void testGenerateGenericNegativeWidth() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(1, cipherHandler, "", password, generator, renderer, 3, -1, true));
- }
-
- @Test
- public void testGenerateGenericNull() {
- assertThrows(IllegalArgumentException.class, () -> handler.generate(10, cipherHandler, null, password, null, null, 60, 300, true));
- }
-
- @Test
- public void testGenerateGenericShort() {
- TextCaptcha captcha = handler.generate(5, cipherHandler, "ABC", password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testGenerateGenericWithDummyObj() {
- TextCaptcha captcha = handler.generate(5, cipherHandler, dummySerializable, password, generator, renderer, 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- }
-
- @Test
- public void testValidateEmptyString() {
- assertThrows(IllegalArgumentException.class, () -> handler.toCaptcha("", cipherHandler, dummySerializable, password, new SimpleTextImageRenderer(), 60, 300, true));
- }
-
- @Test
- public void testToCaptchaAndValidate() {
- TextCaptcha captcha = handler.toCaptcha("TESTSTRING", cipherHandler, dummySerializable, password, new SimpleTextImageRenderer(), 60, 300, true);
- assertTrue(captcha.getToken().length() > 0);
- assertNotNull(captcha.getImgData());
- assertTrue(handler.validate("TESTSTRING", captcha.getToken(), cipherHandler, dummySerializable, password));
- }
-
- @Test
- public void testValidation() {
- String myText = "myText";
- Captcha captcha = handler.toCaptcha(myText, cipherHandler, dummySerializable, password, renderer, 100, 50, false);
- assertTrue(handler.validate(myText, captcha.getToken(), cipherHandler, dummySerializable, password));
- }
-
- private CipherHandler getCHMock() {
- CipherHandler cipherHandler = Mockito.mock(CipherHandler.class);
- Mockito.when(cipherHandler.generateIV())
- .thenReturn(new IvParameterSpec(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}));
- Mockito.when(cipherHandler.decryptString(any(byte[].class), anyString(), any()))
- .thenReturn(new byte[]{1, 2, 3});
- Mockito.when(cipherHandler.encryptString(any(byte[].class), anyString(), any(), any(byte[].class)))
- .thenReturn(new byte[]{1, 2, 3});
- return cipherHandler;
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/TextImageRendererTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/TextImageRendererTest.java
deleted file mode 100644
index 6a65182..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/TextImageRendererTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering;
-
-import lombok.Getter;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.awt.image.BufferedImage;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Tests {@link TextImageRenderer} interface
- *
- * @author Yannick Forster
- */
-@Getter
-public abstract class TextImageRendererTest {
-
- private T renderer;
-
- protected abstract T createRenderer();
-
- @Before
- public void setUp() {
- renderer = createRenderer();
- }
-
- @Test
- public void render() {
- int targetHeight = 100;
- int widthHeight = 200;
- BufferedImage image = renderer.render("TEST", targetHeight, widthHeight);
- assertEquals(image.getHeight(), targetHeight);
- assertEquals(image.getWidth(), widthHeight);
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/CleanTextImageRendererTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/CleanTextImageRendererTest.java
deleted file mode 100644
index a28a655..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/CleanTextImageRendererTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRendererTest;
-import org.junit.Test;
-
-public class CleanTextImageRendererTest extends TextImageRendererTest {
-
- @Test
- public void testRender() {
- render();
- }
-
- protected CleanTextImageRenderer createRenderer() {
- return new CleanTextImageRenderer();
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/EffectChainTextImageRendererTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/EffectChainTextImageRendererTest.java
deleted file mode 100644
index 0202d8a..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/EffectChainTextImageRendererTest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRendererTest;
-import org.junit.Test;
-
-//TODO: Implement testing effect chaining
-public class EffectChainTextImageRendererTest extends TextImageRendererTest {
-
- @Test
- public void testRender() {
- render();
- }
-
- @Override
- protected EffectChainTextImageRenderer createRenderer() {
- return new EffectChainTextImageRenderer();
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/SimpleTextImageRendererTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/SimpleTextImageRendererTest.java
deleted file mode 100644
index 716aadb..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/SimpleTextImageRendererTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRendererTest;
-import org.junit.Test;
-
-public class SimpleTextImageRendererTest extends TextImageRendererTest {
-
- @Test
- public void testRender() {
- render();
- }
-
- @Test
- public void renderWithNonExistantFont_ShouldWork() {
- getRenderer().setFontName("DoesntExist");
- render();
- }
-
- @Override
- protected SimpleTextImageRenderer createRenderer() {
- return new SimpleTextImageRenderer();
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/TwirledTextImageRendererTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/TwirledTextImageRendererTest.java
deleted file mode 100644
index d7a94d7..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/rendering/impl/TwirledTextImageRendererTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.rendering.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.rendering.TextImageRendererTest;
-import org.junit.Test;
-
-public class TwirledTextImageRendererTest extends TextImageRendererTest {
-
- @Test
- public void testRender() {
- render();
- }
-
- @Override
- protected TwirledTextImageRenderer createRenderer() {
- return new TwirledTextImageRenderer();
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/textbased/textgen/impl/SimpleCaptchaTextGeneratorTest.java b/src/test/java/io/github/yaforster/flexcaptcha/textbased/textgen/impl/SimpleCaptchaTextGeneratorTest.java
deleted file mode 100644
index f235faa..0000000
--- a/src/test/java/io/github/yaforster/flexcaptcha/textbased/textgen/impl/SimpleCaptchaTextGeneratorTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package io.github.yaforster.flexcaptcha.textbased.textgen.impl;
-
-import io.github.yaforster.flexcaptcha.textbased.enums.Case;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Locale;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests {@link SimpleCaptchaTextGenerator}
- *
- * @author Yannick Forster
- */
-public class SimpleCaptchaTextGeneratorTest {
- static final int TESTSTRINGLENGTH10 = 10;
- static final int TESTSTRINGLENGTH5 = 5;
- private SimpleCaptchaTextGenerator generator;
-
- @Before
- public void init() {
- generator = new SimpleCaptchaTextGenerator();
- }
-
- @Test
- public void testGetCaptchaStringInt() {
- String s = generator.generate(TESTSTRINGLENGTH10);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- }
-
- @Test
- public void testGetCaptchaStringInt5() {
- String s = generator.generate(TESTSTRINGLENGTH5);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH5, s.length());
- }
-
- @Test
- public void testGetCaptchaStringIntLowerCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, Case.LOWERCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertEquals("CaptchaString is not lowercase", s, s.toLowerCase(Locale.ROOT));
- }
-
- @Test
- public void testGetCaptchaStringIntUpperCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, Case.UPPERCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertEquals("CaptchaString is not uppercase", s, s.toUpperCase(Locale.ROOT));
- }
-
- @Test
- public void testGetCaptchaStringIntStringCaseNumOnly() {
- String s = generator.generate(TESTSTRINGLENGTH10, "123456789");
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString is not a number", s.chars().allMatch(Character::isDigit));
- }
-
- @Test
- public void testGetCaptchaStringIntStringCaseLetterOnly() {
- String s = generator.generate(TESTSTRINGLENGTH10, "abcdefghijklmnopqrstuvwxyz");
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString is not a letter", s.chars().allMatch(Character::isLetter));
- }
-
- @Test
- public void testGetCaptchaStringIntStringCaseNumOnlyMixedCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, "123456789", Case.MIXEDCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString is not a number", s.chars().allMatch(Character::isDigit));
- }
-
- @Test
- public void testGetCaptchaStringIntStringCaseLetterOnlyMixedCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, "abcdefghijklmnopqrstuvwxyz", Case.MIXEDCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString is not a letter", s.chars().allMatch(Character::isLetter));
- }
-
- @Test
- public void testGetCaptchaStringMixedStringMixedCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, "abcdefghijklmnopqrstuvwxyz1234567890",
- Case.MIXEDCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString is not a letter or a number",
- s.chars().allMatch(i -> (Character.isLetter(i) || Character.isDigit(i))));
- }
-
- @Test
- public void testGetCaptchaStringMixedStringUpperCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, "abcdefghijklmnopqrstuvwxyz1234567890",
- Case.UPPERCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString contains character or case that should not appear with the given configuration.",
- s.chars().allMatch(i -> ((Character.isLetter(i) && Character.isUpperCase(i)) || Character.isDigit(i))));
- }
-
- @Test
- public void testGetCaptchaStringMixedStringLowerCase() {
- String s = generator.generate(TESTSTRINGLENGTH10, "abcdefghijklmnopqrstuvwxyz1234567890",
- Case.LOWERCASE);
- assertEquals("CaptchaString is not of specified length.", TESTSTRINGLENGTH10, s.length());
- assertTrue("CaptchaString contains character or case that should not appear with the given configuration.",
- s.chars().allMatch(i -> ((Character.isLetter(i) && Character.isLowerCase(i)) || Character.isDigit(i))));
- }
-
-}
diff --git a/src/test/java/io/github/yaforster/flexcaptcha/util/TextGeneratorTest.java b/src/test/java/io/github/yaforster/flexcaptcha/util/TextGeneratorTest.java
new file mode 100644
index 0000000..ad126c4
--- /dev/null
+++ b/src/test/java/io/github/yaforster/flexcaptcha/util/TextGeneratorTest.java
@@ -0,0 +1,102 @@
+package io.github.yaforster.flexcaptcha.util;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Locale;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class TextGeneratorTest {
+
+ static final int TESTSTRINGLENGTH10 = 10;
+ static final int TESTSTRINGLENGTH5 = 5;
+
+ @Test
+ public final void testGetCaptchaStringInt() {
+ TextGenerator generator = TextGenerator.builder().build();
+ String s = generator.generate(TESTSTRINGLENGTH10);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ }
+
+ @Test
+ public final void testGetCaptchaStringInt5() {
+ TextGenerator generator = TextGenerator.builder().build();
+ String s = generator.generate(TESTSTRINGLENGTH5);
+ assertEquals(TESTSTRINGLENGTH5, s.length());
+ }
+
+ @Test
+ public final void testGetCaptchaStringIntLowerCase() {
+ TextGenerator generator = TextGenerator.builder().build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.LOWERCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertEquals(s, s.toLowerCase(Locale.ROOT));
+ }
+
+ @Test
+ public final void testGetCaptchaStringIntUpperCase() {
+ TextGenerator generator = TextGenerator.builder().build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.UPPERCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertEquals(s, s.toUpperCase(Locale.ROOT));
+ }
+
+ @Test
+ public final void testGetCaptchaStringIntStringCaseNumOnly() {
+ TextGenerator generator = TextGenerator.builder().characterbase("1234567890").build();
+ String s = generator.generate(TESTSTRINGLENGTH10);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars().allMatch(Character::isDigit));
+ }
+
+ @Test
+ public final void testGetCaptchaStringIntStringCaseLetterOnly() {
+ TextGenerator generator = TextGenerator.builder().characterbase("abcdefg").build();
+ String s = generator.generate(TESTSTRINGLENGTH10);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars().allMatch(Character::isLetter));
+ }
+
+ @Test
+ public final void testGetCaptchaStringIntStringCaseNumOnlyMixedCase() {
+ TextGenerator generator = TextGenerator.builder().characterbase("1234567890").build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.MIXEDCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars().allMatch(Character::isDigit));
+ }
+
+ @Test
+ public final void testGetCaptchaStringIntStringCaseLetterOnlyMixedCase() {
+ TextGenerator generator = TextGenerator.builder().characterbase("abcdefg").build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.MIXEDCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars().allMatch(Character::isLetter));
+ }
+
+ @Test
+ public final void testGetCaptchaStringMixedStringMixedCase() {
+ TextGenerator generator = TextGenerator.builder().characterbase("abcdefg123456").build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.MIXEDCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars().allMatch(i -> (Character.isLetter(i) || Character.isDigit(i))));
+ }
+
+ @Test
+ public final void testGetCaptchaStringMixedStringUpperCase() {
+ TextGenerator generator = TextGenerator.builder().characterbase("abcdefg123456").build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.UPPERCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars()
+ .allMatch(i -> ((Character.isLetter(i) && Character.isUpperCase(i)) || Character.isDigit(i))));
+ }
+
+ @Test
+ public final void testGetCaptchaStringMixedStringLowerCase() {
+ TextGenerator generator = TextGenerator.builder().characterbase("abcdefg123456").build();
+ String s = generator.generate(TESTSTRINGLENGTH10, TextCase.LOWERCASE);
+ assertEquals(TESTSTRINGLENGTH10, s.length());
+ assertTrue(s.chars()
+ .allMatch(i -> ((Character.isLetter(i) && Character.isLowerCase(i)) || Character.isDigit(i))));
+ }
+}
\ No newline at end of file