1package com.peachpasswords.autofill23import org.junit.Assert.assertFalse4import org.junit.Assert.assertTrue5import org.junit.Test67891011121314class AssistStructureOtpRegexTest {1516 private val rx = AssistStructureParser.OTP_HAYSTACK_RX1718 @Test fun matches_textbook_2fa_labels() {19 20 assertTrue(rx.containsMatchIn("otp"))21 assertTrue(rx.containsMatchIn("2fa"))22 assertTrue(rx.containsMatchIn("mfa"))23 assertTrue(rx.containsMatchIn("one-time password"))24 assertTrue(rx.containsMatchIn("verification code"))25 assertTrue(rx.containsMatchIn("auth code"))26 }2728 @Test fun does_not_match_card_number_label() {29 assertFalse(rx.containsMatchIn("card number"))30 }3132 @Test fun matches_labels_real_forms_use() {33 34 assertTrue(rx.containsMatchIn("verification"))35 assertTrue(rx.containsMatchIn("authentication"))36 assertTrue(rx.containsMatchIn("security code"))37 assertTrue(rx.containsMatchIn("token"))38 assertTrue(rx.containsMatchIn("confirm"))39 }4041 @Test fun does_not_match_unrelated_code_fields() {42 43 44 45 assertFalse(rx.containsMatchIn("code"))46 assertFalse(rx.containsMatchIn("promo code"))47 assertFalse(rx.containsMatchIn("coupon code"))48 assertFalse(rx.containsMatchIn("discount code"))49 assertFalse(rx.containsMatchIn("zip code"))50 assertFalse(rx.containsMatchIn("area code"))51 }5253 @Test fun measures_realistic_labelled_form_corpus() {54 val otpLabels = listOf(55 "Verification code",56 "One-time code",57 "Enter the 6-digit code",58 "Authenticator code",59 "Security code",60 )61 val unrelatedNumericLabels = listOf(62 "CVV",63 "ZIP code",64 "Card number",65 "Amount",66 "Quantity",67 "Postcode",68 "Date of birth",69 "PIN",70 )7172 73 74 val otpMisses = otpLabels.filterNot { rx.containsMatchIn(it.lowercase()) }75 val falsePositives = unrelatedNumericLabels.filter { rx.containsMatchIn(it.lowercase()) }7677 78 79 80 81 82 val knownGaps = setOf("Enter the 6-digit code", "Authenticator code")83 assertTrue("Unrelated labels classified as OTP: $falsePositives", falsePositives.isEmpty())84 assertTrue(85 "New OTP detection gap: ${otpMisses.filterNot { it in knownGaps }}",86 otpMisses.all { it in knownGaps },87 )88 }89}