This commit is contained in:
Adam Laszlo Rocska 2022-03-02 18:08:04 +01:00
parent bb24ef5a6a
commit 51ca53da70
111 changed files with 1248 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

2
.idea/Beton.iml Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="External" external.linked.project.id="Beton" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="SPM" type="CPP_MODULE" version="4" />

View File

@ -0,0 +1,50 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="FORMATTER_TAGS_ENABLED" value="true" />
<HTMLCodeStyleSettings>
<option name="HTML_UNIFORM_INDENT" value="true" />
<option name="HTML_ATTRIBUTE_WRAP" value="4" />
<option name="HTML_KEEP_BLANK_LINES" value="1" />
<option name="HTML_ALIGN_TEXT" value="true" />
<option name="HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE" value="" />
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="" />
<option name="HTML_ENFORCE_QUOTES" value="true" />
<option name="HTML_NEWLINE_AFTER_LAST_ATTRIBUTE" value="When multiline" />
</HTMLCodeStyleSettings>
<SwiftCodeStyleSettings>
<option name="INDENT_DIRECTIVE_CHILDREN" value="true" />
</SwiftCodeStyleSettings>
<XML>
<option name="XML_ATTRIBUTE_WRAP" value="4" />
</XML>
<codeStyleSettings language="HTML">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Swift">
<option name="BLANK_LINES_AROUND_CLASS" value="0" />
<option name="BLANK_LINES_AROUND_METHOD" value="0" />
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<option name="SOFT_MARGINS" value="120" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

9
.idea/markdown.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<enabledExtensions>
<entry key="MermaidLanguageExtension" value="false" />
<entry key="PlantUMLLanguageExtension" value="true" />
</enabledExtensions>
</component>
</project>

16
.idea/misc.xml Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SwiftPackageManagerSettings">
<option name="linkedExternalProjectsSettings">
<SwiftPackageManagerProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</SwiftPackageManagerProjectSettings>
</option>
</component>
<component name="SwiftPackageManagerWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Beton.iml" filepath="$PROJECT_DIR$/.idea/Beton.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 21Gram Consulting
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

51
Package.swift Normal file
View File

@ -0,0 +1,51 @@
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "Beton",
defaultLocalization: LanguageTag("en_US"),
platforms: [
.macOS(.v12)
],
products: [
.library(name: "Beton", targets: ["Beton"]),
],
targets: [
.target(name: "Beton"),
.target(
name: "XCTBeton",
dependencies: [
.byName(name: "Beton")
]
),
.testTarget(type: .unit),
.testTarget(type: .component),
.testTarget(type: .integration),
.testTarget(type: .system),
.testTarget(type: .performance),
]
)
/// MARK: Convenience units
extension PackageDescription.Target {
enum TestType: String {
case unit = "Unit"
case component = "Component"
case integration = "Integration"
case system = "System"
case performance = "Performance"
}
static func testTarget(type: TestType) -> PackageDescription.Target {
.testTarget(
name: "\(type.rawValue)Tests",
dependencies: [
.byName(name: "Beton"),
.byName(name: "XCTBeton")
],
resources: [.process("Resources")]
)
}
}

10
README.md Normal file
View File

@ -0,0 +1,10 @@
# Beton
A description of this package.
```bash
docc convert --transform-for-static-hosting \
--additional-symbol-graph-dir .build
```

View File

@ -0,0 +1 @@
@_exported import Foundation

View File

@ -0,0 +1,17 @@
import Foundation
public extension Bundle {
var localizationBundles: [Locale: Bundle] {
localizations
.compactMap { [self] in
guard let path = path(forResource: $0, ofType: "lproj") else { return nil }
guard let bundle = Bundle(path: path) else { return nil }
return (key: Locale(identifier: $0), value: bundle)
}
.reduce([:]) { (bundles: [Locale: Bundle], entry: (key: Locale, value: Bundle)) in
var bundles = bundles
bundles[entry.key] = entry.value
return bundles
}
}
}

View File

@ -0,0 +1,15 @@
import Foundation
public extension Bundle {
func localizedString(_ key: String) -> String {
self.localizedString(forKey: key, value: nil, table: nil)
}
func localizedString(_ key: String, from table: String) -> String {
self.localizedString(forKey: key, value: nil, table: table)
}
func localizedString(_ key: String, fallback: String) -> String {
self.localizedString(forKey: key, value: fallback, table: nil)
}
}

View File

@ -0,0 +1,8 @@
import Foundation
public func pow<Unit>(_ x: Measurement<Unit>, _ y: Double) -> Measurement<Unit> {
Measurement<Unit>(
value: pow(x.value, y),
unit: x.unit
)
}

View File

@ -0,0 +1,8 @@
import Foundation
public func sqrt<Unit>(_ x: Measurement<Unit>) -> Measurement<Unit> {
Measurement<Unit>(
value: sqrt(x.value),
unit: x.unit
)
}

View File

@ -0,0 +1,5 @@
import Foundation
extension Measurement: AdditiveArithmetic where UnitType: Unit, UnitType.U == UnitType {
public static var zero: Self { Self.init(value: 0.0, unit: .default) }
}

View File

@ -0,0 +1,6 @@
import Foundation
public protocol Unit: Foundation.Unit {
associatedtype U = Self
static var `default`: U { get }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitAcceleration: Unit {
public static var `default`: UnitAcceleration { .metersPerSecondSquared }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitAngle: Unit {
public static var `default`: UnitAngle { .degrees }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitArea: Unit {
public static var `default`: UnitArea { .squareMeters }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitConcentrationMass: Unit {
public static var `default`: UnitConcentrationMass { .gramsPerLiter }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitDispersion: Unit {
public static var `default`: UnitDispersion { .partsPerMillion }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitDuration: Unit {
public static var `default`: UnitDuration { .seconds }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitElectricCharge: Unit {
public static var `default`: UnitElectricCharge { .ampereHours }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitElectricCurrent: Unit {
public static var `default`: UnitElectricCurrent { .amperes }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitElectricPotentialDifference: Unit {
public static var `default`: UnitElectricPotentialDifference { .volts }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitElectricResistance: Unit {
public static var `default`: UnitElectricResistance { .ohms }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitEnergy: Unit {
public static var `default`: UnitEnergy { .joules }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitFrequency: Unit {
public static var `default`: UnitFrequency { .hertz }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitFuelEfficiency: Unit {
public static var `default`: UnitFuelEfficiency { .litersPer100Kilometers }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitIlluminance: Unit {
public static var `default`: UnitIlluminance { .lux }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitInformationStorage: Unit {
public static var `default`: UnitInformationStorage { .bits }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitLength: Unit {
public static var `default`: UnitLength { .meters }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitMass: Unit {
public static var `default`: UnitMass { .grams }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitPower: Unit {
public static var `default`: UnitPower { .watts }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitPressure: Unit {
public static var `default`: UnitPressure { .bars }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitSpeed: Unit {
public static var `default`: UnitSpeed { .kilometersPerHour }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitTemperature: Unit {
public static var `default`: UnitTemperature { .celsius }
}

View File

@ -0,0 +1,5 @@
import Foundation
extension UnitVolume: Unit {
public static var `default`: UnitVolume { .liters }
}

View File

@ -0,0 +1,5 @@
import Foundation
public extension Sequence where Self.Element: AdditiveArithmetic {
func sum() -> Element { reduce(Element.zero, +) }
}

View File

@ -0,0 +1,4 @@
import Beton
import class XCTest.XCTMeasureOptions
open class XCTMeasureOptions: XCTest.XCTMeasureOptions {}

View File

@ -0,0 +1,15 @@
import Beton
import class XCTest.XCTCPUMetric
public class XCTCPUMetric: XCTest.XCTCPUMetric, XCTMetric {
deinit { forgetSelf() }
public override func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] {
storing(measurements: try super.reportMeasurements(from: startTime, to: endTime))
}
override public func copy(with zone: NSZone? = nil) -> Any {
remembering(copy: super.copy(with: zone))
}
}

View File

@ -0,0 +1,15 @@
import Beton
import class XCTest.XCTClockMetric
public class XCTClockMetric: XCTest.XCTClockMetric, XCTMetric {
deinit { forgetSelf() }
public override func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] {
storing(measurements: try super.reportMeasurements(from: startTime, to: endTime))
}
override public func copy(with zone: NSZone? = nil) -> Any {
remembering(copy: super.copy(with: zone))
}
}

View File

@ -0,0 +1,15 @@
import Beton
import class XCTest.XCTMemoryMetric
public class XCTMemoryMetric: XCTest.XCTMemoryMetric, XCTMetric {
deinit { forgetSelf() }
public override func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] {
storing(measurements: try super.reportMeasurements(from: startTime, to: endTime))
}
override public func copy(with zone: NSZone? = nil) -> Any {
remembering(copy: super.copy(with: zone))
}
}

View File

@ -0,0 +1,37 @@
import Beton
fileprivate var results: [ObjectIdentifier: [XCTPerformanceMeasurement]] = [:]
fileprivate var copyMap: [ObjectIdentifier: ObjectIdentifier] = [:]
public extension XCTMetric {
var measurements: [XCTPerformanceMeasurement] { results[id] ?? [] }
}
internal extension XCTMetric {
func storing(measurements: [XCTPerformanceMeasurement]) -> [XCTPerformanceMeasurement] {
if results[originId] == nil { results[originId] = [] }
results[originId]?.append(contentsOf: measurements)
return measurements
}
func remembering<Copy>(copy: Copy) -> Copy {
if let copy = copy as? Self { copyMap[copy.id] = id }
return copy
}
func forgetSelf() {
results[id] = nil
copyMap[id] = nil
}
}
fileprivate extension XCTMetric {
var id: ObjectIdentifier { ObjectIdentifier(self) }
var originId: ObjectIdentifier {
var originId = id
while copyMap[originId] != nil { originId = copyMap[originId]! }
return originId
}
}

View File

@ -0,0 +1,7 @@
import Beton
import protocol XCTest.XCTMetric
import class XCTest.XCTPerformanceMeasurement
public protocol XCTMetric: XCTest.XCTMetric {
var measurements: [XCTPerformanceMeasurement] { get }
}

View File

@ -0,0 +1,16 @@
import Beton
import class XCTest.XCTStorageMetric
public class XCTStorageMetric: XCTest.XCTStorageMetric, XCTMetric {
deinit { forgetSelf() }
public override func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] {
storing(measurements: try super.reportMeasurements(from: startTime, to: endTime))
}
override public func copy(with zone: NSZone? = nil) -> Any {
remembering(copy: super.copy(with: zone))
}
}

View File

@ -0,0 +1,97 @@
@_exported import func XCTest.XCTAssertEqual
@_exported import var XCTest.XCT_UI_TESTING_AVAILABLE
@_exported import let XCTest.XCTestErrorDomain
@_exported import struct XCTest.XCTestError
@_exported import class XCTest._XCTestCaseInterruptionException
@_exported import func XCTest._XCTPreformattedFailureHandler
@_exported import func XCTest.XCTAssertThrowsError
@_exported import class XCTest.XCUIElement
@_exported import func XCTest.XCTAssertNil
@_exported import class XCTest.XCTestObserver
@_exported import protocol XCTest.XCTestObservation
@_exported import class XCTest.XCTestObservationCenter
@_exported import class XCTest.XCTIssueReference
@_exported import enum XCTest.XCUIProtectedResource
@_exported import protocol XCTest.XCUIScreenshotProviding
@_exported import func XCTest.XCTAssertNotEqualWithAccuracy
@_exported import class XCTest.XCTExpectedFailure
@_exported import func XCTest.XCTAssertEqualWithAccuracy
@_exported import class XCTest.XCTKVOExpectation
@_exported import func XCTest.XCTAssertTrue
@_exported import class XCTest.XCTMutableIssue
@_exported import class XCTest.XCTDarwinNotificationExpectation
@_exported import class XCTest.XCTestLog
@_exported import protocol XCTest.XCUIElementAttributes
@_exported import class XCTest.XCTSourceCodeSymbolInfo
@_exported import func XCTest.XCTAssertNotIdentical
@_exported import typealias XCTest.XCWaitCompletionHandler
@_exported import let XCTest.XCTestScopeNone
@_exported import let XCTest.XCUIIdentifierCloseWindow
@_exported import struct XCTest.XCUIKeyboardKey
@_exported import class XCTest.XCUIScreenshot
@_exported import let XCTest.XCTestToolKey
@_exported import func XCTest.XCTSkipUnless
@_exported import class XCTest.XCTApplicationLaunchMetric
@_exported import struct XCTest.XCTSkip
@_exported import class XCTest.XCTPerformanceMeasurement
@_exported import let XCTest.XCUIIdentifierZoomWindow
@_exported import class XCTest.XCTNSNotificationExpectation
@_exported import func XCTest.XCTAssertIdentical
@_exported import let XCTest.XCTestScopeAll
@_exported import class XCTest.XCTSourceCodeLocation
@_exported import class XCTest.XCUIElementQuery
@_exported import func XCTest.XCTAssert
@_exported import func XCTest.XCTAssertNoThrow
@_exported import func XCTest.XCTAssertLessThan
@_exported import let XCTest.XCTestObserverClassKey
@_exported import func XCTest._XCTDescriptionForValue
@_exported import func XCTest.XCTAssertNotEqual
@_exported import protocol XCTest.XCUIElementTypeQueryProvider
@_exported import class XCTest.XCTPerformanceMeasurementTimestamp
@_exported import let XCTest.XCTestedUnitPath
@_exported import class XCTest.XCTestSuite
@_exported import func XCTest.XCTAssertNotNil
@_exported import class XCTest.XCUIApplication
@_exported import class XCTest.XCTNSPredicateExpectation
@_exported import class XCTest.XCTAttachment
@_exported import class XCTest.XCUICoordinate
@_exported import class XCTest.XCTOSSignpostMetric
@_exported import enum XCTest.XCUIRemoteButton
@_exported import let XCTest.XCUIIdentifierMinimizeWindow
@_exported import class XCTest.XCTestRun
@_exported import protocol XCTest.XCUIElementSnapshotProviding
@_exported import protocol XCTest.XCUIElementSnapshot
@_exported import func XCTest.XCTFail
@_exported import struct XCTest.XCTPerformanceMetric
@_exported import let XCTest.XCTestScopeKey
@_exported import class XCTest.XCTestProbe
@_exported import func XCTest.XCTAssertGreaterThan
@_exported import class XCTest.XCTestExpectation
@_exported import func XCTest.XCTExpectFailure
@_exported import struct XCTest.XCTIssue
@_exported import enum XCTest._XCTAssertionType
@_exported import func XCTest._XCTFailureFormat
@_exported import func XCTest.XCTAssertFalse
@_exported import func XCTest.XCTAssertGreaterThanOrEqual
@_exported import class XCTest.XCTSourceCodeContext
@_exported import class XCTest.XCTSourceCodeFrame
@_exported import class XCTest.XCTestSuiteRun
@_exported import class XCTest.XCTWaiter
@_exported import func XCTest.XCTSelfTestMain
@_exported import let XCTest.XCUIIdentifierFullScreenWindow
@_exported import protocol XCTest.XCTActivity
@_exported import func XCTest.XCTAssertLessThanOrEqual
@_exported import func XCTest.XCTSkipIf
@_exported import struct XCTest.XCUIGestureVelocity
@_exported import func XCTest.XCTUnwrap
@_exported import protocol XCTest.XCTWaiterDelegate
@_exported import class XCTest._XCTSkipFailureException
@_exported import let XCTest.XCTestScopeSelf
@_exported import class XCTest.XCTContext
@_exported import class XCTest.XCUIScreen
@_exported import class XCTest.XCTestCaseRun
@_exported import func XCTest.XCTAssertEqual
import class XCTest.XCTest
public typealias XCTBeton = XCTest

View File

@ -0,0 +1,15 @@
import Beton
public enum XCTAssertClockIdentifier {
case timeMonotonic
}
extension XCTAssertClockIdentifier: XCTAssertMetricIdentifier {
public typealias RelatedMetric = XCTClockMetric
public var identifier: String {
switch self {
case .timeMonotonic: return "com.apple.dt.XCTMetric_Clock.time.monotonic"
}
}
}

View File

@ -0,0 +1,19 @@
import Beton
public enum XCTAssertCpuIdentifier {
case time
case cycles
case instructionsRetired
}
extension XCTAssertCpuIdentifier: XCTAssertMetricIdentifier {
public typealias RelatedMetric = XCTCPUMetric
public var identifier: String {
switch self {
case .time: return "com.apple.dt.XCTMetric_CPU.time"
case .cycles: return "com.apple.dt.XCTMetric_CPU.cycles"
case .instructionsRetired: return "com.apple.dt.XCTMetric_CPU.instructions_retired"
}
}
}

View File

@ -0,0 +1,15 @@
import Beton
public enum XCTAssertDiskIdentifier {
case logicalWrites
}
extension XCTAssertDiskIdentifier: XCTAssertMetricIdentifier {
public typealias RelatedMetric = XCTStorageMetric
public var identifier: String {
switch self {
case .logicalWrites: return "com.apple.dt.XCTMetric_Disk.logical_writes"
}
}
}

View File

@ -0,0 +1,17 @@
import Beton
public enum XCTAssertMemoryIdentifier {
case physical
case physicalPeak
}
extension XCTAssertMemoryIdentifier: XCTAssertMetricIdentifier {
public typealias RelatedMetric = XCTMemoryMetric
public var identifier: String {
switch self {
case .physical: return "com.apple.dt.XCTMetric_Memory.physical"
case .physicalPeak: return "com.apple.dt.XCTMetric_Memory.physical_peak"
}
}
}

View File

@ -0,0 +1,25 @@
import Beton
public struct XCTAssertMetric<Identifier> where Identifier: XCTAssertMetricIdentifier {}
public extension XCTAssertMetric {
static var cpu: XCTAssertMetric<XCTAssertCpuIdentifier> { .init() }
static var memory: XCTAssertMetric<XCTAssertMemoryIdentifier> { .init() }
static var disk: XCTAssertMetric<XCTAssertDiskIdentifier> { .init() }
static var clock: XCTAssertMetric<XCTAssertClockIdentifier> { .init() }
}
public extension XCTAssertMetric {
enum Aspect {
case average(maximum: Double)
case relativeStandardDeviation(maximum: Double)
}
}
internal extension XCTAssertMetric.Aspect {
var maximum: Double {
switch self {
case let .average(maximum): return maximum
case let .relativeStandardDeviation(maximum): return maximum
}
}
}

View File

@ -0,0 +1,67 @@
import Beton
import XCTest
extension XCTestCase {
public final func XCTAssertMetric<Identifier>(
_ metric: XCTAssertMetric<Identifier>,
_ identifier: Identifier,
_ aspect: XCTAssertMetric<Identifier>.Aspect,
_ message: @autoclosure () -> String = "",
file: StaticString = #filePath,
line: UInt = #line
) {
let measurements: [Double] = fetchMeasurement(for: identifier).map(\.value).map(\.value)
XCTAssertLessThanOrEqual(
measurements[keyPath: aspect.measurementKeyPath],
aspect.maximum,
errorMessage(for: identifier, message: message()),
file: file,
line: line
)
XCTAssertFalse(
measurements.isEmpty,
errorMessage(
for: identifier,
message: "No measurement results found."
),
file: file,
line: line
)
}
private func errorMessage<Identifier>(for identifier: Identifier, message: String) -> String {
message.isEmpty
? #"XCTAssertMetric<\#(Identifier.self).\#(identifier)>"#
: #"XCTAssertMetric<\#(Identifier.self).\#(identifier)> - \#(message)"#
}
internal func fetchMeasurement<Identifier>(for identifier: Identifier) -> [XCTPerformanceMeasurement] where Identifier: XCTAssertMetricIdentifier {
lastRunMetrics
.compactMap { $0 as? Identifier.RelatedMetric }
.map(\.measurements)
.reduce([], +)
.filter { $0.identifier == identifier.identifier } // TODO: this naming is fucking dumb
}
}
fileprivate extension Array where Element == Double {
var average: Element { sum() / Double(count) }
var standardDeviation: Element {
let squaredDifferences = map { pow($0 - average, 2.0) }
let variance = squaredDifferences.reduce(.zero, +) / Double(count - 1)
return sqrt(variance)
}
var relativeStandardDeviation: Double { standardDeviation / average }
}
fileprivate extension XCTAssertMetric.Aspect {
var measurementKeyPath: KeyPath<[Double], Double> {
switch self {
case .average: return \.average
case .relativeStandardDeviation: return \.relativeStandardDeviation
}
}
}

View File

@ -0,0 +1,6 @@
import Beton
public protocol XCTAssertMetricIdentifier {
associatedtype RelatedMetric: XCTMetric
var identifier: String { get }
}

View File

@ -0,0 +1,17 @@
import Beton
extension XCTestCase {
@nonobjc open func measure(metrics: [XCTMetric], block: () -> Void) {
self.measure(metrics: metrics, options: Self.defaultMeasureOptions, block: block)
}
@nonobjc open func measure(options: XCTMeasureOptions, block: () -> Void) {
self.measure(metrics: Self.defaultMetrics, options: options, block: block)
}
@nonobjc open func measure(metrics: [XCTMetric], options: XCTMeasureOptions, block: () -> Void) {
super.measure(metrics: metrics, options: options, block: block)
precondition(lastRunMetrics.isEmpty, "Must not have performed measurements yet!")
lastRunMetrics = metrics
}
}

View File

@ -0,0 +1,11 @@
import Beton
import class XCTest.XCTestCase
open class XCTestCase: XCTest.XCTestCase {
internal var lastRunMetrics: [XCTMetric] = []
}
extension XCTest.XCTestCase {
open class var defaultMetrics: [XCTMetric] { [XCTClockMetric()] }
open class var defaultMeasureOptions: XCTMeasureOptions { XCTMeasureOptions() }
}

View File

@ -0,0 +1 @@
"Test" = "Test";

View File

@ -0,0 +1 @@
"Test" = "Teszt";

View File

@ -0,0 +1 @@
"Test" = "Test";

View File

@ -0,0 +1 @@
"Test" = "Teszt";

View File

@ -0,0 +1,51 @@
import Beton
import XCTBeton
class BundleTest: XCTestCase {
override func tearDown() {
super.tearDown()
XCTAssertMetric(.cpu, .cycles, .average(maximum: 5000))
XCTAssertMetric(.cpu, .instructionsRetired, .average(maximum: 4500))
XCTAssertMetric(.cpu, .time, .average(maximum: 0.002))
XCTAssertMetric(.memory, .physical, .average(maximum: 60))
XCTAssertMetric(.memory, .physicalPeak, .average(maximum: 0))
XCTAssertMetric(.disk, .logicalWrites, .average(maximum: 0))
XCTAssertMetric(.clock, .timeMonotonic, .average(maximum: 0.005))
}
func testLocalizationBundles() {
measure(metrics: .defaults) {
Bundle.module.localizationBundles
}
}
func testLocalizedString_keyOnly() {
measure(metrics: .defaults) {
Bundle.module.localizedString("Test")
}
}
func testLocalizedString_keyAndTableOnly() {
measure(metrics: .defaults) {
Bundle.module.localizedString("Test", from: "Test")
}
}
func testLocalizedString_keyAndValueOnly() {
measure(metrics: .defaults) {
Bundle.module.localizedString("Test", fallback: "Test")
}
}
}
extension Array where Self.Element == XCTMetric {
static var defaults: [Element] {
[
XCTCPUMetric(),
XCTMemoryMetric(),
XCTStorageMetric(),
XCTClockMetric(),
]
}
}

View File

@ -0,0 +1 @@
"Test" = "Test";

View File

@ -0,0 +1 @@
"Test" = "Teszt";

View File

@ -0,0 +1 @@
"Test" = "Test";

View File

@ -0,0 +1 @@
"Test" = "Teszt";

View File

@ -0,0 +1,26 @@
import Foundation
import XCTest
@testable import Beton
extension BundleTest {
func testLocalizedString_keyOnly() {
XCTAssertEqual(
Bundle.module.localizedString("Test"),
Bundle.module.localizedString(forKey: "Test", value: nil, table: nil)
)
}
func testLocalizedString_keyAndTableOnly() {
XCTAssertEqual(
Bundle.module.localizedString("Test", from: "Test"),
Bundle.module.localizedString(forKey: "Test", value: nil, table: "Test")
)
}
func testLocalizedString_keyAndValueOnly() {
XCTAssertEqual(
Bundle.module.localizedString("Test", fallback: "Test"),
Bundle.module.localizedString(forKey: "Test", value: "Test", table: nil)
)
}
}

View File

@ -0,0 +1,11 @@
import Foundation
import XCTest
@testable import Beton
extension BundleTest {
func testLocalizationBundles() {
XCTAssertTrue(Bundle.module.localizationBundles.keys.contains(Locale(identifier: "en_US")))
XCTAssertTrue(Bundle.module.localizationBundles.keys.contains(Locale(identifier: "hu_HU")))
XCTAssertFalse(Bundle.module.localizationBundles.keys.contains(Locale(identifier: "de_DE")))
}
}

View File

@ -0,0 +1,4 @@
import Foundation
import XCTest
class BundleTest: XCTestCase {}

View File

@ -0,0 +1,20 @@
import Foundation
import XCTest
@testable import Beton
class MathTest: XCTestCase {
func testPow() {
XCTAssertEqual(
pow(Measurement<UnitInformationStorage>(value: 2, unit: .bits), 3),
Measurement<UnitInformationStorage>(value: 1, unit: .bytes)
)
}
func testSqrt() {
XCTAssertEqual(
sqrt(Measurement<UnitInformationStorage>(value: 8, unit: .bits)),
Measurement<UnitInformationStorage>(value: sqrt(8), unit: .bits)
)
}
}

View File

@ -0,0 +1,30 @@
import Foundation
import XCTest
@testable import Beton
extension MeasurementTest {
func testZero() {
XCTAssertEqual(Measurement<UnitAcceleration>.zero, Measurement<UnitAcceleration>(value: 0, unit: UnitAcceleration.default))
XCTAssertEqual(Measurement<UnitAngle>.zero, Measurement<UnitAngle>(value: 0, unit: UnitAngle.default))
XCTAssertEqual(Measurement<UnitArea>.zero, Measurement<UnitArea>(value: 0, unit: UnitArea.default))
XCTAssertEqual(Measurement<UnitConcentrationMass>.zero, Measurement<UnitConcentrationMass>(value: 0, unit: UnitConcentrationMass.default))
XCTAssertEqual(Measurement<UnitDispersion>.zero, Measurement<UnitDispersion>(value: 0, unit: UnitDispersion.default))
XCTAssertEqual(Measurement<UnitDuration>.zero, Measurement<UnitDuration>(value: 0, unit: UnitDuration.default))
XCTAssertEqual(Measurement<UnitElectricCharge>.zero, Measurement<UnitElectricCharge>(value: 0, unit: UnitElectricCharge.default))
XCTAssertEqual(Measurement<UnitElectricCurrent>.zero, Measurement<UnitElectricCurrent>(value: 0, unit: UnitElectricCurrent.default))
XCTAssertEqual(Measurement<UnitElectricPotentialDifference>.zero, Measurement<UnitElectricPotentialDifference>(value: 0, unit: UnitElectricPotentialDifference.default))
XCTAssertEqual(Measurement<UnitElectricResistance>.zero, Measurement<UnitElectricResistance>(value: 0, unit: UnitElectricResistance.default))
XCTAssertEqual(Measurement<UnitEnergy>.zero, Measurement<UnitEnergy>(value: 0, unit: UnitEnergy.default))
XCTAssertEqual(Measurement<UnitFrequency>.zero, Measurement<UnitFrequency>(value: 0, unit: UnitFrequency.default))
XCTAssertEqual(Measurement<UnitFuelEfficiency>.zero, Measurement<UnitFuelEfficiency>(value: 0, unit: UnitFuelEfficiency.default))
XCTAssertEqual(Measurement<UnitIlluminance>.zero, Measurement<UnitIlluminance>(value: 0, unit: UnitIlluminance.default))
XCTAssertEqual(Measurement<UnitInformationStorage>.zero, Measurement<UnitInformationStorage>(value: 0, unit: UnitInformationStorage.default))
XCTAssertEqual(Measurement<UnitLength>.zero, Measurement<UnitLength>(value: 0, unit: UnitLength.default))
XCTAssertEqual(Measurement<UnitMass>.zero, Measurement<UnitMass>(value: 0, unit: UnitMass.default))
XCTAssertEqual(Measurement<UnitPower>.zero, Measurement<UnitPower>(value: 0, unit: UnitPower.default))
XCTAssertEqual(Measurement<UnitPressure>.zero, Measurement<UnitPressure>(value: 0, unit: UnitPressure.default))
XCTAssertEqual(Measurement<UnitSpeed>.zero, Measurement<UnitSpeed>(value: 0, unit: UnitSpeed.default))
XCTAssertEqual(Measurement<UnitTemperature>.zero, Measurement<UnitTemperature>(value: 0, unit: UnitTemperature.default))
XCTAssertEqual(Measurement<UnitVolume>.zero, Measurement<UnitVolume>(value: 0, unit: UnitVolume.default))
}
}

View File

@ -0,0 +1,6 @@
import Foundation
import XCTest
@testable import Beton
class MeasurementTest: XCTestCase {
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitAccelerationTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitAcceleration.default, .metersPerSecondSquared)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitAngleTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitAngle.default, .degrees)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitAreaTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitArea.default, .squareMeters)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitConcentrationMassTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitConcentrationMass.default, .gramsPerLiter)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitDispersionTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitDispersion.default, .partsPerMillion)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitDurationTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitDuration.default, .seconds )
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitElectricChargeTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitElectricCharge.default, .ampereHours)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitElectricCurrentTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitElectricCurrent.default, .default)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitElectricPotentialDifferenceTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitElectricPotentialDifference.default, .volts)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitElectricResistanceTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitElectricResistance.default, .ohms)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitEnergyTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitEnergy.default, .joules)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitFrequencyTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitFrequency.default, .hertz)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitFuelEfficiencyTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitFuelEfficiency.default, .litersPer100Kilometers)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitIlluminanceTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitIlluminance.default, .lux)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitInformationStorageTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitInformationStorage.default, .bits)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitLengthTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitLength.default, .meters)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitMassTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitMass.default, .grams)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitPowerTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitPower.default, .watts)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitPressureTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitPressure.default, .bars)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitSpeedTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitSpeed.default, .kilometersPerHour)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitTemperatureTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitTemperature.default, .celsius)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
class UnitVolumeTest: XCTestCase {
func testDefault() {
XCTAssertEqual(UnitVolume.default, .liters)
}
}

View File

@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import Beton
extension SequenceTest {
func testSum() {
XCTAssertEqual([1, 2, 3, 4, 5, 6].sum(), 21)
}
}

View File

@ -0,0 +1,6 @@
import Foundation
import XCTest
@testable import Beton
class SequenceTest: XCTestCase {
}

View File

@ -0,0 +1 @@
"Test" = "Test";

View File

@ -0,0 +1 @@
"Test" = "Teszt";

Some files were not shown because too many files have changed in this diff Show More