mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
110 lines
3.9 KiB
Swift
110 lines
3.9 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import VibeTunnel
|
|
|
|
/// Tests to verify that the race condition in GitHub URL fetching is fixed
|
|
@Suite("Git Repository Monitor Race Condition Tests", .tags(.concurrency, .gitRepository))
|
|
@MainActor
|
|
struct GitRepositoryMonitorRaceConditionTests {
|
|
@Test(
|
|
"Concurrent GitHub URL fetches don't cause duplicate Git operations",
|
|
.tags(.attachmentTests),
|
|
.enabled(if: TestConditions.isInGitRepository())
|
|
)
|
|
func concurrentGitHubURLFetches() async throws {
|
|
// Attach test environment information
|
|
Attachment.record("""
|
|
Git Repository: \(FileManager.default.fileExists(atPath: ".git") ? "Valid" : "Invalid")
|
|
Test Repository Path: /test/repo/path
|
|
Concurrent Operations: 10
|
|
Test Type: Race Condition Prevention
|
|
""", named: "Git Test Environment")
|
|
|
|
// Attach initial monitor state
|
|
Attachment.record("Monitor created: \(type(of: GitRepositoryMonitor()))", named: "Initial Monitor State")
|
|
let monitor = GitRepositoryMonitor()
|
|
let testRepoPath = "/test/repo/path"
|
|
|
|
// Create a mock repository
|
|
_ = GitRepository(
|
|
path: testRepoPath,
|
|
modifiedCount: 0,
|
|
addedCount: 0,
|
|
deletedCount: 0,
|
|
untrackedCount: 0,
|
|
currentBranch: "main"
|
|
)
|
|
|
|
// Use reflection to access private properties for testing
|
|
let mirror = Mirror(reflecting: monitor)
|
|
|
|
// Find the githubURLFetchesInProgress property
|
|
var inProgressSet: Set<String>?
|
|
for child in mirror.children {
|
|
if child.label == "githubURLFetchesInProgress",
|
|
let set = child.value as? Set<String>
|
|
{
|
|
inProgressSet = set
|
|
break
|
|
}
|
|
}
|
|
|
|
// Simulate multiple concurrent requests for the same repository
|
|
let concurrentTasks = (0..<10).map { _ in
|
|
Task {
|
|
// Access private method through mirror or simulate the behavior
|
|
// Since we can't directly call private methods, we'll test the public API
|
|
_ = await monitor.findRepository(for: testRepoPath)
|
|
}
|
|
}
|
|
|
|
// Wait a bit to allow tasks to start (increased for CI)
|
|
let waitTime: UInt64 = TestConditions.isRunningInCI() ? 500_000_000 : 100_000_000 // 0.5s in CI, 0.1s locally
|
|
try await Task.sleep(nanoseconds: waitTime)
|
|
|
|
// Verify that in-progress tracking is working
|
|
// Note: This is a simplified test since we can't easily access private properties
|
|
// In a real scenario, we'd need to refactor for better testability
|
|
|
|
// Wait for all tasks to complete
|
|
for task in concurrentTasks {
|
|
_ = await task.value
|
|
}
|
|
|
|
// Clear cache to clean up
|
|
monitor.clearCache()
|
|
}
|
|
|
|
@Test("GitHub URL fetch completes even on failure")
|
|
func gitHubURLFetchFailureHandling() async throws {
|
|
let monitor = GitRepositoryMonitor()
|
|
let invalidRepoPath = "/this/is/not/a/git/repo"
|
|
|
|
// This should not throw and should handle the failure gracefully
|
|
let result = await monitor.findRepository(for: invalidRepoPath)
|
|
|
|
// Should return nil for invalid repo
|
|
#expect(result == nil)
|
|
|
|
// Clear cache to clean up
|
|
monitor.clearCache()
|
|
}
|
|
|
|
@Test("Clear cache removes in-progress fetches")
|
|
func clearCacheRemovesInProgressFetches() async throws {
|
|
let monitor = GitRepositoryMonitor()
|
|
|
|
// Start a fetch (simulated through public API)
|
|
let testPath = "/test/path"
|
|
Task {
|
|
_ = await monitor.findRepository(for: testPath)
|
|
}
|
|
|
|
// Clear cache immediately
|
|
monitor.clearCache()
|
|
|
|
// Verify cache is cleared (through public API)
|
|
let cached = monitor.getCachedRepository(for: testPath)
|
|
#expect(cached == nil)
|
|
}
|
|
}
|