Skip to content
This repository was archived by the owner on Oct 14, 2020. It is now read-only.

Commit

Permalink
Merge pull request #451 from kazk/rewrite-swift
Browse files Browse the repository at this point in the history
Rewrite Swift runner
  • Loading branch information
jhoffner authored Jul 12, 2017
2 parents f6c48ed + 2cd6a60 commit 241a65b
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 1,120 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ env:
- TEST_IMG=dart
- TEST_IMG=crystal
- TEST_IMG=ocaml
# - TEST_IMG=swift
- TEST_IMG=swift
- TEST_IMG=haskell
- TEST_IMG=objc
- TEST_IMG=go
Expand Down
115 changes: 57 additions & 58 deletions docker/swift.docker
Original file line number Diff line number Diff line change
@@ -1,74 +1,73 @@
# EXAMPLE USAGE: docker run --privileged --rm codewars/swift-runner run -l swift -c "print(1+1)"

# Pull base image.
# EXAMPLE USAGE: docker run --rm codewars/swift-runner run -l swift -c "print(1+1)"
FROM codewars/base-runner

# Optionally mount '/swift-vol' on ephemeral storage vol for faster
# installing of packages, compiling, etc.
env SWIFT_VOL /swift-vol
env SWIFT_GEN_DIR $SWIFT_VOL/swift-gen
env SWIFT_SOURCE_DIR $SWIFT_VOL/swift-source

# Install required dependencies for building Swift.
# See https://github.com/apple/swift
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get install -y curl rsync cmake git ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev

# Install cmake (Cmake version must be at least 3.4.3)
RUN wget http://www.cmake.org/files/v3.5/cmake-3.5.2.tar.gz
RUN tar xzf cmake-3.5.2.tar.gz
RUN cd cmake-3.5.2 && ./configure && make && sudo make install
RUN sudo rm -f /usr/bin/cmake
RUN sudo ln -s /usr/local/bin/cmake /usr/bin/cmake

# Install clang
RUN apt-get install -y clang-3.6
RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100
RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100

# Downalod all Swift related Git repos.
# See https://github.com/apple/swift
WORKDIR $SWIFT_SOURCE_DIR
RUN git clone https://github.com/apple/swift.git && ./swift/utils/update-checkout --clone
RUN git clone https://github.com/ninja-build/ninja.git && cd ninja && git checkout release

# Copy our custom codewars standard output files to the swift-corelibs-xctest directory.
COPY frameworks/swift/xctest/PrintObserver.swift $SWIFT_SOURCE_DIR/swift-corelibs-xctest/Sources/XCTest/Private/PrintObserver.swift
COPY frameworks/swift/xctest/XCTAssert.swift $SWIFT_SOURCE_DIR/swift-corelibs-xctest/Sources/XCTest/Public/XCTAssert.swift

# Copy our custom build-presets file to the swift directory.
COPY frameworks/swift/xctest/codewars-build-presets.ini $SWIFT_SOURCE_DIR/swift/codewars-build-presets.ini

# Build Swift
WORKDIR $SWIFT_SOURCE_DIR/swift
RUN utils/build-script --preset-file=codewars-build-presets.ini --preset=codewars_linux_1404 install_destdir=$SWIFT_GEN_DIR installable_package=$SWIFT_GEN_DIR/swift.tar.gz
env PATH $SWIFT_GEN_DIR/usr/bin:$PATH

# Remove swift source code to save space on the image.
RUN rm -rf $SWIFT_SOURCE_DIR/*

# Change permissions so we maybe don't have to use the --privileged docker run flag.
RUN chmod -R a+rx $SWIFT_VOL/*
# Based on https://github.com/swiftdocker/docker-swift/blob/master/Dockerfile
RUN apt-get -q update && \
apt-get -q install -y --no-install-recommends \
clang-3.6 \
curl \
git \
libc6-dev \
libedit-dev \
libicu-dev \
libssl-dev \
libcurl4-openssl-dev \
libxml2 \
pkg-config \
python2.7 \
python2.7-dev \
make \
&& update-alternatives --quiet --install /usr/bin/clang clang /usr/bin/clang-3.6 100 \
&& update-alternatives --quiet --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100 \
&& rm -r /var/lib/apt/lists/*

RUN set -ex \
&& export GNUPGHOME="$(mktemp -d)" \
&& \
for key in \
# pub 4096R/412B37AD 2015-11-19 [expires: 2017-11-18]
# Key fingerprint = 7463 A81A 4B2E EA1B 551F FBCF D441 C977 412B 37AD
# uid Swift Automatic Signing Key #1 <swift-infrastructure@swift.org>
7463A81A4B2EEA1B551FFBCFD441C977412B37AD \
# pub 4096R/21A56D5F 2015-11-28 [expires: 2017-11-27]
# Key fingerprint = 1BE1 E29A 084C B305 F397 D62A 9F59 7F4D 21A5 6D5F
# uid Swift 2.2 Release Signing Key <swift-infrastructure@swift.org>
1BE1E29A084CB305F397D62A9F597F4D21A56D5F \
# pub 4096R/91D306C6 2016-05-31 [expires: 2018-05-31]
# Key fingerprint = A3BA FD35 56A5 9079 C068 94BD 63BC 1CFE 91D3 06C6
# uid Swift 3.x Release Signing Key <swift-infrastructure@swift.org>
A3BAFD3556A59079C06894BD63BC1CFE91D306C6 \
; do \
gpg --quiet --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done \
&& cd /tmp \
&& curl -fSsL https://swift.org/builds/swift-3.1.1-release/ubuntu1404/swift-3.1.1-RELEASE/swift-3.1.1-RELEASE-ubuntu14.04.tar.gz -o swift.tar.gz \
&& curl -fSsL https://swift.org/builds/swift-3.1.1-release/ubuntu1404/swift-3.1.1-RELEASE/swift-3.1.1-RELEASE-ubuntu14.04.tar.gz.sig -o swift.tar.gz.sig \
&& gpg --batch --verify --quiet swift.tar.gz.sig swift.tar.gz \
&& tar -xzf swift.tar.gz --directory / --strip-components=1 \
&& rm -r "$GNUPGHOME" swift.tar.gz.sig swift.tar.gz \
&& rm -rf /var/lib/apt/lists/* \
&& chmod -R o+r /usr/lib/swift

# Add the package json first to a tmp directory and build, copy over so that we dont rebuild every time
ADD package.json /tmp/package.json
RUN cd /tmp && npm install --production
RUN mkdir -p /runner && cp -a /tmp/node_modules /runner
COPY package.json /tmp/package.json
WORKDIR /tmp
RUN npm install --production \
&& mkdir -p /runner \
&& cp -a /tmp/node_modules /runner \
&& rm -rf /tmp/node_modules

# ADD cli-runner and install node deps
ADD . /runner

WORKDIR /runner
RUN ln -s /home/codewarrior /workspace

# Run the test suite to make sure this thing works

USER codewarrior

# Set environment variables
ENV USER codewarrior
ENV HOME /home/codewarrior
ENV USER=codewarrior HOME=/home/codewarrior

# Run the test suite to make sure this thing works
RUN mocha -t 5000 test/runners/swift_spec.js

# timeout is a fallback in case an error with node
Expand Down
187 changes: 71 additions & 116 deletions examples/swift.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
cw-2:
xctest:
algorithms:
initial: |-
// return the two oldest/oldest ages within the array of ages passed in.
// it should return the two ages as a sorted array, youngest age first
func twoOldestAges(ages: [Int]) -> [Int] {
// TODO: complete
func twoOldestAges(ages: [Int]) -> [Int] { // TODO: complete
}
answer: |-
Expand All @@ -21,102 +20,102 @@ cw-2:
return [nextOldest, oldest]
}
fixture: |-
// some example data
let results1 = twoOldestAges(ages: [1,5,87,45,8,8])
let results2 = twoOldestAges(ages: [6,5,83,5,3,18])
// NOTE: You can use Test or test, whichever you prefer.
// Use "describe" to label your test suite.
Test.describe("twoOldestAges")
// Use "it" to identify the conditions you are testing for
Test.it("should return the second oldest age first")
// using assert_equals will report the invalid values to the user
Test.assert_equals(results1[0], 45)
// using expect will just give a user a generic error message, unless you provide a message
Test.expect(results2[0] == 18, "Number is not the second oldest")
import XCTest
// its best practice to test for multiple groups of tests, using it calls.
Test.it("should return the oldest age last")
class TwoOldestAgesTest: XCTestCase {
static var allTests = [
("testReturnSecondOldestFirst", testReturnSecondOldestFirst),
("testReturnOldestSecond", testReturnOldestSecond),
]
func testReturnSecondOldestFirst() {
let r1 = twoOldestAges(ages: [1,5,87,45,8,8])
XCTAssertEqual(r1[0], 45)
let r2 = twoOldestAges(ages: [6,5,83,5,3,18])
XCTAssertEqual(r2[0], 18)
}
func testReturnOldestSecond() {
let r1 = twoOldestAges(ages: [1,5,87,45,8,8])
XCTAssertEqual(r1[1], 87)
let r2 = twoOldestAges(ages: [6,5,83,5,3,18])
XCTAssertEqual(r2[1], 83)
}
}
Test.assert_equals(results1[1], 87)
Test.expect(results2[1] == 83, "Number is not the oldest")
_XCTMain([
testCase(TwoOldestAgesTest.allTests)
])
bug fixes:
initial: |-
func add(a: Int, b: Int) -> Int {
func add(_ a: Int, _ b: Int) -> Int {
a + b
}
answer: |-
func add(a: Int, b: Int) -> Int {
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
fixture: |-
// Use "describe" to define the test suite
Test.describe("add method")
import XCTest
// Use "it" to indicate a condition you are testing for
Test.it("should add both arguments and return")
class AddTest: XCTestCase {
static var allTests = [
("testAdd", testAdd),
]
func testAdd() {
XCTAssertEqual(add(1, 1), 2)
}
}
// "assert_equals" will return information about what values were
// expect if the assertion fails. This can be very useful to other
// users trying to pass the kata.
Test.assert_equals(add(a:1,b:2), 3)
_XCTMain([
testCase(AddTest.allTests)
])
// "expect" is a lower level assertion that will allow you to test
// anything. It just needs a boolean result. You should pass a message
// as the second parameter so that if the assertion fails the user
// will be giving some useful information.
Test.expect(add(a:1,b:1) == 2, "add(a:1,b:1) should == 2")
refactoring:
initial: |-
// refactor this method into a Person class with its own greet method
// let p = Person("foo")
// p.name == "foo"
// p.greet("bar") == "Hello bar, my name is foo"
func greet(other: String, name: String) -> String {
return "Hello \(other), my name is \(name)"
}
answer: |-
class Person {
let name: String
init(name: String) {
init(_ name: String) {
self.name = name
}
func greet(other: String) -> String {
func greet(_ other: String) -> String {
return "Hello \(other), my name is \(self.name)"
}
}
fixture: |-
// Use "describe" to define the test suite
Test.describe("Person")
let jack = Person(name: "Jack")
// Use "it" to indicate a condition you are testing for
Test.it("should have a name")
// "assert_equals" will return information about what values were
// expected if the assertion fails. This can be very useful to other
// users trying to pass the kata.
Test.assert_equals(jack.name, "Jack")
Test.it("should greet Jill")
Test.assert_equals(jack.greet(other: "Jill"), "Hello Jill, my name is Jack")
Test.it("should greet other people as well")
import XCTest
class PersonTest: XCTestCase {
static var allTests = [
("testName", testName),
("testGreet", testGreet),
]
func testName() {
let jack = Person("Jack")
XCTAssertEqual(jack.name, "Jack")
}
func testGreet() {
let jack = Person("Jack")
XCTAssertEqual(jack.greet("Jill"), "Hello Jill, my name is Jack")
XCTAssertEqual(jack.greet("Jane"), "Hello Jane, my name is Jack")
}
}
// unlike "assert_equals", "expect" is a lower level assertion that
// takes a boolean to determine if it passes. If it fails it will
// output the message that you give it, or a generic one. It is a good
// idea to provide a custom error message to help users pass the kata
Test.expect(jack.greet(other: "Jane") == "Hello Jane, my name is Jack", "Jack apparently is only able to greet Jane")
_XCTMain([
testCase(PersonTest.allTests)
])
reference:
initial: |-
Expand All @@ -125,62 +124,18 @@ cw-2:
answer: |-
let websites = ["codewars"]
fixture: |-
// Use test.describe (or Test.describe) to describe your test suite
Test.describe("websites")
// Use "it" calls to describe the specific test case
Test.it("should have the value 'codewars' inside of it")
// assert equals will pass if both items equal each other (using ==). If
// the test fails, assert_equals will output a descriptive message indicating
// what the values were expected to be.
Test.assert_equals(["codewars"], websites)
// you can also use the lower level test.expect. If you use test.expect directly then
// you should provide a custom error message, as the default one will be pretty useless
// to users trying to pass the kata.
Test.expect(["codewars"] == websites, "Array does not have correct value")
xctest:
reference:
initial: |-
class Person {
let name: String
init(_ name: String) {
// TODO: Program Constructor
}
func greet(_ other: String) -> String {
// TODO: Write a greeting string
}
}
answer: |-
class Person {
let name: String
init(_ name: String) {
self.name = name
}
func greet(_ other: String) -> String {
return "Hello, \(other), I am \(name), it's nice to meet you!"
}
}
fixture: |-
import XCTest
class PersonTest: XCTestCase {
class WebsitesTest: XCTestCase {
static var allTests = [
("testGreet", testGreet),
("testDefined", testDefined),
]
func testGreet() {
let person = Person("Jorge")
XCTAssertEqual(person.greet("Aditya"), "Hello, Aditya, I am Jorge, it's nice to meet you!")
func testDefined() {
XCTAssertEqual(websites[0], "codewars")
}
}
XCTMain([
testCase(PersonTest.allTests)
])
}
_XCTMain([
testCase(WebsitesTest.allTests)
])
Loading

0 comments on commit 241a65b

Please sign in to comment.