-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
runTestCase c, c++, java, js, rust, python 지원 맥북테스트 완료
- Loading branch information
1 parent
c307bfc
commit 7f03a77
Showing
7 changed files
with
222 additions
and
6 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,5 @@ dist | |
node_modules | ||
.vscode-test/ | ||
*.vsix | ||
.DS_Store | ||
*/.DS_Store |
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,168 @@ | ||
import * as vscode from "vscode"; | ||
import { searchProblem } from "../libs/searchProblem"; | ||
import { getProbNum } from "../libs/getProbNum"; | ||
import { spawn, execSync } from "child_process"; | ||
import * as path from "path"; | ||
import * as fs from "fs"; | ||
|
||
export async function runTestCase(context: vscode.ExtensionContext) { | ||
const outputChannel = vscode.window.createOutputChannel("Test Cases"); | ||
try { | ||
const problemNumber = getProbNum(); | ||
|
||
if (!problemNumber) { | ||
vscode.window.showErrorMessage("Problem number not found."); | ||
return; | ||
} | ||
|
||
const sp = await searchProblem(problemNumber, context); | ||
|
||
if (!sp.sampleInputs || !sp.sampleOutputs) { | ||
vscode.window.showErrorMessage( | ||
"Sample inputs or outputs not found." | ||
); | ||
return; | ||
} | ||
|
||
const editor = vscode.window.activeTextEditor; | ||
if (!editor) { | ||
vscode.window.showErrorMessage("No editor found."); | ||
return; | ||
} | ||
|
||
const filePath = editor.document.uri.fsPath; | ||
|
||
const config = vscode.workspace.getConfiguration("BOJ"); | ||
const extension = config.get<string>("extension", ""); | ||
|
||
const maxWidth = 40; | ||
|
||
const preMessage1 = centerText( | ||
` ${problemNumber}. ${sp.title} `, | ||
maxWidth | ||
); | ||
const preMessage2 = `문제링크: https://boj.kr/${problemNumber}`; | ||
|
||
outputChannel.appendLine(preMessage1); | ||
outputChannel.appendLine(preMessage2); | ||
outputChannel.appendLine(``); | ||
|
||
const createOutputMessage = ( | ||
testCaseIndex, | ||
result, | ||
expected, | ||
actual | ||
) => { | ||
const passedMessage = `✅ Test Case #${testCaseIndex + 1}: Passed`; | ||
const failedMessage = `❌ Test Case #${ | ||
testCaseIndex + 1 | ||
}: Failed\n${centerText( | ||
` Expected `, | ||
maxWidth | ||
)}\n${expected}${centerText(` Actual `, maxWidth)}\n${actual}`; | ||
|
||
return result ? passedMessage : failedMessage; | ||
}; | ||
|
||
const runTest = (input, expectedOutput, testCaseIndex) => { | ||
return new Promise<void>((resolve, reject) => { | ||
const processIO = getProcessIO(extension, filePath); | ||
let outputData = ""; | ||
|
||
processIO!.stdout.on("data", (data) => { | ||
outputData += data.toString(); | ||
}); | ||
|
||
processIO!.stderr.on("data", (data) => { | ||
console.error(`에러: ${data}`); | ||
reject(new Error(data.toString())); | ||
}); | ||
|
||
processIO!.on("close", (code) => { | ||
const actualOutput = outputData.trim(); | ||
const isPassed = actualOutput === expectedOutput.trim(); | ||
const message = createOutputMessage( | ||
testCaseIndex, | ||
isPassed, | ||
expectedOutput, | ||
actualOutput | ||
); | ||
outputChannel.appendLine(message); | ||
|
||
resolve(); | ||
}); | ||
|
||
processIO!.on("error", (err) => { | ||
console.error(`에러: ${err}`); | ||
reject(err); | ||
}); | ||
|
||
processIO!.stdin.write(input); | ||
processIO!.stdin.end(); | ||
}); | ||
}; | ||
|
||
for (let i = 0; i < sp.sampleInputs.length; i++) { | ||
await runTest(sp.sampleInputs[i], sp.sampleOutputs[i], i); | ||
} | ||
|
||
const postMessage1 = centerText(` 채점 종료 `, maxWidth); | ||
const postMessage2 = `결과 창은 1분 뒤에 닫힙니다.`; | ||
|
||
outputChannel.appendLine(``); | ||
outputChannel.appendLine(postMessage1); | ||
outputChannel.appendLine(postMessage2); | ||
|
||
outputChannel.show(true); | ||
setTimeout(() => { | ||
outputChannel.dispose(); | ||
}, 60000); | ||
} catch (error) { | ||
vscode.window.showErrorMessage( | ||
"테스트 케이스 실행 중 오류가 발생했습니다. 직접 실행해서 오류를 확인해주세요." | ||
); | ||
} | ||
} | ||
|
||
function centerText(text, maxWidth) { | ||
const padding = Math.max(0, maxWidth - text.length); | ||
const paddingLeft = Math.floor(padding / 2); | ||
const paddingRight = padding - paddingLeft; | ||
return "-".repeat(paddingLeft) + text + "-".repeat(paddingRight); | ||
} | ||
|
||
function getProcessIO(extension: string, filePath: string) { | ||
if (extension === "c") { | ||
const objectFileURL = filePath.replace(/\.[^/.]+$/, ""); | ||
execSync(`gcc "${filePath}" -o "${objectFileURL}"`); | ||
return spawn(`${objectFileURL}`); | ||
} else if (extension === "cpp") { | ||
const objectFileURL = filePath.slice(0, filePath.length - 4); | ||
execSync(`g++ -std=c++17 "${filePath}" -o "${objectFileURL}"`); | ||
return spawn(`${objectFileURL}`); | ||
} else if (extension === "java") { | ||
const dirName = path.dirname(filePath); | ||
return spawn(`java`, ["-cp", dirName, filePath]); | ||
} else if (extension === "js") { | ||
return spawn("node", [filePath]); | ||
} else if (extension === "rs") { | ||
const fileName = path.basename(filePath, ".rs"); | ||
const crateName = fileName.replace(/[^a-zA-Z0-9]+/g, "_").toLowerCase(); | ||
const objectFileURL = path.join(".", `${crateName}.out`); | ||
const dirName = path.dirname(filePath); | ||
const options = { | ||
cwd: path.dirname(filePath), | ||
env: { | ||
...process.env, | ||
RUSTC_FLAGS: "-D tempdir=/tmp", | ||
}, | ||
}; | ||
execSync( | ||
`rustc --crate-name "${crateName}" "${filePath}" -o "${objectFileURL}"`, | ||
options | ||
); | ||
return spawn(`${dirName}/${objectFileURL}`); | ||
} else if (extension === "py") { | ||
return spawn("python3", [filePath]); | ||
} | ||
} |
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,21 @@ | ||
import * as vscode from "vscode"; | ||
import * as path from "path"; | ||
|
||
export function getProbNum(): string | null { | ||
const editor = vscode.window.activeTextEditor; | ||
if (!editor) { | ||
vscode.window.showErrorMessage("No editor found."); | ||
return null; | ||
} | ||
|
||
const filePath = editor.document.uri.fsPath; | ||
const dirName = path.basename(path.dirname(filePath)); | ||
|
||
const match = dirName.match(/^(\d+)/); | ||
if (match) { | ||
return match[1]; | ||
} else { | ||
vscode.window.showErrorMessage("Problem number not found."); | ||
return null; | ||
} | ||
} |
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