1
1
mirror of https://github.com/theoludwig/programming-challenges.git synced 2025-05-18 12:02:53 +02:00

feat(cli): add commands/run/solution

This commit is contained in:
Divlo
2022-08-30 15:48:07 +02:00
parent 6427b3d273
commit d6a6c706ce
8 changed files with 272 additions and 13 deletions

View File

@ -1,7 +1,14 @@
import { performance } from 'node:perf_hooks'
import { execaCommand } from 'execa'
import ora from 'ora'
import ms from 'ms'
export interface DockerRunResult {
stdout: string
elapsedTimeMilliseconds: number
}
export class Docker {
static CONTAINER_TAG = 'programming-challenges'
static SIGSEGV_EXIT_CODE = 139
@ -19,7 +26,7 @@ export class Docker {
}
}
public async run(input: string): Promise<string> {
public async run(input: string): Promise<DockerRunResult> {
const subprocess = execaCommand(
`docker run --interactive --rm ${Docker.CONTAINER_TAG}`,
{
@ -32,12 +39,17 @@ export class Docker {
isValid = false
}, Docker.MAXIMUM_TIMEOUT_MILLISECONDS)
try {
const start = performance.now()
const { stdout, stderr } = await subprocess
const end = performance.now()
if (stderr.length !== 0) {
throw new Error(stderr)
}
clearTimeout(timeout)
return stdout
return {
stdout,
elapsedTimeMilliseconds: end - start
}
} catch (error: any) {
if (!isValid) {
throw new Error(

View File

@ -2,6 +2,9 @@ import { fileURLToPath } from 'node:url'
import path from 'node:path'
import fs from 'node:fs'
import chalk from 'chalk'
import ora from 'ora'
import {
createTemporaryEmptyFolder,
TEMPORARY_PATH
@ -64,6 +67,24 @@ export class Solution implements SolutionOptions {
await Test.runAll(this)
}
public async run(input: string, output: boolean = false): Promise<void> {
await this.prepareTemporaryFolder()
await docker.build()
const loader = ora('Running...').start()
try {
const { stdout, elapsedTimeMilliseconds } = await docker.run(input)
loader.succeed(chalk.bold.green('Success!'))
Test.printBenchmark(elapsedTimeMilliseconds)
if (output) {
console.log(`${chalk.bold('Output:')}`)
console.log(stdout)
}
} catch (error) {
loader.fail()
throw error
}
}
static async generate(options: GenerateSolutionOptions): Promise<Solution> {
const { name, challengeName, programmingLanguageName, githubUser } = options
const challenge = new Challenge({ name: challengeName })

View File

@ -1,6 +1,5 @@
import fs from 'node:fs'
import path from 'node:path'
import { performance } from 'node:perf_hooks'
import ora from 'ora'
import chalk from 'chalk'
@ -84,17 +83,21 @@ export class Test implements TestOptions {
console.log()
console.log(table(tableResult))
}
const elapsedTime = totalElapsedTimeMilliseconds / 1000
const testsResult = isSuccess
? chalk.bold.green(`${totalCorrectTests} passed`)
: chalk.bold.red(`${totalFailedTests} failed`)
console.log(`${chalk.bold('Tests:')} ${testsResult}, ${tests.length} total`)
console.log(`${chalk.bold('Benchmark:')} ${elapsedTime} seconds`)
Test.printBenchmark(totalElapsedTimeMilliseconds)
if (!isSuccess) {
throw new Error('Tests failed, try again!')
}
}
static printBenchmark(elapsedTimeMilliseconds: number): void {
const elapsedTime = elapsedTimeMilliseconds / 1000
console.log(`${chalk.bold('Benchmark:')} ${elapsedTime} seconds`)
}
static async runAll(solution: Solution): Promise<void> {
const name = `${solution.challenge.name}/${solution.programmingLanguageName}/${solution.name}`
const testsPath = path.join(solution.challenge.path, 'test')
@ -154,9 +157,7 @@ export class Test implements TestOptions {
static async run(options: TestRunOptions): Promise<Test> {
const { input, output } = await Test.getInputOutput(options.path)
const start = performance.now()
const stdout = await docker.run(input)
const end = performance.now()
const { stdout, elapsedTimeMilliseconds } = await docker.run(input)
const test = new Test({
path: options.path,
index: options.index,
@ -164,7 +165,7 @@ export class Test implements TestOptions {
output,
stdout,
isSuccess: stdout === output,
elapsedTimeMilliseconds: end - start
elapsedTimeMilliseconds
})
return test
}