Skip to content

Commit d436239

Browse files
committed
Add tests
1 parent 8e59b05 commit d436239

1 file changed

Lines changed: 152 additions & 0 deletions

File tree

BitkitTests/AddressTypeIntegrationTests.swift

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,156 @@ final class AddressTypeIntegrationTests: XCTestCase {
171171
context: "AddressTypeIntegrationTests"
172172
)
173173
}
174+
175+
// MARK: - Mutex / Concurrency
176+
177+
@MainActor
178+
func testUpdateAddressTypeMutexReturnsImmediately() async throws {
179+
try await setupWalletAndNode()
180+
181+
Logger.test("Testing updateAddressType mutex guard", context: "AddressTypeIntegrationTests")
182+
// First call should succeed
183+
let success = await settings.updateAddressType(.taproot, wallet: nil)
184+
XCTAssertTrue(success)
185+
186+
// Same type returns true (guard: addressType == selectedAddressType)
187+
let sameTypeResult = await settings.updateAddressType(.taproot, wallet: nil)
188+
XCTAssertTrue(sameTypeResult, "Same type should return true immediately")
189+
}
190+
191+
// MARK: - Channel Fundable Balance Excludes Legacy
192+
193+
@MainActor
194+
func testGetChannelFundableBalanceExcludesLegacy() async throws {
195+
try await setupWalletAndNode()
196+
197+
let blocktank = CoreService.shared.blocktank
198+
199+
// Enable legacy monitoring and switch to legacy
200+
settings.addressTypesToMonitor = [.nativeSegwit, .legacy]
201+
UserDefaults.standard.synchronize()
202+
let updateSuccess = await settings.updateAddressType(.legacy, wallet: nil)
203+
XCTAssertTrue(updateSuccess)
204+
205+
let legacyAddress = try await lightning.newAddressForType(.legacy)
206+
Logger.test("Funding legacy address: \(legacyAddress)", context: "AddressTypeIntegrationTests")
207+
let txId = try await blocktank.regtestDepositFunds(address: legacyAddress, amountSat: 50000)
208+
XCTAssertFalse(txId.isEmpty)
209+
210+
try await blocktank.regtestMineBlocks(6)
211+
try await Task.sleep(nanoseconds: 15_000_000_000)
212+
try await lightning.sync()
213+
214+
// Verify legacy has balance
215+
let legacyBalance = try await lightning.getBalanceForAddressType(.legacy)
216+
XCTAssertGreaterThan(legacyBalance.totalSats, 0, "Legacy should have balance")
217+
218+
// Channel fundable should NOT include legacy
219+
let fundable = try await lightning.getChannelFundableBalance(
220+
selectedType: .legacy,
221+
monitoredTypes: [.nativeSegwit, .legacy]
222+
)
223+
XCTAssertEqual(fundable, 0, "Channel fundable should exclude legacy even when it has balance")
224+
Logger.test("Channel fundable correctly excludes legacy: \(fundable)", context: "AddressTypeIntegrationTests")
225+
}
226+
227+
// MARK: - Disable Monitoring With Balance Fails
228+
229+
@MainActor
230+
func testSetMonitoringDisableWithBalanceFails() async throws {
231+
try await setupWalletAndNode()
232+
233+
let blocktank = CoreService.shared.blocktank
234+
235+
// Enable taproot monitoring
236+
settings.addressTypesToMonitor = [.nativeSegwit]
237+
UserDefaults.standard.synchronize()
238+
let addSuccess = await settings.setMonitoring(.taproot, enabled: true, wallet: nil)
239+
XCTAssertTrue(addSuccess, "Adding taproot should succeed")
240+
241+
// Fund the taproot address
242+
let taprootAddress = try await lightning.newAddressForType(.taproot)
243+
Logger.test("Funding taproot address: \(taprootAddress)", context: "AddressTypeIntegrationTests")
244+
let txId = try await blocktank.regtestDepositFunds(address: taprootAddress, amountSat: 50000)
245+
XCTAssertFalse(txId.isEmpty)
246+
247+
try await blocktank.regtestMineBlocks(6)
248+
try await Task.sleep(nanoseconds: 15_000_000_000)
249+
try await lightning.sync()
250+
251+
// Verify taproot has balance
252+
let taprootBalance = try await lightning.getBalanceForAddressType(.taproot)
253+
XCTAssertGreaterThan(taprootBalance.totalSats, 0, "Taproot should have balance after funding")
254+
255+
// Attempt to disable — should fail because of balance
256+
Logger.test("Attempting to disable taproot monitoring with balance", context: "AddressTypeIntegrationTests")
257+
let disableSuccess = await settings.setMonitoring(.taproot, enabled: false, wallet: nil)
258+
XCTAssertFalse(disableSuccess, "Disabling type with balance should fail")
259+
XCTAssertTrue(settings.addressTypesToMonitor.contains(.taproot), "Taproot should remain monitored")
260+
}
261+
262+
// MARK: - Prune Preserves Types With Balance
263+
264+
@MainActor
265+
func testPruneEmptyPreservesTypesWithBalance() async throws {
266+
try await setupWalletAndNode()
267+
268+
let blocktank = CoreService.shared.blocktank
269+
270+
// Enable taproot monitoring
271+
settings.addressTypesToMonitor = [.nativeSegwit]
272+
UserDefaults.standard.synchronize()
273+
let addSuccess = await settings.setMonitoring(.taproot, enabled: true, wallet: nil)
274+
XCTAssertTrue(addSuccess)
275+
276+
// Fund the taproot address
277+
let taprootAddress = try await lightning.newAddressForType(.taproot)
278+
Logger.test("Funding taproot for prune test: \(taprootAddress)", context: "AddressTypeIntegrationTests")
279+
let txId = try await blocktank.regtestDepositFunds(address: taprootAddress, amountSat: 50000)
280+
XCTAssertFalse(txId.isEmpty)
281+
282+
try await blocktank.regtestMineBlocks(6)
283+
try await Task.sleep(nanoseconds: 15_000_000_000)
284+
try await lightning.sync()
285+
286+
// Add legacy (will be empty)
287+
let addLegacy = await settings.setMonitoring(.legacy, enabled: true, wallet: nil)
288+
XCTAssertTrue(addLegacy)
289+
XCTAssertEqual(settings.addressTypesToMonitor.count, 3)
290+
291+
Logger.test("Pruning — should remove empty legacy but keep funded taproot", context: "AddressTypeIntegrationTests")
292+
await settings.pruneEmptyAddressTypesAfterRestore()
293+
294+
XCTAssertTrue(settings.addressTypesToMonitor.contains(.nativeSegwit), "nativeSegwit should remain")
295+
XCTAssertTrue(settings.addressTypesToMonitor.contains(.taproot), "Funded taproot should remain")
296+
XCTAssertFalse(settings.addressTypesToMonitor.contains(.legacy), "Empty legacy should be pruned")
297+
}
298+
299+
// MARK: - Address Format Verification
300+
301+
@MainActor
302+
func testNewAddressMatchesTypeFormat() async throws {
303+
try await setupWalletAndNode()
304+
305+
// Enable all types so LDK creates wallets for each
306+
settings.addressTypesToMonitor = [.nativeSegwit]
307+
UserDefaults.standard.synchronize()
308+
for type in [LDKNode.AddressType.taproot, .nestedSegwit, .legacy] {
309+
let success = await settings.setMonitoring(type, enabled: true, wallet: nil)
310+
XCTAssertTrue(success, "Enabling \(type.stringValue) monitoring should succeed")
311+
}
312+
313+
let expectations: [(LDKNode.AddressType, String, String)] = [
314+
(.legacy, "m", "Legacy address should start with m or n on regtest"),
315+
(.nestedSegwit, "2", "Nested SegWit address should start with 2 on regtest"),
316+
(.nativeSegwit, "bcrt1q", "Native SegWit address should start with bcrt1q on regtest"),
317+
(.taproot, "bcrt1p", "Taproot address should start with bcrt1p on regtest"),
318+
]
319+
320+
for (type, prefix, message) in expectations {
321+
let address = try await lightning.newAddressForType(type)
322+
Logger.test("\(type.stringValue) address: \(address)", context: "AddressTypeIntegrationTests")
323+
XCTAssertTrue(address.hasPrefix(prefix), "\(message), got: \(address)")
324+
}
325+
}
174326
}

0 commit comments

Comments
 (0)