Skip to content
This repository has been archived by the owner on Sep 17, 2020. It is now read-only.

Commit

Permalink
feat(test-framework): add infinite loop protection (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
no-stack-dub-sack committed Feb 7, 2018
1 parent 3db76f2 commit b7cff4c
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 5 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
"private": true,
"dependencies": {
"axios": "^0.17.1",
"babel-standalone": "^6.26.0",
"codemirror": "^5.31.0",
"jshint": "^2.9.5",
"lodash": "^4.17.4",
"loop-protect": "^2.1.6",
"react": "16.2.0",
"react-codemirror2": "^3.0.7",
"react-dom": "^16.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/utils/regexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
export const RESET_STATE = new RegExp('resetState\\(\\)')
export const SUPPRESS_TESTS = new RegExp('\\/\\/\\s\\s?SUPPRESS\\s\\s?TESTS', 'i')
export const DO_NOT_SAVE = new RegExp('\\/\\/\\s\\s?DO\\s\\s?NOT\\s\\s?SAVE', 'i')
export const ERROR_TYPES = new RegExp('tests failed|WARNING:|Fail:|AssertionError|InternalError|RangeError|ReferenceError|EvalError|SyntaxError|TypeError|URIError')
export const ERROR_TYPES = new RegExp('tests failed|WARNING:|Fail:|AssertionError|InternalError|RangeError|ReferenceError|EvalError|SyntaxError|TypeError|URIError|Error')
7 changes: 3 additions & 4 deletions src/utils/test/challenge/eval-code-run-tests.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import executeTests from './execute-tests'
import { SUPPRESS_TESTS } from '../../regexp'
import TESTS from '../../../assets/testRef'

// TODO: remove check for tests once all challenges have tests
import loopProtect from './loop-protect'

export default (code, id) => {
try {
Expand All @@ -21,10 +20,10 @@ export default (code, id) => {
tests = prepend + JSON.stringify(TESTS[id].tests)
if (TESTS[id].tail) tail += TESTS[id].tail
}

// eslint-disable-next-line
eval(
code +
loopProtect(code) +
tail +
tests +
executeTests
Expand Down
19 changes: 19 additions & 0 deletions src/utils/test/challenge/loop-protect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export default (code) => {
const timeout = 500
const Babel = require('babel-standalone')
const protect = require('loop-protect')

Babel.registerPlugin('loopProtection', protect(timeout))
const transform = source => Babel.transform(source, {
plugins: ['loopProtection'],
}).code

const error = `Error('Timed out after ${timeout}ms due to an infinite loop. Check your code and try again.')`
const _this = new RegExp(`if \\(Date\\.now\\(\\) - _LP > ${timeout}\\)\\s+break;`)
const withThis = `if (Date.now() - _LP > ${timeout}) throw new ${error}`

// use babel and loop-protect to transform user code
// into protected loops. Instead of simply breaking the
// loop, add replacement logic to throw error to warn user
return transform(code).replace(_this, withThis)
}
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,10 @@ babel-runtime@6.26.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtim
core-js "^2.4.0"
regenerator-runtime "^0.11.0"

babel-standalone@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886"

babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
Expand Down Expand Up @@ -4032,6 +4036,10 @@ longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"

loop-protect@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/loop-protect/-/loop-protect-2.1.6.tgz#03840f79591121c37a53a87fb9aff2841e488c2d"

loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
Expand Down

0 comments on commit b7cff4c

Please sign in to comment.