// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: objc_interop import Foundation #if FOUNDATION_XCTEST import XCTest class TestMeasurementSuper : XCTestCase { } #else import StdlibUnittest class TestMeasurementSuper { } #endif // We define our own units here so that we can have closer control over checking the behavior of just struct Measurement and not the rest of Foundation @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) class MyDimensionalUnit : Dimension { class var unitA : MyDimensionalUnit { return MyDimensionalUnit(symbol: "a", converter: UnitConverterLinear(coefficient: 1)) } class var unitKiloA : MyDimensionalUnit { return MyDimensionalUnit(symbol: "ka", converter: UnitConverterLinear(coefficient: 1_000)) } class var unitMegaA : MyDimensionalUnit { return MyDimensionalUnit(symbol: "Ma", converter: UnitConverterLinear(coefficient: 1_000_000)) } override class func baseUnit() -> MyDimensionalUnit { return MyDimensionalUnit.unitA } } @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) class CustomUnit : Unit { override init(symbol: String) { super.init(symbol: symbol) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } public static let bugs = CustomUnit(symbol: "bug") public static let features = CustomUnit(symbol: "feature") } @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) class TestMeasurement : TestMeasurementSuper { func testBasicConstruction() { let m1 = Measurement(value: 3, unit: MyDimensionalUnit.unitA) let m2 = Measurement(value: 3, unit: MyDimensionalUnit.unitA) let m3 = m1 + m2 expectEqual(6, m3.value) expectEqual(m1, m2) let m10 = Measurement(value: 2, unit: CustomUnit.bugs) let m11 = Measurement(value: 2, unit: CustomUnit.bugs) let m12 = Measurement(value: 3, unit: CustomUnit.bugs) expectEqual(m10, m11) expectNotEqual(m10, m12) // This test has 2 + 2 + 3 bugs expectEqual((m10 + m11 + m12).value, 7) } func testConversion() { let m1 = Measurement(value: 1000, unit: MyDimensionalUnit.unitA) let kiloM1 = Measurement(value: 1, unit: MyDimensionalUnit.unitKiloA) let result = m1.converted(to: MyDimensionalUnit.unitKiloA) expectEqual(kiloM1, result) let sameResult = m1.converted(to: MyDimensionalUnit.unitA) expectEqual(sameResult, m1) // This correctly fails to build // let m2 = Measurement(value: 1, unit: CustomUnit.bugs) // m2.converted(to: MyDimensionalUnit.unitKiloA) } func testOperators() { // Which is bigger: 1 ka or 1 Ma? let oneKiloA = Measurement(value: 1, unit: MyDimensionalUnit.unitKiloA) let oneMegaA = Measurement(value: 1, unit: MyDimensionalUnit.unitMegaA) expectTrue(oneKiloA < oneMegaA) expectFalse(oneKiloA > oneMegaA) expectTrue(oneKiloA * 2000 > oneMegaA) expectTrue(oneMegaA / 1_000_000 < oneKiloA) expectTrue(2000 * oneKiloA > oneMegaA) expectTrue(2 / oneMegaA > oneMegaA) expectEqual(2 / (oneMegaA * 2), oneMegaA) expectTrue(oneMegaA <= oneKiloA * 1000) expectTrue(oneMegaA - oneKiloA <= oneKiloA * 1000) expectTrue(oneMegaA >= oneKiloA * 1000) expectTrue(oneMegaA >= ((oneKiloA * 1000) - oneKiloA)) // Dynamically different dimensions expectEqual(Measurement(value: 1_001_000, unit: MyDimensionalUnit.unitA), oneMegaA + oneKiloA) var bugCount = Measurement(value: 1, unit: CustomUnit.bugs) expectEqual(bugCount.value, 1) bugCount = bugCount + Measurement(value: 4, unit: CustomUnit.bugs) expectEqual(bugCount.value, 5) } func testUnits() { expectEqual(MyDimensionalUnit.unitA, MyDimensionalUnit.unitA) expectTrue(MyDimensionalUnit.unitA == MyDimensionalUnit.unitA) } func testMeasurementFormatter() { let formatter = MeasurementFormatter() let measurement = Measurement(value: 100, unit: UnitLength.kilometers) let result = formatter.string(from: measurement) // Just make sure we get a result at all here expectFalse(result.isEmpty) } func testEquality() { let fiveKM = Measurement(value: 5, unit: UnitLength.kilometers) let fiveSeconds = Measurement(value: 5, unit: UnitDuration.seconds) let fiveThousandM = Measurement(value: 5000, unit: UnitLength.meters) expectTrue(fiveKM == fiveThousandM) expectEqual(fiveKM, fiveThousandM) expectFalse(fiveKM == fiveSeconds) } func testComparison() { let fiveKM = Measurement(value: 5, unit: UnitLength.kilometers) let fiveThousandM = Measurement(value: 5000, unit: UnitLength.meters) let sixKM = Measurement(value: 6, unit: UnitLength.kilometers) let sevenThousandM = Measurement(value: 7000, unit: UnitLength.meters) expectTrue(fiveKM < sixKM) expectTrue(fiveKM < sevenThousandM) expectTrue(fiveKM <= fiveThousandM) } func testHashing() { guard #available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *) else { return } let lengths: [[Measurement]] = [ [ Measurement(value: 5, unit: UnitLength.kilometers), Measurement(value: 5000, unit: UnitLength.meters), Measurement(value: 5000, unit: UnitLength.meters), ], [ Measurement(value: 1, unit: UnitLength.kilometers), Measurement(value: 1000, unit: UnitLength.meters), ], [ Measurement(value: 1, unit: UnitLength.meters), Measurement(value: 1000, unit: UnitLength.millimeters), ], ] checkHashableGroups(lengths) let durations: [[Measurement]] = [ [ Measurement(value: 3600, unit: UnitDuration.seconds), Measurement(value: 60, unit: UnitDuration.minutes), Measurement(value: 1, unit: UnitDuration.hours), ], [ Measurement(value: 1800, unit: UnitDuration.seconds), Measurement(value: 30, unit: UnitDuration.minutes), Measurement(value: 0.5, unit: UnitDuration.hours), ] ] checkHashableGroups(durations) let custom: [Measurement] = [ Measurement(value: 1, unit: CustomUnit.bugs), Measurement(value: 2, unit: CustomUnit.bugs), Measurement(value: 3, unit: CustomUnit.bugs), Measurement(value: 4, unit: CustomUnit.bugs), Measurement(value: 1, unit: CustomUnit.features), Measurement(value: 2, unit: CustomUnit.features), Measurement(value: 3, unit: CustomUnit.features), Measurement(value: 4, unit: CustomUnit.features), ] checkHashable(custom, equalityOracle: { $0 == $1 }) } func test_AnyHashableContainingMeasurement() { let values: [Measurement] = [ Measurement(value: 100, unit: UnitLength.meters), Measurement(value: 100, unit: UnitLength.kilometers), Measurement(value: 100, unit: UnitLength.kilometers), ] let anyHashables = values.map(AnyHashable.init) expectEqual(Measurement.self, type(of: anyHashables[0].base)) expectEqual(Measurement.self, type(of: anyHashables[1].base)) expectEqual(Measurement.self, type(of: anyHashables[2].base)) expectNotEqual(anyHashables[0], anyHashables[1]) expectEqual(anyHashables[1], anyHashables[2]) } func test_AnyHashableCreatedFromNSMeasurement() { let values: [NSMeasurement] = [ NSMeasurement(doubleValue: 100, unit: UnitLength.meters), NSMeasurement(doubleValue: 100, unit: UnitLength.kilometers), NSMeasurement(doubleValue: 100, unit: UnitLength.kilometers), ] let anyHashables = values.map(AnyHashable.init) expectEqual(Measurement.self, type(of: anyHashables[0].base)) expectEqual(Measurement.self, type(of: anyHashables[1].base)) expectEqual(Measurement.self, type(of: anyHashables[2].base)) expectNotEqual(anyHashables[0], anyHashables[1]) expectEqual(anyHashables[1], anyHashables[2]) } } #if !FOUNDATION_XCTEST if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) { let MeasurementTests = TestSuite("TestMeasurement") MeasurementTests.test("testBasicConstruction") { TestMeasurement().testBasicConstruction() } MeasurementTests.test("testConversion") { TestMeasurement().testConversion() } MeasurementTests.test("testOperators") { TestMeasurement().testOperators() } MeasurementTests.test("testUnits") { TestMeasurement().testUnits() } MeasurementTests.test("testMeasurementFormatter") { TestMeasurement().testMeasurementFormatter() } MeasurementTests.test("testEquality") { TestMeasurement().testEquality() } MeasurementTests.test("testComparison") { TestMeasurement().testComparison() } MeasurementTests.test("testHashing") { TestMeasurement().testHashing() } MeasurementTests.test("test_AnyHashableContainingMeasurement") { TestMeasurement().test_AnyHashableContainingMeasurement() } MeasurementTests.test("test_AnyHashableCreatedFromNSMeasurement") { TestMeasurement().test_AnyHashableCreatedFromNSMeasurement() } runAllTests() } #endif