forked from codewars/codewars-runner-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start of enhancements to Rust language support, issue codewars#128
- Fixed up dockerfile - Change runner to use cargo - Setup basic tests and mappings
- Loading branch information
Showing
5 changed files
with
248 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
FROM codewars/base-runner | ||
|
||
# Install Rust Compiler | ||
RUN curl -sSf https://static.rust-lang.org/rustup.sh | sh | ||
|
||
# Setup env | ||
ENV USER codewarrior | ||
ENV HOME /home/codewarrior | ||
|
||
# Copy package json to tmp | ||
ADD package.json /tmp/package.json | ||
|
||
# Do npm install in tmp and setup cargo dir | ||
RUN \ | ||
cd /tmp && npm install --production && \ | ||
mkdir -p /runner && cp -a /tmp/node_modules /runner | ||
|
||
# ADD cli-runner | ||
ADD . /runner | ||
|
||
# Working dir is /runner | ||
WORKDIR /runner | ||
|
||
# Codewarrior... | ||
USER codewarrior | ||
|
||
RUN mocha -t 10000 test/runners/rust_spec.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,98 @@ | ||
var shovel = require('../shovel'), | ||
util = require('../util'), | ||
path = require('path'), | ||
temp = require('temp'), | ||
exec = require('child_process').exec; | ||
|
||
function compile(args, cb) { | ||
args.unshift('rustc'); | ||
exec(args.join(' '), cb); | ||
} | ||
'use strict' | ||
|
||
const shovel = require('../shovel'); | ||
const util = require('../util'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const exec = require('child_process').exec; | ||
// const temp = require('temp'); | ||
const temp = require('temp').track(); | ||
|
||
const dir = temp.mkdirSync('rust'); | ||
|
||
module.exports.run = function run(opts, cb) { | ||
temp.track(); | ||
var dir = temp.mkdirSync('rust'); | ||
|
||
shovel.start(opts, cb, { | ||
solutionOnly: function (run) { | ||
var executable = path.join(dir, 'solution'), | ||
solutionFile = util.codeWriteSync('rust', opts.solution, dir, 'solution.rs'), | ||
args = [solutionFile, '-o', executable]; | ||
compile(args, function (error, stdout, stderr) { | ||
if (stdout) console.log(stdout); | ||
if (stderr) throw new Error(stderr); | ||
if (error !== null) throw error; | ||
run({'name': executable, 'args': []}); | ||
}); | ||
}, | ||
testIntegration: function (run) { | ||
throw new Error('Test framework is not supported'); | ||
} | ||
}); | ||
}; | ||
shovel.start(opts, cb, { | ||
solutionOnly: function(run) { | ||
_init(err => { | ||
let file = _createSolution(opts); | ||
|
||
// Run | ||
run({ | ||
name: 'cargo', | ||
args: ['run'], | ||
options: { | ||
cwd: dir | ||
} | ||
}); | ||
}); | ||
}, | ||
testIntegration: function(run) { | ||
// test is the only one supported right now... | ||
if (opts.testFramework != 'cargo') | ||
throw 'Test framework is not supported'; | ||
_init(err => { | ||
let file = _createSpec(opts); | ||
|
||
// Run | ||
run({ | ||
name: 'cargo', | ||
args: ['test'], | ||
options: { | ||
cwd: dir | ||
} | ||
}); | ||
}); | ||
|
||
}, | ||
sanitizeStdOut: function(stdout) { | ||
if (opts.fixture) return _format(stdout) | ||
else return stdout; | ||
} | ||
}); | ||
}; | ||
|
||
// Create the solution file | ||
const _createSolution = function(opts) { | ||
// Set the code | ||
let code = ` | ||
${opts.setup ? opts.setup : ''} | ||
${opts.code} | ||
`; | ||
|
||
return util.codeWriteSync('rust', code, `${dir}/src`,'main.rs', true); | ||
} | ||
|
||
// Create the spec | ||
const _createSpec = function(opts) { | ||
let code = ` | ||
${opts.setup ? opts.setup : ''} | ||
${opts.code} | ||
${opts.fixture} | ||
`; | ||
|
||
return util.codeWriteSync('rust', code, `${dir}/src`,'main.rs', true); | ||
} | ||
|
||
// Initalizes the Rust dir via cargo | ||
const _init = function(cb) { | ||
exec(`cargo init --bin`,{cwd: dir},cb); | ||
} | ||
|
||
const _format = function(stdout) { | ||
let output = ''; | ||
let tests = stdout.split(/\n/gm).filter(v => !v.search(/^test.*(?:ok|FAILED)$/)); | ||
|
||
for(let test of tests) output += _parseTest(test); | ||
|
||
return output; | ||
} | ||
|
||
const _parseTest = function(test) { | ||
let result = test.split(' '); | ||
let out = `<DESCRIBE::>${result[1]}\n`; | ||
out += result[3] != 'FAILED' ? `<PASSED::>Test Passed\n` : `<FAILED::>Test Failed\n`; | ||
return out; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
const expect = require('chai').expect; | ||
const runner = require('../runner'); | ||
|
||
describe('rust runner', function() { | ||
describe('.run', function() { | ||
// Basic code run | ||
it('should handle basic code evaluation', function(done) { | ||
runner.run({ | ||
language: 'rust', | ||
code: ` | ||
fn main() { | ||
println!("Bam"); | ||
} | ||
` | ||
}, function(buffer) { | ||
expect(buffer.stdout).to.equal('Bam\n'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should handle invalid code', function(done) { | ||
runner.run({ | ||
language: 'rust', | ||
code: ` | ||
fn main() { | ||
println!("Bam); | ||
} | ||
` | ||
}, function(buffer) { | ||
expect(buffer.stderr).to.contain('unterminated double quote'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should allow mods inside setup', function(done) { | ||
runner.run({ | ||
language: 'rust', | ||
setup: ` | ||
use std::thread; | ||
use std::sync::mpsc::channel; | ||
`, | ||
code: ` | ||
fn main() { | ||
let (tx, rx) = channel(); | ||
thread::spawn(move|| { | ||
tx.send(10).unwrap(); | ||
}); | ||
println!("{}", rx.recv().unwrap()); | ||
} | ||
` | ||
}, function(buffer) { | ||
expect(buffer.stdout).to.contain(`10`); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should handle basic tests', function(done) { | ||
runner.run({ | ||
language: 'rust', | ||
code: ` | ||
fn test_function() -> i32 { | ||
return 69; | ||
} | ||
`, | ||
fixture: ` | ||
#[test] | ||
fn returns_number() { | ||
assert_eq!(test_function(),69); | ||
} | ||
`, | ||
testFramework: 'cargo' | ||
}, function(buffer) { | ||
expect(buffer.stdout).to.contain(`<DESCRIBE::>returns_number`); | ||
expect(buffer.stdout).to.contain(`<PASSED::>Test Passed`); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should handle tests with setup', function(done) { | ||
runner.run({ | ||
language: 'rust', | ||
setup: ` | ||
use std::thread; | ||
use std::sync::mpsc::channel; | ||
`, | ||
code: ` | ||
fn async_thingo() { | ||
let (tx, rx) = channel(); | ||
thread::spawn(move|| { | ||
tx.send(10).unwrap(); | ||
}); | ||
} | ||
fn doubler(n: i32) -> i32 { | ||
return n * 2; | ||
} | ||
`, | ||
fixture: ` | ||
#[test] | ||
fn doubler_works() { | ||
assert_eq!(doubler(2),4); | ||
} | ||
`, | ||
testFramework: 'cargo' | ||
}, function(buffer) { | ||
expect(buffer.stdout).to.contain(`<DESCRIBE::>doubler_works`); | ||
expect(buffer.stdout).to.contain(`<PASSED::>Test Passed`); | ||
done(); | ||
}); | ||
}); | ||
|
||
}); | ||
}); |