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:
@ -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(
|
||||
|
@ -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 })
|
||||
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user