Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add xcodebuild exit status to travis #93

Merged
merged 7 commits into from May 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 7 additions & 5 deletions .travis.yml
Expand Up @@ -23,13 +23,15 @@ jobs:
install: skip
env: TEST_DEVICE='platform=iOS Simulator,OS=12.2,name=iPhone SE'
script:
- xcodebuild -scheme TokamakUIKit -sdk iphonesimulator | xcpretty
- xcodebuild -scheme TokamakAppKit -sdk macosx | xcpretty
- xcodebuild test -scheme TokamakCLI -sdk macosx | xcpretty
- swift package generate-xcodeproj --xcconfig-overrides Package.xcconfig
- git checkout HEAD Tokamak.xcodeproj/xcshareddata/xcschemes/TokamakCLI.xcscheme
- 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
# that `Package.swift` is in a good state
- swift build --target Tokamak
- xcodebuild test -enableCodeCoverage YES -scheme Tokamak | xcpretty
- set -o pipefail && xcodebuild test -enableCodeCoverage YES -scheme Tokamak | xcpretty
after_success:
- bash <(curl -s https://codecov.io/bash)
# before_install:
Expand All @@ -41,5 +43,5 @@ jobs:
# - gem install cocoapods # Since Travis is not always on latest version
# - pod install --project-directory=Example
# - 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
72 changes: 8 additions & 64 deletions Sources/Tokamak/Components/Props/Color.swift
Expand Up @@ -49,77 +49,21 @@ extension Color: ExpressibleByIntegerLiteral {

extension Color {
public init?(hex: String) {
let cString = hex.utf8CString
let cArray = Array(hex.replacingOccurrences(of: "#", with: ""))

// - 1 for the trailing null terminator
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 cArray.count == 6 else { return nil }

guard
let red = nextByte(),
let green = nextByte(),
let blue = nextByte()
let red = Int(String(cArray[0...1]), radix: 16),
let green = Int(String(cArray[2...3]), radix: 16),
let blue = Int(String(cArray[4...5]), radix: 16)
else {
return nil
}

self.red = Double(UInt8(bitPattern: red)) / 255
self.green = Double(UInt8(bitPattern: green)) / 255
self.blue = Double(UInt8(bitPattern: blue)) / 255
self.red = Double(red) / 255
self.green = Double(green) / 255
self.blue = Double(blue) / 255
alpha = 1
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
}
33 changes: 33 additions & 0 deletions Tests/TokamakTests/ColorTests.swift
Expand Up @@ -17,5 +17,38 @@ final class ColorTests: XCTestCase {
Color(hex: "FF00FF"),
"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)
}
}
3 changes: 3 additions & 0 deletions codecov.yml
@@ -0,0 +1,3 @@
ignore:
- "Example" # ignore folders and all its contents
- "Tests"