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

Rewrite Swift runner #451

Merged
merged 1 commit into from
Jul 12, 2017
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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