Skip to content

Commit

Permalink
remove unneeded pending state, more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mattmassicotte committed Feb 8, 2024
1 parent e49e0c2 commit c8fe131
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 29 deletions.
8 changes: 2 additions & 6 deletions Sources/RangeState/RangeValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ public final class RangeValidator<Content: VersionedContent> {
public typealias ContentRange = VersionedRange<Content.Version>
public typealias ValidationProvider = HybridValueProvider<ContentRange, Validation>

public enum Action: Sendable {
public enum Action: Sendable, Equatable {
case none
case needed(ContentRange)
case pending(NSRange)
}

private var validSet = IndexSet()
Expand Down Expand Up @@ -58,10 +57,6 @@ public final class RangeValidator<Content: VersionedContent> {

guard let neededRange = nextNeededRange(in: set, prioritizing: range) else { return .none }

if pendingSet.contains(integersIn: neededRange) {
return .pending(neededRange)
}

self.pendingSet.insert(range: neededRange)
self.pendingRequests += 1

Expand Down Expand Up @@ -175,3 +170,4 @@ extension RangeValidator {
}
}

extension RangeValidator.Action: Hashable where Content.Version: Hashable {}
32 changes: 17 additions & 15 deletions Sources/RangeState/SinglePhaseRangeValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Rearrange

@MainActor
public final class SinglePhaseRangeValidator<Content: VersionedContent> {

public typealias ContentRange = RangeValidator<Content>.ContentRange
public typealias Provider = HybridValueProvider<ContentRange, Validation>
public typealias PriorityRangeProvider = () -> NSRange
Expand Down Expand Up @@ -68,25 +69,26 @@ public final class SinglePhaseRangeValidator<Content: VersionedContent> {

let action = primaryValidator.beginValidation(of: target, prioritizing: range)

guard case let .needed(contentRange) = action else {
return action
}

// if we have an outstanding async operation going, force this to be async too
if outstanding {
enqueueValidation(for: contentRange)
return action
}
switch action {
case .none:
return .none
case let .needed(contentRange):
// if we have an outstanding async operation going, force this to be async too
if outstanding {
enqueueValidation(for: contentRange)
return action
}

guard let validation = configuration.provider.sync(contentRange) else {
enqueueValidation(for: contentRange)
guard let validation = configuration.provider.sync(contentRange) else {
enqueueValidation(for: contentRange)

return .pending(contentRange.value)
}
return action
}

completePrimaryValidation(of: contentRange, with: validation)
completePrimaryValidation(of: contentRange, with: validation)

return .none
return .none
}
}

private func completePrimaryValidation(of contentRange: ContentRange, with validation: Validation) {
Expand Down
7 changes: 1 addition & 6 deletions Sources/RangeState/ThreePhaseRangeValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ public final class ThreePhaseRangeValidator<Content: VersionedContent> {
switch action {
case .none:
scheduleSecondaryValidation(of: target, prioritizing: range)
case let .pending(pendingRange):
fallbackValidate(pendingRange, prioritizing: range)
case let .needed(contentRange):
// same as above
fallbackValidate(contentRange.value, prioritizing: range)
}
}
Expand All @@ -98,8 +95,6 @@ public final class ThreePhaseRangeValidator<Content: VersionedContent> {
switch action {
case .none:
return
case .pending:
preconditionFailure("It makes no sense for this to be pending")
case let .needed(contentRange):
provider(contentRange.value)

Expand Down Expand Up @@ -169,7 +164,7 @@ extension ThreePhaseRangeValidator {
let action = validator.beginValidation(of: target, prioritizing: range)

switch action {
case .none, .pending:
case .none:
return
case let .needed(contentRange):
let validation = await provider(contentRange)
Expand Down
43 changes: 43 additions & 0 deletions Tests/RangeStateTests/RangeValidatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import XCTest

import RangeState

final class RangeValidatorTests: XCTestCase {
typealias StringValidator = RangeValidator<StringContent>

@MainActor
func testHandleCompletedValidation() {
let content = StringContent(string: "abc")
let validator = StringValidator(content: content)

let range = NSRange(0..<3)
let contentRange = StringValidator.ContentRange(range, version: content.currentVersion)

let val1 = validator.beginValidation(of: .all)

XCTAssertEqual(val1, .needed(contentRange))

validator.completeValidation(of: contentRange, with: .success(range))

let val2 = validator.beginValidation(of: .all)

XCTAssertEqual(val2, .none)
}

@MainActor
func testHandleDuplicateValidation() {
let content = StringContent(string: "abc")
let validator = StringValidator(content: content)

let range = NSRange(0..<3)
let contentRange = StringValidator.ContentRange(range, version: content.currentVersion)

let val1 = validator.beginValidation(of: .all)

XCTAssertEqual(val1, .needed(contentRange))

let val2 = validator.beginValidation(of: .all)

XCTAssertEqual(val2, .none)
}
}
5 changes: 3 additions & 2 deletions Tests/RangeStateTests/SinglePhaseRangeValidatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,13 @@ final class SinglePhaseRangeValidatorTests: XCTestCase {
let provider = StringValidator.Provider(
syncValue: {
validationExp.fulfill()

return .success($0.value)
},
asyncValue: { contentRange, _ in
return .success(contentRange.value)
})
}
)

let validator = StringValidator(
configuration: .init(
Expand Down

0 comments on commit c8fe131

Please sign in to comment.