From 1bb0eb0e706284dc5829d9fb1a34a637a20c7668 Mon Sep 17 00:00:00 2001 From: Ameya Lokare Date: Mon, 30 Sep 2024 11:21:05 -0700 Subject: [PATCH] Integer comparison of captcha scores --- .../captcha/AssessmentResult.java | 8 +++++++- .../captcha/HCaptchaClientTest.java | 18 +++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/captcha/AssessmentResult.java b/service/src/main/java/org/whispersystems/textsecuregcm/captcha/AssessmentResult.java index 0db5d0753..4a3fd9334 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/captcha/AssessmentResult.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/captcha/AssessmentResult.java @@ -76,7 +76,13 @@ public class AssessmentResult { if (!solved) { return false; } - return this.actualScore >= scoreThreshold.orElse(this.defaultScoreThreshold); + // Since HCaptcha scores are truncated to 2 decimal places, we can multiply by 100 and round to the nearest int for + // comparison instead of floating point comparisons + return normalizedIntScore(this.actualScore) >= normalizedIntScore(scoreThreshold.orElse(this.defaultScoreThreshold)); + } + + private static int normalizedIntScore(final float score) { + return Math.round(score * 100); } public String getScoreString() { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/captcha/HCaptchaClientTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/captcha/HCaptchaClientTest.java index 06dcef0ba..12410c396 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/captcha/HCaptchaClientTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/captcha/HCaptchaClientTest.java @@ -35,16 +35,20 @@ public class HCaptchaClientTest { static Stream captchaProcessed() { return Stream.of( - Arguments.of(true, 0.6f, true), - Arguments.of(false, 0.6f, false), - Arguments.of(true, 0.4f, false), - Arguments.of(false, 0.4f, false) + // hCaptcha scores are inverted compared to recaptcha scores. (low score is good) + Arguments.of(true, 0.4f, 0.5f, true), + Arguments.of(false, 0.4f, 0.5f, false), + Arguments.of(true, 0.6f, 0.5f, false), + Arguments.of(false, 0.6f, 0.5f, false), + Arguments.of(true, 0.6f, 0.4f, true), + Arguments.of(true, 0.61f, 0.4f, false), + Arguments.of(true, 0.7f, 0.3f, true) ); } @ParameterizedTest @MethodSource - public void captchaProcessed(final boolean success, final float score, final boolean expectedResult) + public void captchaProcessed(final boolean success, final float hCaptchaScore, final float scoreFloor, final boolean expectedResult) throws IOException, InterruptedException { final FaultTolerantHttpClient client = mockResponder(200, String.format(""" @@ -54,9 +58,9 @@ public class HCaptchaClientTest { "score-reasons": ["great job doing this captcha"] } """, - success, 1 - score)); // hCaptcha scores are inverted compared to recaptcha scores. (low score is good) + success, hCaptchaScore)); - final AssessmentResult result = new HCaptchaClient("fake", client, mockConfig(true, 0.5)) + final AssessmentResult result = new HCaptchaClient("fake", client, mockConfig(true, scoreFloor)) .verify(SITE_KEY, Action.CHALLENGE, TOKEN, null, USER_AGENT); if (!success) { assertThat(result).isEqualTo(AssessmentResult.invalid());