Added the repeater feature we wanted for so long.
This commit is contained in:
parent
49abbea360
commit
64705e7bb7
|
@ -13,8 +13,16 @@ let package = Package(
|
|||
.library(name: "Beton", targets: ["Beton"]),
|
||||
.library(name: "XCTBeton", targets: ["XCTBeton"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-async-algorithms.git", from: "0.1.0"),
|
||||
],
|
||||
targets: [
|
||||
.target(name: "Beton"),
|
||||
.target(
|
||||
name: "Beton",
|
||||
dependencies: [
|
||||
.product(name: "AsyncAlgorithms", package: "swift-async-algorithms"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "XCTBeton",
|
||||
dependencies: [
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
import Foundation
|
||||
import AsyncAlgorithms
|
||||
|
||||
// MARK: Mappers
|
||||
|
||||
/// Runs the provided callback consecutively one after another,
|
||||
/// passing the current iteration count as an argument,
|
||||
/// and returning the array of results in iteration order.
|
||||
/// - Parameters:
|
||||
/// - count: Number of times to run the given function.
|
||||
/// - function: The callback to execute mapping its results to the final result.
|
||||
/// - Returns: An array of all the values returned by the callback.
|
||||
public func repeating<T>(count: Int, _ function: (Int) -> T) -> [T] {
|
||||
(0..<count).map { function($0) }
|
||||
}
|
||||
|
||||
public typealias AsyncRepeatingChannel<T: Sendable> = AsyncChannel<(iteration: Int, result: T)> where T: Sendable
|
||||
/// Runs the provided callback asynchronously,
|
||||
/// passing the current iteration count as an argument,
|
||||
/// and returning an AsyncSequence of the results.
|
||||
/// **This function is by design out-of-order.**
|
||||
/// - Parameters:
|
||||
/// - count: Number of times to run the given function.
|
||||
/// - function: The callback to execute, mapping results to the final result.
|
||||
/// - Returns: A channel of results.
|
||||
public func repeating<T>(
|
||||
count: Int,
|
||||
_ function: @escaping (Int) async -> T
|
||||
) async -> AsyncRepeatingChannel<T> where T: Sendable {
|
||||
let channel = AsyncRepeatingChannel<T>()
|
||||
|
||||
Task {
|
||||
await withTaskGroup(of: Void.self) { group in
|
||||
for i in 0..<count {
|
||||
group.addTask { await channel.send((i, function(i))) }
|
||||
}
|
||||
}
|
||||
channel.finish()
|
||||
}
|
||||
|
||||
return channel
|
||||
}
|
||||
|
||||
// MARK: Resolvers
|
||||
|
||||
/// Runs the provided callback consecutively one after another, returning the array of results in iteration order.
|
||||
/// - Parameters:
|
||||
/// - count: Number of times to run the given function.
|
||||
/// - function: The callback to execute mapping its results to the final result.
|
||||
/// - Returns: An array of all the values returned by the callback.
|
||||
public func repeating<T>(
|
||||
count: Int,
|
||||
_ function: @autoclosure () -> T
|
||||
) -> [T] {
|
||||
repeating(count: count) { _ in function() }
|
||||
}
|
||||
|
||||
/// Runs the provided callback asynchronously, returning the results.
|
||||
/// **This function is by design out-of-order.**
|
||||
/// - Parameters:
|
||||
/// - count: Number of times to run the given function.
|
||||
/// - function: The callback to execute mapping its results to the final result.
|
||||
/// - Returns: A channel of all the values returned by the callback.
|
||||
public func repeating<T>(
|
||||
count: Int,
|
||||
_ function: @escaping @autoclosure () async -> T
|
||||
) async -> AsyncRepeatingChannel<T> where T: Sendable {
|
||||
await repeating(count: count) { _ in await function()}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Performers
|
||||
|
||||
/// Runs the provided callback `count` number of times, ignoring its results.
|
||||
/// - Parameters:
|
||||
/// - count: Number of times to run the given function.
|
||||
/// - function: The callback to execute `count` times.
|
||||
public func repeating(count: Int, _ function: @autoclosure () -> ()) {
|
||||
let _ = repeating(count: count) { [function] _ in function() }
|
||||
}
|
||||
|
||||
/// Runs asynchronously the provided callback `count` number of times, ignoring the results.
|
||||
/// - Parameters:
|
||||
/// - count: Number of times to run the given function.
|
||||
/// - function: The callback to execute `count` times
|
||||
public func repeating(
|
||||
count: Int,
|
||||
_ function: @autoclosure @escaping () async -> ()
|
||||
) async {
|
||||
let _ = await repeating(count: count) { _ in await function() }
|
||||
}
|
|
@ -5,7 +5,7 @@ class BundleTest: XCTestCase {
|
|||
override func tearDown() {
|
||||
super.tearDown()
|
||||
XCTAssertMetric(.cpu, .cycles, .average(maximum: 5000))
|
||||
XCTAssertMetric(.cpu, .instructionsRetired, .average(maximum: 4500))
|
||||
XCTAssertMetric(.cpu, .instructionsRetired, .average(maximum: 10_000))
|
||||
XCTAssertMetric(.cpu, .time, .average(maximum: 0.002))
|
||||
XCTAssertMetric(.memory, .physical, .average(maximum: 60))
|
||||
XCTAssertMetric(.memory, .physicalPeak, .average(maximum: 0))
|
||||
|
@ -15,25 +15,25 @@ class BundleTest: XCTestCase {
|
|||
|
||||
func testLocalizationBundles() {
|
||||
measure(metrics: .defaults) {
|
||||
Bundle.module.localizationBundles
|
||||
let _ = Bundle.module.localizationBundles
|
||||
}
|
||||
}
|
||||
|
||||
func testLocalizedString_keyOnly() {
|
||||
measure(metrics: .defaults) {
|
||||
Bundle.module.localizedString("Test")
|
||||
let _ = Bundle.module.localizedString("Test")
|
||||
}
|
||||
}
|
||||
|
||||
func testLocalizedString_keyAndTableOnly() {
|
||||
measure(metrics: .defaults) {
|
||||
Bundle.module.localizedString("Test", from: "Test")
|
||||
let _ = Bundle.module.localizedString("Test", from: "Test")
|
||||
}
|
||||
}
|
||||
|
||||
func testLocalizedString_keyAndValueOnly() {
|
||||
measure(metrics: .defaults) {
|
||||
Bundle.module.localizedString("Test", fallback: "Test")
|
||||
let _ = Bundle.module.localizedString("Test", fallback: "Test")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
@testable import Beton
|
||||
import XCTBeton
|
||||
|
||||
class RepeatingTests: XCTestCase {
|
||||
func testRepeating_sync_mapper () {
|
||||
XCTAssertEqual(repeating(count: 3) { $0 + 5 }, [5, 6, 7])
|
||||
XCTAssertEqual(repeating(count: 3) { $0 + 10 }, [10, 11, 12])
|
||||
XCTAssertEqual(repeating(count: 5) { $0 + 5 }, [5, 6, 7, 8, 9])
|
||||
XCTAssertEqual(repeating(count: 5) { $0 + 10 }, [10, 11, 12, 13, 14])
|
||||
}
|
||||
|
||||
func testRepeating_sync_resolver () {
|
||||
XCTAssertEqual(repeating(count: 3, 5), [5, 5, 5,])
|
||||
XCTAssertEqual(repeating(count: 3, 10), [10, 10, 10])
|
||||
XCTAssertEqual(repeating(count: 5, 5), [5, 5, 5, 5, 5,])
|
||||
XCTAssertEqual(repeating(count: 5, 10), [10, 10, 10, 10, 10])
|
||||
}
|
||||
|
||||
func testRepeating_sync_performer() {
|
||||
var counter = 0
|
||||
|
||||
repeating(count: 3, counter += 1)
|
||||
XCTAssertEqual(counter, 3)
|
||||
|
||||
repeating(count: 5, counter += 2)
|
||||
XCTAssertEqual(counter, 13)
|
||||
}
|
||||
|
||||
func testRepeating_async_mapper() async throws {
|
||||
for try await item in await repeating(count: 10, { $0 + 5 }) {
|
||||
XCTAssertEqual(item.result, item.iteration + 5)
|
||||
}
|
||||
}
|
||||
|
||||
func testRepeating_async_resolver() async throws {
|
||||
for try await item in await repeating(count: 10, 100) {
|
||||
XCTAssertEqual(item.result, 100)
|
||||
}
|
||||
}
|
||||
|
||||
func testRepeating_async_performer() async throws {
|
||||
var a = [Int]()
|
||||
await repeating(count: 13, a.append(1))
|
||||
print(a)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue