PasswordPolicyTest.kt

3.3 KB · raw

1package com.peachpasswords.autofill23import org.junit.Assert.assertEquals4import org.junit.Assert.assertNull5import org.junit.Assert.assertTrue6import org.junit.Test78class PasswordPolicyTest {910    @Test fun reads_minlength_and_maxlength_attributes() {11        val p = PasswordPolicy.fromHtmlAttributes(mapOf("minlength" to "8", "maxlength" to "64"))12        assertEquals(8, p.minLength)13        assertEquals(64, p.maxLength)14    }1516    @Test fun ignores_non_positive_lengths() {17        val p = PasswordPolicy.fromHtmlAttributes(mapOf("minlength" to "0", "maxlength" to "-1"))18        assertNull(p.minLength)19        assertNull(p.maxLength)20    }2122    @Test fun pattern_range_fills_both_bounds() {23        val p = PasswordPolicy.fromHtmlAttributes(mapOf("pattern" to ".{8,20}"))24        assertEquals(8, p.minLength)25        assertEquals(20, p.maxLength)26    }2728    @Test fun pattern_min_only() {29        val p = PasswordPolicy.fromHtmlAttributes(mapOf("pattern" to ".{12,}"))30        assertEquals(12, p.minLength)31        assertNull(p.maxLength)32    }3334    @Test fun pattern_exact_sets_both() {35        val p = PasswordPolicy.fromHtmlAttributes(mapOf("pattern" to "[a-z]{10}"))36        assertEquals(10, p.minLength)37        assertEquals(10, p.maxLength)38    }3940    @Test fun attributes_win_over_pattern() {41        val p = PasswordPolicy.fromHtmlAttributes(42            mapOf("minlength" to "6", "maxlength" to "30", "pattern" to ".{8,20}"),43        )44        assertEquals(6, p.minLength)45        assertEquals(30, p.maxLength)46    }4748    @Test fun no_constraints_yields_empty_policy() {49        val p = PasswordPolicy.fromHtmlAttributes(mapOf("autocomplete" to "new-password"))50        assertNull(p.minLength)51        assertNull(p.maxLength)52    }5354    @Test fun generation_prefers_max_length() {55        // Strongest the site accepts.56        assertEquals(64, PasswordPolicy(minLength = 8, maxLength = 64).generationLength())57    }5859    @Test fun generation_caps_at_hard_max() {60        assertEquals(256, PasswordPolicy(maxLength = 500).generationLength())61    }6263    @Test fun generation_snaps_up_to_min() {64        // default 20 < min 25 -> snap up.65        assertEquals(25, PasswordPolicy(minLength = 25).generationLength())66    }6768    @Test fun generation_default_when_unconstrained() {69        assertEquals(PasswordPolicy.DEFAULT_LENGTH, PasswordPolicy().generationLength())70    }7172    @Test fun generation_never_below_the_floor() {73        // A page cannot talk the generator below the minimum under a74        // "strong password" label (PB-26-136).75        assertEquals(PasswordPolicy.MIN_GENERATION_LENGTH, PasswordPolicy(maxLength = 0).generationLength())76        assertEquals(PasswordPolicy.MIN_GENERATION_LENGTH, PasswordPolicy(maxLength = 1).generationLength())77        assertTrue(PasswordPolicy(maxLength = 1).isWeaklyConstrained)78    }7980    @Test fun constraint_note_max() {81        val p = PasswordPolicy(maxLength = 20)82        assertEquals("This site allows max 20 characters", p.constraintNote(20))83    }8485    @Test fun constraint_note_min() {86        val p = PasswordPolicy(minLength = 12)87        assertEquals("This site requires at least 12 characters", p.constraintNote(12))88    }8990    @Test fun constraint_note_empty_when_interior() {91        val p = PasswordPolicy(minLength = 8, maxLength = 64)92        assertEquals("", p.constraintNote(30))93    }94}