Skip to content

Commit

Permalink
Memory database for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
flypaper0 committed Nov 1, 2023
1 parent 0ad5de7 commit 9cd1164
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 70 deletions.
4 changes: 3 additions & 1 deletion Example/IntegrationTests/Push/NotifyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ final class NotifyTests: XCTestCase {
keychainStorage: keychain,
environment: .sandbox)
let keyserverURL = URL(string: "https://keys.walletconnect.com")!
let sqlite = try! MemorySqlite()
// Note:- prod project_id do not exists on staging, we can use gmDappProjectId
let client = NotifyClientFactory.create(projectId: InputConfig.gmDappProjectId,
keyserverURL: keyserverURL,
keyserverURL: keyserverURL,
sqlite: sqlite,
logger: notifyLogger,
keyValueStorage: keyValueStorage,
keychainStorage: keychain,
Expand Down
51 changes: 51 additions & 0 deletions Sources/Database/DiskSqlite.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Foundation
import SQLite3

public final class DiskSqlite: Sqlite {

private let path: String

private var db: OpaquePointer?

public init(path: String) {
self.path = path
}

public func openDatabase() throws {
guard sqlite3_open_v2(path, &db, SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK else {
throw SQLiteError.openDatabase(path: path)
}
var error: UnsafeMutablePointer<CChar>?
guard sqlite3_exec(db, "PRAGMA journal_mode=WAL;", nil, nil, &error) == SQLITE_OK else {
let message = error.map { String(cString: $0) }
throw SQLiteError.exec(error: message)
}
}

public func query<Row: SqliteRow>(sql: String) throws -> [Row] {
var queryStatement: OpaquePointer?
guard sqlite3_prepare_v2(db, sql, -1, &queryStatement, nil) == SQLITE_OK else {
throw SQLiteError.queryPrepare(statement: sql)
}
var rows: [Row] = []
while sqlite3_step(queryStatement) == SQLITE_ROW {
let decoder = SqliteRowDecoder(statement: queryStatement)
guard let row = try? Row(decoder: decoder) else { continue }
rows.append(row)
}
sqlite3_finalize(queryStatement)
return rows
}

public func execute(sql: String) throws {
var error: UnsafeMutablePointer<CChar>?
guard sqlite3_exec(db, sql, nil, nil, &error) == SQLITE_OK else {
let message = error.map { String(cString: $0) }
throw SQLiteError.exec(error: message)
}
}

public func closeConnection() {
sqlite3_close(db)
}
}
49 changes: 49 additions & 0 deletions Sources/Database/MemorySqlite.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Foundation
import SQLite3

public final class MemorySqlite: Sqlite {

private var db: OpaquePointer?

public init() throws {
guard sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK else {
throw SQLiteError.openDatabaseMemory
}
var error: UnsafeMutablePointer<CChar>?
guard sqlite3_exec(db, "PRAGMA journal_mode=WAL;", nil, nil, &error) == SQLITE_OK else {
let message = error.map { String(cString: $0) }
throw SQLiteError.exec(error: message)
}
}

public func openDatabase() throws {
// No op
}

public func query<Row: SqliteRow>(sql: String) throws -> [Row] {
var queryStatement: OpaquePointer?
guard sqlite3_prepare_v2(db, sql, -1, &queryStatement, nil) == SQLITE_OK else {
throw SQLiteError.queryPrepare(statement: sql)
}
var rows: [Row] = []
while sqlite3_step(queryStatement) == SQLITE_ROW {
let decoder = SqliteRowDecoder(statement: queryStatement)
guard let row = try? Row(decoder: decoder) else { continue }
rows.append(row)
}
sqlite3_finalize(queryStatement)
return rows
}

public func execute(sql: String) throws {
var error: UnsafeMutablePointer<CChar>?
guard sqlite3_exec(db, sql, nil, nil, &error) == SQLITE_OK else {
let message = error.map { String(cString: $0) }
throw SQLiteError.exec(error: message)
}
}

public func closeConnection() {
// No op
}
}
45 changes: 5 additions & 40 deletions Sources/Database/Sqlite.swift
Original file line number Diff line number Diff line change
@@ -1,55 +1,20 @@
import Foundation
import SQLite3

public final class Sqlite {

private var db: OpaquePointer?

public init() { }
public protocol Sqlite {

/// Opening A New Database Connection
/// - Parameter path: Path to database
public func openDatabase(path: String) throws {
guard sqlite3_open_v2(path, &db, SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK else {
throw SQLiteError.openDatabase(path: path)
}
var error: UnsafeMutablePointer<CChar>?
guard sqlite3_exec(db, "PRAGMA journal_mode=WAL;", nil, nil, &error) == SQLITE_OK else {
let message = error.map { String(cString: $0) }
throw SQLiteError.exec(error: message)
}
}
func openDatabase() throws

/// Evaluate an SQL Statement
/// - Parameter sql: SQL query
/// - Returns: Table rows array
public func query<Row: SqliteRow>(sql: String) throws -> [Row] {
var queryStatement: OpaquePointer?
guard sqlite3_prepare_v2(db, sql, -1, &queryStatement, nil) == SQLITE_OK else {
throw SQLiteError.queryPrepare(statement: sql)
}
var rows: [Row] = []
while sqlite3_step(queryStatement) == SQLITE_ROW {
let decoder = SqliteRowDecoder(statement: queryStatement)
guard let row = try? Row(decoder: decoder) else { continue }
rows.append(row)
}
sqlite3_finalize(queryStatement)
return rows
}
func query<Row: SqliteRow>(sql: String) throws -> [Row]

/// One-Step query execution
/// - Parameter sql: SQL query
public func execute(sql: String) throws {
var error: UnsafeMutablePointer<CChar>?
guard sqlite3_exec(db, sql, nil, nil, &error) == SQLITE_OK else {
let message = error.map { String(cString: $0) }
throw SQLiteError.exec(error: message)
}
}
func execute(sql: String) throws

/// Closing A Database Connection
public func closeConnection() {
sqlite3_close(db)
}
func closeConnection()
}
1 change: 1 addition & 0 deletions Sources/Database/SqliteError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

public enum SQLiteError: Error {
case openDatabase(path: String)
case openDatabaseMemory
case queryPrepare(statement: String)
case exec(error: String?)
case decodeString(index: Int32)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ public struct NotifyClientFactory {
let keyserverURL = URL(string: "https://keys.walletconnect.com")!
let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk")
let groupKeychainService = GroupKeychainStorage(serviceIdentifier: groupIdentifier)
let databasePath = databasePath(appGroup: groupIdentifier, database: "notify.db")
let sqlite = DiskSqlite(path: databasePath)

return NotifyClientFactory.create(
projectId: projectId,
keyserverURL: keyserverURL,
groupIdentifier: groupIdentifier,
sqlite: sqlite,
logger: logger,
keyValueStorage: keyValueStorage,
keychainStorage: keychainStorage,
Expand All @@ -29,7 +31,7 @@ public struct NotifyClientFactory {
static func create(
projectId: String,
keyserverURL: URL,
groupIdentifier: String,
sqlite: Sqlite,
logger: ConsoleLogging,
keyValueStorage: KeyValueStorage,
keychainStorage: KeychainStorageProtocol,
Expand All @@ -43,7 +45,7 @@ public struct NotifyClientFactory {
) -> NotifyClient {
let kms = KeyManagementService(keychain: keychainStorage)
let notifyAccountProvider = NotifyAccountProvider()
let database = NotifyDatabase(appGroup: groupIdentifier, database: "notify.db", sqlite: Sqlite(), logger: logger)
let database = NotifyDatabase(sqlite: sqlite, logger: logger)
let notifyStorage = NotifyStorage(database: database, accountProvider: notifyAccountProvider)
let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger)
let notifyMessageSubscriber = NotifyMessageSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, notifyStorage: notifyStorage, crypto: crypto, logger: logger)
Expand Down Expand Up @@ -93,4 +95,15 @@ public struct NotifyClientFactory {
subscriptionWatcher: subscriptionWatcher
)
}

static func databasePath(appGroup: String, database: String) -> String {
guard let path = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: appGroup)?
.appendingPathComponent(database) else {

fatalError("Database path not exists")
}

return path.absoluteString
}
}
25 changes: 5 additions & 20 deletions Sources/WalletConnectNotify/Client/Wallet/NotifyDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,13 @@ final class NotifyDatabase {
static let messages = "NotifyMessage"
}

private let appGroup: String
private let database: String
private let sqlite: Sqlite
private let logger: ConsoleLogging

var onSubscriptionsUpdate: (() throws -> Void)?
var onMessagesUpdate: (() throws -> Void)?

init(appGroup: String, database: String, sqlite: Sqlite, logger: ConsoleLogging) {
self.appGroup = appGroup
self.database = database
init(sqlite: Sqlite, logger: ConsoleLogging) {
self.sqlite = sqlite
self.logger = logger

Expand Down Expand Up @@ -107,21 +103,10 @@ final class NotifyDatabase {

private extension NotifyDatabase {

var path: String {
guard let path = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: appGroup)?
.appendingPathComponent(database) else {

fatalError("Database path not exists")
}

return path.absoluteString
}

func prepareDatabase() {
do {
defer { sqlite.closeConnection() }
try sqlite.openDatabase(path: path)
try sqlite.openDatabase()

try sqlite.execute(sql: """
CREATE TABLE IF NOT EXISTS \(Table.subscriptions) (
Expand Down Expand Up @@ -149,21 +134,21 @@ private extension NotifyDatabase {
);
""")

logger.debug("SQlite database created at path \(path)")
logger.debug("SQlite database created")
} catch {
logger.error("SQlite database creation error: \(error.localizedDescription)")
}
}

func execute(sql: String) throws {
try sqlite.openDatabase(path: path)
try sqlite.openDatabase()
defer { sqlite.closeConnection() }

try sqlite.execute(sql: sql)
}

func query<T: SqliteRow>(sql: String) throws -> [T] {
try sqlite.openDatabase(path: path)
try sqlite.openDatabase()
defer { sqlite.closeConnection() }

return try sqlite.query(sql: sql)
Expand Down
6 changes: 2 additions & 4 deletions Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import Combine

protocol NotifyStoring {
func getAllSubscriptions() -> [NotifySubscription]
func getSubscriptions(account: Account) throws -> [NotifySubscription]
func getSubscription(topic: String) throws -> NotifySubscription?
func getSubscriptions(account: Account) -> [NotifySubscription]
func getSubscription(topic: String) -> NotifySubscription?
func setSubscription(_ subscription: NotifySubscription) throws
func replaceAllSubscriptions(_ subscriptions: [NotifySubscription]) throws
func deleteSubscription(topic: String) throws
func clearDatabase(account: Account) throws
func updateSubscription(_ subscription: NotifySubscription, scope: [String: ScopeValue], expiry: UInt64) throws
}

final class NotifyStorage: NotifyStoring {
Expand Down
4 changes: 2 additions & 2 deletions Tests/NotifyTests/Mocks/MockNotifyStoring.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class MockNotifyStoring: NotifyStoring {
return subscriptions
}

func setSubscription(_ subscription: NotifySubscription) async throws {
func setSubscription(_ subscription: NotifySubscription) {
if let index = subscriptions.firstIndex(where: { $0.topic == subscription.topic }) {
subscriptions[index] = subscription
} else {
Expand All @@ -33,7 +33,7 @@ class MockNotifyStoring: NotifyStoring {
subscriptions = subscriptions.filter { $0.account != account }
}

func deleteSubscription(topic: String) async throws {
func deleteSubscription(topic: String) throws {
subscriptions.removeAll(where: { $0.topic == topic })
}
}

0 comments on commit 9cd1164

Please sign in to comment.