From 1cd733355d1d8abf73545cf59e2a2514587a8553 Mon Sep 17 00:00:00 2001 From: Jeehoon Kang Date: Tue, 16 Aug 2022 00:24:21 +0900 Subject: [PATCH] Initial commit --- .gitignore | 2 + Cargo.toml | 8 +++ rust-toolchain | 1 + scripts/grade-01.sh | 34 ++++++++++++ scripts/grade-utils.sh | 78 +++++++++++++++++++++++++++ src/assignments/assignment01.rs | 19 +++++++ src/assignments/assignment01_grade.rs | 24 +++++++++ src/assignments/mod.rs | 5 ++ src/lib.rs | 33 ++++++++++++ suppress_tsan.txt | 0 10 files changed, 204 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 rust-toolchain create mode 100755 scripts/grade-01.sh create mode 100755 scripts/grade-utils.sh create mode 100644 src/assignments/assignment01.rs create mode 100644 src/assignments/assignment01_grade.rs create mode 100644 src/assignments/mod.rs create mode 100644 src/lib.rs create mode 100644 suppress_tsan.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..3e53bb3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cs220" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..7cc6ef4 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +1.63.0 \ No newline at end of file diff --git a/scripts/grade-01.sh b/scripts/grade-01.sh new file mode 100755 index 0000000..6505296 --- /dev/null +++ b/scripts/grade-01.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -e +set -uo pipefail +IFS=$'\n\t' + +# Imports library. +BASEDIR=$(dirname "$0") +source $BASEDIR/grade-utils.sh + +RUNNERS=( + "cargo" + "cargo --release" + "cargo_asan" + "cargo_asan --release" + "cargo_tsan" + "cargo_tsan --release" +) + +# Lints. +cargo fmt --check +cargo clippy + +# Executes test for each runner. +for RUNNER in "${RUNNERS[@]}"; do + echo "Running with $RUNNER..." + + TESTS=("--lib assignment01_grade") + if [ $(run_tests) -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/scripts/grade-utils.sh b/scripts/grade-utils.sh new file mode 100755 index 0000000..5c6b6b7 --- /dev/null +++ b/scripts/grade-utils.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Global variables +# * TEMPLATE_REV: git revision of the latest homework template +# * TESTS: array of "[TARGET] [TEST_NAME] [-- ...]" +# e.g. "--test linked_list", "--lib cache", "--test list_set -- --test-thread 1" +# * RUNNERS: array of "cargo[_asan | _tsan] [--release]" +# * TIMEOUT: default 10s + +rustup toolchain update stable nightly + +echo_err() { + echo -e "\033[0;31m\033[1m$@\033[0m" 1>&2 +} +export -f echo_err + +# check_diff FILE TEST_LINES_FROM_TAIL +# Abort if tests are modified. +# Uses global variable TEMPLATE_REV. +check_diff() { + local FILE=$1 + local TAIL_N=$2 + diff <(tail -n $TAIL_N <(git show $TEMPLATE_REV:$FILE)) <(tail -n $TAIL_N $FILE) \ + || (echo_err "You modified tests for ${FILE}!"; exit 1) +} +export -f check_diff + +# usage: cargo_asan [SUBCOMMAND] [OPTIONS] [-- ...] +# example: cargo_asan test --release TEST_NAME -- --skip SKIPPED +cargo_asan() { + local SUBCOMMAND=$1; shift + RUSTFLAGS="-Z sanitizer=address" \ + RUSTDOCFLAGS="-Z sanitizer=address" \ + cargo +nightly $SUBCOMMAND --target x86_64-unknown-linux-gnu $@ +} +export -f cargo_asan + +cargo_tsan() { + local SUBCOMMAND=$1; shift + RUSTFLAGS="-Z sanitizer=thread" \ + TSAN_OPTIONS="suppressions=suppress_tsan.txt" \ + RUSTDOCFLAGS="-Z sanitizer=thread" \ + RUST_TEST_THREADS=1 \ + cargo +nightly $SUBCOMMAND --target x86_64-unknown-linux-gnu $@ +} +export -f cargo_tsan + +# usage: _run_tests_with CARGO [OPTIONS] +# example: _run_tests_with cargo_tsan --release +# echos number of failed tests +# Uses global variable TESTS, TIMEOUT +# [OPTIONS] must not contain " -- " (cargo options only) +_run_tests_with() { + local CARGO=$1; shift + $CARGO test --no-run $@ &>/dev/null \ + || (echo_err "Build failed!"; exit 1) + + local FAILED=0 + for TEST in "${TESTS[@]}"; do + local TEST_CMD="$CARGO test $@ $TEST" + timeout ${TIMEOUT:-10s} bash -c "$TEST_CMD 2>/dev/null" 1>&2 + case $? in + 0) ;; + 124) echo_err "Test timed out: $TEST_CMD"; FAILED=$((FAILED + 1));; + *) echo_err "Test failed: $TEST_CMD"; FAILED=$((FAILED + 1));; + esac + done + echo $FAILED +} + +# example: run_tests +# Uses global variable RUNNER and TESTS +run_tests() { + # "cargo --relase" should be split into "cargo" and "--release" + local IFS=' ' + echo $(_run_tests_with $RUNNER) +} +export -f run_tests diff --git a/src/assignments/assignment01.rs b/src/assignments/assignment01.rs new file mode 100644 index 0000000..d5673e0 --- /dev/null +++ b/src/assignments/assignment01.rs @@ -0,0 +1,19 @@ +//! Assignment 1: Preparing for Rust Development Environment. +//! +//! The primary goal of this assignment is bringing up SSH, VSCode, and all the other necessary tools to develop Rust programs. +//! Please make sure you're comfortable with developing Rust programs before moving on to the next assignments. +//! +//! You should fill out `add()` and `sub()` function bodies in such a way that `/scripts/grade-01.sh` works fine. +//! See `assignment01_grade.rs` and `/scripts/grade-01.sh` for the test script. +//! +//! Hint: https://doc.rust-lang.org/std/primitive.usize.html + +/// Adds two unsigned words. If overflow happens, just wrap around. +pub(crate) fn add(lhs: usize, rhs: usize) -> usize { + todo!() +} + +/// Adds two unsigned words. If underflow happens, just wrap around. +pub(crate) fn sub(lhs: usize, rhs: usize) -> usize { + todo!() +} diff --git a/src/assignments/assignment01_grade.rs b/src/assignments/assignment01_grade.rs new file mode 100644 index 0000000..327494b --- /dev/null +++ b/src/assignments/assignment01_grade.rs @@ -0,0 +1,24 @@ +#[cfg(test)] +mod test { + use super::super::assignment01::*; + + #[test] + fn add_7_3() { + assert_eq!(add(7, 3), 10); + } + + #[test] + fn add_overflow() { + assert_eq!(add(usize::MAX, 1), usize::MIN); + } + + #[test] + fn sub_7_3() { + assert_eq!(sub(7, 3), 4); + } + + #[test] + fn sub_underflow() { + assert_eq!(sub(usize::MIN, 1), usize::MAX); + } +} diff --git a/src/assignments/mod.rs b/src/assignments/mod.rs new file mode 100644 index 0000000..1fdfbd8 --- /dev/null +++ b/src/assignments/mod.rs @@ -0,0 +1,5 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +mod assignment01; +mod assignment01_grade; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..14c5653 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,33 @@ +//! KAIST CS220: Programming Principles + +// # Tries to deny all lints (`rustc -W help`). +#![deny(absolute_paths_not_starting_with_crate)] +#![deny(anonymous_parameters)] +#![deny(box_pointers)] +#![deny(deprecated_in_future)] +#![deny(explicit_outlives_requirements)] +#![deny(keyword_idents)] +#![deny(macro_use_extern_crate)] +#![deny(missing_debug_implementations)] +#![deny(non_ascii_idents)] +#![deny(pointer_structural_match)] +#![deny(rust_2018_idioms)] +#![deny(trivial_numeric_casts)] +#![deny(unaligned_references)] +// #![deny(unused_crate_dependencies)] // TODO: uncomment +#![deny(unused_extern_crates)] +#![deny(unused_import_braces)] +#![deny(unused_qualifications)] +#![deny(unused_results)] +#![deny(variant_size_differences)] +#![deny(warnings)] +#![deny(rustdoc::invalid_html_tags)] +#![deny(rustdoc::missing_doc_code_examples)] +#![deny(missing_docs)] +#![deny(rustdoc::all)] +#![deny(unreachable_pub)] +#![deny(single_use_lifetimes)] +#![deny(unused_lifetimes)] +#![deny(unstable_features)] + +mod assignments; diff --git a/suppress_tsan.txt b/suppress_tsan.txt new file mode 100644 index 0000000..e69de29