Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve test coverage #33

Merged
merged 11 commits into from
May 9, 2023
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
/result
/box
/program
/lcov*.info
/lcov_html
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ need to have a Sandkasten instance running on `127.0.0.1:8000`. You can also spe
instance via the `TARGET` environment variable. If you only want to run the integration tests that
do not require a nix development shell, you can omit the `-F nix`. In the development shell you can
also run the `integration-tests` command to automatically start a temporary sandkasten instance and
run the integration tests against it.
run the integration tests against it. There is also a `cov` command that runs the integration tests
and writes an html coverage report to `lcov_html/index.html`.

### Packages
All packages are defined using nix expressions in
Expand Down
21 changes: 17 additions & 4 deletions nix/dev/shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,41 @@
jobs_dir = "jobs";
program_ttl = 60;
prune_programs_interval = 30;
run_limits = config.run_limits // {network = true;};
}));
};
test-script = pkgs.writeShellScript "integration-tests.sh" ''
export PROPTEST_CASES=''${1:-256}
rm -rf programs jobs
cargo llvm-cov run -r --locked --lcov --output-path lcov.info -F test_api &
cargo llvm-cov run --lcov --output-path lcov-server.info --release --locked -F test_api &
pid=$!
while ! ${pkgs.curl}/bin/curl -so/dev/null localhost:8000; do
sleep 1
done
cargo test --locked --all-features --all-targets --no-fail-fast -- --ignored
cargo llvm-cov test --lcov --output-path lcov-tests.info --locked --all-features --all-targets --no-fail-fast -- --include-ignored
out=$?
${pkgs.curl}/bin/curl -X POST localhost:8000/test/exit
wait $pid
${pkgs.lcov}/bin/lcov -a lcov-server.info -a lcov-tests.info -o lcov.info
exit $out
'';
cov = pkgs.writeShellScript "cov.sh" ''
rm -rf lcov*.info lcov_html
${test-script} "''${1:-16}"
${pkgs.lcov}/bin/genhtml -o lcov_html lcov.info
'';
scripts = pkgs.stdenv.mkDerivation {
name = "scripts";
unpackPhase = "true";
installPhase = "mkdir -p $out/bin && ln -s ${test-script} $out/bin/integration-tests";
installPhase = ''
mkdir -p $out/bin \
&& ln -s ${test-script} $out/bin/integration-tests \
&& ln -s ${cov} $out/bin/cov
'';
};
in {
default = pkgs.mkShell ({
packages = [pkgs.nsjail pkgs.cargo-llvm-cov time scripts];
packages = [pkgs.nsjail pkgs.cargo-llvm-cov pkgs.lcov time scripts];
RUST_LOG = "info,sandkasten=trace,difft=off";
}
// test-env);
Expand Down
35 changes: 14 additions & 21 deletions src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub async fn build_program(
&env.version,
&env.compile_script,
&data.files,
&data.environment,
&data.env_vars,
))?)
.finalize();
let id = Uuid::from_u128(
Expand Down Expand Up @@ -67,6 +67,15 @@ pub async fn build_program(
fs::write(path.join("compile_result"), serialized).await?;
}
fs::write(path.join("ok"), []).await?;
fs::write(
path.join("last_run"),
time::SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
.to_string(),
)
.await?;
Ok((
BuildResult {
program_id: id,
Expand All @@ -77,8 +86,10 @@ pub async fn build_program(
))
}
Err(err) => {
if let Err(err) = fs::remove_dir_all(&path).await {
error!("could not remove program directory {path:?}: {err}");
if fs::try_exists(&path).await? {
if let Err(err) = fs::remove_dir_all(&path).await {
error!("could not remove program directory {path:?}: {err}");
}
}
Err(err)
}
Expand Down Expand Up @@ -164,16 +175,6 @@ pub async fn run_program(
.await??)
}

/// Delete a program's directly and all its contents.
pub async fn delete_program(config: &Config, program_id: Uuid) -> Result<(), DeleteProgramError> {
let path = config.programs_dir.join(program_id.to_string());
if !fs::try_exists(&path).await? {
return Err(DeleteProgramError::ProgramNotFound);
}
fs::remove_dir_all(path).await?;
Ok(())
}

pub async fn prune_programs(
config: &Config,
program_lock: Arc<KeyRwLock<Uuid>>,
Expand Down Expand Up @@ -264,14 +265,6 @@ pub enum RunProgramError {
LimitsExceeded(Vec<LimitExceeded>),
}

#[derive(Debug, Error)]
pub enum DeleteProgramError {
#[error("program does not exist")]
ProgramNotFound,
#[error("io error: {0}")]
IOError(#[from] std::io::Error),
}

async fn store_program(
config: &Config,
environments: &Environments,
Expand Down
Loading