diff --git a/Database/Package.resolved b/Database/Package.resolved new file mode 100644 index 00000000..d03e5483 --- /dev/null +++ b/Database/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "3d98e183a568a5accbc0c0c5599a833ac3f72dcbc6225970d7263ed1570547d8", + "pins" : [ + { + "identity" : "rocksdb.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/TapeIt/rocksdb.swift.git", + "state" : { + "revision" : "7eae85eb67d8225efd7e313d3900820032ae51fe", + "version" : "6.29.5" + } + } + ], + "version" : 3 +} diff --git a/Database/Package.swift b/Database/Package.swift index d495d31b..dd4c442b 100644 --- a/Database/Package.swift +++ b/Database/Package.swift @@ -12,11 +12,17 @@ let package = Package( targets: ["Database"] ), ], + dependencies: [ + .package(url: "https://github.com/TapeIt/rocksdb.swift.git", from: "6.29.5"), + ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .target( - name: "Database" + name: "Database", + dependencies: [ + .product(name: "RocksDB", package: "rocksdb.swift"), + ] ), .testTarget( name: "DatabaseTests", diff --git a/Database/Sources/Database/Database.swift b/Database/Sources/Database/Database.swift index 08b22b80..07b11d65 100644 --- a/Database/Sources/Database/Database.swift +++ b/Database/Sources/Database/Database.swift @@ -1,2 +1 @@ -// The Swift Programming Language -// https://docs.swift.org/swift-book +@_exported import RocksDB diff --git a/Database/Tests/DatabaseTests/DatabaseTests.swift b/Database/Tests/DatabaseTests/DatabaseTests.swift index 0272d175..63516da6 100644 --- a/Database/Tests/DatabaseTests/DatabaseTests.swift +++ b/Database/Tests/DatabaseTests/DatabaseTests.swift @@ -1,13 +1,151 @@ +@testable import RocksDB import XCTest -@testable import Database - final class DatabaseTests: XCTestCase { - func testExample() throws { - // XCTest Documentation - // https://developer.apple.com/documentation/xctest + var database: RocksDB! + + func testSimplePut() { + let path = URL(fileURLWithPath: "/tmp/\(UUID().uuidString)") + + do { + database = try RocksDB(path: path) + + try database.put(key: "testText", value: "lolamkhaha") + try database.put(key: "testEmoji", value: "😂") + try database.put(key: "testTextEmoji", value: "emojitext 😂") + try database.put(key: "testMultipleEmoji", value: "😂😂😂") + + XCTAssertEqual(try database.get(type: String.self, key: "testText"), "lolamkhaha") + XCTAssertEqual(try database.get(type: String.self, key: "testEmoji"), "😂") + XCTAssertEqual(try database.get(type: String.self, key: "testTextEmoji"), "emojitext 😂") + XCTAssertEqual(try database.get(type: String.self, key: "testMultipleEmoji"), "😂😂😂") + } catch { + XCTFail("An error occurred during simple put test: \(error)") + } + + do { + try FileManager.default.removeItem(at: database.path) + database = nil + } catch { + XCTFail("Failed to remove RocksDB path: \(error)") + } + } + + func testSimpleDelete() { + let path = URL(fileURLWithPath: "/tmp/\(UUID().uuidString)") + + do { + database = try RocksDB(path: path) + + try database.put(key: "testDeleteKey", value: "this is a simple value 😘") + try database.delete(key: "testDeleteKey") + + XCTAssertEqual(try database.get(type: String.self, key: "testDeleteKey"), "") + + } catch { + XCTFail("An error occurred during simple delete test: \(error)") + } + do { + try FileManager.default.removeItem(at: database.path) + database = nil + } catch { + XCTFail("Failed to remove RocksDB path: \(error)") + } + } + + func testSimpleIterator() { + let orderedKeysAndValues = [ + (key: "testEmoji", value: "😂"), + (key: "testMultipleEmoji", value: "😂😂😂"), + (key: "testText", value: "lolamkhaha"), + (key: "testTextEmoji", value: "emojitext 😂"), + ] + + do { + let path = URL(fileURLWithPath: "/tmp/\(UUID().uuidString)") + database = try RocksDB(path: path) + + for (k, v) in orderedKeysAndValues { + try database.put(key: k, value: v) + } + + var i = 0 + for (key, val) in database.sequence(keyType: String.self, valueType: String.self) { + XCTAssertEqual(key, orderedKeysAndValues[i].key) + XCTAssertEqual(val, orderedKeysAndValues[i].value) + i += 1 + } + XCTAssertEqual(i, 4) + + i = 1 + for (key, val) in database.sequence(keyType: String.self, valueType: String.self, gte: "testMultipleEmoji") { + XCTAssertEqual(key, orderedKeysAndValues[i].key) + XCTAssertEqual(val, orderedKeysAndValues[i].value) + i += 1 + } + XCTAssertEqual(i, 4) + + i = 2 + for (key, val) in database.sequence(keyType: String.self, valueType: String.self, gte: "testText") { + XCTAssertEqual(key, orderedKeysAndValues[i].key) + XCTAssertEqual(val, orderedKeysAndValues[i].value) + i += 1 + } + XCTAssertEqual(i, 4) + + i = 3 + for (key, val) in database.sequence(keyType: String.self, valueType: String.self, lte: "testTextEmoji") { + XCTAssertEqual(key, orderedKeysAndValues[i].key) + XCTAssertEqual(val, orderedKeysAndValues[i].value) + i -= 1 + } + XCTAssertEqual(i, -1) + + i = 2 + for (key, val) in database.sequence(keyType: String.self, valueType: String.self, lte: "testText") { + XCTAssertEqual(key, orderedKeysAndValues[i].key) + XCTAssertEqual(val, orderedKeysAndValues[i].value) + i -= 1 + } + XCTAssertEqual(i, -1) + } catch { + XCTFail("An error occurred during simple iterator test: \(error)") + } + + do { + try FileManager.default.removeItem(at: database.path) + database = nil + } catch { + XCTFail("Failed to remove RocksDB path: \(error)") + } + } + + func testBatchOperations() { + do { + let prefixedPath = "/tmp/\(UUID().uuidString)" + let prefixedDB = try RocksDB(path: URL(fileURLWithPath: prefixedPath), prefix: "correctprefix") + try prefixedDB.put(key: "testText", value: "lolamkhaha") + try prefixedDB.put(key: "testEmoji", value: "😂") + try prefixedDB.put(key: "testTextEmoji", value: "emojitext 😂") + try prefixedDB.put(key: "testMultipleEmoji", value: "😂😂😂") + + try prefixedDB.batch(operations: [ + .delete(key: "testText"), + .put(key: "someThing", value: "someValue"), + .delete(key: "someThing"), + .put(key: "secondKey", value: "anotherValue"), + .put(key: "testText", value: "textTextValue"), + ]) + + XCTAssertEqual(try prefixedDB.get(type: String.self, key: "testEmoji"), "😂") + XCTAssertEqual(try prefixedDB.get(type: String.self, key: "someThing"), "") + XCTAssertEqual(try prefixedDB.get(type: String.self, key: "secondKey"), "anotherValue") + XCTAssertEqual(try prefixedDB.get(type: String.self, key: "testText"), "textTextValue") + + try FileManager.default.removeItem(at: prefixedDB.path) - // Defining Test Cases and Test Methods - // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } catch { + XCTFail("An error occurred during batch test: \(error)") + } } }