AutofillMatchTest.kt

5.2 KB · raw

1package com.peachpasswords.autofill23import com.peachpasswords.vault.VaultEntry4import org.junit.Assert.assertEquals5import org.junit.Assert.assertFalse6import org.junit.Assert.assertTrue7import org.junit.Test89class AutofillMatchTest {10    private fun entry(title: String, url: String?) =11        VaultEntry(id = title, title = title, url = url, createdAt = 0, modifiedAt = 0)1213    @Test fun strict_domain_match_hits_only_the_matching_site() {14        val peach = entry("Peach", "https://peachpasswords.com/login")15        val mail = entry("Fastmail", "https://fastmail.com")16        val result = AutofillResponseBuilder.matchEntries(listOf(mail, peach), "peachpasswords.com")17        assertEquals(listOf(peach), result.hits)18        assertTrue("no unrelated entries leak for a web origin", result.rest.isEmpty())19    }2021    @Test fun no_false_positive_on_substring_lookalike() {22        val gh = entry("GitHub", "https://github.com/login")23        val result = AutofillResponseBuilder.matchEntries(listOf(gh), "notgithub.com")24        assertTrue("github.com must not match notgithub.com", result.hits.isEmpty())25        assertTrue(result.rest.isEmpty())26    }2728    @Test fun subdomain_origin_matches_registrable_domain() {29        val peach = entry("Peach", "https://peachpasswords.com")30        val result = AutofillResponseBuilder.matchEntries(listOf(peach), "app.peachpasswords.com")31        assertEquals(listOf(peach), result.hits)32    }3334    @Test fun additional_urls_match_registrable_domain() {35        val peach = entry("Peach", "https://peachpasswords.com")36            .copy(additionalUrls = listOf("https://accounts.peachpasswords.co.uk/login"))37        val result = AutofillResponseBuilder.matchEntries(listOf(peach), "signin.peachpasswords.co.uk")38        assertEquals(listOf(peach), result.hits)39    }4041    @Test fun additional_urls_do_not_match_substring_lookalikes() {42        val gh = entry("GitHub", null)43            .copy(additionalUrls = listOf("https://github.com/login"))44        val result = AutofillResponseBuilder.matchEntries(listOf(gh), "evilgithub.com")45        assertTrue(result.hits.isEmpty())46        assertTrue(result.rest.isEmpty())47    }4849    @Test fun picker_web_origin_uses_domain_matching() {50        val peach = entry("Peach", "https://peachpasswords.com")51        val parsed = ParsedStructure(52            webDomain = "app.peachpasswords.com",53            originTrust = AutofillOriginTrust.TRUSTED_WEB,54        )55        assertEquals(listOf(peach), autofillPickerEntries(listOf(peach), parsed, limit = 12))56    }5758    @Test fun picker_native_origin_uses_verified_app_link_domains() {59        val app = entry("Native", "https://example.com/login")60        val other = entry("Other", "https://other.example.net")61        val parsed = ParsedStructure(62            packageName = "com.example.app",63            originTrust = AutofillOriginTrust.TRUSTED_NATIVE,64            verifiedDomains = listOf("example.com"),65        )66        assertEquals(listOf(app), autofillPickerEntries(listOf(app, other), parsed, limit = 12))67    }6869    @Test fun unknown_native_origin_has_no_matches() {70        val app = entry("Native", "https://example.com/login")71        val parsed = ParsedStructure(packageName = "com.example.app")72        assertTrue(autofillPickerEntries(listOf(app), parsed, limit = 12).isEmpty())73    }7475    @Test fun picker_label_routes_locked_users_to_unlock() {76        assertEquals("Unlock Peach", autofillPickerLabel(unlocked = false, datasetCount = 3))77    }7879    @Test fun picker_label_names_no_match_state() {80        assertEquals("No saved logins for this site", autofillPickerLabel(unlocked = true, datasetCount = 0))81    }8283    @Test fun picker_label_keeps_search_affordance_when_matches_exist() {84        assertEquals("Search Peach…", autofillPickerLabel(unlocked = true, datasetCount = 1))85    }8687    @Test fun null_origin_yields_no_entries() {88        val a = entry("A", "https://a.com")89        val b = entry("B", "https://b.com")90        val result = AutofillResponseBuilder.matchEntries(listOf(a, b), null)91        assertTrue(result.all.isEmpty())92    }9394    @Test fun unknown_origin_returns_no_preselected_credentials() {95        val bank = entry("Bank", "https://bank.example.com")96        val parsed = ParsedStructure(97            webDomain = "bank.example.com",98            packageName = "com.evil.phisher",99            originTrust = AutofillOriginTrust.UNKNOWN,100        )101102        assertTrue(AutofillResponseBuilder.matchEntries(listOf(bank), parsed).all.isEmpty())103    }104105    @Test fun trusted_browser_certificate_pins() {106        assertTrue(107            TrustedBrowsers.hasExpectedCertificate(108                "com.android.chrome",109                "f0fd6c5b410f25cb25c3b53346c8972fae30f8ee7411df910480ad6b2d60db83",110            ),111        )112        assertTrue(113            TrustedBrowsers.hasExpectedCertificate(114                "org.mozilla.firefox",115                "a78b62a5165b4494b2fead9e76a280d22d937fee6251aece599446b2ea319b04",116            ),117        )118        assertFalse(TrustedBrowsers.hasExpectedCertificate("com.android.chrome", "00".repeat(32)))119        assertFalse(TrustedBrowsers.hasExpectedCertificate("com.evil.phisher", "00".repeat(32)))120        assertFalse(TrustedBrowsers.hasExpectedCertificate(null, "00".repeat(32)))121    }122}