Skip to content

Commit

Permalink
Many updates
Browse files Browse the repository at this point in the history
  • Loading branch information
MikailBag committed Mar 19, 2020
1 parent 0aeb500 commit 205468d
Show file tree
Hide file tree
Showing 21 changed files with 216 additions and 251 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

int main() {
testgen::TestgenSession args = testgen::init();
fprintf(args.out_file, "%d %d\n", args.test_id, args.test_id * 2 + 1);
printf("%d %d\n", args.test_id, args.test_id * 2 + 1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ int main() {
auto sess = testgen::init();
auto a = gen(sess);
auto b = gen(sess);
fprintf(sess.out_file, "%lld %lld\n", a, b);
printf("%lld %lld\n", a, b);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
int main() {
testgen::TestgenSession sess = testgen::init();
int num_cnt = sess.gen.next_range(1, 10001);
fprintf(sess.out_file, "%d\n%ld", num_cnt, sess.gen.next_range(1, 10001));
printf("%d\n%ld", num_cnt, sess.gen.next_range(1, 10001));
for (int i = 1; i < num_cnt; i++) {
fprintf(sess.out_file, " %ld", sess.gen.next_range(1, 10001));
printf(" %ld", sess.gen.next_range(1, 10001));
}
fprintf(sess.out_file, "\n");
printf("\n");
return 0;
}
2 changes: 1 addition & 1 deletion jtl-cpp/JtlConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Jtl_INCLUDES: add to include path
set(Jtl_HW foo)
if (DEFINED ENV{JJS_PATH})
set(Jtl_LIBS $ENV{JJS_PATH}/lib/libjtl.a $ENV{JJS_PATH}/lib/libjtlrs.a pthread m dl rt)
set(Jtl_LIBS $ENV{JJS_PATH}/lib/libjtl.a pthread m dl rt)
set(Jtl_INCLUDES $ENV{JJS_PATH}/include/)
else ()
message(FATAL_ERROR "$JJS_PATH env var is not set")
Expand Down
4 changes: 1 addition & 3 deletions jtl-cpp/include/testgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ class Generator {
};

struct TestgenSession {
FILE* out_file = nullptr;
int test_id = 0;
Generator gen;
int64_t fd_out_file = -1;

TestgenSession(uint64_t _seed);
};

/// Call this first in test generator
TestgenSession init(bool open_files = true);
TestgenSession init();
} // namespace testgen
7 changes: 1 addition & 6 deletions jtl-cpp/src/testgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ uint64_t testgen::Generator::next_range(uint64_t lo, uint64_t hi) {
return lo + get_rand(hi - lo, gen);
}
testgen::TestgenSession::TestgenSession(uint64_t _seed) : gen(_seed) {}
testgen::TestgenSession testgen::init(bool open_files) {
testgen::TestgenSession testgen::init() {
auto rand_seed = get_env_hex("JJS_RANDOM_SEED");
if (rand_seed.len != 8) {
die("rand_seed has incorrect length (%zu instead of 8)\n",
Expand All @@ -47,10 +47,5 @@ testgen::TestgenSession testgen::init(bool open_files) {
memcpy(&random_seed, rand_seed.head.get(), 8);
testgen::TestgenSession sess {random_seed};
sess.test_id = get_env_int("JJS_TEST_ID");
if (open_files) {
sess.out_file = get_env_file("JJS_TEST", "w");
} else {
sess.fd_out_file = get_env_int("JJS_TEST");
}
return sess;
}
2 changes: 1 addition & 1 deletion src/ppc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ thiserror = "1.0.11"
pest = "2.1.3"
pest_derive = "2.1.0"
serde_yaml = "0.8.11"
entity = {path = "../entity"}
entity = {path = "../entity"}
11 changes: 5 additions & 6 deletions src/ppc/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,29 @@ impl Command {
out
}

pub fn run_quiet(&mut self) {
use std::{os::unix::process::ExitStatusExt, process::exit};
pub fn run_quiet(&mut self) -> std::process::Output {
use std::{os::unix::process::ExitStatusExt};
let mut s = self.to_std_command();
let out = s.output().expect("couldn't spawn");
let status = out.status;
if status.success() {
return;
return out;
}
eprintln!("error: child returned error");

let exit_code = if status.code().is_some() {
format!("normal: {}", status.code().unwrap())
} else {
format!("signaled: {}", status.signal().unwrap())
};
eprintln!(
"testgen did not finished successfully (exit code {})",
"Chiild did not finished successfully (exit code {})",
exit_code
);

eprintln!("command: `{}`", self);
eprintln!("child stdout:\n{}", String::from_utf8_lossy(&out.stdout));
eprintln!("child stderr:\n{}", String::from_utf8_lossy(&out.stderr));
exit(1);
std::process::exit(1);
}
}

Expand Down
42 changes: 32 additions & 10 deletions src/ppc/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ impl<'a> ProblemBuilder<'a> {
Ok(cmd) => cmd.command,
Err(err) => {
eprintln!("Build error: unable to run build task: {}", err);
if let build::TaskError::ExitCodeNonZero(out) = err {
eprintln!("--- stdout ---\n{}", String::from_utf8_lossy(&out.stdout));
eprintln!("--- stderr ---\n{}", String::from_utf8_lossy(&out.stderr));
}
eprintln!("Build task: {:#?}", task);
exit(1);
}
Expand Down Expand Up @@ -110,6 +114,7 @@ impl<'a> ProblemBuilder<'a> {
.to_str()
.expect("path is not utf8")
.to_owned();
println!("Building solution {}", &sol_id);
let out_path = format!("{}/assets/sol-{}", self.out_dir.display(), &sol_id);
(sol_id, self.do_build(&sol_path, &PathBuf::from(&out_path)))
}
Expand All @@ -124,13 +129,14 @@ impl<'a> ProblemBuilder<'a> {
}

fn build_testgen(&self, testgen_path: &Path, testgen_name: &str) -> Command {
println!("Building generator {}", testgen_name);
let out_path = format!("{}/assets/testgen-{}", self.out_dir.display(), testgen_name);
self.do_build(testgen_path, &Path::new(&out_path))
}

fn build_testgens(&self) -> HashMap<String, Command> {
let mut out = HashMap::new();
for testgen in self.glob("testgens/*") {
for testgen in self.glob("generators/*") {
let testgen_name = testgen.file_stem().unwrap().to_str().expect("utf8 error");
let testgen_launch_cmd = self.build_testgen(&testgen, testgen_name);
out.insert(testgen_name.to_string(), testgen_launch_cmd);
Expand All @@ -154,6 +160,9 @@ impl<'a> ProblemBuilder<'a> {
let mut out = vec![];
for (i, test_spec) in self.cfg.tests.iter().enumerate() {
let tid = i + 1;
if tid % 10 == 0 {
println!("Building test {}/{}", tid, self.cfg.tests.len());
}
let out_file_path = format!("{}/{}-in.txt", &tests_path, tid);
match &test_spec.gen {
crate::manifest::TestGenSpec::Generate { testgen, args } => {
Expand All @@ -171,12 +180,10 @@ impl<'a> ProblemBuilder<'a> {
cmd.arg(a);
}
cmd.env("JJS_TEST_ID", &tid.to_string());
let out_file_handle = crate::open_as_handle(&out_file_path)
.expect("couldn't create test output file");
cmd.env("JJS_TEST", &out_file_handle.to_string());
cmd.env("JJS_RANDOM_SEED", &entropy);
self.configure_command(&mut cmd);
cmd.run_quiet();
let gen_out = cmd.run_quiet();
std::fs::write(&out_file_path, gen_out.stdout).expect("failed to write test");
}
crate::manifest::TestGenSpec::File { path } => {
let src_path = self.problem_dir.join("tests").join(path);
Expand Down Expand Up @@ -209,13 +216,18 @@ impl<'a> ProblemBuilder<'a> {
let mut cmd = cmd.clone();
self.configure_command(&mut cmd);
let mut cmd = cmd.to_std_command();
let mut close_handles = vec![];
unsafe {
use std::os::unix::{io::IntoRawFd, process::CommandExt};
let test_data_fd = test_data.into_raw_fd();
close_handles.push(test_data_fd);
let test_data_fd = libc::dup(test_data_fd);
close_handles.push(test_data_fd);

let ans_data_fd = answer_data.into_raw_fd();
close_handles.push(ans_data_fd);
let ans_data_fd = libc::dup(ans_data_fd);
close_handles.push(ans_data_fd);
cmd.pre_exec(move || {
if libc::dup2(test_data_fd, 0) == -1 {
return Err(std::io::Error::last_os_error());
Expand All @@ -226,23 +238,33 @@ impl<'a> ProblemBuilder<'a> {
Ok(())
});
}
let status = cmd
let output = cmd
.stdin(crate::Stdio::piped())
.stdout(crate::Stdio::piped())
.status()
.unwrap_or_else(|err| panic!("launching gen_answers cmd failed: {}", err));
if !status.success() {
.stderr(crate::Stdio::piped())
.output()
.unwrap_or_else(|err| panic!("launch main solution error: {}", err));
if !output.status.success() {
eprintln!(
"Error when generating correct answer for test {}: primary solution failed",
"Error when generating correct answer for test {}: main solution failed",
tid
);
eprintln!(
"solution stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
exit(1);
}
let short_file_path = format!("tests/{}-out.txt", tid);
test_info.correct.replace(FileRef {
path: short_file_path,
root: FileRefRoot::Problem,
});
for handle in close_handles {
unsafe {
libc::close(handle);
}
}
}
out.push(test_info);
}
Expand Down
53 changes: 44 additions & 9 deletions src/ppc/src/compile/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use thiserror::{Error};
use std::path::Path;
use thiserror::Error;

#[derive(Debug, Copy, Clone)]
pub(crate) struct Task<'a> {
Expand All @@ -15,13 +15,15 @@ pub(crate) struct TaskSuccess {
pub(crate) command: crate::command::Command,
}

//pub(crate) type TaskError = Box<dyn std::error::Error + 'static>;
#[derive(Debug, Error)]
pub(crate) enum TaskError {
#[error("child command returned non-zero code")]
ExitCodeNonZero,
#[error("child execution failed: {source}")]
ChildExecError { #[from] source: std::io::Error },
#[error("child command errored: code {:?}", _0.status.code())]
ExitCodeNonZero(std::process::Output),
#[error("io error: {source}")]
Io {
#[from]
source: std::io::Error,
},
#[error("feature not supported: {feature}")]
FeatureNotSupported { feature: &'static str },
}
Expand All @@ -38,11 +40,11 @@ trait CommandExt {

impl CommandExt for std::process::Command {
fn run(&mut self) -> Result<(), TaskError> {
let st = self.status()?;
if st.success() {
let out = self.output()?;
if out.status.success() {
Ok(())
} else {
Err(TaskError::ExitCodeNonZero {})
Err(TaskError::ExitCodeNonZero(out))
}
}
}
Expand All @@ -56,9 +58,42 @@ pub(crate) struct Pibs<'a> {
pub(crate) jjs_dir: &'a Path,
}

impl<'a> Pibs<'a> {
fn process_cmake_task(&self, task: Task) -> Result<TaskSuccess, TaskError> {
// let cmake_lists = task.src.join("CMakeLists.txt");
std::process::Command::new("cmake")
.arg("-S")
.arg(task.src)
.arg("-B")
.arg(task.tmp)
.run()?;

std::process::Command::new("cmake")
.arg("--build")
.arg(task.tmp)
.run()?;

let dst = task.dest.join("bin");
std::fs::copy(task.tmp.join("Out"), &dst)?;
let run_cmd = crate::command::Command::new(dst);
Ok(TaskSuccess { command: run_cmd })
}
}
impl<'a> BuildBackend for Pibs<'a> {
fn process_task(&self, task: Task) -> Result<TaskSuccess, TaskError> {
if task.multi_file() {
let cmake_lists_path = task.src.join("CMakeLists.txt");
if cmake_lists_path.exists() {
return self.process_cmake_task(task);
}
let python_path = task.src.join("main.py");
if python_path.exists() {
let out_path = task.dest.join("out.py");
std::fs::copy(&python_path, &out_path)?;
let mut command = crate::command::Command::new("python3");
command.arg(&out_path);
return Ok(TaskSuccess { command });
}
return Err(TaskError::FeatureNotSupported {
feature: "multi-file sources",
});
Expand Down
32 changes: 24 additions & 8 deletions src/ppc/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::{
path::{Path, PathBuf},
};

fn import_one_problem(src: &Path, dest: &Path) -> anyhow::Result<()> {
fn import_one_problem(src: &Path, dest: &Path, build: bool, force: bool) -> anyhow::Result<()> {
let manifest_path = src.join("problem.xml");
let manifest = std::fs::read_to_string(manifest_path).context("failed read problem.xml")?;
let doc = roxmltree::Document::parse(&manifest).context("parse error")?;
Expand All @@ -36,6 +36,23 @@ fn import_one_problem(src: &Path, dest: &Path) -> anyhow::Result<()> {
)
});
std::fs::write(manifest_path, manifest_data).expect("write ppc manifest");
if build {
println!("building problem {}", &importer.problem_cfg.name);
let problems_dir: PathBuf = std::env::var("JJS_DATA")?.into();
let out_path = problems_dir
.join("var/problems")
.join(&importer.problem_cfg.name);
if force {
std::fs::remove_dir_all(&out_path).ok();
}
std::fs::create_dir(&out_path)?;
crate::compile_problem(crate::args::CompileArgs {
pkg_path: dest.to_path_buf(),
out_path,
force,
verbose: true,
});
}
Ok(())
}

Expand All @@ -61,8 +78,8 @@ fn detect_import_kind(path: &Path) -> anyhow::Result<ImportKind> {

pub fn exec(args: crate::args::ImportArgs) -> anyhow::Result<()> {
if args.force {
std::fs::remove_dir_all(&args.out_path).context("remove out dir")?;
std::fs::create_dir(&args.out_path).context("recreate out dir")?;
std::fs::remove_dir_all(&args.out_path).ok();
std::fs::create_dir(&args.out_path).context("create out dir")?;
} else {
crate::check_dir(&PathBuf::from(&args.out_path), false /* TODO */);
}
Expand All @@ -71,7 +88,7 @@ pub fn exec(args: crate::args::ImportArgs) -> anyhow::Result<()> {
let dest = Path::new(&args.out_path);
let kind = detect_import_kind(src).context("failed to detect import operation kind")?;
match kind {
ImportKind::Problem => import_one_problem(src, dest)?,
ImportKind::Problem => import_one_problem(src, dest, args.build, args.force)?,
ImportKind::Contest => {
println!("Importing contest");
println!("Importing problems");
Expand All @@ -86,16 +103,15 @@ pub fn exec(args: crate::args::ImportArgs) -> anyhow::Result<()> {
let problem_dir = item.path();
let target_dir = dest.join("problems").join(&problem_name);
std::fs::create_dir_all(&target_dir)?;
import_one_problem(&problem_dir, &target_dir)?;
import_one_problem(&problem_dir, &target_dir, args.build, args.force)?;
}
if args.update_cfg {
let contest_name = args
.contest_name
.as_ref()
.ok_or_else(|| anyhow::anyhow!("missing --contest-name"))?;
let contest_config =
contest_import::import(&src.join("contest.xml"), contest_name)
.context("import contest config")?;
let contest_config = contest_import::import(&src.join("contest.xml"), contest_name)
.context("import contest config")?;
let jjs_data_dir = std::env::var("JJS_DATA").context("JJS_DATA missing")?;
let path = PathBuf::from(jjs_data_dir)
.join("etc/objects/contests")
Expand Down
2 changes: 2 additions & 0 deletions src/ppc/src/import/checker_tpl.cmake
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
project(Checker)
cmake_minimum_required(VERSION 3.12)
add_executable(Out main.cpp)
target_include_directories(Out PUBLIC ../../)
Loading

0 comments on commit 205468d

Please sign in to comment.