Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
2.0.0
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
/* 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/. */
import Foundation
import Shared
@testable import Storage
import Deferred
import SDWebImage
import XCTest
private let microsecondsPerMinute: UInt64 = 60_000_000 // 1000 * 1000 * 60
private let oneHourInMicroseconds: UInt64 = 60 * microsecondsPerMinute
private let oneDayInMicroseconds: UInt64 = 24 * oneHourInMicroseconds
class TestSQLiteHistoryRecommendations: XCTestCase {
let files = MockFiles()
var db: BrowserDB!
var prefs: MockProfilePrefs!
var history: SQLiteHistory!
var bookmarks: MergedSQLiteBookmarks!
var metadata: SQLiteMetadata!
override func setUp() {
super.setUp()
db = BrowserDB(filename: "browser.db", schema: BrowserSchema(), files: files)
metadata = SQLiteMetadata(db: db)
prefs = MockProfilePrefs()
history = SQLiteHistory(db: db, prefs: prefs)
bookmarks = MergedSQLiteBookmarks(db: db)
}
override func tearDown() {
// Clear out anything we might have changed on disk
history.clearHistory().succeeded()
db.run("DELETE FROM page_metadata").succeeded()
db.run("DELETE FROM highlights").succeeded()
db.run("DELETE FROM activity_stream_blocklist").succeeded()
SDWebImageManager.shared().imageCache?.clearDisk()
SDWebImageManager.shared().imageCache?.clearMemory()
super.tearDown()
}
/*
* Verify that we return a non-recent history highlight if:
*
* 1. We haven't visited the site in the last 30 minutes
* 2. We've only visited the site less than or equal to 3 times
* 3. The site we visited has a non-empty title
*
*/
func testHistoryHighlights() {
let startTime = Date.nowMicroseconds()
let oneHourAgo = startTime - oneHourInMicroseconds
let fifteenMinutesAgo = startTime - 15 * microsecondsPerMinute
/*
* Site A: 1 visit, 1 hour ago = highlight
* Site B: 1 visits, 15 minutes ago = non-highlight
* Site C: 3 visits, 1 hour ago = highlight
* Site D: 4 visits, 1 hour ago = non-highlight
*/
let siteA = Site(url: "http://siteA/", title: "A")
let siteB = Site(url: "http://siteB/", title: "B")
let siteC = Site(url: "http://siteC/", title: "C")
let siteD = Site(url: "http://siteD/", title: "D")
let siteVisitA1 = SiteVisit(site: siteA, date: oneHourAgo, type: .link)
let siteVisitB1 = SiteVisit(site: siteB, date: fifteenMinutesAgo, type: .link)
let siteVisitC1 = SiteVisit(site: siteC, date: oneHourAgo + 1, type: .link)
let siteVisitC2 = SiteVisit(site: siteC, date: oneHourAgo + 1000, type: .link)
let siteVisitC3 = SiteVisit(site: siteC, date: oneHourAgo + 2000, type: .link)
let siteVisitD1 = SiteVisit(site: siteD, date: oneHourAgo, type: .link)
let siteVisitD2 = SiteVisit(site: siteD, date: oneHourAgo + 1000, type: .link)
let siteVisitD3 = SiteVisit(site: siteD, date: oneHourAgo + 2000, type: .link)
let siteVisitD4 = SiteVisit(site: siteD, date: oneHourAgo + 3000, type: .link)
history.clearHistory().succeeded()
history.addLocalVisit(siteVisitA1).succeeded()
history.addLocalVisit(siteVisitB1).succeeded()
history.addLocalVisit(siteVisitC1).succeeded()
history.addLocalVisit(siteVisitC2).succeeded()
history.addLocalVisit(siteVisitC3).succeeded()
history.addLocalVisit(siteVisitD1).succeeded()
history.addLocalVisit(siteVisitD2).succeeded()
history.addLocalVisit(siteVisitD3).succeeded()
history.addLocalVisit(siteVisitD4).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
let highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 2)
XCTAssertEqual(highlights[0]!.title, "A")
XCTAssertEqual(highlights[1]!.title, "C")
}
/*
* Verify that we do not return a highlight if
* its domain is in the blacklist
*
*/
func testBlacklistHighlights() {
let startTime = Date.nowMicroseconds()
let oneHourAgo = startTime - oneHourInMicroseconds
let fifteenMinutesAgo = startTime - 15 * microsecondsPerMinute
/*
* Site A: 1 visit, 1 hour ago = highlight that is on the blacklist
* Site B: 1 visits, 15 minutes ago = non-highlight
* Site C: 3 visits, 1 hour ago = highlight that is on the blacklist
* Site D: 4 visits, 1 hour ago = non-highlight
*/
let siteA = Site(url: "http://www.google.com", title: "A")
let siteB = Site(url: "http://siteB/", title: "B")
let siteC = Site(url: "http://www.search.yahoo.com/", title: "C")
let siteD = Site(url: "http://siteD/", title: "D")
let siteVisitA1 = SiteVisit(site: siteA, date: oneHourAgo, type: .link)
let siteVisitB1 = SiteVisit(site: siteB, date: fifteenMinutesAgo, type: .link)
let siteVisitC1 = SiteVisit(site: siteC, date: oneHourAgo, type: .link)
let siteVisitC2 = SiteVisit(site: siteC, date: oneHourAgo + 1000, type: .link)
let siteVisitC3 = SiteVisit(site: siteC, date: oneHourAgo + 2000, type: .link)
let siteVisitD1 = SiteVisit(site: siteD, date: oneHourAgo, type: .link)
let siteVisitD2 = SiteVisit(site: siteD, date: oneHourAgo + 1000, type: .link)
let siteVisitD3 = SiteVisit(site: siteD, date: oneHourAgo + 2000, type: .link)
let siteVisitD4 = SiteVisit(site: siteD, date: oneHourAgo + 3000, type: .link)
history.clearHistory().succeeded()
history.addLocalVisit(siteVisitA1).succeeded()
history.addLocalVisit(siteVisitB1).succeeded()
history.addLocalVisit(siteVisitC1).succeeded()
history.addLocalVisit(siteVisitC2).succeeded()
history.addLocalVisit(siteVisitC3).succeeded()
history.addLocalVisit(siteVisitD1).succeeded()
history.addLocalVisit(siteVisitD2).succeeded()
history.addLocalVisit(siteVisitD3).succeeded()
history.addLocalVisit(siteVisitD4).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
let highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 0)
}
/*
* Verify that we return the most recent highlight per domain
*/
func testMostRecentUniqueDomainReturnedInHighlights() {
let startTime = Date.nowMicroseconds()
let oneHourAgo = startTime - oneHourInMicroseconds
let twoHoursAgo = startTime - 2 * oneHourInMicroseconds
/*
* Site A: 1 visit, 1 hour ago = highlight
* Site C: 2 visits, 2 hours ago = highlight with the same domain
*/
let siteA = Site(url: "http://www.foo.com/", title: "A")
let siteC = Site(url: "http://m.foo.com/", title: "C")
let siteVisitA1 = SiteVisit(site: siteA, date: oneHourAgo, type: .link)
let siteVisitC1 = SiteVisit(site: siteC, date: twoHoursAgo, type: .link)
let siteVisitC2 = SiteVisit(site: siteC, date: twoHoursAgo + 1000, type: .link)
history.clearHistory().succeeded()
history.addLocalVisit(siteVisitA1).succeeded()
history.addLocalVisit(siteVisitC1).succeeded()
history.addLocalVisit(siteVisitC2).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
let highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 1)
XCTAssertEqual(highlights[0]!.title, "A")
}
func testBookmarkHighlights() {
history.clearHistory().succeeded()
populateForRecommendationCalculations(history, bookmarks: bookmarks, metadata: metadata, historyCount: 10, bookmarkCount: 10)
let sites = history.getRecentBookmarks(5).value.successValue?.asArray()
XCTAssertEqual(sites!.count, 5, "5 bookmarks should have been fetched")
sites!.forEach { XCTAssertEqual($0.guid, "bookmark-\(sites!.index(of: $0)!)"); XCTAssertEqual($0.metadata?.description, "Test Description") }
}
func testMetadataReturnedInHighlights() {
let startTime = Date.nowMicroseconds()
let oneHourAgo = startTime - oneHourInMicroseconds
let siteA = Site(url: "http://siteA.com", title: "Site A")
let siteB = Site(url: "http://siteB.com/", title: "Site B")
let siteC = Site(url: "http://siteC.com/", title: "Site C")
let siteVisitA1 = SiteVisit(site: siteA, date: oneHourAgo, type: .link)
let siteVisitB1 = SiteVisit(site: siteB, date: oneHourAgo + 1000, type: .link)
let siteVisitC1 = SiteVisit(site: siteC, date: oneHourAgo, type: .link)
let siteVisitC2 = SiteVisit(site: siteC, date: oneHourAgo + 1000, type: .link)
let siteVisitC3 = SiteVisit(site: siteC, date: oneHourAgo + 2000, type: .link)
history.clearHistory().succeeded()
history.addLocalVisit(siteVisitA1).succeeded()
history.addLocalVisit(siteVisitB1).succeeded()
history.addLocalVisit(siteVisitC1).succeeded()
history.addLocalVisit(siteVisitC2).succeeded()
history.addLocalVisit(siteVisitC3).succeeded()
// add metadata for 2 of the sites
let metadata = SQLiteMetadata(db: db)
let pageA = PageMetadata(id: nil, siteURL: siteA.url, mediaURL: "http://image.com",
title: siteA.title, description: "Test Description", type: nil, providerName: nil)
metadata.storeMetadata(pageA, forPageURL: siteA.url.asURL!, expireAt: Date.now() + 3000).succeeded()
let pageB = PageMetadata(id: nil, siteURL: siteB.url, mediaURL: "http://image.com",
title: siteB.title, description: "Test Description", type: nil, providerName: nil)
metadata.storeMetadata(pageB, forPageURL: siteB.url.asURL!, expireAt: Date.now() + 3000).succeeded()
let pageC = PageMetadata(id: nil, siteURL: siteC.url, mediaURL: "http://image.com",
title: siteC.title, description: "Test Description", type: nil, providerName: nil)
metadata.storeMetadata(pageC, forPageURL: siteC.url.asURL!, expireAt: Date.now() + 3000).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
let highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 3)
for highlight in highlights {
XCTAssertNotNil(highlight?.metadata)
XCTAssertNotNil(highlight?.metadata?.mediaURL)
}
}
func testRemoveHighlightForURL() {
let startTime = Date.nowMicroseconds()
let oneHourAgo = startTime - oneHourInMicroseconds
let siteA = Site(url: "http://siteA/", title: "A")
let siteVisitA1 = SiteVisit(site: siteA, date: oneHourAgo, type: .link)
history.clearHistory().succeeded()
history.addLocalVisit(siteVisitA1).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
var highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 1)
XCTAssertEqual(highlights[0]!.title, "A")
history.removeHighlightForURL(siteA.url).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 0)
}
func testClearHighlightsCache() {
let startTime = Date.nowMicroseconds()
let oneHourAgo = startTime - oneHourInMicroseconds
let siteA = Site(url: "http://siteA/", title: "A")
let siteVisitA1 = SiteVisit(site: siteA, date: oneHourAgo, type: .link)
history.clearHistory().succeeded()
history.addLocalVisit(siteVisitA1).succeeded()
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
let highlights = history.getHighlights().value.successValue!
XCTAssertEqual(highlights.count, 1)
XCTAssertEqual(highlights[0]!.title, "A")
}
}
class TestSQLiteHistoryRecommendationsPerf: XCTestCase {
func testRecommendationPref() {
let files = MockFiles()
let db = BrowserDB(filename: "browser.db", schema: BrowserSchema(), files: files)
let metadata = SQLiteMetadata(db: db)
let prefs = MockProfilePrefs()
let history = SQLiteHistory(db: db, prefs: prefs)
let bookmarks = MergedSQLiteBookmarks(db: db)
let count = 500
history.clearHistory().succeeded()
populateForRecommendationCalculations(history, bookmarks: bookmarks, metadata: metadata, historyCount: count, bookmarkCount: count)
self.measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true) {
for _ in 0...5 {
history.repopulate(invalidateTopSites: true, invalidateHighlights: true).succeeded()
}
self.stopMeasuring()
}
}
}
private func populateForRecommendationCalculations(_ history: SQLiteHistory, bookmarks: MergedSQLiteBookmarks, metadata: SQLiteMetadata, historyCount: Int, bookmarkCount: Int) {
let baseMillis: UInt64 = baseInstantInMillis - 20000
for i in 0..<historyCount {
let site = Site(url: "http://s\(i)ite\(i)/foo", title: "A \(i)")
site.guid = "abc\(i)def"
history.insertOrUpdatePlace(site.asPlace(), modified: baseMillis).succeeded()
for j in 0...20 {
let visitTime = advanceMicrosecondTimestamp(baseInstantInMicros, by: (1000000 * i) + (1000 * j))
addVisitForSite(site, intoHistory: history, from: .local, atTime: visitTime)
addVisitForSite(site, intoHistory: history, from: .remote, atTime: visitTime)
}
}
(0..<bookmarkCount).forEach { i in
let modifiedTime = advanceMicrosecondTimestamp(baseInstantInMicros, by: (1000000 * i))
let bookmarkSite = Site(url: "http://bookmark-\(i)/", title: "\(i) Bookmark")
bookmarkSite.guid = "bookmark-\(i)"
addVisitForSite(bookmarkSite, intoHistory: history, from: .local, atTime: modifiedTime)
addVisitForSite(bookmarkSite, intoHistory: history, from: .remote, atTime: modifiedTime)
addVisitForSite(bookmarkSite, intoHistory: history, from: .local, atTime: modifiedTime)
addVisitForSite(bookmarkSite, intoHistory: history, from: .remote, atTime: modifiedTime)
let pageA = PageMetadata(id: nil, siteURL: bookmarkSite.url, mediaURL: "http://image.com",
title: bookmarkSite.title, description: "Test Description", type: nil, providerName: nil)
metadata.storeMetadata(pageA, forPageURL: bookmarkSite.url.asURL!, expireAt: Date.now() + 3000).succeeded()
bookmarks.local.addToMobileBookmarks(URL(string:"http://bookmark-\(i)/")!, title: "\(i) Bookmark", favicon: nil).succeeded()
}
}