diff --git a/Sources/SemVer/Conveniences.swift b/Sources/SemVer/Conveniences.swift index e33931d..11aa589 100644 --- a/Sources/SemVer/Conveniences.swift +++ b/Sources/SemVer/Conveniences.swift @@ -3,7 +3,7 @@ // SemVer // // Created by Ben Leggiero on 2018-01-14. -// Copyright © 2020 Ben Leggiero BH-1-PS. +// Copyright © 2021 Ben Leggiero BH-1-PS. // import Foundation diff --git a/Sources/SemVer/Semantic Version + Hashable.swift b/Sources/SemVer/Semantic Version + Hashable.swift index 82aa0cd..d974e01 100644 --- a/Sources/SemVer/Semantic Version + Hashable.swift +++ b/Sources/SemVer/Semantic Version + Hashable.swift @@ -3,7 +3,7 @@ // SemVer // // Created by Ben Leggiero on 2020-04-19. -// Copyright © 2020 Ben Leggiero BH-1-PS. +// Copyright © 2021 Ben Leggiero BH-1-PS. // import Foundation diff --git a/Sources/SemVer/Semantic Version.swift b/Sources/SemVer/Semantic Version.swift index c98ad03..18cd781 100644 --- a/Sources/SemVer/Semantic Version.swift +++ b/Sources/SemVer/Semantic Version.swift @@ -3,7 +3,7 @@ // SemVer // // Created by Ben Leggiero on 2018-01-09. -// Copyright © 2020 Ben Leggiero BH-1-PS. +// Copyright © 2021 Ben Leggiero BH-1-PS. // import Foundation @@ -41,6 +41,15 @@ public struct SemanticVersion { public typealias Build = Extension.Build + /// Holds the raw, unmanaged value for `major` + private var _major: Major + + /// Holds the raw, unmanaged value for `minor` + private var _minor: Minor + + /// Holds the raw, unmanaged value for `patch` + private var _patch: Patch + /// The MAJOR version; increment this when you make incompatible API changes. /// @@ -49,15 +58,32 @@ public struct SemanticVersion { /// Patch and minor version MUST be reset to `0` when major version is incremented. This is done automatically if /// you set this variable. /// + /// This MUST increase numerically. For instance: 1.9.0 ➡️ 2.0.0 ➡️ 3.0.0. + /// /// https://semver.org/spec/v2.0.0.html#spec-item-8 /// - /// - Attention: Changing this immediately sets `minor` and `patch` to `0`. + /// - Attention: Increasing this immediately sets `minor` and `patch` to `0`. /// - Note: If this is `0`, then further rules don't apply. public var major: Major { - willSet { - minor = 0 - patch = 0 + set { + if newValue < _major { + assertionFailure( + """ + Major version number was decremented (went from \(_major) to \(newValue))! + In production builds, this will result in the Major version number not changing. + """) + } + else { + if newValue > _major { + _minor = 0 + _patch = 0 + } + + _major = newValue + } } + + get { _major } } /// The MINOR version; increment this when you add functionality in a backwards-compatible manner. @@ -69,13 +95,30 @@ public struct SemanticVersion { /// Patch version MUST be reset to `0` when minor version is incremented. This is done automatically if you set /// this variable. /// + /// This MUST increase numerically. For instance: 1.9.0 ➡️ 1.10.0 ➡️ 1.11.0. + /// /// https://semver.org/spec/v2.0.0.html#spec-item-7 /// - /// - Attention: Changing this immediately sets `minor` and `patch` to `0`. + /// - Attention: Increasing this immediately sets `patch` to `0`. public var minor: Minor { - willSet { - patch = 0 + set { + if newValue < _minor { + assertionFailure( + """ + Minor version number was decremented (went from \(_minor) to \(newValue))! + In production builds, this will result in the Minor version number not changing. + """) + } + else { + if newValue > _minor { + _patch = 0 + } + + _minor = newValue + } } + + get { _minor } } /// The PATCH version; increment this when you make backwards compatible bug fixes. @@ -83,8 +126,25 @@ public struct SemanticVersion { /// This MUST be incremented if only backwards compatible bug fixes are introduced. A bug fix is defined as an /// internal change that fixes incorrect behavior /// + /// This MUST increase numerically. For instance: 1.0.9.➡️ 1.0.10 ➡️ 1.0.11. + /// /// https://semver.org/spec/v2.0.0.html#spec-item-6 - public var patch: Patch + public var patch: Patch { + set { + if newValue < _patch { + assertionFailure( + """ + Patch version number was decremented (went from \(_patch) to \(newValue))! + In production builds, this will result in the Patch version number not changing. + """) + } + else { + _patch = newValue + } + } + + get { _patch } + } /// The PRE-RELEASE extension; this identifies versions that are available before being declared stable. /// @@ -94,7 +154,19 @@ public struct SemanticVersion { /// Pre-release versions have a lower precedence than the associated normal version. /// A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility /// requirements as denoted by its associated normal version. - public var preRelease: PreRelease? + public var preRelease: PreRelease? { + didSet { + if !isValid { + assertionFailure( + """ + Pre-Release extension set to an invalid value (\(preRelease ?? "nil"))! + In production builds, this will result in the Pre-Release extension being reset to its previous value. + """) + + preRelease = oldValue + } + } + } /// The BUILD metadata; this identifies some information about a particular build of a version, and is not /// considered for equivalence nor precedence. @@ -103,7 +175,30 @@ public struct SemanticVersion { /// Identifiers MUST NOT be empty. /// Build metadata MUST be ignored when determining version precedence. /// Thus two versions that differ only in the build metadata, have the same precedence. - public var build: Build? + public var build: Build? { + didSet { + if !isValid { + assertionFailure( + """ + Build extension set to an invalid value (\(build ?? "nil"))! + In production builds, this will result in the Build extension being reset to its previous value. + """) + + build = oldValue + } + } + } + + + /// Create a new Semantic Version without checking the validity of any of the pieces + /// - Parameter unchecked: All the semantic version values, without checking their validity + private init(unchecked: (major: Major, minor: Minor, patch: Patch, preRelease: PreRelease?, build: Build?)) { + self._major = unchecked.major + self._minor = unchecked.minor + self._patch = unchecked.patch + self.preRelease = unchecked.preRelease + self.build = unchecked.build + } /// Create a new Semantic Version with explicit parts. This returns `nil` if the given parts would create an invalid regex, like `1.02.3` @@ -115,17 +210,17 @@ public struct SemanticVersion { /// - preRelease: Indicates some specific information about a pre-release build, like `RC.1` /// - build: The build number, like `123` or `exp.sha.5114f85` or `2018.01.14.00.01` public init?(major: Major, minor: Minor, patch: Patch, preRelease: PreRelease? = nil, build: Build? = nil) { - self.major = major - self.minor = minor - self.patch = patch - self.preRelease = preRelease - self.build = build + self.init(unchecked: (major: major, + minor: minor, + patch: patch, + preRelease: preRelease, + build: build)) guard isValid else { return nil } } - /// Create a new Semantic Version with explicit (yet unlabelled) parts. This returns `nil` if the given parts would create an invalid regex, like `1.02.3` + /// Create a new Semantic Version with explicit (yet unlabelled) parts. This returns `nil` if the given parts would create an invalid SemVer, like `1.02.3` /// /// - Parameters: /// - major: The MAJOR version @@ -136,6 +231,40 @@ public struct SemanticVersion { public init?(_ major: Major, _ minor: Minor, _ patch: Patch, preRelease: PreRelease? = nil, build: Build? = nil) { self.init(major: major, minor: minor, patch: patch, preRelease: preRelease, build: build) } + + + /// Create a new simple Semantic Version with explicit parts and no extensions. + /// + /// This always succeeds, unlike the more-freeform initializers, since it's guaranteed to be correct at compile-time. If you need to set the Pre-Release andor Build extension, you must use one of the failable initializers. + /// + /// - Parameters: + /// - major: The MAJOR version + /// - minor: The MINOR version + /// - patch: The PATCH version + public init(major: UInt, minor: UInt, patch: UInt) { + self.init(unchecked: (major: major, + minor: minor, + patch: patch, + preRelease: nil, + build: nil)) + } + + + /// Create a new simple Semantic Version with explicit (yet unlabelled) parts and no extensions. + /// + /// This always succeeds, unlike the more-freeform initializers, since it's guaranteed to be correct at compile-time. If you need to set the Pre-Release andor Build extension, you must use one of the failable initializers. + /// + /// - Parameters: + /// - major: The MAJOR version + /// - minor: The MINOR version + /// - patch: The PATCH version + public init(_ major: UInt, _ minor: UInt, _ patch: UInt) { + self.init(unchecked: (major: major, + minor: minor, + patch: patch, + preRelease: nil, + build: nil)) + } } @@ -269,12 +398,14 @@ extension SemanticVersion: LosslessStringConvertible { return nil } - self.major = major - self.minor = minor - self.patch = patch - - self.preRelease = matches[0].group("preRelease", in: stringValue).flatMap { PreRelease($0) } - self.build = matches[0].group("build", in: stringValue).flatMap { Build($0) } + self.init(unchecked: ( + major: major, + minor: minor, + patch: patch, + + preRelease: matches[0].group("preRelease", in: stringValue).flatMap { PreRelease($0) }, + build: matches[0].group("build", in: stringValue).flatMap { Build($0) }) + ) } else { // FIXME: Remove ASAP guard @@ -287,12 +418,14 @@ extension SemanticVersion: LosslessStringConvertible { return nil } - self.major = major - self.minor = minor - self.patch = patch - - self.preRelease = matches[0].group(4, in: stringValue).flatMap { PreRelease($0) } - self.build = matches[0].group(6, in: stringValue).flatMap { Build($0) } + self.init(unchecked: ( + major: major, + minor: minor, + patch: patch, + + preRelease: matches[0].group(4, in: stringValue).flatMap { PreRelease($0) }, + build: matches[0].group(6, in: stringValue).flatMap { Build($0) }) + ) } } diff --git a/Sources/SemVer/Testing tools.swift b/Sources/SemVer/Testing tools.swift new file mode 100644 index 0000000..4db1ba7 --- /dev/null +++ b/Sources/SemVer/Testing tools.swift @@ -0,0 +1,29 @@ +// +// Testing tools.swift +// SemVer +// +// Created by Ky Leggiero on 2021-10-12. +// Copyright © 2021 Ben Leggiero BH-1-PS. +// + +import Foundation + + + +/// A bodge to change behavior based on whether a test suite is running. +/// +/// Ideally, this would be a compile-time flag. However, it seems that isn't being respected with my current setup, so I don't trust it. +internal var isTesting = false + + + +/// In non-test runs, this indicates that an internal sanity check failed. +/// +/// To perform an assertion in test runs as well, use `Swift.assertionFailure` instead. +/// +/// - Parameter message: _optional_ - A string to print in a playground or `-Onone` non-test build. Defaults to an empty string. +@inline(__always) +internal func assertionFailure(_ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) { + guard !isTesting else { return } + Swift.assertionFailure(message(), file: file, line: line) +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index e097780..f365bd2 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -2,6 +2,8 @@ import XCTest import SemVerTests -var tests = [XCTestCaseEntry]() -tests += SemVerTests.allTests() -XCTMain(tests) +isTesting = true + +XCTMain(SemVerTests.allTests + + SemVerHashableTests.allTests + + SemVerMutationTests.allTests) diff --git a/Tests/SemVerTests/SemVer mutations tests.swift b/Tests/SemVerTests/SemVer mutations tests.swift new file mode 100644 index 0000000..9d1fffc --- /dev/null +++ b/Tests/SemVerTests/SemVer mutations tests.swift @@ -0,0 +1,1104 @@ +// +// SemVer mutations tests.swift +// SemVer +// +// Created by Ky Leggiero on 2021-10-12. +// Copyright © 2021 Ben Leggiero BH-1-PS. +// + +import XCTest +@testable import SemVer + + + +class SemVerMutationTests: XCTestCase { + + override func setUp() { + isTesting = true + } + + + // MARK: - Increment + + func testIncrementMajorVersion() { + + var versions = Versions() + + versions.v0_0_0.major += 1 + XCTAssertEqual(versions.v0_0_0, SemVer(1,0,0)) + + versions.v0_0_1.major += 1 + XCTAssertEqual(versions.v0_0_1, SemVer(1,0,0)) + + versions.v0_0_999.major += 1 + XCTAssertEqual(versions.v0_0_999, SemVer(1,0,0)) + + versions.v0_1_0.major += 1 + XCTAssertEqual(versions.v0_1_0, SemVer(1,0,0)) + + versions.v0_1_999.major += 1 + XCTAssertEqual(versions.v0_1_999, SemVer(1,0,0)) + + versions.v0_999_0.major += 1 + XCTAssertEqual(versions.v0_999_0, SemVer(1,0,0)) + + versions.v0_999_1.major += 1 + XCTAssertEqual(versions.v0_999_1, SemVer(1,0,0)) + + versions.v0_999_999.major += 1 + XCTAssertEqual(versions.v0_999_999, SemVer(1,0,0)) + + + versions.v1_0_0.major += 1 + XCTAssertEqual(versions.v1_0_0, SemVer(2,0,0)) + + versions.v1_0_1.major += 1 + XCTAssertEqual(versions.v1_0_1, SemVer(2,0,0)) + + versions.v1_0_999.major += 1 + XCTAssertEqual(versions.v1_0_999, SemVer(2,0,0)) + + versions.v1_1_0.major += 1 + XCTAssertEqual(versions.v1_1_0, SemVer(2,0,0)) + + versions.v1_1_999.major += 1 + XCTAssertEqual(versions.v1_1_999, SemVer(2,0,0)) + + versions.v1_999_0.major += 1 + XCTAssertEqual(versions.v1_999_0, SemVer(2,0,0)) + + versions.v1_999_1.major += 1 + XCTAssertEqual(versions.v1_999_1, SemVer(2,0,0)) + + versions.v1_999_999.major += 1 + XCTAssertEqual(versions.v1_999_999, SemVer(2,0,0)) + + + versions.v2_0_0.major += 1 + XCTAssertEqual(versions.v2_0_0, SemVer(3,0,0)) + + versions.v2_0_1.major += 1 + XCTAssertEqual(versions.v2_0_1, SemVer(3,0,0)) + + versions.v2_0_999.major += 1 + XCTAssertEqual(versions.v2_0_999, SemVer(3,0,0)) + + versions.v2_1_0.major += 1 + XCTAssertEqual(versions.v2_1_0, SemVer(3,0,0)) + + versions.v2_1_999.major += 1 + XCTAssertEqual(versions.v2_1_999, SemVer(3,0,0)) + + versions.v2_999_0.major += 1 + XCTAssertEqual(versions.v2_999_0, SemVer(3,0,0)) + + versions.v2_999_1.major += 1 + XCTAssertEqual(versions.v2_999_1, SemVer(3,0,0)) + + versions.v2_999_999.major += 1 + XCTAssertEqual(versions.v2_999_999, SemVer(3,0,0)) + + + versions.v999_0_0.major += 1 + XCTAssertEqual(versions.v999_0_0, SemVer(1000,0,0)) + + versions.v999_0_1.major += 1 + XCTAssertEqual(versions.v999_0_1, SemVer(1000,0,0)) + + versions.v999_0_999.major += 1 + XCTAssertEqual(versions.v999_0_999, SemVer(1000,0,0)) + + versions.v999_1_0.major += 1 + XCTAssertEqual(versions.v999_1_0, SemVer(1000,0,0)) + + versions.v999_1_999.major += 1 + XCTAssertEqual(versions.v999_1_999, SemVer(1000,0,0)) + + versions.v999_999_0.major += 1 + XCTAssertEqual(versions.v999_999_0, SemVer(1000,0,0)) + + versions.v999_999_1.major += 1 + XCTAssertEqual(versions.v999_999_1, SemVer(1000,0,0)) + + versions.v999_999_999.major += 1 + XCTAssertEqual(versions.v999_999_999, SemVer(1000,0,0)) + } + + + func testIncrementMinorVersion() { + + var versions = Versions() + + versions.v0_0_0.minor += 1 + XCTAssertEqual(versions.v0_0_0, SemVer(0,1,0)) + + versions.v0_0_1.minor += 1 + XCTAssertEqual(versions.v0_0_1, SemVer(0,1,0)) + + versions.v0_0_999.minor += 1 + XCTAssertEqual(versions.v0_0_999, SemVer(0,1,0)) + + versions.v0_1_0.minor += 1 + XCTAssertEqual(versions.v0_1_0, SemVer(0,2,0)) + + versions.v0_1_999.minor += 1 + XCTAssertEqual(versions.v0_1_999, SemVer(0,2,0)) + + versions.v0_999_0.minor += 1 + XCTAssertEqual(versions.v0_999_0, SemVer(0,1000,0)) + + versions.v0_999_1.minor += 1 + XCTAssertEqual(versions.v0_999_1, SemVer(0,1000,0)) + + versions.v0_999_999.minor += 1 + XCTAssertEqual(versions.v0_999_999, SemVer(0,1000,0)) + + + versions.v1_0_0.minor += 1 + XCTAssertEqual(versions.v1_0_0, SemVer(1,1,0)) + + versions.v1_0_1.minor += 1 + XCTAssertEqual(versions.v1_0_1, SemVer(1,1,0)) + + versions.v1_0_999.minor += 1 + XCTAssertEqual(versions.v1_0_999, SemVer(1,1,0)) + + versions.v1_1_0.minor += 1 + XCTAssertEqual(versions.v1_1_0, SemVer(1,2,0)) + + versions.v1_1_999.minor += 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,2,0)) + + versions.v1_999_0.minor += 1 + XCTAssertEqual(versions.v1_999_0, SemVer(1,1000,0)) + + versions.v1_999_1.minor += 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,1000,0)) + + versions.v1_999_999.minor += 1 + XCTAssertEqual(versions.v1_999_999, SemVer(1,1000,0)) + + + versions.v2_0_0.minor += 1 + XCTAssertEqual(versions.v2_0_0, SemVer(2,1,0)) + + versions.v2_0_1.minor += 1 + XCTAssertEqual(versions.v2_0_1, SemVer(2,1,0)) + + versions.v2_0_999.minor += 1 + XCTAssertEqual(versions.v2_0_999, SemVer(2,1,0)) + + versions.v2_1_0.minor += 1 + XCTAssertEqual(versions.v2_1_0, SemVer(2,2,0)) + + versions.v2_1_999.minor += 1 + XCTAssertEqual(versions.v2_1_999, SemVer(2,2,0)) + + versions.v2_999_0.minor += 1 + XCTAssertEqual(versions.v2_999_0, SemVer(2,1000,0)) + + versions.v2_999_1.minor += 1 + XCTAssertEqual(versions.v2_999_1, SemVer(2,1000,0)) + + versions.v2_999_999.minor += 1 + XCTAssertEqual(versions.v2_999_999, SemVer(2,1000,0)) + + + versions.v999_0_0.minor += 1 + XCTAssertEqual(versions.v999_0_0, SemVer(999,1,0)) + + versions.v999_0_1.minor += 1 + XCTAssertEqual(versions.v999_0_1, SemVer(999,1,0)) + + versions.v999_0_999.minor += 1 + XCTAssertEqual(versions.v999_0_999, SemVer(999,1,0)) + + versions.v999_1_0.minor += 1 + XCTAssertEqual(versions.v999_1_0, SemVer(999,2,0)) + + versions.v999_1_999.minor += 1 + XCTAssertEqual(versions.v999_1_999, SemVer(999,2,0)) + + versions.v999_999_0.minor += 1 + XCTAssertEqual(versions.v999_999_0, SemVer(999,1000,0)) + + versions.v999_999_1.minor += 1 + XCTAssertEqual(versions.v999_999_1, SemVer(999,1000,0)) + + versions.v999_999_999.minor += 1 + XCTAssertEqual(versions.v999_999_999, SemVer(999,1000,0)) + } + + + func testIncrementPatchVersion() { + + var versions = Versions() + + versions.v0_0_0.patch += 1 + XCTAssertEqual(versions.v0_0_0, SemVer(0,0,1)) + + versions.v0_0_1.patch += 1 + XCTAssertEqual(versions.v0_0_1, SemVer(0,0,2)) + + versions.v0_0_999.patch += 1 + XCTAssertEqual(versions.v0_0_999, SemVer(0,0,1000)) + + versions.v0_1_0.patch += 1 + XCTAssertEqual(versions.v0_1_0, SemVer(0,1,1)) + + versions.v0_1_999.patch += 1 + XCTAssertEqual(versions.v0_1_999, SemVer(0,1,1000)) + + versions.v0_999_0.patch += 1 + XCTAssertEqual(versions.v0_999_0, SemVer(0,999,1)) + + versions.v0_999_1.patch += 1 + XCTAssertEqual(versions.v0_999_1, SemVer(0,999,2)) + + versions.v0_999_999.patch += 1 + XCTAssertEqual(versions.v0_999_999, SemVer(0,999,1000)) + + + versions.v1_0_0.patch += 1 + XCTAssertEqual(versions.v1_0_0, SemVer(1,0,1)) + + versions.v1_0_1.patch += 1 + XCTAssertEqual(versions.v1_0_1, SemVer(1,0,2)) + + versions.v1_0_999.patch += 1 + XCTAssertEqual(versions.v1_0_999, SemVer(1,0,1000)) + + versions.v1_1_0.patch += 1 + XCTAssertEqual(versions.v1_1_0, SemVer(1,1,1)) + + versions.v1_1_999.patch += 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,1000)) + + versions.v1_999_0.patch += 1 + XCTAssertEqual(versions.v1_999_0, SemVer(1,999,1)) + + versions.v1_999_1.patch += 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,2)) + + versions.v1_999_999.patch += 1 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,1000)) + + + versions.v2_0_0.patch += 1 + XCTAssertEqual(versions.v2_0_0, SemVer(2,0,1)) + + versions.v2_0_1.patch += 1 + XCTAssertEqual(versions.v2_0_1, SemVer(2,0,2)) + + versions.v2_0_999.patch += 1 + XCTAssertEqual(versions.v2_0_999, SemVer(2,0,1000)) + + versions.v2_1_0.patch += 1 + XCTAssertEqual(versions.v2_1_0, SemVer(2,1,1)) + + versions.v2_1_999.patch += 1 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,1000)) + + versions.v2_999_0.patch += 1 + XCTAssertEqual(versions.v2_999_0, SemVer(2,999,1)) + + versions.v2_999_1.patch += 1 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,2)) + + versions.v2_999_999.patch += 1 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,1000)) + + + versions.v999_0_0.patch += 1 + XCTAssertEqual(versions.v999_0_0, SemVer(999,0,1)) + + versions.v999_0_1.patch += 1 + XCTAssertEqual(versions.v999_0_1, SemVer(999,0,2)) + + versions.v999_0_999.patch += 1 + XCTAssertEqual(versions.v999_0_999, SemVer(999,0,1000)) + + versions.v999_1_0.patch += 1 + XCTAssertEqual(versions.v999_1_0, SemVer(999,1,1)) + + versions.v999_1_999.patch += 1 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,1000)) + + versions.v999_999_0.patch += 1 + XCTAssertEqual(versions.v999_999_0, SemVer(999,999,1)) + + versions.v999_999_1.patch += 1 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,2)) + + versions.v999_999_999.patch += 1 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,1000)) + } + + + // MARK: - Set to identity + + func testIdentityMajorVersion() { + + var versions = Versions() + + versions.v0_0_0.major = 0 + XCTAssertEqual(versions.v0_0_0, SemVer(0,0,0)) + + versions.v0_0_1.major = 0 + XCTAssertEqual(versions.v0_0_1, SemVer(0,0,1)) + + versions.v0_0_999.major = 0 + XCTAssertEqual(versions.v0_0_999, SemVer(0,0,999)) + + versions.v0_1_0.major = 0 + XCTAssertEqual(versions.v0_1_0, SemVer(0,1,0)) + + versions.v0_1_999.major = 0 + XCTAssertEqual(versions.v0_1_999, SemVer(0,1,999)) + + versions.v0_999_0.major = 0 + XCTAssertEqual(versions.v0_999_0, SemVer(0,999,0)) + + versions.v0_999_1.major = 0 + XCTAssertEqual(versions.v0_999_1, SemVer(0,999,1)) + + versions.v0_999_999.major = 0 + XCTAssertEqual(versions.v0_999_999, SemVer(0,999,999)) + + + versions.v1_0_0.major = 1 + XCTAssertEqual(versions.v1_0_0, SemVer(1,0,0)) + + versions.v1_0_1.major = 1 + XCTAssertEqual(versions.v1_0_1, SemVer(1,0,1)) + + versions.v1_0_999.major = 1 + XCTAssertEqual(versions.v1_0_999, SemVer(1,0,999)) + + versions.v1_1_0.major = 1 + XCTAssertEqual(versions.v1_1_0, SemVer(1,1,0)) + + versions.v1_1_999.major = 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,999)) + + versions.v1_999_0.major = 1 + XCTAssertEqual(versions.v1_999_0, SemVer(1,999,0)) + + versions.v1_999_1.major = 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,1)) + + versions.v1_999_999.major = 1 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,999)) + + + versions.v2_0_0.major = 2 + XCTAssertEqual(versions.v2_0_0, SemVer(2,0,0)) + + versions.v2_0_1.major = 2 + XCTAssertEqual(versions.v2_0_1, SemVer(2,0,1)) + + versions.v2_0_999.major = 2 + XCTAssertEqual(versions.v2_0_999, SemVer(2,0,999)) + + versions.v2_1_0.major = 2 + XCTAssertEqual(versions.v2_1_0, SemVer(2,1,0)) + + versions.v2_1_999.major = 2 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,999)) + + versions.v2_999_0.major = 2 + XCTAssertEqual(versions.v2_999_0, SemVer(2,999,0)) + + versions.v2_999_1.major = 2 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,1)) + + versions.v2_999_999.major = 2 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,999)) + + + versions.v999_0_0.major = 9 + XCTAssertEqual(versions.v999_0_0, SemVer(999,0,0)) + + versions.v999_0_1.major = 9 + XCTAssertEqual(versions.v999_0_1, SemVer(999,0,1)) + + versions.v999_0_999.major = 9 + XCTAssertEqual(versions.v999_0_999, SemVer(999,0,999)) + + versions.v999_1_0.major = 9 + XCTAssertEqual(versions.v999_1_0, SemVer(999,1,0)) + + versions.v999_1_999.major = 9 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,999)) + + versions.v999_999_0.major = 9 + XCTAssertEqual(versions.v999_999_0, SemVer(999,999,0)) + + versions.v999_999_1.major = 9 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,1)) + + versions.v999_999_999.major = 9 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,999)) + } + + + func testIdentityMinorVersion() { + + var versions = Versions() + + versions.v0_0_0.minor = 0 + XCTAssertEqual(versions.v0_0_0, SemVer(0,0,0)) + + versions.v0_0_1.minor = 0 + XCTAssertEqual(versions.v0_0_1, SemVer(0,0,1)) + + versions.v0_0_999.minor = 0 + XCTAssertEqual(versions.v0_0_999, SemVer(0,0,999)) + + versions.v0_1_0.minor = 1 + XCTAssertEqual(versions.v0_1_0, SemVer(0,1,0)) + + versions.v0_1_999.minor = 1 + XCTAssertEqual(versions.v0_1_999, SemVer(0,1,999)) + + versions.v0_999_0.minor = 9 + XCTAssertEqual(versions.v0_999_0, SemVer(0,999,0)) + + versions.v0_999_1.minor = 9 + XCTAssertEqual(versions.v0_999_1, SemVer(0,999,1)) + + versions.v0_999_999.minor = 9 + XCTAssertEqual(versions.v0_999_999, SemVer(0,999,999)) + + + versions.v1_0_0.minor = 0 + XCTAssertEqual(versions.v1_0_0, SemVer(1,0,0)) + + versions.v1_0_1.minor = 0 + XCTAssertEqual(versions.v1_0_1, SemVer(1,0,1)) + + versions.v1_0_999.minor = 0 + XCTAssertEqual(versions.v1_0_999, SemVer(1,0,999)) + + versions.v1_1_0.minor = 1 + XCTAssertEqual(versions.v1_1_0, SemVer(1,1,0)) + + versions.v1_1_999.minor = 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,999)) + + versions.v1_999_0.minor = 9 + XCTAssertEqual(versions.v1_999_0, SemVer(1,999,0)) + + versions.v1_999_1.minor = 9 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,1)) + + versions.v1_999_999.minor = 9 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,999)) + + + versions.v2_0_0.minor = 0 + XCTAssertEqual(versions.v2_0_0, SemVer(2,0,0)) + + versions.v2_0_1.minor = 0 + XCTAssertEqual(versions.v2_0_1, SemVer(2,0,1)) + + versions.v2_0_999.minor = 0 + XCTAssertEqual(versions.v2_0_999, SemVer(2,0,999)) + + versions.v2_1_0.minor = 1 + XCTAssertEqual(versions.v2_1_0, SemVer(2,1,0)) + + versions.v2_1_999.minor = 1 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,999)) + + versions.v2_999_0.minor = 9 + XCTAssertEqual(versions.v2_999_0, SemVer(2,999,0)) + + versions.v2_999_1.minor = 9 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,1)) + + versions.v2_999_999.minor = 9 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,999)) + + + versions.v999_0_0.minor = 0 + XCTAssertEqual(versions.v999_0_0, SemVer(999,0,0)) + + versions.v999_0_1.minor = 0 + XCTAssertEqual(versions.v999_0_1, SemVer(999,0,1)) + + versions.v999_0_999.minor = 0 + XCTAssertEqual(versions.v999_0_999, SemVer(999,0,999)) + + versions.v999_1_0.minor = 1 + XCTAssertEqual(versions.v999_1_0, SemVer(999,1,0)) + + versions.v999_1_999.minor = 1 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,999)) + + versions.v999_999_0.minor = 9 + XCTAssertEqual(versions.v999_999_0, SemVer(999,999,0)) + + versions.v999_999_1.minor = 9 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,1)) + + versions.v999_999_999.minor = 9 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,999)) + } + + + func testIdentityPatchVersion() { + + var versions = Versions() + + versions.v0_0_0.patch = 0 + XCTAssertEqual(versions.v0_0_0, SemVer(0,0,0)) + + versions.v0_0_1.patch = 1 + XCTAssertEqual(versions.v0_0_1, SemVer(0,0,1)) + + versions.v0_0_999.patch = 999 + XCTAssertEqual(versions.v0_0_999, SemVer(0,0,999)) + + versions.v0_1_0.patch = 0 + XCTAssertEqual(versions.v0_1_0, SemVer(0,1,0)) + + versions.v0_1_999.patch = 999 + XCTAssertEqual(versions.v0_1_999, SemVer(0,1,999)) + + versions.v0_999_0.patch = 0 + XCTAssertEqual(versions.v0_999_0, SemVer(0,999,0)) + + versions.v0_999_1.patch = 1 + XCTAssertEqual(versions.v0_999_1, SemVer(0,999,1)) + + versions.v0_999_999.patch = 999 + XCTAssertEqual(versions.v0_999_999, SemVer(0,999,999)) + + + versions.v1_0_0.patch = 0 + XCTAssertEqual(versions.v1_0_0, SemVer(1,0,0)) + + versions.v1_0_1.patch = 1 + XCTAssertEqual(versions.v1_0_1, SemVer(1,0,1)) + + versions.v1_0_999.patch = 999 + XCTAssertEqual(versions.v1_0_999, SemVer(1,0,999)) + + versions.v1_1_0.patch = 0 + XCTAssertEqual(versions.v1_1_0, SemVer(1,1,0)) + + versions.v1_1_999.patch = 999 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,999)) + + versions.v1_999_0.patch = 0 + XCTAssertEqual(versions.v1_999_0, SemVer(1,999,0)) + + versions.v1_999_1.patch = 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,1)) + + versions.v1_999_999.patch = 999 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,999)) + + + versions.v2_0_0.patch = 0 + XCTAssertEqual(versions.v2_0_0, SemVer(2,0,0)) + + versions.v2_0_1.patch = 1 + XCTAssertEqual(versions.v2_0_1, SemVer(2,0,1)) + + versions.v2_0_999.patch = 999 + XCTAssertEqual(versions.v2_0_999, SemVer(2,0,999)) + + versions.v2_1_0.patch = 0 + XCTAssertEqual(versions.v2_1_0, SemVer(2,1,0)) + + versions.v2_1_999.patch = 999 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,999)) + + versions.v2_999_0.patch = 0 + XCTAssertEqual(versions.v2_999_0, SemVer(2,999,0)) + + versions.v2_999_1.patch = 1 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,1)) + + versions.v2_999_999.patch = 999 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,999)) + + + versions.v999_0_0.patch = 0 + XCTAssertEqual(versions.v999_0_0, SemVer(999,0,0)) + + versions.v999_0_1.patch = 1 + XCTAssertEqual(versions.v999_0_1, SemVer(999,0,1)) + + versions.v999_0_999.patch = 999 + XCTAssertEqual(versions.v999_0_999, SemVer(999,0,999)) + + versions.v999_1_0.patch = 0 + XCTAssertEqual(versions.v999_1_0, SemVer(999,1,0)) + + versions.v999_1_999.patch = 999 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,999)) + + versions.v999_999_0.patch = 0 + XCTAssertEqual(versions.v999_999_0, SemVer(999,999,0)) + + versions.v999_999_1.patch = 1 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,1)) + + versions.v999_999_999.patch = 999 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,999)) + } + + + // MARK: - Decrement + + // I've commented-out tests which would cause a Swift runtime arithmetic overflow, since those always crash + + func testDecrementMajorVersion() { + + var versions = Versions() + +// versions.v0_0_0.major -= 1 +// XCTAssertEqual(versions.v0_0_0, SemVer(0,0,0)) +// +// versions.v0_0_1.major -= 1 +// XCTAssertEqual(versions.v0_0_1, SemVer(0,0,1)) +// +// versions.v0_0_999.major -= 1 +// XCTAssertEqual(versions.v0_0_999, SemVer(0,0,999)) +// +// versions.v0_1_0.major -= 1 +// XCTAssertEqual(versions.v0_1_0, SemVer(0,1,0)) +// +// versions.v0_1_999.major -= 1 +// XCTAssertEqual(versions.v0_1_999, SemVer(0,1,999)) +// +// versions.v0_999_0.major -= 1 +// XCTAssertEqual(versions.v0_999_0, SemVer(0,999,0)) +// +// versions.v0_999_1.major -= 1 +// XCTAssertEqual(versions.v0_999_1, SemVer(0,999,1)) +// +// versions.v0_999_999.major -= 1 +// XCTAssertEqual(versions.v0_999_999, SemVer(0,999,999)) + + + versions.v1_0_0.major -= 1 + XCTAssertEqual(versions.v1_0_0, SemVer(1,0,0)) + + versions.v1_0_1.major -= 1 + XCTAssertEqual(versions.v1_0_1, SemVer(1,0,1)) + + versions.v1_0_999.major -= 1 + XCTAssertEqual(versions.v1_0_999, SemVer(1,0,999)) + + versions.v1_1_0.major -= 1 + XCTAssertEqual(versions.v1_1_0, SemVer(1,1,0)) + + versions.v1_1_999.major -= 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,999)) + + versions.v1_999_0.major -= 1 + XCTAssertEqual(versions.v1_999_0, SemVer(1,999,0)) + + versions.v1_999_1.major -= 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,1)) + + versions.v1_999_999.major -= 1 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,999)) + + + versions.v2_0_0.major -= 1 + XCTAssertEqual(versions.v2_0_0, SemVer(2,0,0)) + + versions.v2_0_1.major -= 1 + XCTAssertEqual(versions.v2_0_1, SemVer(2,0,1)) + + versions.v2_0_999.major -= 1 + XCTAssertEqual(versions.v2_0_999, SemVer(2,0,999)) + + versions.v2_1_0.major -= 1 + XCTAssertEqual(versions.v2_1_0, SemVer(2,1,0)) + + versions.v2_1_999.major -= 1 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,999)) + + versions.v2_999_0.major -= 1 + XCTAssertEqual(versions.v2_999_0, SemVer(2,999,0)) + + versions.v2_999_1.major -= 1 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,1)) + + versions.v2_999_999.major -= 1 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,999)) + + + versions.v999_0_0.major -= 1 + XCTAssertEqual(versions.v999_0_0, SemVer(999,0,0)) + + versions.v999_0_1.major -= 1 + XCTAssertEqual(versions.v999_0_1, SemVer(999,0,1)) + + versions.v999_0_999.major -= 1 + XCTAssertEqual(versions.v999_0_999, SemVer(999,0,999)) + + versions.v999_1_0.major -= 1 + XCTAssertEqual(versions.v999_1_0, SemVer(999,1,0)) + + versions.v999_1_999.major -= 1 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,999)) + + versions.v999_999_0.major -= 1 + XCTAssertEqual(versions.v999_999_0, SemVer(999,999,0)) + + versions.v999_999_1.major -= 1 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,1)) + + versions.v999_999_999.major -= 1 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,999)) + } + + + func testDecrementMinorVersion() { + + var versions = Versions() + +// versions.v0_0_0.minor -= 1 +// XCTAssertEqual(versions.v0_0_0, SemVer(0,0,0)) +// +// versions.v0_0_1.minor -= 1 +// XCTAssertEqual(versions.v0_0_1, SemVer(0,0,1)) +// +// versions.v0_0_999.minor -= 1 +// XCTAssertEqual(versions.v0_0_999, SemVer(0,0,999)) + + versions.v0_1_0.minor -= 1 + XCTAssertEqual(versions.v0_1_0, SemVer(0,1,0)) + + versions.v0_1_999.minor -= 1 + XCTAssertEqual(versions.v0_1_999, SemVer(0,1,999)) + + versions.v0_999_0.minor -= 1 + XCTAssertEqual(versions.v0_999_0, SemVer(0,999,0)) + + versions.v0_999_1.minor -= 1 + XCTAssertEqual(versions.v0_999_1, SemVer(0,999,1)) + + versions.v0_999_999.minor -= 1 + XCTAssertEqual(versions.v0_999_999, SemVer(0,999,999)) + + +// versions.v1_0_0.minor -= 1 +// XCTAssertEqual(versions.v1_0_0, SemVer(1,0,0)) +// +// versions.v1_0_1.minor -= 1 +// XCTAssertEqual(versions.v1_0_1, SemVer(1,0,1)) +// +// versions.v1_0_999.minor -= 1 +// XCTAssertEqual(versions.v1_0_999, SemVer(1,0,999)) + + versions.v1_1_0.minor -= 1 + XCTAssertEqual(versions.v1_1_0, SemVer(1,1,0)) + + versions.v1_1_999.minor -= 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,999)) + + versions.v1_999_0.minor -= 1 + XCTAssertEqual(versions.v1_999_0, SemVer(1,999,0)) + + versions.v1_999_1.minor -= 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,1)) + + versions.v1_999_999.minor -= 1 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,999)) + + +// versions.v2_0_0.minor -= 1 +// XCTAssertEqual(versions.v2_0_0, SemVer(2,0,0)) +// +// versions.v2_0_1.minor -= 1 +// XCTAssertEqual(versions.v2_0_1, SemVer(2,0,1)) +// +// versions.v2_0_999.minor -= 1 +// XCTAssertEqual(versions.v2_0_999, SemVer(2,0,999)) + + versions.v2_1_0.minor -= 1 + XCTAssertEqual(versions.v2_1_0, SemVer(2,1,0)) + + versions.v2_1_999.minor -= 1 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,999)) + + versions.v2_999_0.minor -= 1 + XCTAssertEqual(versions.v2_999_0, SemVer(2,999,0)) + + versions.v2_999_1.minor -= 1 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,1)) + + versions.v2_999_999.minor -= 1 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,999)) + + +// versions.v999_0_0.minor -= 1 +// XCTAssertEqual(versions.v999_0_0, SemVer(999,0,0)) +// +// versions.v999_0_1.minor -= 1 +// XCTAssertEqual(versions.v999_0_1, SemVer(999,0,1)) +// +// versions.v999_0_999.minor -= 1 +// XCTAssertEqual(versions.v999_0_999, SemVer(999,0,999)) + + versions.v999_1_0.minor -= 1 + XCTAssertEqual(versions.v999_1_0, SemVer(999,1,0)) + + versions.v999_1_999.minor -= 1 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,999)) + + versions.v999_999_0.minor -= 1 + XCTAssertEqual(versions.v999_999_0, SemVer(999,999,0)) + + versions.v999_999_1.minor -= 1 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,1)) + + versions.v999_999_999.minor -= 1 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,999)) + } + + + func testDecrementPatchVersion() { + + var versions = Versions() + +// versions.v0_0_0.patch -= 1 +// XCTAssertEqual(versions.v0_0_0, SemVer(0,0,0)) + + versions.v0_0_1.patch -= 1 + XCTAssertEqual(versions.v0_0_1, SemVer(0,0,1)) + + versions.v0_0_999.patch -= 1 + XCTAssertEqual(versions.v0_0_999, SemVer(0,0,999)) + +// versions.v0_1_0.patch -= 1 +// XCTAssertEqual(versions.v0_1_0, SemVer(0,1,0)) + + versions.v0_1_999.patch -= 1 + XCTAssertEqual(versions.v0_1_999, SemVer(0,1,999)) + +// versions.v0_999_0.patch -= 1 +// XCTAssertEqual(versions.v0_999_0, SemVer(0,999,0)) + + versions.v0_999_1.patch -= 1 + XCTAssertEqual(versions.v0_999_1, SemVer(0,999,1)) + + versions.v0_999_999.patch -= 1 + XCTAssertEqual(versions.v0_999_999, SemVer(0,999,999)) + + +// versions.v1_0_0.patch -= 1 +// XCTAssertEqual(versions.v1_0_0, SemVer(1,0,0)) + + versions.v1_0_1.patch -= 1 + XCTAssertEqual(versions.v1_0_1, SemVer(1,0,1)) + + versions.v1_0_999.patch -= 1 + XCTAssertEqual(versions.v1_0_999, SemVer(1,0,999)) + +// versions.v1_1_0.patch -= 1 +// XCTAssertEqual(versions.v1_1_0, SemVer(1,1,0)) + + versions.v1_1_999.patch -= 1 + XCTAssertEqual(versions.v1_1_999, SemVer(1,1,999)) + +// versions.v1_999_0.patch -= 1 +// XCTAssertEqual(versions.v1_999_0, SemVer(1,999,0)) + + versions.v1_999_1.patch -= 1 + XCTAssertEqual(versions.v1_999_1, SemVer(1,999,1)) + + versions.v1_999_999.patch -= 1 + XCTAssertEqual(versions.v1_999_999, SemVer(1,999,999)) + + +// versions.v2_0_0.patch -= 1 +// XCTAssertEqual(versions.v2_0_0, SemVer(2,0,0)) + + versions.v2_0_1.patch -= 1 + XCTAssertEqual(versions.v2_0_1, SemVer(2,0,1)) + + versions.v2_0_999.patch -= 1 + XCTAssertEqual(versions.v2_0_999, SemVer(2,0,999)) + +// versions.v2_1_0.patch -= 1 +// XCTAssertEqual(versions.v2_1_0, SemVer(2,1,0)) + + versions.v2_1_999.patch -= 1 + XCTAssertEqual(versions.v2_1_999, SemVer(2,1,999)) + +// versions.v2_999_0.patch -= 1 +// XCTAssertEqual(versions.v2_999_0, SemVer(2,999,0)) + + versions.v2_999_1.patch -= 1 + XCTAssertEqual(versions.v2_999_1, SemVer(2,999,1)) + + versions.v2_999_999.patch -= 1 + XCTAssertEqual(versions.v2_999_999, SemVer(2,999,999)) + + +// versions.v999_0_0.patch -= 1 +// XCTAssertEqual(versions.v999_0_0, SemVer(999,0,0)) + + versions.v999_0_1.patch -= 1 + XCTAssertEqual(versions.v999_0_1, SemVer(999,0,1)) + + versions.v999_0_999.patch -= 1 + XCTAssertEqual(versions.v999_0_999, SemVer(999,0,999)) + +// versions.v999_1_0.patch -= 1 +// XCTAssertEqual(versions.v999_1_0, SemVer(999,1,0)) + + versions.v999_1_999.patch -= 1 + XCTAssertEqual(versions.v999_1_999, SemVer(999,1,999)) + +// versions.v999_999_0.patch -= 1 +// XCTAssertEqual(versions.v999_999_0, SemVer(999,999,0)) + + versions.v999_999_1.patch -= 1 + XCTAssertEqual(versions.v999_999_1, SemVer(999,999,1)) + + versions.v999_999_999.patch -= 1 + XCTAssertEqual(versions.v999_999_999, SemVer(999,999,999)) + } + + + // MARK: - Set extensions + + func testSetExtensions() { + var allNumbers = SemVer(1,2,3, preRelease: [4, 5, 6], build: [7, 8, 9])! + + allNumbers.preRelease = [10, 11, 12] + XCTAssertEqual(allNumbers, SemVer(1,2,3, preRelease: [10, 11, 12], build: [7, 8, 9])!) + + allNumbers.build = [13, 14, 15] + XCTAssertEqual(allNumbers, SemVer(1,2,3, preRelease: [10, 11, 12], build: [13, 14, 15])!) + + allNumbers.preRelease = nil + XCTAssertEqual(allNumbers, SemVer(1,2,3, build: [13, 14, 15])!) + + + var stringy = SemVer(1,2,3, preRelease: ["fore", "5", "sicks"], build: ["heaven", "ate", "nein"])! + + stringy.preRelease = ["tin", "leaven", "dealve"] + XCTAssertEqual(stringy, SemVer(1,2,3, preRelease: ["tin", "leaven", "dealve"], build: ["heaven", "ate", "nein"])!) + + stringy.build = ["hurting", "forting", "15"] + XCTAssertEqual(stringy, SemVer(1,2,3, preRelease: ["tin", "leaven", "dealve"], build: ["hurting", "forting", "15"])!) + + stringy.build = nil + XCTAssertEqual(stringy, SemVer(1,2,3, preRelease: ["tin", "leaven", "dealve"])!) + + + var buildLater = SemVer(1,2,3, preRelease: "RC")! + + buildLater.build = "2021.10.12" + XCTAssertEqual(buildLater, SemVer(1,2,3, preRelease: "RC", build: "2021.10.12")!) + + + var preReleaseLater = SemVer(1,2,3, build: "567")! + + preReleaseLater.preRelease = ["Beta", 1] + XCTAssertEqual(preReleaseLater, SemVer(1,2,3, preRelease: ["Beta", 1], build: "567")!) + } + + + func testInvalidPreRelease() { + var semVer = SemVer(1,2,3)! + + semVer.preRelease = "00" + XCTAssertEqual(semVer, SemVer(1,2,3)) + + semVer.preRelease = ["", "", ""] + XCTAssertEqual(semVer, SemVer(1,2,3)) + + semVer.preRelease = "%" + XCTAssertEqual(semVer, SemVer(1,2,3)) + + semVer.preRelease = "⛔️" + XCTAssertEqual(semVer, SemVer(1,2,3)) + } + + + func testInvalidBuild() { + var semVer = SemVer(1,2,3)! + + semVer.build = ["", "", ""] + XCTAssertEqual(semVer, SemVer(1,2,3)) + + semVer.build = "%" + XCTAssertEqual(semVer, SemVer(1,2,3)) + + semVer.build = "⛔️" + XCTAssertEqual(semVer, SemVer(1,2,3)) + } + + + // MARK: - Requirements + + static let allTests = [ + ("testIncrementMajorVersion", testIncrementMajorVersion), + ("testIncrementMinorVersion", testIncrementMinorVersion), + ("testIncrementPatchVersion", testIncrementPatchVersion), + + ("testIdentityMajorVersion", testIdentityMajorVersion), + ("testIdentityMinorVersion", testIdentityMinorVersion), + ("testIdentityPatchVersion", testIdentityPatchVersion), + + ("testDecrementMajorVersion", testDecrementMajorVersion), + ("testDecrementMinorVersion", testDecrementMinorVersion), + ("testDecrementPatchVersion", testDecrementPatchVersion), + + ("testSetExtensions", testSetExtensions), + ] +} + + + +// MARK: - Utilities for this test class + +private struct Versions { + var v0_0_0 = SemVer(0,0,0) + var v0_0_1 = SemVer(0,0,1) + var v0_0_999 = SemVer(0,0,999) + var v0_1_0 = SemVer(0,1,0) + var v0_1_999 = SemVer(0,1,999) + var v0_999_0 = SemVer(0,999,0) + var v0_999_1 = SemVer(0,999,1) + var v0_999_999 = SemVer(0,999,999) + + var v1_0_0 = SemVer(1,0,0) + var v1_0_1 = SemVer(1,0,1) + var v1_0_999 = SemVer(1,0,999) + var v1_1_0 = SemVer(1,1,0) + var v1_1_999 = SemVer(1,1,999) + var v1_999_0 = SemVer(1,999,0) + var v1_999_1 = SemVer(1,999,1) + var v1_999_999 = SemVer(1,999,999) + + var v2_0_0 = SemVer(2,0,0) + var v2_0_1 = SemVer(2,0,1) + var v2_0_999 = SemVer(2,0,999) + var v2_1_0 = SemVer(2,1,0) + var v2_1_999 = SemVer(2,1,999) + var v2_999_0 = SemVer(2,999,0) + var v2_999_1 = SemVer(2,999,1) + var v2_999_999 = SemVer(2,999,999) + + var v999_0_0 = SemVer(999,0,0) + var v999_0_1 = SemVer(999,0,1) + var v999_0_999 = SemVer(999,0,999) + var v999_1_0 = SemVer(999,1,0) + var v999_1_999 = SemVer(999,1,999) + var v999_999_0 = SemVer(999,999,0) + var v999_999_1 = SemVer(999,999,1) + var v999_999_999 = SemVer(999,999,999) +} diff --git a/Tests/SemVerTests/SemVer+Hashable Tests.swift b/Tests/SemVerTests/SemVer+Hashable Tests.swift index 49f133d..2dd3596 100644 --- a/Tests/SemVerTests/SemVer+Hashable Tests.swift +++ b/Tests/SemVerTests/SemVer+Hashable Tests.swift @@ -3,7 +3,7 @@ // SemVer // // Created by Ben Leggiero on 2020-04-19. -// Copyright © 2020 Ben Leggiero BH-1-PS. +// Copyright © 2021 Ben Leggiero BH-1-PS. // import XCTest @@ -12,6 +12,12 @@ import XCTest class SemVerHashableTests: XCTestCase { + + override func setUp() { + isTesting = true + } + + func testHashable() { let v0_0_0 = SemVer(0,0,0)! let v0_0_0__0 = SemVer(0,0,0, preRelease: 0)! @@ -131,6 +137,11 @@ class SemVerHashableTests: XCTestCase { XCTAssertTrue(all.allPairsSatisfy { $0.hashValue != $1.hashValue }) } + + + static let allTests = [ + ("testHashable", testHashable), + ] } diff --git a/Tests/SemVerTests/SemVerTests.swift b/Tests/SemVerTests/SemVerTests.swift index 1274bba..3641a9b 100644 --- a/Tests/SemVerTests/SemVerTests.swift +++ b/Tests/SemVerTests/SemVerTests.swift @@ -3,22 +3,18 @@ // SemVer // // Created by Ben Leggiero on 2018-01-09. -// Copyright © 2020 Ben Leggiero BH-1-PS. +// Copyright © 2021 Ben Leggiero BH-1-PS. // import XCTest @testable import SemVer + + class SemVerTests: XCTestCase { override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() + isTesting = true } @@ -248,7 +244,7 @@ class SemVerTests: XCTestCase { } - static var allTests = [ + static let allTests = [ ("testDescription", testDescription), ("testFromString", testFromString), ("testPrecedence", testPrecedence), diff --git a/Tests/SemVerTests/XCTestManifests.swift b/Tests/SemVerTests/XCTestManifests.swift index fb3a147..3911b09 100644 --- a/Tests/SemVerTests/XCTestManifests.swift +++ b/Tests/SemVerTests/XCTestManifests.swift @@ -2,8 +2,12 @@ import XCTest #if !canImport(ObjectiveC) public func allTests() -> [XCTestCaseEntry] { + isTesting = true + return [ testCase(SemVerTests.allTests), + testCase(SemVerHashableTests.allTests), + testCase(SemVerMutationTests.allTests), ] } #endif