diff --git a/.buildconfig.yml b/.buildconfig.yml index 5540d962f12..0f9a68aceb3 100644 --- a/.buildconfig.yml +++ b/.buildconfig.yml @@ -235,10 +235,6 @@ projects: path: components/browser/state description: 'Component responsible for maintaining the centralized state of a browser engine.' publish: true - browser-storage-memory: - path: components/browser/storage-memory - description: 'A memory-backed implementation of core data storage.' - publish: true browser-storage-sync: path: components/browser/storage-sync description: 'A syncable, Rust Places-backed implementation of core data storage.' diff --git a/CODEOWNERS b/CODEOWNERS index baad841cc54..5f1781c3773 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -40,7 +40,6 @@ /components/browser/menu2/ @jonalmeida /components/browser/search/ @pocmo /components/browser/state/ @pocmo @csadilek -/components/browser/storage-memory/ @grigoryk /components/browser/storage-sync/ @grigoryk /components/browser/tabstray/ @jonalmeida /components/browser/thumbnails/ @jonalmeida @gabrielluong diff --git a/README.md b/README.md index 5fe48e7d937..ba686fa2492 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,6 @@ High-level components for building browser(-like) apps. * πŸ”΅ [**State**](components/browser/state/README.md) - Component for maintaining the centralized state of the browser and its components. -* πŸ”΅ [**Storage-Memory**](components/browser/storage-memory/README.md) - An in-memory implementation of browser storage. - * πŸ”΅ [**Storage-Sync**](components/browser/storage-sync/README.md) - A syncable implementation of browser storage backed by [application-services' Places lib](https://github.com/mozilla/application-services). * βšͺ [**Tabstray**](components/browser/tabstray/README.md) - A customizable tabs tray for browsers. diff --git a/components/browser/storage-memory/README.md b/components/browser/storage-memory/README.md deleted file mode 100644 index 683b6ce3808..00000000000 --- a/components/browser/storage-memory/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# [Android Components](../../../README.md) > Browser > Memory Storage - -An in-memory implementation of `concept-storage`. Data is not persisted to disk, and does not survive a restart. Not suitable for syncing. - -### Setting up the dependency - -Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): - -```Groovy -implementation "org.mozilla.components:browser-storage-memory:{latest-version}" -``` - -## License - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/ diff --git a/components/browser/storage-memory/build.gradle b/components/browser/storage-memory/build.gradle deleted file mode 100644 index c6aec653ba4..00000000000 --- a/components/browser/storage-memory/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion config.compileSdkVersion - - defaultConfig { - minSdkVersion config.minSdkVersion - targetSdkVersion config.targetSdkVersion - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - // This dependency is part of this module's public API. - api project(':concept-storage') - implementation project(':support-utils') - - implementation Dependencies.kotlin_stdlib - - testImplementation Dependencies.androidx_test_junit - testImplementation Dependencies.testing_robolectric - testImplementation Dependencies.testing_mockito - - testImplementation project(':support-test') -} - -apply from: '../../../publish.gradle' -ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/components/browser/storage-memory/proguard-rules.pro b/components/browser/storage-memory/proguard-rules.pro deleted file mode 100644 index f1b424510da..00000000000 --- a/components/browser/storage-memory/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/components/browser/storage-memory/src/main/AndroidManifest.xml b/components/browser/storage-memory/src/main/AndroidManifest.xml deleted file mode 100644 index 92faf390ed7..00000000000 --- a/components/browser/storage-memory/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/components/browser/storage-memory/src/main/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorage.kt b/components/browser/storage-memory/src/main/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorage.kt deleted file mode 100644 index 858287c4231..00000000000 --- a/components/browser/storage-memory/src/main/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorage.kt +++ /dev/null @@ -1,200 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package mozilla.components.browser.storage.memory - -import androidx.annotation.VisibleForTesting -import mozilla.components.concept.storage.FrecencyThresholdOption -import mozilla.components.concept.storage.HistoryAutocompleteResult -import mozilla.components.concept.storage.HistoryStorage -import mozilla.components.concept.storage.PageObservation -import mozilla.components.concept.storage.PageVisit -import mozilla.components.concept.storage.RedirectSource -import mozilla.components.concept.storage.SearchResult -import mozilla.components.concept.storage.TopFrecentSiteInfo -import mozilla.components.concept.storage.VisitInfo -import mozilla.components.concept.storage.VisitType -import mozilla.components.support.utils.StorageUtils.levenshteinDistance -import mozilla.components.support.utils.segmentAwareDomainMatch - -data class Visit(val timestamp: Long, val type: VisitType) - -const val AUTOCOMPLETE_SOURCE_NAME = "memoryHistory" - -/** - * An in-memory implementation of [mozilla.components.concept.storage.HistoryStorage]. - */ -class InMemoryHistoryStorage : HistoryStorage { - @VisibleForTesting - internal var pages: HashMap> = linkedMapOf() - @VisibleForTesting - internal val pageMeta: HashMap = hashMapOf() - - override suspend fun warmUp() { - // No-op for an in-memory store - } - - override suspend fun recordVisit(uri: String, visit: PageVisit) { - val now = System.currentTimeMillis() - if (visit.redirectSource != RedirectSource.NOT_A_SOURCE) { - return - } - - synchronized(pages) { - if (!pages.containsKey(uri)) { - pages[uri] = mutableListOf(Visit(now, visit.visitType)) - } else { - pages[uri]!!.add(Visit(now, visit.visitType)) - } - } - } - - override suspend fun recordObservation(uri: String, observation: PageObservation) = synchronized(pageMeta) { - val existingPageObservation = pageMeta[uri] - - if (existingPageObservation == null || - (!observation.title.isNullOrEmpty() && !observation.previewImageUrl.isNullOrEmpty()) - ) { - pageMeta[uri] = observation - } else if (!observation.title.isNullOrEmpty()) { - // Carryover the existing observed previewImageUrl - pageMeta[uri] = observation.copy(previewImageUrl = existingPageObservation.previewImageUrl) - } else { - // Carryover the existing observed title - pageMeta[uri] = observation.copy(title = existingPageObservation.title) - } - } - - override suspend fun getVisited(uris: List): List = synchronized(pages) { - return uris.map { - if (pages[it] != null && pages[it]!!.size > 0) { - return@map true - } - return@map false - } - } - - override suspend fun getVisited(): List = synchronized(pages) { - return pages.keys.toList() - } - - override suspend fun getVisitsPaginated(offset: Long, count: Long, excludeTypes: List): List { - throw UnsupportedOperationException("Pagination is not yet supported by the in-memory history storage") - } - - override suspend fun getDetailedVisits( - start: Long, - end: Long, - excludeTypes: List - ): List = synchronized(pages + pageMeta) { - val visits = mutableListOf() - - pages.forEach { - it.value.forEach { visit -> - if (visit.timestamp in start..end && !excludeTypes.contains(visit.type)) { - visits.add( - VisitInfo( - url = it.key, - title = pageMeta[it.key]?.title, - visitTime = visit.timestamp, - visitType = visit.type, - previewImageUrl = pageMeta[it.key]?.previewImageUrl - ) - ) - } - } - } - - return visits - } - - override suspend fun getTopFrecentSites( - numItems: Int, - frecencyThreshold: FrecencyThresholdOption - ): List { - throw UnsupportedOperationException("getTopFrecentSites is not yet supported by the in-memory history storage") - } - - override fun getSuggestions(query: String, limit: Int): List = synchronized(pages + pageMeta) { - data class Hit(val url: String, val score: Int) - - val urlMatches = pages.asSequence().map { - Hit(it.key, levenshteinDistance(it.key, query)) - } - val titleMatches = pageMeta.asSequence().map { - Hit(it.key, levenshteinDistance(it.value.title ?: "", query)) - } - val matchedUrls = mutableMapOf() - urlMatches.plus(titleMatches).forEach { - if (matchedUrls.containsKey(it.url) && matchedUrls[it.url]!! < it.score) { - matchedUrls[it.url] = it.score - } else { - matchedUrls[it.url] = it.score - } - } - // Calculate maxScore so that we can invert our scoring. - // Lower Levenshtein distance should produce a higher score. - val maxScore = urlMatches.maxByOrNull { it.score }?.score ?: return@synchronized listOf() - - // TODO exclude non-matching results entirely? Score that implies complete mismatch. - matchedUrls.asSequence().sortedBy { it.value }.map { - SearchResult(id = it.key, score = maxScore - it.value, url = it.key, title = pageMeta[it.key]?.title) - }.take(limit).toList() - } - - override fun getAutocompleteSuggestion(query: String): HistoryAutocompleteResult? = synchronized(pages) { - return segmentAwareDomainMatch(query, pages.keys)?.let { urlMatch -> - HistoryAutocompleteResult( - query, urlMatch.matchedSegment, urlMatch.url, AUTOCOMPLETE_SOURCE_NAME, pages.size - ) - } - } - - override suspend fun deleteEverything() = synchronized(pages + pageMeta) { - pages.clear() - pageMeta.clear() - } - - override suspend fun deleteVisitsSince(since: Long) = synchronized(pages) { - pages.entries.forEach { - it.setValue(it.value.filterNot { visit -> visit.timestamp >= since }.toMutableList()) - } - pages = pages.filter { it.value.isNotEmpty() } as HashMap> - } - - override suspend fun deleteVisitsBetween(startTime: Long, endTime: Long) = synchronized(pages) { - pages.entries.forEach { - it.setValue( - it.value.filterNot { visit -> - visit.timestamp >= startTime && visit.timestamp <= endTime - }.toMutableList() - ) - } - pages = pages.filter { it.value.isNotEmpty() } as HashMap> - } - - override suspend fun deleteVisitsFor(url: String) = synchronized(pages + pageMeta) { - pages.remove(url) - pageMeta.remove(url) - Unit - } - - override suspend fun deleteVisit(url: String, timestamp: Long) = synchronized(pages) { - if (pages.containsKey(url)) { - pages[url] = pages[url]!!.filter { it.timestamp != timestamp }.toMutableList() - } - } - - override suspend fun prune() { - // Not applicable. - } - - override suspend fun runMaintenance() { - // Not applicable. - } - - override fun cleanup() { - // GC will take care of our internal data structures, so there's nothing to do here. - } -} diff --git a/components/browser/storage-memory/src/test/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorageTest.kt b/components/browser/storage-memory/src/test/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorageTest.kt deleted file mode 100644 index 8c5f358da93..00000000000 --- a/components/browser/storage-memory/src/test/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorageTest.kt +++ /dev/null @@ -1,401 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package mozilla.components.browser.storage.memory - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import kotlinx.coroutines.runBlocking -import mozilla.components.concept.storage.PageObservation -import mozilla.components.concept.storage.PageVisit -import mozilla.components.concept.storage.RedirectSource -import mozilla.components.concept.storage.VisitType -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test -import org.junit.runner.RunWith -import java.lang.Thread.sleep - -@RunWith(AndroidJUnit4::class) -class InMemoryHistoryStorageTest { - - @Test - fun `store can be used to track visit information`() = runBlocking { - val history = InMemoryHistoryStorage() - - assertEquals(0, history.pages.size) - - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals(1, history.pages.size) - assertEquals(1, history.pages["http://www.mozilla.org"]!!.size) - assertEquals(VisitType.LINK, history.pages["http://www.mozilla.org"]!![0].type) - - // Reloads are recorded. - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE)) - assertEquals(1, history.pages.size) - assertEquals(2, history.pages["http://www.mozilla.org"]!!.size) - assertEquals(VisitType.LINK, history.pages["http://www.mozilla.org"]!![0].type) - assertEquals(VisitType.RELOAD, history.pages["http://www.mozilla.org"]!![1].type) - - // Visits for multiple pages are tracked. - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals(2, history.pages.size) - assertEquals(2, history.pages["http://www.mozilla.org"]!!.size) - assertEquals(VisitType.LINK, history.pages["http://www.mozilla.org"]!![0].type) - assertEquals(VisitType.RELOAD, history.pages["http://www.mozilla.org"]!![1].type) - assertEquals(1, history.pages["http://www.firefox.com"]!!.size) - assertEquals(VisitType.LINK, history.pages["http://www.firefox.com"]!![0].type) - } - - @Test - fun `store can be used to query detailed visit information`() = runBlocking { - val history = InMemoryHistoryStorage() - - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE)) - history.recordObservation( - "http://www.mozilla.org", - PageObservation("Mozilla", "https://test.com/og-image-url") - ) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.REDIRECT_TEMPORARY, RedirectSource.NOT_A_SOURCE)) - - val visits = history.getDetailedVisits(0, excludeTypes = listOf(VisitType.REDIRECT_TEMPORARY)) - assertEquals(3, visits.size) - assertEquals("http://www.mozilla.org", visits[0].url) - assertEquals("Mozilla", visits[0].title) - assertEquals("https://test.com/og-image-url", visits[0].previewImageUrl) - assertEquals(VisitType.LINK, visits[0].visitType) - - assertEquals("http://www.mozilla.org", visits[1].url) - assertEquals("Mozilla", visits[1].title) - assertEquals("https://test.com/og-image-url", visits[1].previewImageUrl) - assertEquals(VisitType.RELOAD, visits[1].visitType) - - assertEquals("http://www.firefox.com", visits[2].url) - assertEquals(null, visits[2].title) - assertEquals(VisitType.LINK, visits[2].visitType) - - val visitsAll = history.getDetailedVisits(0) - assertEquals(4, visitsAll.size) - } - - @Test - fun `store can be used to record and retrieve history via webview-style callbacks`() = runBlocking { - val history = InMemoryHistoryStorage() - - // Empty. - assertEquals(0, history.getVisited().size) - - // Regular visits are tracked. - history.recordVisit("https://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals(listOf("https://www.mozilla.org"), history.getVisited()) - - // Multiple visits can be tracked, results ordered by "URL's first seen first". - history.recordVisit("https://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals(listOf("https://www.mozilla.org", "https://www.firefox.com"), history.getVisited()) - - // Visits marked as reloads can be tracked. - history.recordVisit("https://www.firefox.com", PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE)) - assertEquals(listOf("https://www.mozilla.org", "https://www.firefox.com"), history.getVisited()) - - // Visited urls are certainly a set. - history.recordVisit("https://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("https://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("https://www.wikipedia.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals( - listOf("https://www.mozilla.org", "https://www.firefox.com", "https://www.wikipedia.org"), - history.getVisited() - ) - } - - @Test - fun `store can be used to record and retrieve history via gecko-style callbacks`() = runBlocking { - val history = InMemoryHistoryStorage() - - assertEquals(0, history.getVisited(listOf()).size) - - // Regular visits are tracked - history.recordVisit("https://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals(listOf(true), history.getVisited(listOf("https://www.mozilla.org"))) - - // Duplicate requests are handled. - assertEquals(listOf(true, true), history.getVisited(listOf("https://www.mozilla.org", "https://www.mozilla.org"))) - - // Visit map is returned in correct order. - assertEquals(listOf(true, false), history.getVisited(listOf("https://www.mozilla.org", "https://www.unknown.com"))) - - assertEquals(listOf(false, true), history.getVisited(listOf("https://www.unknown.com", "https://www.mozilla.org"))) - - // Multiple visits can be tracked. Reloads can be tracked. - history.recordVisit("https://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("https://www.mozilla.org", PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("https://www.wikipedia.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - assertEquals(listOf(true, true, false, true), history.getVisited(listOf("https://www.firefox.com", "https://www.wikipedia.org", "https://www.unknown.com", "https://www.mozilla.org"))) - } - - @Test - fun `store can be used to track page meta information - title and previewImageUrl changes`() = runBlocking { - val history = InMemoryHistoryStorage() - assertEquals(0, history.pageMeta.size) - - // Title and previewImageUrl changes are recorded. - history.recordObservation( - "https://www.wikipedia.org", - PageObservation("Wikipedia", "https://test.com/og-image-url") - ) - assertEquals(1, history.pageMeta.size) - assertEquals( - PageObservation("Wikipedia", "https://test.com/og-image-url"), - history.pageMeta["https://www.wikipedia.org"] - ) - - history.recordObservation("https://www.wikipedia.org", PageObservation("ВикипСдия")) - assertEquals(1, history.pageMeta.size) - assertEquals( - PageObservation("ВикипСдия", "https://test.com/og-image-url"), - history.pageMeta["https://www.wikipedia.org"] - ) - - // Titles for different pages are recorded. - history.recordObservation("https://www.firefox.com", PageObservation("Firefox")) - history.recordObservation("https://www.mozilla.org", PageObservation("Мозилла")) - assertEquals(3, history.pageMeta.size) - assertEquals( - PageObservation("ВикипСдия", "https://test.com/og-image-url"), - history.pageMeta["https://www.wikipedia.org"] - ) - assertEquals(PageObservation("Firefox"), history.pageMeta["https://www.firefox.com"]) - assertEquals(PageObservation("Мозилла"), history.pageMeta["https://www.mozilla.org"]) - } - - @Test - fun `store can provide suggestions`() = runBlocking { - val history = InMemoryHistoryStorage() - assertEquals(0, history.getSuggestions("Mozilla", 100).size) - - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - val search = history.getSuggestions("Mozilla", 100) - assertEquals(1, search.size) - assertEquals("http://www.firefox.com", search[0].url) - - history.recordVisit("http://www.wikipedia.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.moscow.ru", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordObservation("http://www.mozilla.org", PageObservation("Mozilla")) - history.recordObservation("http://www.firefox.com", PageObservation("Mozilla Firefox")) - history.recordObservation("http://www.moscow.ru", PageObservation("Moscow City")) - history.recordObservation("http://www.moscow.ru/notitle", PageObservation("")) - - // Empty search. - assertEquals(5, history.getSuggestions("", 100).size) - - val search2 = history.getSuggestions("Mozilla", 100) - assertEquals(5, search2.size) - assertEquals("http://www.mozilla.org", search2[0].id) - assertEquals("http://www.mozilla.org", search2[0].url) - assertEquals("Mozilla", search2[0].title) - - assertEquals("http://www.firefox.com", search2[1].id) - assertEquals("http://www.firefox.com", search2[1].url) - assertEquals("Mozilla Firefox", search2[1].title) - - assertEquals("http://www.moscow.ru", search2[2].id) - assertEquals("http://www.moscow.ru", search2[2].url) - assertEquals("Moscow City", search2[2].title) - - assertEquals("http://www.wikipedia.org", search2[3].id) - assertEquals("http://www.wikipedia.org", search2[3].url) - assertEquals(null, search2[3].title) - } - - @Test - fun `store can provide suggestions respecting the limit`() = runBlocking { - val history = InMemoryHistoryStorage() - history.recordVisit("http://www.wikipedia.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.moscow.ru", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - history.recordObservation("http://www.mozilla.org", PageObservation("Mozilla")) - history.recordObservation("http://www.firefox.com", PageObservation("Mozilla Firefox")) - history.recordObservation("http://www.moscow.ru", PageObservation("Moscow")) - - assertEquals(3, history.getSuggestions("Mozilla", 3).size) - assertEquals(2, history.getSuggestions("Mozilla", 2).size) - assertEquals(1, history.getSuggestions("Mozilla", 1).size) - - val results = history.getSuggestions("Mozilla", 3) - assertEquals("http://www.mozilla.org", results[0].url) - assertEquals("http://www.moscow.ru", results[1].url) - assertEquals("http://www.firefox.com", results[2].url) - - val results2 = history.getSuggestions("Mozilla", 1) - assertEquals("http://www.mozilla.org", results2[0].url) - } - - @Test - fun `store can provide autocomplete suggestions`() = runBlocking { - val history = InMemoryHistoryStorage() - - assertNull(history.getAutocompleteSuggestion("moz")) - - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - var res = history.getAutocompleteSuggestion("moz")!! - assertEquals("mozilla.org", res.text) - assertEquals("http://www.mozilla.org", res.url) - assertEquals("memoryHistory", res.source) - assertEquals(1, res.totalItems) - - history.recordVisit("http://firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - res = history.getAutocompleteSuggestion("firefox")!! - assertEquals("firefox.com", res.text) - assertEquals("http://firefox.com", res.url) - assertEquals("memoryHistory", res.source) - assertEquals(2, res.totalItems) - - history.recordVisit("https://en.wikipedia.org/wiki/Mozilla", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - res = history.getAutocompleteSuggestion("en")!! - assertEquals("en.wikipedia.org/wiki/mozilla", res.text) - assertEquals("https://en.wikipedia.org/wiki/mozilla", res.url) - assertEquals("memoryHistory", res.source) - assertEquals(3, res.totalItems) - - assertNull(history.getAutocompleteSuggestion("hello")) - } - - @Test - fun `store can delete everything`() = runBlocking { - val history = InMemoryHistoryStorage() - - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.DOWNLOAD, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.BOOKMARK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.EMBED, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.REDIRECT_PERMANENT, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.REDIRECT_TEMPORARY, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - - history.recordObservation("http://www.firefox.com", PageObservation("Firefox")) - - assertEquals(2, history.getVisited().size) - - history.deleteEverything() - - assertEquals(0, history.getVisited().size) - } - - @Test - fun `store can delete by url`() = runBlocking { - val history = InMemoryHistoryStorage() - - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.DOWNLOAD, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.BOOKMARK, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.EMBED, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.REDIRECT_PERMANENT, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.REDIRECT_TEMPORARY, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.firefox.com", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE)) - - history.recordObservation("http://www.firefox.com", PageObservation("Firefox")) - - assertEquals(2, history.getVisited().size) - - history.deleteVisitsFor("http://www.mozilla.org") - - assertEquals(1, history.getVisited().size) - assertEquals("http://www.firefox.com", history.getVisited()[0]) - - history.deleteVisitsFor("http://www.firefox.com") - assertEquals(0, history.getVisited().size) - } - - @Test - fun `store can delete by 'since'`() = runBlocking { - val history = InMemoryHistoryStorage() - - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.DOWNLOAD, RedirectSource.NOT_A_SOURCE)) - history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.BOOKMARK, RedirectSource.NOT_A_SOURCE)) - - history.deleteVisitsSince(0) - val visits = history.getVisited() - assertEquals(0, visits.size) - } - - @Test - fun `store can delete by 'range'`() { - val history = InMemoryHistoryStorage() - - runBlocking { - history.recordVisit("http://www.mozilla.org/1", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - sleep(10) - history.recordVisit("http://www.mozilla.org/2", PageVisit(VisitType.DOWNLOAD, RedirectSource.NOT_A_SOURCE)) - sleep(10) - history.recordVisit("http://www.mozilla.org/3", PageVisit(VisitType.BOOKMARK, RedirectSource.NOT_A_SOURCE)) - } - - val ts = runBlocking { - val visits = history.getDetailedVisits(0, Long.MAX_VALUE) - - assertEquals(3, visits.size) - visits[1].visitTime - } - - runBlocking { - history.deleteVisitsBetween(ts - 1, ts + 1) - } - val visits = runBlocking { - history.getDetailedVisits(0, Long.MAX_VALUE) - } - assertEquals(2, visits.size) - - assertEquals("http://www.mozilla.org/1", visits[0].url) - assertEquals("http://www.mozilla.org/3", visits[1].url) - } - - @Test - fun `store can delete visit by 'url' and 'timestamp'`() { - val history = InMemoryHistoryStorage() - - runBlocking { - history.recordVisit("http://www.mozilla.org/1", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - sleep(10) - history.recordVisit("http://www.mozilla.org/2", PageVisit(VisitType.DOWNLOAD, RedirectSource.NOT_A_SOURCE)) - sleep(10) - history.recordVisit("http://www.mozilla.org/3", PageVisit(VisitType.BOOKMARK, RedirectSource.NOT_A_SOURCE)) - } - - val ts = runBlocking { - val visits = history.getDetailedVisits(0, Long.MAX_VALUE) - - assertEquals(3, visits.size) - visits[1].visitTime - } - - runBlocking { - history.deleteVisit("http://www.mozilla.org/4", 111) - // There are no visits for this url, delete is a no-op. - assertEquals(3, history.getDetailedVisits(0, Long.MAX_VALUE).size) - } - - runBlocking { - history.deleteVisit("http://www.mozilla.org/1", ts) - // There is no such visit for this url, delete is a no-op. - assertEquals(3, history.getDetailedVisits(0, Long.MAX_VALUE).size) - } - - runBlocking { - history.deleteVisit("http://www.mozilla.org/2", ts) - } - - val visits = runBlocking { - history.getDetailedVisits(0, Long.MAX_VALUE) - } - assertEquals(2, visits.size) - - assertEquals("http://www.mozilla.org/1", visits[0].url) - assertEquals("http://www.mozilla.org/3", visits[1].url) - } -} diff --git a/components/browser/storage-memory/src/test/resources/robolectric.properties b/components/browser/storage-memory/src/test/resources/robolectric.properties deleted file mode 100644 index 89a6c8b4c2e..00000000000 --- a/components/browser/storage-memory/src/test/resources/robolectric.properties +++ /dev/null @@ -1 +0,0 @@ -sdk=28 \ No newline at end of file diff --git a/components/concept/storage/README.md b/components/concept/storage/README.md index e23ddcbc002..5afcfb9e293 100644 --- a/components/concept/storage/README.md +++ b/components/concept/storage/README.md @@ -4,8 +4,7 @@ The `concept-storage` component contains interfaces and abstract classes that de This abstraction makes it possible to build components that work independently of the storage layer being used. -Currently two store implementations are available: -- [in-memory storage](../../browser/storage-memory) +Currently a single store implementation is available: - [syncable, Rust Places storage](../../browser/storage-sync) - compatible with the Firefox Sync ecosystem ## Usage diff --git a/components/feature/awesomebar/build.gradle b/components/feature/awesomebar/build.gradle index d3858870aa7..4a2cced89d0 100644 --- a/components/feature/awesomebar/build.gradle +++ b/components/feature/awesomebar/build.gradle @@ -42,7 +42,6 @@ dependencies { implementation Dependencies.kotlin_stdlib testImplementation project(':support-test') - testImplementation project(':browser-storage-memory') testImplementation project(':lib-fetch-httpurlconnection') testImplementation Dependencies.androidx_test_core diff --git a/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProvider.kt b/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProvider.kt index ebceee44f30..d34a55b2fa3 100644 --- a/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProvider.kt +++ b/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProvider.kt @@ -55,6 +55,7 @@ class HistoryStorageSuggestionProvider( val suggestions = historyStorage.getSuggestions(text, maxNumberOfSuggestions) .sortedByDescending { it.score } .distinctBy { it.id } + .take(maxNumberOfSuggestions) suggestions.firstOrNull()?.url?.let { url -> engine?.speculativeConnect(url) } diff --git a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/CombinedHistorySuggestionProviderTest.kt b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/CombinedHistorySuggestionProviderTest.kt index 59fbbe0d04f..ceb7c2081cd 100644 --- a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/CombinedHistorySuggestionProviderTest.kt +++ b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/CombinedHistorySuggestionProviderTest.kt @@ -6,18 +6,14 @@ package mozilla.components.feature.awesomebar.provider import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.runBlocking -import mozilla.components.browser.storage.memory.InMemoryHistoryStorage import mozilla.components.concept.storage.DocumentType import mozilla.components.concept.storage.HistoryMetadata import mozilla.components.concept.storage.HistoryMetadataKey import mozilla.components.concept.storage.HistoryMetadataStorage -import mozilla.components.concept.storage.PageVisit -import mozilla.components.concept.storage.RedirectSource +import mozilla.components.concept.storage.HistoryStorage import mozilla.components.concept.storage.SearchResult -import mozilla.components.concept.storage.VisitType import mozilla.components.support.test.eq import mozilla.components.support.test.mock -import mozilla.components.support.test.whenever import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -27,6 +23,7 @@ import org.mockito.Mockito.doReturn @RunWith(AndroidJUnit4::class) class CombinedHistorySuggestionProviderTest { + private val historyEntry = HistoryMetadata( key = HistoryMetadataKey("http://www.mozilla.com", null, null), title = "mozilla", @@ -39,11 +36,11 @@ class CombinedHistorySuggestionProviderTest { @Test fun `GIVEN history items exists WHEN onInputChanged is called with empty text THEN return empty suggestions list`() = runBlocking { - val storage: HistoryMetadataStorage = mock() - whenever(storage.queryHistoryMetadata("moz", DEFAULT_METADATA_SUGGESTION_LIMIT)).thenReturn(listOf(historyEntry)) - val history = InMemoryHistoryStorage() - history.recordVisit("http://www.mozilla.com", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - val provider = CombinedHistorySuggestionProvider(history, storage, mock()) + val metadata: HistoryMetadataStorage = mock() + doReturn(listOf(historyEntry)).`when`(metadata).queryHistoryMetadata(eq("moz"), anyInt()) + val history: HistoryStorage = mock() + doReturn(listOf(SearchResult("id", "http://www.mozilla.com", 10))).`when`(history).getSuggestions(eq("moz"), anyInt()) + val provider = CombinedHistorySuggestionProvider(history, metadata, mock()) assertTrue(provider.onInputChanged("").isEmpty()) assertTrue(provider.onInputChanged(" ").isEmpty()) @@ -53,23 +50,23 @@ class CombinedHistorySuggestionProviderTest { fun `GIVEN more suggestions asked than metadata items exist WHEN user changes input THEN return a combined list of suggestions`() = runBlocking { val storage: HistoryMetadataStorage = mock() doReturn(listOf(historyEntry)).`when`(storage).queryHistoryMetadata(eq("moz"), anyInt()) - val history = InMemoryHistoryStorage() - history.recordVisit("http://www.mozilla.com/firefox", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) + val history: HistoryStorage = mock() + doReturn(listOf(SearchResult("id", "http://www.mozilla.com/firefox/", 10))).`when`(history).getSuggestions(eq("moz"), anyInt()) val provider = CombinedHistorySuggestionProvider(history, storage, mock()) val result = provider.onInputChanged("moz") assertEquals(2, result.size) assertEquals("http://www.mozilla.com", result[0].description) - assertEquals("http://www.mozilla.com/firefox", result[1].description) + assertEquals("http://www.mozilla.com/firefox/", result[1].description) } @Test fun `GIVEN fewer suggestions asked than metadata items exist WHEN user changes input THEN return suggestions only based on metadata items`() = runBlocking { val storage: HistoryMetadataStorage = mock() doReturn(listOf(historyEntry)).`when`(storage).queryHistoryMetadata(eq("moz"), anyInt()) - val history = InMemoryHistoryStorage() - history.recordVisit("http://www.mozilla.com/firefox", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) + val history: HistoryStorage = mock() + doReturn(listOf(SearchResult("id", "http://www.mozilla.com/firefox/", 10))).`when`(history).getSuggestions(eq("moz"), anyInt()) val provider = CombinedHistorySuggestionProvider(history, storage, mock(), maxNumberOfSuggestions = 1) val result = provider.onInputChanged("moz") @@ -80,27 +77,24 @@ class CombinedHistorySuggestionProviderTest { @Test fun `GIVEN only storage history items exist WHEN user changes input THEN return suggestions only based on storage items`() = runBlocking { - val storage: HistoryMetadataStorage = mock() - doReturn(emptyList()).`when`(storage).queryHistoryMetadata(eq("moz"), anyInt()) - val history = InMemoryHistoryStorage() - history.recordVisit("http://www.mozilla.com/firefox", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - val provider = CombinedHistorySuggestionProvider(history, storage, mock(), maxNumberOfSuggestions = 1) + val metadata: HistoryMetadataStorage = mock() + doReturn(emptyList()).`when`(metadata).queryHistoryMetadata(eq("moz"), anyInt()) + val history: HistoryStorage = mock() + doReturn(listOf(SearchResult("id", "http://www.mozilla.com/firefox/", 10))).`when`(history).getSuggestions(eq("moz"), anyInt()) + val provider = CombinedHistorySuggestionProvider(history, metadata, mock(), maxNumberOfSuggestions = 1) val result = provider.onInputChanged("moz") assertEquals(1, result.size) - assertEquals("http://www.mozilla.com/firefox", result[0].description) + assertEquals("http://www.mozilla.com/firefox/", result[0].description) } @Test fun `GIVEN duplicated metadata and storage entries WHEN user changes input THEN return distinct suggestions`() = runBlocking { val storage: HistoryMetadataStorage = mock() doReturn(listOf(historyEntry)).`when`(storage).queryHistoryMetadata(eq("moz"), anyInt()) - val history = InMemoryHistoryStorage() - history.recordVisit( - "http://www.mozilla.com", - PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE) - ) + val history: HistoryStorage = mock() + doReturn(listOf(SearchResult("id", "http://www.mozilla.com", 10))).`when`(history).getSuggestions(eq("moz"), anyInt()) val provider = CombinedHistorySuggestionProvider(history, storage, mock()) val result = provider.onInputChanged("moz") @@ -146,7 +140,7 @@ class CombinedHistorySuggestionProviderTest { ) val metadataStorage: HistoryMetadataStorage = mock() - val historyStorage: InMemoryHistoryStorage = mock() + val historyStorage: HistoryStorage = mock() doReturn(listOf(metadataEntry2, metadataEntry1)).`when`(metadataStorage).queryHistoryMetadata(eq("moz"), anyInt()) doReturn(listOf(searchResult1, searchResult2)).`when`(historyStorage).getSuggestions(eq("moz"), anyInt()) diff --git a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProviderTest.kt b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProviderTest.kt index 78d06bd3fd1..a50f4c46c22 100644 --- a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProviderTest.kt +++ b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/HistoryStorageSuggestionProviderTest.kt @@ -4,14 +4,11 @@ package mozilla.components.feature.awesomebar.provider +import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.runBlocking -import mozilla.components.browser.storage.memory.InMemoryHistoryStorage import mozilla.components.concept.engine.Engine import mozilla.components.concept.storage.HistoryStorage -import mozilla.components.concept.storage.PageVisit -import mozilla.components.concept.storage.RedirectSource import mozilla.components.concept.storage.SearchResult -import mozilla.components.concept.storage.VisitType import mozilla.components.feature.awesomebar.facts.AwesomeBarFacts import mozilla.components.support.base.Component import mozilla.components.support.base.facts.Action @@ -24,12 +21,15 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyString +import org.mockito.Mockito import org.mockito.Mockito.`when` import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify +@RunWith(AndroidJUnit4::class) class HistoryStorageSuggestionProviderTest { @Before @@ -47,55 +47,59 @@ class HistoryStorageSuggestionProviderTest { @Test fun `Provider returns suggestions from configured history storage`() = runBlocking { - val history = InMemoryHistoryStorage() + val history: HistoryStorage = mock() + Mockito.doReturn(listOf(SearchResult("id", "http://www.mozilla.com/", 10))).`when`(history).getSuggestions(eq("moz"), Mockito.anyInt()) val provider = HistoryStorageSuggestionProvider(history, mock()) - history.recordVisit("http://www.mozilla.com", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - val suggestions = provider.onInputChanged("moz") assertEquals(1, suggestions.size) - assertEquals("http://www.mozilla.com", suggestions[0].description) + assertEquals("http://www.mozilla.com/", suggestions[0].description) } @Test - fun `Provider limits number of returned suggestions to 20 by default`() = runBlocking { - val history = InMemoryHistoryStorage() - val provider = HistoryStorageSuggestionProvider(history, mock()) - - for (i in 1..100) { - history.recordVisit("http://www.mozilla.com/$i", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - } + fun `Provider limits number of returned suggestions to a max of 20 by default`() = runBlocking { + val history: HistoryStorage = mock() + Mockito.doReturn( + (1..100).map { + SearchResult("id$it", "http://www.mozilla.com/$it/", 10) + } + ).`when`(history).getSuggestions(eq("moz"), Mockito.anyInt()) + val provider = HistoryStorageSuggestionProvider(history, mock()) val suggestions = provider.onInputChanged("moz") assertEquals(20, suggestions.size) } @Test fun `Provider allows lowering the number of returned suggestions beneath the default`() = runBlocking { - val history = InMemoryHistoryStorage() + val history: HistoryStorage = mock() + Mockito.doReturn( + (1..50).map { + SearchResult("id$it", "http://www.mozilla.com/$it/", 10) + } + ).`when`(history).getSuggestions(eq("moz"), Mockito.anyInt()) + val provider = HistoryStorageSuggestionProvider( historyStorage = history, loadUrlUseCase = mock(), maxNumberOfSuggestions = 2 ) - for (i in 1..50) { - history.recordVisit("http://www.mozilla.com/$i", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - } - val suggestions = provider.onInputChanged("moz") assertEquals(2, suggestions.size) } @Test fun `Provider allows increasing the number of returned suggestions above the default`() = runBlocking { - val history = InMemoryHistoryStorage() + val history: HistoryStorage = mock() + Mockito.doReturn( + (1..50).map { + SearchResult("id$it", "http://www.mozilla.com/$it/", 10) + } + ).`when`(history).getSuggestions(eq("moz"), Mockito.anyInt()) + val provider = HistoryStorageSuggestionProvider( historyStorage = history, loadUrlUseCase = mock(), maxNumberOfSuggestions = 22 ) - for (i in 1..50) { - history.recordVisit("http://www.mozilla.com/$i", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - } - val suggestions = provider.onInputChanged("moz") assertEquals(22, suggestions.size) } @@ -141,7 +145,7 @@ class HistoryStorageSuggestionProviderTest { @Test fun `provider calls speculative connect for URL of highest scored suggestion`() = runBlocking { - val history = InMemoryHistoryStorage() + val history: HistoryStorage = mock() val engine: Engine = mock() val provider = HistoryStorageSuggestionProvider(history, mock(), engine = engine) @@ -149,17 +153,17 @@ class HistoryStorageSuggestionProviderTest { assertTrue(suggestions.isEmpty()) verify(engine, never()).speculativeConnect(anyString()) - history.recordVisit("http://www.mozilla.com", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) + Mockito.doReturn(listOf(SearchResult("id", "http://www.mozilla.com/", 10))).`when`(history).getSuggestions(eq("moz"), Mockito.anyInt()) suggestions = provider.onInputChanged("moz") assertEquals(1, suggestions.size) - assertEquals("http://www.mozilla.com", suggestions[0].description) + assertEquals("http://www.mozilla.com/", suggestions[0].description) verify(engine, times(1)).speculativeConnect(suggestions[0].description!!) } @Test fun `fact is emitted when suggestion is clicked`() = runBlocking { - val history = InMemoryHistoryStorage() + val history: HistoryStorage = mock() val engine: Engine = mock() val provider = HistoryStorageSuggestionProvider(history, mock(), engine = engine) @@ -167,7 +171,7 @@ class HistoryStorageSuggestionProviderTest { assertTrue(suggestions.isEmpty()) verify(engine, never()).speculativeConnect(anyString()) - history.recordVisit("http://www.mozilla.com", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) + Mockito.doReturn(listOf(SearchResult("id", "http://www.mozilla.com/", 10))).`when`(history).getSuggestions(eq("moz"), Mockito.anyInt()) suggestions = provider.onInputChanged("moz") assertEquals(1, suggestions.size) diff --git a/components/feature/toolbar/build.gradle b/components/feature/toolbar/build.gradle index 5069f62fb27..2edb3b89e36 100644 --- a/components/feature/toolbar/build.gradle +++ b/components/feature/toolbar/build.gradle @@ -44,7 +44,6 @@ dependencies { implementation Dependencies.kotlin_coroutines testImplementation project(':support-test') - testImplementation project(':browser-storage-memory') testImplementation Dependencies.androidx_test_core testImplementation Dependencies.androidx_test_junit diff --git a/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarAutocompleteFeatureTest.kt b/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarAutocompleteFeatureTest.kt index 82900eecfe6..755b5db0a10 100644 --- a/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarAutocompleteFeatureTest.kt +++ b/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarAutocompleteFeatureTest.kt @@ -9,12 +9,9 @@ import kotlinx.coroutines.runBlocking import mozilla.components.browser.domains.Domain import mozilla.components.browser.domains.autocomplete.BaseDomainAutocompleteProvider import mozilla.components.browser.domains.autocomplete.DomainList -import mozilla.components.browser.storage.memory.InMemoryHistoryStorage import mozilla.components.concept.engine.Engine +import mozilla.components.concept.storage.HistoryAutocompleteResult import mozilla.components.concept.storage.HistoryStorage -import mozilla.components.concept.storage.PageVisit -import mozilla.components.concept.storage.RedirectSource -import mozilla.components.concept.storage.VisitType import mozilla.components.concept.toolbar.AutocompleteDelegate import mozilla.components.concept.toolbar.AutocompleteResult import mozilla.components.concept.toolbar.Toolbar @@ -26,6 +23,7 @@ import org.junit.Assert.assertNotNull import org.junit.Assert.fail import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.doReturn import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.times @@ -153,7 +151,7 @@ class ToolbarAutocompleteFeatureTest { var feature = ToolbarAutocompleteFeature(toolbar) val autocompleteDelegate: AutocompleteDelegate = mock() - var history: HistoryStorage = InMemoryHistoryStorage() + var history: HistoryStorage = mock() val domains = object : BaseDomainAutocompleteProvider(DomainList.CUSTOM, { emptyList() }) { fun testDomains(list: List) { domains = list @@ -165,9 +163,15 @@ class ToolbarAutocompleteFeatureTest { verifyNoAutocompleteResult(toolbar, autocompleteDelegate, "hi") // Can autocomplete with a non-empty history provider. - runBlocking { - history.recordVisit("https://www.mozilla.org", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - } + doReturn( + HistoryAutocompleteResult( + input = "mo", + text = "mozilla.org", + url = "https://www.mozilla.org", + source = "memoryHistory", + totalItems = 1 + ) + ).`when`(history).getAutocompleteSuggestion("mo") verifyNoAutocompleteResult(toolbar, autocompleteDelegate, "hi") verifyAutocompleteResult( @@ -206,7 +210,7 @@ class ToolbarAutocompleteFeatureTest { ) // Can autocomplete with empty history and domain providers. - history = InMemoryHistoryStorage() + history = mock() domains.testDomains(listOf()) feature.addHistoryStorageProvider(history) @@ -232,9 +236,15 @@ class ToolbarAutocompleteFeatureTest { ) ) - runBlocking { - history.recordVisit("https://www.mozilla.org", PageVisit(VisitType.TYPED, RedirectSource.NOT_A_SOURCE)) - } + doReturn( + HistoryAutocompleteResult( + input = "mo", + text = "mozilla.org", + url = "https://www.mozilla.org", + source = "memoryHistory", + totalItems = 1 + ) + ).`when`(history).getAutocompleteSuggestion("mo") verifyAutocompleteResult( toolbar, autocompleteDelegate, "mo", diff --git a/taskcluster/ci/config.yml b/taskcluster/ci/config.yml index 649b7a1c6e2..8dc7d1dbd72 100644 --- a/taskcluster/ci/config.yml +++ b/taskcluster/ci/config.yml @@ -17,7 +17,6 @@ treeherder: browser-menu2: browser-menu2 browser-session-storage: browser-session-storage browser-state: browser-state - browser-storage-memory: browser-storage-memory browser-storage-sync: browser-storage-sync browser-tabstray: browser-tabstray browser-thumbnails: browser-thumbnails