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

Commit 2f75f83

Browse files
committed
Mixed fixes:
-Readme update -Test Crashed message and unit test -Test timeout message and unit test -Replace \n with <:LF:> and unit test -C unit test on docker build
1 parent a2d4512 commit 2f75f83

File tree

4 files changed

+94
-31
lines changed

4 files changed

+94
-31
lines changed

README.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
[![Build Status](https://travis-ci.org/Codewars/codewars-runner-cli.svg?branch=master)](https://travis-ci.org/Codewars/codewars-runner-cli)
44

55
This project is used by [Codewars](http://www.codewars.com) and [Qualified.io](https://www.qualified.io) to execute small sets of code within various languages, using various testing frameworks.
6-
Each time code is run, it is executed within a Docker container in order to secure unsafe code execution.
6+
Each time code is run, it is executed within a Docker container in order to secure unsafe code execution.
77

88
All execution is done within Docker, with a Node CLI app contained within each container
9-
that manages the code execution for that specific language environment and returns the result via stdout.
9+
that manages the code execution for that specific language environment and returns the result via stdout.
1010

1111
## Contributions
1212

1313
This project has been open-sourced so that the Codewars and Qualified communites can contribute support for new languages and
1414
frameworks. See the [Language Support Status section](#user-content-language-support-status) for more information regarding which languages are currently supported
1515
and where their Codewars/Qualified support has been added.
16-
16+
1717
## Basic Usage
1818

1919
Within each Docker image, there is a copy of the Node executable and a `run` script. That script accepts multiple options
@@ -35,7 +35,7 @@ docker run --rm -it codewars/node-runner bash
3535
docker-compose run node-runner
3636
```
3737

38-
Or you could choose to execute the code outside of Docker by creating a container that will remove itself after it executes:
38+
Or you could choose to execute the code outside of Docker by creating a container that will remove itself after it executes:
3939

4040
```
4141
# direct Docker call:
@@ -50,9 +50,9 @@ docker-compose run ruby -c "puts 'I ran inside of Docker using Ruby'"
5050
### Integrated Test Suites
5151
The most significant aspect of this project is that integrated test support is built in to many languages. This is how
5252
Codewars and Qualified work, instead of testing STDOUT of a program, the executed code is tested using traditional
53-
code testing methods, with unit-tests and language-specific testing frameworks.
53+
code testing methods, with unit-tests and language-specific testing frameworks.
5454

55-
Here is a very simple example of running tests using the simplified Codewars testing framework.
55+
Here is a very simple example of running tests using the simplified Codewars testing framework.
5656

5757
```
5858
# manually running docker
@@ -64,7 +64,7 @@ docker-compose run javascript -c "var a = 1;" -t cw -f "Test.assertEquals(a, 1)"
6464

6565
Which would output `<PASSED::>Test Passed: Value == 1` to STDOUT.
6666

67-
## Language Support Status
67+
## Language Support Status
6868

6969
Many languages are currently supported in various states of completeness. This list tries to keep track of each.
7070

@@ -74,7 +74,7 @@ Many languages are currently supported in various states of completeness. This l
7474
|----------------|---------------|--------------|------------------|---------------|----------------|----------------|--------------|-------------------------------------------------------------------------|
7575
| Assembly (GAS) | | !!! | | | | systems-runner | | Travis is failing, tests pass locally |
7676
| Bash | || | Kumite Only | | * | | |
77-
| C | | !!! | !!! | | | systems-runner | | Travis is failing, tests pass locally |
77+
| C | 99 | | criterion | | | systems-runner | | |
7878
| Clojure | 1.6.0 || clojure.test | clojure.test | clojure.test | func-runner | clojure.test | |
7979
| CoffeeScript | 1.10.0 || cw-2 | cw-2 | cw-2 | node-runner | cw-2 | |
8080
| C++ | 14 || igloo | | | systems-runner | | |
@@ -119,7 +119,7 @@ You should have [Docker](https://www.docker.com/) installed, if not do that firs
119119
environments you will need to build the proper Docker image. To get started lets work with the
120120
node image.
121121

122-
Run `make node` to build the base and node images. This will take a few minutes. You can speed up the process by first
122+
Run `make node` to build the base and node images. This will take a few minutes. You can speed up the process by first
123123
downloading the existing images that you intend to work on, which will allow you to only need to build when you make a change.
124124

125125
For example, if you intend to work on the jvm image, you would do this:
@@ -129,7 +129,7 @@ For example, if you intend to work on the jvm image, you would do this:
129129
docker pull codewars/base-runner
130130
docker pull codewars/jvm-runner
131131

132-
# now build the jvm image, so that any recent changes that have may not have been pushed yet get added into the image
132+
# now build the jvm image, so that any recent changes that have may not have been pushed yet get added into the image
133133
make jvm
134134
```
135135

@@ -161,8 +161,8 @@ to update these you should `make {image_you_want_to_update}` the image to ensure
161161
We mentioned before that you also have the option of using [Docker Compose](https://docs.docker.com/compose/) to run the CLI tool. We have setup the `docker-compose.yml`
162162
file to provide very useful pre-configured services for making development easier. Instead of having to issue the long command
163163
mentioned above, you can simply run `docker-compose run node-runner` to bash into a fresh container with your local volumes already mounted.
164-
165-
All of the docker compose services are setup to mount volumes to make development easier, so that is the recommended way of
164+
165+
All of the docker compose services are setup to mount volumes to make development easier, so that is the recommended way of
166166
interacting with the codebase. You should note though that the compose file is unable to build images due to how
167167
the directory structure is laid out, so you have to first `make {runner_name}` the image before you can run it. Otherwise
168168
it will pull down the latest copy from Docker Hub.
@@ -181,7 +181,7 @@ docker-compose run typescript_test
181181

182182
## Test Suite Output Format
183183

184-
A custom and very basic format is used for sending data out of the CLI tool. All formatted data is returned via STDOUT.
184+
A custom and very basic format is used for sending data out of the CLI tool. All formatted data is returned via STDOUT.
185185
If you do nothing but write normal strings to STDOUT, then codewars.com will display each line as you would expect, unformatted.
186186

187187
A small subset of commands is supported that can be used to format output. They are:
@@ -193,8 +193,8 @@ A small subset of commands is supported that can be used to format output. They
193193
- `<ERROR::>`
194194
- `<COMPLETEDIN::>`
195195

196-
Prefixing a new line with these commands will cause that line to be formatted.
197-
Since each new STDOUT line is considered a new piece of data, if you wish to format multiple lines as one
196+
Prefixing a new line with these commands will cause that line to be formatted.
197+
Since each new STDOUT line is considered a new piece of data, if you wish to format multiple lines as one
198198
item (such as a multi line "passed" message), then you must replace all \n line feed characters with the `<:LF:>` token.
199199

200200
For example, in Ruby, if you wanted to write a multi-line passed message:
@@ -207,8 +207,8 @@ end
207207

208208
### Nested Describes
209209

210-
Some test frameworks support nested levels of describes. In order for our output to support multiple levels,
211-
you must also use the `<COMPLETEDIN::>` token, which acts as a terminator for the current item. This should be used
210+
Some test frameworks support nested levels of describes. In order for our output to support multiple levels,
211+
you must also use the `<COMPLETEDIN::>` token, which acts as a terminator for the current item. This should be used
212212
to terminate both `<DESCRIBE::>` and `<IT::>` statements.
213213

214214
The following is a full example of what the output might look like, that supports nested describes:
@@ -218,7 +218,7 @@ The following is a full example of what the output might look like, that support
218218
<IT::>It should return a string
219219
<PASSED::>Test Passed
220220
<COMPLETEDIN::>23
221-
<IT::>It should return "foo"
221+
<IT::>It should return "foo"
222222
This is some direct output (i.e. console.log("..."))
223223
<FAILED::>Expected "foo" but instead got ""
224224
<COMPLETEDIN::>10
@@ -236,21 +236,21 @@ statement, the 2nd completes the nested DESCRIBE and the 3rd completes the top l
236236
#### <COMPLETEDIN::> Details
237237

238238
The value of COMPLETEDIN should be time spent executing the related statement, in milliseconds. It is not required
239-
to support time. `<COMPLETEDIN::>` is valid on its own, and in that case it is only used to terminate the current statement.
239+
to support time. `<COMPLETEDIN::>` is valid on its own, and in that case it is only used to terminate the current statement.
240240

241241
### Why the custom format?
242242

243-
Getting different test suites in different languages to all play together with the same format can be tricky. In many cases,
244-
customizing the test suite output is very limited (sometimes requiring hacking). Because of this, using formats such as
245-
XML and JSON are complicated because its not always possibly to correctly close out the data format when a program raises an exception.
243+
Getting different test suites in different languages to all play together with the same format can be tricky. In many cases,
244+
customizing the test suite output is very limited (sometimes requiring hacking). Because of this, using formats such as
245+
XML and JSON are complicated because its not always possibly to correctly close out the data format when a program raises an exception.
246246

247247
The format choosen was originally done so that at any point in time the program could exit while still having readable data.
248248
Other formats, such as TAP (Test Anything Protocol) could also be an option. However another requirement that we had when
249249
designing the format was to have it be incredibly simple yet flexible, so that Codewars.com could support more than simply
250250
outputing test results. With the current format there is nothing stopping you from outputing HTML, JS canvas code, etc in order
251251
to create a rich and even interactive test result output.
252-
253-
252+
253+
254254
## How to add a new language
255255

256256
> Note: These steps all assume you are adding a completely new language to the project. Many languages are currently in an incomplete
@@ -272,22 +272,22 @@ as a part of the test suite.
272272

273273
The runner script is responsible for outputing a `run` method. This method utilizes the shovel helper which will handle
274274
all of the inter-process communication for you. The shovel config accepts strategies to determine how to handle running
275-
the code based on the options passed in. There are currently two types of strategies.
275+
the code based on the options passed in. There are currently two types of strategies.
276276

277277
- `solutionOnly`: Code is simply executed and its STDOUT returned. There is no test integration.
278278
- `testIntegration`: Code is executed within a configurable test suite and the test output is returned via STDOUT.
279279

280280
Each of these strategies is passed in a `run` method which is used to ultimately execute the final command.
281-
281+
282282
## TODO
283283

284284
### Paradigm Shift
285285

286-
There is currently no way of handling language/package versioning well. This is largely caused by the Node CLI tool having to be
286+
There is currently no way of handling language/package versioning well. This is largely caused by the Node CLI tool having to be
287287
baked in to the Docker container. A more ideal solution would involve keeping the CLI outside of Docker (or within its own sibling container)
288288
and communicating to language specific containers. This would allow us to easily swap out container versions that have no
289289
dependencies on the CLI codebase. This would involve having to utilize the `docker cp` command to copy
290-
files to the docker container in order to be compiled. Upgrading to this newer paradigm is the next big phase of this project.
290+
files to the docker container in order to be compiled. Upgrading to this newer paradigm is the next big phase of this project.
291291

292292
### Ability to send input parameters and return data
293293

docker/systems.docker

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ USER codewarrior
5454
ENV USER codewarrior
5555
ENV HOME /home/codewarrior
5656
#RUN mocha -t 5000 test/runners/{gas,arm,nasm,cpp,c}_spec.js
57-
RUN mocha -t 5000 test/runners/cpp_spec.js
57+
RUN mocha -t 5000 test/runners/{cpp,c}_spec.js
5858

5959
#timeout is a fallback in case an error with node
6060
#prevents it from exiting properly

frameworks/c/criterion.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <stdio.h>
2+
#include <string.h>
23
#include <criterion/criterion.h>
34
#include <criterion/hooks.h>
45

@@ -23,17 +24,29 @@ ReportHook(ASSERT)(struct criterion_assert_stats *stats) {
2324
if (stats->passed) {
2425
puts("<PASSED::>Test Passed");
2526
} else {
26-
printf("<FAILED::>%s\n",stats->message);
27+
printf("<FAILED::>");
28+
// print the assertion message, replacing \n with <:LF:>
29+
for (const char* p = stats->message; *p != '\0'; ++p) {
30+
if (*p == '\n') {
31+
printf("<:LF:>");
32+
} else {
33+
fputc(*p,stdout);
34+
}
35+
}
36+
fputc('\n',stdout);
2737
}
2838
}
2939

3040
// when a test crashes unexpectedly
3141
ReportHook(TEST_CRASH)(struct criterion_test_stats *stats) {
32-
puts("<FAILED::>Test crashes");
42+
puts("<FAILED::>Test Crashed");
3343
}
3444

3545
// after a test ends
3646
ReportHook(POST_TEST)(struct criterion_test_stats *stats) {
47+
if (stats->timed_out) {
48+
puts("<FAILED::>Test Timedout");
49+
}
3750
printf("<COMPLETEDIN::>%f\n",stats->elapsed_time*1000);
3851
}
3952

test/runners/c_spec.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,56 @@ describe('.run', function() {
164164
done();
165165
});
166166
});
167+
it('should handle a crash', function(done) {
168+
runner.run({
169+
language: 'c',
170+
code: ' ',
171+
fixture: `
172+
#include <criterion/criterion.h>
173+
174+
Test(misc, crash_dereference) {
175+
int *i = NULL;
176+
*i = 42; // CRASH: dereference i on writing
177+
}
178+
`
179+
}, function(buffer) {
180+
expect(buffer.stdout).to.contain('<FAILED::>Test Crashed');
181+
done();
182+
});
183+
});
184+
it('should handle a timeout', function(done) {
185+
runner.run({
186+
language: 'c',
187+
code: ' ',
188+
fixture: `
189+
# include <unistd.h>
190+
#include <criterion/criterion.h>
191+
192+
Test(timeout, should_fail_with_a_timeout, .timeout = 1.) {
193+
sleep(10);
194+
}
195+
`
196+
}, function(buffer) {
197+
expect(buffer.stdout).to.contain('<FAILED::>Test Timedout');
198+
done();
199+
});
200+
});
201+
it('should replace message line feeds', function(done) {
202+
runner.run({
203+
language: 'c',
204+
code: ' ',
205+
fixture: `
206+
#include <criterion/criterion.h>
207+
208+
Test(timeout, simple) {
209+
cr_assert(0, "This message contains \\n 2 \\n line feeds");
210+
}
211+
`
212+
}, function(buffer) {
213+
expect(buffer.stdout.match(/<:LF:>/g).length).to.equal(2);
214+
done();
215+
});
216+
});
167217
});
168218
});
169219
});

0 commit comments

Comments
 (0)