From 26712c4e1c21eda4806befd11c637a0415a6f5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=A9=E6=95=A3=E6=80=A7=E7=99=BE=E4=B8=87=E7=94=9C?= =?UTF-8?q?=E9=9D=A2=E5=8C=85?= Date: Sun, 21 Apr 2019 02:17:57 +0800 Subject: [PATCH] feat: add check park on `Judge` (#116) Signed-off-by: himself65 --- packages/rrreol-core/src/index.js | 2 - packages/rrreol-core/src/judge.js | 58 ++++++++++++++++--- packages/rrreol-core/src/judgeWrapper.js | 31 ---------- packages/rrreol-core/test/unit/index.test.js | 10 ++++ packages/rrreol-core/test/unit/judge.test.js | 35 +++++++++++ .../test/unit/judgeWrapper.test.js | 16 ----- 6 files changed, 94 insertions(+), 58 deletions(-) delete mode 100644 packages/rrreol-core/src/judgeWrapper.js create mode 100644 packages/rrreol-core/test/unit/index.test.js delete mode 100644 packages/rrreol-core/test/unit/judgeWrapper.test.js diff --git a/packages/rrreol-core/src/index.js b/packages/rrreol-core/src/index.js index 7e973ba..f3213d9 100644 --- a/packages/rrreol-core/src/index.js +++ b/packages/rrreol-core/src/index.js @@ -1,14 +1,12 @@ import { Compiler } from './compiler' import { FileManager } from './fileManager' import { Judge } from './judge' -import { JudgeWrapper } from './judgeWrapper' import { Runner } from './runner' export { Compiler, FileManager, Judge, - JudgeWrapper, Runner } diff --git a/packages/rrreol-core/src/judge.js b/packages/rrreol-core/src/judge.js index 6c9b72a..22cedf9 100644 --- a/packages/rrreol-core/src/judge.js +++ b/packages/rrreol-core/src/judge.js @@ -1,12 +1,9 @@ import { existsSync } from 'fs' import chalk from 'chalk' -import { dirname, resolve, basename } from 'path' -import isNumber from 'is-number' import { isString, isNil } from 'lodash' import { curry, equals, propEq, findIndex } from 'ramda' import { EventEmitter } from 'events' import { FileManager } from './fileManager' -import { JudgeWrapper } from './judgeWrapper' import { Runner } from './runner' import { Compiler } from './compiler' import { renameSuffix } from './utils' @@ -17,7 +14,8 @@ export class Judge extends EventEmitter { const { input = [], output = [], - file = isString(props) ? props : null + file = isString(props) ? props : null, + ignoreEndEnter = true } = props this.__outputs = output.map((val) => { @@ -27,13 +25,21 @@ export class Judge extends EventEmitter { return new FileManager(val) }) this.__answer = [] + this.__config = Object.assign({ + ignoreEndEnter: true // if ignore the `\n` at the line end + }, { + ignoreEndEnter + }) + + this.__task = [] this.__path = file || null this.__target = 0 this.on('start', this.exec) - this.on('finished', () => { + this.on('finish_compile', () => { // todo + console.log(chalk.greenBright('finished')) }) } @@ -83,9 +89,10 @@ export class Judge extends EventEmitter { if (isNil(this.__outputs[this.__target])) { console.log(chalk.red('error') + 'target file is empty') } else if (isString(val)) { + // todo findIndex(propEq('name', val))(this.__outputs) } - this.__target = val + this.__target = val - 1 return this } @@ -105,15 +112,48 @@ export class Judge extends EventEmitter { const path = await Compiler.compile(this.__path, outputPath) console.log(`${chalk.yellowBright('Compiled')} file`) const runner = new Runner(path) + + let index = 0 for await (const input of this.__inputs) { const res = await runner.execUnsafe(input) - const fm = FileManager.of().loadContent(res) - this.__answer.push(fm) - this.emit('finished', fm) + const fileManager = FileManager.of().loadContent(res) + this.__answer.push(fileManager) + // check output + const success = this.compareFileManager(fileManager, this.out(index + 1)) + if (!success) { + console.log(`${chalk.red('error on file')} ${index + 1}`) + } + + ++index } return this } + compareFileManager = (realFM, expectedFM) => { + if (!(realFM instanceof FileManager) || + !(expectedFM instanceof FileManager)) { + throw new TypeError() + } + let success = true + Object.keys(Array(realFM.lines()).fill(null)).forEach((_, line) => { + console.log(`judging line ${line + 1}`) + const realLine = realFM.line(++line) + const expectedLine = expectedFM.line(line) + const same = equals(realLine, expectedLine) + if (!same) { + success = false + // todo: support log column + console.log(`${chalk.red('wrong answer:')} On line ${line}, read ${realLine} expected ${expectedLine}`) + } + }) + if (success) { + console.log(`${chalk.greenBright('success')} compare`) + } else { + console.log(`${chalk.yellowBright('finished')} compare`) + } + return success + } + run = () => this.emit('start') } diff --git a/packages/rrreol-core/src/judgeWrapper.js b/packages/rrreol-core/src/judgeWrapper.js deleted file mode 100644 index f193f36..0000000 --- a/packages/rrreol-core/src/judgeWrapper.js +++ /dev/null @@ -1,31 +0,0 @@ -import chalk from 'chalk' -import { isFunction } from 'lodash' -import { equals, isNil } from 'ramda' - -export class JudgeWrapper { - static of (val) { - // called by `call()` or `apply()` - return new JudgeWrapper(val, this) - } - - constructor (val, target) { - if (isNil(val)) { - throw TypeError('val is null') - } - this.__target = target || null - this.__val = val - } - - toBe = (val) => { - if ('on' in this.__target) { - this.__target.on('finished', (answer) => { - - }) - } else { - throw new Error('no property \'on\'') - } - return this.__target - } -} - -export default JudgeWrapper diff --git a/packages/rrreol-core/test/unit/index.test.js b/packages/rrreol-core/test/unit/index.test.js new file mode 100644 index 0000000..a62f27e --- /dev/null +++ b/packages/rrreol-core/test/unit/index.test.js @@ -0,0 +1,10 @@ +import * as rrreol from '@/' + +describe('index test', () => { + it('should have content', () => { + expect(rrreol.Compiler).toBeDefined() + expect(rrreol.FileManager).toBeDefined() + expect(rrreol.Judge).toBeDefined() + expect(rrreol.Runner).toBeDefined() + }) +}) diff --git a/packages/rrreol-core/test/unit/judge.test.js b/packages/rrreol-core/test/unit/judge.test.js index 95879aa..16da804 100644 --- a/packages/rrreol-core/test/unit/judge.test.js +++ b/packages/rrreol-core/test/unit/judge.test.js @@ -10,6 +10,10 @@ describe('Judge base test', () => { judge = new Judge() }) + it('should have correct props', () => { + expect(judge.__config.ignoreEndEnter).toBe(true) + }) + it('should throw error when invoke get method', () => { expect(() => { judge.targetFile = 1 @@ -64,7 +68,38 @@ describe('Judge check test', () => { expect(judge.answer(1).content).toEqual('1 2') }) + it('should emit check running success', () => { + const fm1 = FileManager.of().loadContent('1\n2\n') + const fm2 = FileManager.of().loadContent('1\n2\n') + judge.rawListeners('check') + .map(f => f(fm1, fm2)) + .every(v => expect(v).toBeTruthy()) + }) + afterAll(() => { removeFiles(fixturesPath, /\.test\.out$/) }) }) + +describe('Judge check park', () => { + let judge = null + beforeEach(() => { + judge = new Judge() + }) + + it('should compare success', () => { + const success = judge.compareFileManager( + FileManager.of().loadContent('1'), + FileManager.of().loadContent('1') + ) + expect(success).toBe(true) + }) + + it('should compare fail', () => { + const fail = judge.compareFileManager( + FileManager.of().loadContent('1'), + FileManager.of().loadContent('2') + ) + expect(fail).toBe(false) + }) +}) diff --git a/packages/rrreol-core/test/unit/judgeWrapper.test.js b/packages/rrreol-core/test/unit/judgeWrapper.test.js deleted file mode 100644 index 025b26c..0000000 --- a/packages/rrreol-core/test/unit/judgeWrapper.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import Judge from '@/judge' -import JudgeWrapper from '@/judgeWrapper' - -describe('JudgeWrapper base test', () => { - it('should init success', () => { - const judgeWrapper = new JudgeWrapper(1) - expect(judgeWrapper).toBeDefined() - }) - - it('should expect success', () => { - const target = new Judge() - const judgeWrapper = new JudgeWrapper(1, target) - expect(judgeWrapper.toBe('1')).toBe(target) - expect(judgeWrapper.toBe(1)).toBe(target) - }) -})