Skip to content

Commit

Permalink
feat(lang): support java and golang (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 authored Dec 2, 2024
1 parent bb19118 commit 45b085a
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changes/lang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eval-stack": patch:feat
---

Support for Java and Golang.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"covector",
"fmax",
"getuid",
"javac",
"libc",
"NEWNS",
"prctl",
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "Online Judge core runtime for ACMers",
"main": "index.js",
"scripts": {
"covector": "covector"
"covector": "covector",
"test": "cargo test"
},
"keywords": [
"oj",
Expand Down
3 changes: 3 additions & 0 deletions src/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ where
let exec_path = match &language {
Language::Python => which("python")?,
Language::NodeJs => which("deno")?,
Language::Java => which("java")?,
_ => workspace.join("out"),
};

Expand Down Expand Up @@ -65,9 +66,11 @@ where
"--deny-ffi=*",
source_file_path.as_str(),
];
let java_args = vec!["Main"];
let args = match language {
Language::Python => Some(&py_args),
Language::NodeJs => Some(&deno_args),
Language::Java => Some(&java_args),
_ => None,
}
.map(|v| &**v);
Expand Down
36 changes: 30 additions & 6 deletions src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,30 @@ use std::{
};

use anyhow::Result;
use tokio::process::Command;
use tokio::{fs::File, io, process::Command};

#[derive(Clone, Copy)]
#[derive(Default, Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum Language {
#[default]
Rust,
C,
CPP,
Rust,
Python,
NodeJs,
Golang,
Java,
}

pub async fn compile<B: Into<PathBuf>, E: AsRef<str>, O: AsRef<str>>(
pub async fn compile<B: Into<PathBuf>, S: Into<PathBuf>, O: AsRef<str>>(
language: Language,
base: B,
source_file: E,
source_file_path: S,
output_file: O,
) -> Result<()> {
let base_path = Into::<PathBuf>::into(base);
let source_path = base_path.join(source_file.as_ref());
let source_path = Into::<PathBuf>::into(source_file_path);
let source_path_str = source_path.to_string_lossy();
let output_path = base_path.join(output_file.as_ref());
let output_path_str = output_path.to_string_lossy();
Expand Down Expand Up @@ -84,6 +87,27 @@ pub async fn compile<B: Into<PathBuf>, E: AsRef<str>, O: AsRef<str>>(
Some(command)
}
Language::NodeJs => None,
Language::Golang => {
let mut command = Command::new("go");
command.args([
"build",
"-o",
output_path_str.as_ref(),
source_path_str.as_ref(),
]);
Some(command)
}
Language::Java => {
let java_path = base_path.join("Main.java");
let mut command = Command::new("javac");
io::copy(
&mut File::open(source_path_str.as_ref()).await?,
&mut File::create(&java_path).await?,
)
.await?;
command.arg(java_path.to_string_lossy().as_ref());
Some(command)
}
};

if let Some(mut command) = command {
Expand Down
12 changes: 12 additions & 0 deletions tests/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdio.h>

typedef long long int i64;

int main()
{
i64 a, b;
scanf("%lld %lld", &a, &b);
printf("%lld\n", a + b);
printf("%lld\n", a + b);
return 0;
}
17 changes: 17 additions & 0 deletions tests/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"fmt"
)

func main() {
var num1, num2 int32

fmt.Scan(&num1)

fmt.Scan(&num2)

sum := num1 + num2
fmt.Println(sum)
fmt.Println(sum)
}
17 changes: 17 additions & 0 deletions tests/test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

int num1 = scanner.nextInt();

int num2 = scanner.nextInt();

int sum = num1 + num2;
System.out.printf("%d\n", sum);
System.out.printf("%d", sum);

scanner.close();
}
}
2 changes: 1 addition & 1 deletion tests/test_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use eval_stack::{case::run_test_cases, compile::Language, config::JudgeOptions};
#[tokio::test]
async fn test_fs() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("workspace");
let workspace_path = current_dir.join("fs_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Expand Down
106 changes: 101 additions & 5 deletions tests/test_judge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use eval_stack::{case::run_test_cases, compile::Language, config::JudgeOptions};
#[tokio::test]
async fn test_rust_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("workspace");
let workspace_path = current_dir.join("rust_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Expand Down Expand Up @@ -61,7 +61,7 @@ async fn test_rust_judge() -> Result<()> {
#[tokio::test]
async fn test_cpp_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("workspace");
let workspace_path = current_dir.join("cpp_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Expand Down Expand Up @@ -90,10 +90,42 @@ async fn test_cpp_judge() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn test_c_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("c_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Language::C,
&workspace_path,
&tests_path.join("test.c"),
JudgeOptions {
time_limit: Duration::from_secs(1),
memory_limit: 128 * 1024 * 1024,
fail_fast: true,
no_startup_limits: false,
},
vec![
(tests_path.join("1.in"), tests_path.join("1.out")),
(tests_path.join("2.in"), tests_path.join("2.out")),
],
true,
)
.await?;

for result in results {
println!("{:?}", result);
assert!(result.is_accepted())
}

Ok(())
}

#[tokio::test]
async fn test_python_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("workspace");
let workspace_path = current_dir.join("python_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Expand Down Expand Up @@ -125,7 +157,7 @@ async fn test_python_judge() -> Result<()> {
#[tokio::test]
async fn test_nodejs_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("workspace");
let workspace_path = current_dir.join("nodejs_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Expand All @@ -142,7 +174,71 @@ async fn test_nodejs_judge() -> Result<()> {
(tests_path.join("1.in"), tests_path.join("1.out")),
(tests_path.join("2.in"), tests_path.join("2.out")),
],
false,
true,
)
.await?;

for result in results {
println!("{:?}", result);
assert!(result.is_accepted())
}

Ok(())
}

#[tokio::test]
async fn test_golang_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("golang_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Language::Golang,
&workspace_path,
&tests_path.join("test.go"),
JudgeOptions {
time_limit: Duration::from_secs(1),
memory_limit: 128 * 1024 * 1024,
fail_fast: true,
no_startup_limits: true,
},
vec![
(tests_path.join("1.in"), tests_path.join("1.out")),
(tests_path.join("2.in"), tests_path.join("2.out")),
],
true,
)
.await?;

for result in results {
println!("{:?}", result);
assert!(result.is_accepted())
}

Ok(())
}

#[tokio::test]
async fn test_java_judge() -> Result<()> {
let current_dir = std::env::current_dir()?;
let workspace_path = current_dir.join("java_workspace");
let tests_path = current_dir.join("tests");

let results = run_test_cases(
Language::Java,
&workspace_path,
&tests_path.join("test.java"),
JudgeOptions {
time_limit: Duration::from_secs(1),
memory_limit: 128 * 1024 * 1024,
fail_fast: true,
no_startup_limits: true,
},
vec![
(tests_path.join("1.in"), tests_path.join("1.out")),
(tests_path.join("2.in"), tests_path.join("2.out")),
],
true,
)
.await?;

Expand Down

0 comments on commit 45b085a

Please sign in to comment.