Add xcodebuild exit status to travis (#93)
* Add exit status * Fix Color * Update travis.yml script * Remove unused extension * Add condition for safe * Add Color tests * Add codecov.yml
This commit is contained in:
parent
4f02218fdb
commit
5c65df1375
12
.travis.yml
12
.travis.yml
|
@ -23,13 +23,15 @@ jobs:
|
||||||
install: skip
|
install: skip
|
||||||
env: TEST_DEVICE='platform=iOS Simulator,OS=12.2,name=iPhone SE'
|
env: TEST_DEVICE='platform=iOS Simulator,OS=12.2,name=iPhone SE'
|
||||||
script:
|
script:
|
||||||
- xcodebuild -scheme TokamakUIKit -sdk iphonesimulator | xcpretty
|
- swift package generate-xcodeproj --xcconfig-overrides Package.xcconfig
|
||||||
- xcodebuild -scheme TokamakAppKit -sdk macosx | xcpretty
|
- git checkout HEAD Tokamak.xcodeproj/xcshareddata/xcschemes/TokamakCLI.xcscheme
|
||||||
- xcodebuild test -scheme TokamakCLI -sdk macosx | xcpretty
|
- set -o pipefail && xcodebuild -scheme TokamakUIKit -sdk iphonesimulator | xcpretty
|
||||||
|
- set -o pipefail && xcodebuild -scheme TokamakAppKit -sdk macosx | xcpretty
|
||||||
|
- set -o pipefail && xcodebuild test -scheme TokamakCLI -sdk macosx | xcpretty
|
||||||
# this runs the build the second time, but it's the only way to make sure
|
# this runs the build the second time, but it's the only way to make sure
|
||||||
# that `Package.swift` is in a good state
|
# that `Package.swift` is in a good state
|
||||||
- swift build --target Tokamak
|
- swift build --target Tokamak
|
||||||
- xcodebuild test -enableCodeCoverage YES -scheme Tokamak | xcpretty
|
- set -o pipefail && xcodebuild test -enableCodeCoverage YES -scheme Tokamak | xcpretty
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
# before_install:
|
# before_install:
|
||||||
|
@ -41,5 +43,5 @@ jobs:
|
||||||
# - gem install cocoapods # Since Travis is not always on latest version
|
# - gem install cocoapods # Since Travis is not always on latest version
|
||||||
# - pod install --project-directory=Example
|
# - pod install --project-directory=Example
|
||||||
# - swift build
|
# - swift build
|
||||||
# - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/Tokamak.xcworkspace -scheme Tokamak-Example -sdk iphonesimulator11.0 ONLY_ACTIVE_ARCH=NO | xcpretty
|
# - set -o pipefail && set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/Tokamak.xcworkspace -scheme Tokamak-Example -sdk iphonesimulator11.0 ONLY_ACTIVE_ARCH=NO | xcpretty
|
||||||
# - pod lib lint
|
# - pod lib lint
|
||||||
|
|
|
@ -49,77 +49,21 @@ extension Color: ExpressibleByIntegerLiteral {
|
||||||
|
|
||||||
extension Color {
|
extension Color {
|
||||||
public init?(hex: String) {
|
public init?(hex: String) {
|
||||||
let cString = hex.utf8CString
|
let cArray = Array(hex.replacingOccurrences(of: "#", with: ""))
|
||||||
|
|
||||||
// - 1 for the trailing null terminator
|
guard cArray.count == 6 else { return nil }
|
||||||
let hexSize = cString.count - 1
|
|
||||||
|
|
||||||
// If the first character is a '#', skip it
|
|
||||||
var offset = cString.first == 0x23 ? 1 : 0
|
|
||||||
|
|
||||||
// We only support 6 hexadecimal characters
|
|
||||||
if hexSize - offset != 6 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextByte() -> Int8? {
|
|
||||||
// Take the first byte as the high 4 bits
|
|
||||||
// Then the second byte as the low 4 bits
|
|
||||||
if
|
|
||||||
let high = cString[offset].hexDecoded(),
|
|
||||||
let low = cString[offset].hexDecoded() {
|
|
||||||
// In this case, unchecked is still safe as it's between 0 and 6
|
|
||||||
offset = offset &+ 2
|
|
||||||
|
|
||||||
// Adds the two 4-bit pairs together to form a full byte
|
|
||||||
return (high << 4) & low
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard
|
guard
|
||||||
let red = nextByte(),
|
let red = Int(String(cArray[0...1]), radix: 16),
|
||||||
let green = nextByte(),
|
let green = Int(String(cArray[2...3]), radix: 16),
|
||||||
let blue = nextByte()
|
let blue = Int(String(cArray[4...5]), radix: 16)
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
self.red = Double(red) / 255
|
||||||
self.red = Double(UInt8(bitPattern: red)) / 255
|
self.green = Double(green) / 255
|
||||||
self.green = Double(UInt8(bitPattern: green)) / 255
|
self.blue = Double(blue) / 255
|
||||||
self.blue = Double(UInt8(bitPattern: blue)) / 255
|
|
||||||
alpha = 1
|
alpha = 1
|
||||||
space = .sRGB
|
space = .sRGB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Int8 {
|
|
||||||
func hexDecoded() -> Int8? {
|
|
||||||
// If the character is between 0x30 and 0x39 it is a textual number
|
|
||||||
// 0x30 is equal to the ASCII `0` and 0x30 is equal to `0x39`
|
|
||||||
if self >= 0x30 && self <= 0x39 {
|
|
||||||
// The binary representation of this character can be found by subtracting `0` in ASCII
|
|
||||||
// This will then match `0` in binary. Which means `1` in ASCII matches `1` in binary
|
|
||||||
return self &- 0x30
|
|
||||||
} else if self >= 0x41 && self <= 0x46 {
|
|
||||||
// This block executes if the integer is within the `a-z` lowercased ASCII range
|
|
||||||
// Then uses the algorithm described below to find the correct representation
|
|
||||||
return self &- Int8.lowercasedOffset
|
|
||||||
} else if self >= 0x61 && self <= 0x66 {
|
|
||||||
// This block executes if the integer is within the `A-Z` uppercased ASCII range
|
|
||||||
// Then uses the algorithm described below to find the correct representation
|
|
||||||
return self &- Int8.uppercasedOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'a' in hexadecimal is equal to `10` in decimal
|
|
||||||
// So by subtracting `a` we get the lowercased character narrowed down to base10 offset by 10
|
|
||||||
// By adding 10 (or reducing the subtraction size by 10) we represent this character correctly as base10
|
|
||||||
static let lowercasedOffset: Int8 = 0x41 &- 10
|
|
||||||
|
|
||||||
// The same as the lowercasedOffset, except for uppercased ASCII
|
|
||||||
static let uppercasedOffset: Int8 = 0x61 &- 10
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,5 +17,38 @@ final class ColorTests: XCTestCase {
|
||||||
Color(hex: "FF00FF"),
|
Color(hex: "FF00FF"),
|
||||||
"The '#' before a hex code produced a different output than without it"
|
"The '#' before a hex code produced a different output than without it"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
guard let red = Color(hex: "#FF0000") else {
|
||||||
|
XCTFail("Hexadecimal decoding failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(red.red, 1)
|
||||||
|
XCTAssertEqual(red.green, 0)
|
||||||
|
XCTAssertEqual(red.blue, 0)
|
||||||
|
|
||||||
|
guard let green = Color(hex: "#00FF00") else {
|
||||||
|
XCTFail("Hexadecimal decoding failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(green.red, 0)
|
||||||
|
XCTAssertEqual(green.green, 1)
|
||||||
|
XCTAssertEqual(green.blue, 0)
|
||||||
|
|
||||||
|
guard let blue = Color(hex: "#0000FF") else {
|
||||||
|
XCTFail("Hexadecimal decoding failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(blue.red, 0)
|
||||||
|
XCTAssertEqual(blue.green, 0)
|
||||||
|
XCTAssertEqual(blue.blue, 1)
|
||||||
|
|
||||||
|
let broken = Color(hex: "#P000FF")
|
||||||
|
XCTAssertEqual(broken, nil)
|
||||||
|
|
||||||
|
let short = Color(hex: "F01")
|
||||||
|
XCTAssertEqual(short, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ignore:
|
||||||
|
- "Example" # ignore folders and all its contents
|
||||||
|
- "Tests"
|
Loading…
Reference in New Issue