summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Thiel <sthiel@thoughtworks.com>2019-05-29 16:34:49 +0530
committerSebastian Thiel <sthiel@thoughtworks.com>2019-05-29 16:34:49 +0530
commite9a447250ba9ffd10f94f6f7d970c6da141c185d (patch)
tree1f7cef8b6c5ca783c0e37eae77251ed6e5346e63
First instantiation of template
-rw-r--r--.editorconfig22
-rw-r--r--.gitignore16
-rw-r--r--Cargo.toml20
-rw-r--r--Makefile41
-rw-r--r--README.md5
-rw-r--r--etc/developer.Dockerfile8
-rw-r--r--src/lib.rs7
-rw-r--r--src/main.rs40
-rwxr-xr-xtests/stateless-journey.sh25
-rw-r--r--tests/utilities.sh160
10 files changed, 344 insertions, 0 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..762b67e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+[*.sh]
+indent_style = space
+indent_size = 2
+
+# Tab indentation (no size specified)
+[Makefile]
+indent_style = tab
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..25adb76
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+# Created by .ignore support plugin (hsz.mobi)
+### Rust template
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+/.idea/
+
+/callgrind.profile
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..efb8ccc
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "dua"
+version = "1.0.0"
+authors = ["Sebastian Thiel <byronimo@gmail.com>"]
+publish = false
+edition = "2018"
+
+[dependencies]
+failure = "0.1.1"
+failure-tools = "4.0.2"
+structopt = "0.2.14"
+
+[[bin]]
+name="dua"
+path="src/main.rs"
+
+[profile.release]
+panic = 'unwind'
+incremental = false
+overflow-checks = true
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..405efb0
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,41 @@
+docker_image = docker_developer_environment
+
+help:
+ $(info -Targets -----------------------------------------------------------------------------)
+ $(info -Development Targets -----------------------------------------------------------------)
+ $(info lint | run lints with clippy)
+ $(info benchmark | just for fun, really)
+ $(info profile | only on linux - run callgrind and annotate it)
+ $(info journey-tests | run all stateless journey test)
+ $(info continuous-journey-tests | run all stateless journey test whenever something changes)
+ $(info -- Use docker for all dependencies - run make interactively from there ----------------)
+ $(info interactive-developer-environment-in-docker | gives you everything you need to run all targets)
+
+always:
+
+interactive-developer-environment-in-docker:
+ docker build -t $(docker_image) - < etc/developer.Dockerfile
+ docker run -v $$PWD:/volume -w /volume -it $(docker_image)
+
+target/debug/dua: always
+ cargo build
+
+target/release/dua: always
+ cargo build --release
+
+lint:
+ cargo clippy
+
+profile: target/release/dua
+ valgrind --callgrind-out-file=callgrind.profile --tool=callgrind $< >/dev/null
+ callgrind_annotate --auto=yes callgrind.profile
+
+benchmark: target/release/dua
+ hyperfine '$<'
+
+journey-tests: target/debug/dua
+ ./tests/stateless-journey.sh $<
+
+continuous-journey-tests:
+ watchexec $(MAKE) journey-tests
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ac9bdaa
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+## Getting Started
+
+Find-and-replace the term `dua` with the name of your command-line application.
+
+
diff --git a/etc/developer.Dockerfile b/etc/developer.Dockerfile
new file mode 100644
index 0000000..42b52bc
--- /dev/null
+++ b/etc/developer.Dockerfile
@@ -0,0 +1,8 @@
+from guangie88/rustfmt-clippy:nightly
+
+run cargo install hyperfine watchexec
+
+run apt-get update
+run apt-get install -y valgrind
+
+env PATH=$PATH:/root/.cargo/bin
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..a1ed88e
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,7 @@
+extern crate failure;
+
+use failure::Error;
+
+pub fn fun() -> Result<(), Error> {
+ unimplemented!();
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..57406a9
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,40 @@
+extern crate failure;
+extern crate failure_tools;
+extern crate dua;
+#[macro_use]
+extern crate structopt;
+
+use failure::Error;
+use failure_tools::ok_or_exit;
+use structopt::StructOpt;
+
+mod options {
+ use std::path::PathBuf;
+
+ #[derive(Debug, StructOpt)]
+ #[structopt(name = "example", about = "An example of StructOpt usage.")]
+ pub struct Args {
+ /// Activate debug mode
+ #[structopt(short = "d", long = "debug")]
+ debug: bool,
+ /// Set speed
+ #[structopt(short = "s", long = "speed", default_value = "42")]
+ speed: f64,
+ /// Input file
+ #[structopt(parse(from_os_str))]
+ input: PathBuf,
+ /// Output file, stdout if not present
+ #[structopt(parse(from_os_str))]
+ output: Option<PathBuf>,
+ }
+}
+
+fn run() -> Result<(), Error> {
+ let opt = options::Args::from_args();
+ println!("{:?}", opt);
+ dua::fun()
+}
+
+fn main() {
+ ok_or_exit(run())
+}
diff --git a/tests/stateless-journey.sh b/tests/stateless-journey.sh
new file mode 100755
index 0000000..13b5753
--- /dev/null
+++ b/tests/stateless-journey.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+set -eu
+
+exe=${1:?First argument must be the executable to test}
+
+root="$(cd "${0%/*}" && pwd)"
+# shellcheck disable=1090
+source "$root/utilities.sh"
+snapshot="$root/snapshots"
+
+SUCCESSFULLY=0
+WITH_FAILURE=1
+
+(with "no input file"
+ it "fails with an error message" && {
+ WITH_SNAPSHOT="$snapshot/failure-missing-input-file" \
+ expect_run ${WITH_FAILURE} "$exe"
+ }
+)
+(with "a valid input file"
+ it "produces the expected output" && {
+ WITH_SNAPSHOT="$snapshot/success-input-file-produces-correct-output" \
+ expect_run ${SUCCESSFULLY} "$exe" <(echo this is probably not what you want)
+ }
+)
diff --git a/tests/utilities.sh b/tests/utilities.sh
new file mode 100644
index 0000000..86084cf
--- /dev/null
+++ b/tests/utilities.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+
+WHITE="$(tput setaf 9 2>/dev/null || echo -n '')"
+YELLOW="$(tput setaf 3 2>/dev/null || echo -n '')"
+GREEN="$(tput setaf 2 2>/dev/null || echo -n '')"
+RED="$(tput setaf 1 2>/dev/null || echo -n '')"
+OFFSET=( )
+STEP=" "
+
+function with_program () {
+ local program="${1:?}"
+ hash "$program" &>/dev/null || {
+ function expect_run () {
+ echo 1>&2 "${WHITE} - skipped (missing program)"
+ }
+ function expect_run_sh () {
+ echo 1>&2 "${WHITE} - skipped (missing program)"
+ }
+ }
+}
+
+function title () {
+ echo "$WHITE-----------------------------------------------------"
+ echo "${GREEN}$*"
+ echo "$WHITE-----------------------------------------------------"
+}
+
+function _context () {
+ local name="${1:?}"
+ shift
+ echo 1>&2 "${YELLOW}${OFFSET[*]:-}[$name] $*"
+ OFFSET+=("$STEP")
+}
+
+function step () {
+ _note step "${WHITE}" "$*"
+}
+
+function stepn () {
+ step "$*" $'\n'
+}
+
+function with () {
+ _context with "$*"
+}
+
+function when () {
+ _context when "$*"
+}
+
+function _note () {
+ local name="${1:?}"
+ local color="${2:-}"
+ shift 2
+ echo 1>&2 -n "${OFFSET[*]:-}${color}[$name] ${*// /}"
+}
+
+function it () {
+ _note it "${GREEN}" "$*"
+}
+
+function precondition () {
+ _note precondition "${WHITE}" "$*"
+}
+
+function shortcoming () {
+ _note shortcoming "${RED}" "$*"
+}
+
+function step () {
+ _note step "${WHITE}" "$*"
+}
+
+function stepn () {
+ step "$*" $'\n'
+}
+
+function fail () {
+ echo 1>&2 "${RED} $*"
+ exit 1
+}
+
+function sandbox () {
+ sandbox_tempdir="$(mktemp -t sandbox.XXXXXX -d)"
+ # shellcheck disable=2064
+ trap "popd >/dev/null" EXIT
+ pushd "$sandbox_tempdir" >/dev/null \
+ || fail "Could not change directory into temporary directory."
+
+ local custom_init="${1:-}"
+ if [ -n "$custom_init" ]; then
+ eval "$custom_init"
+ fi
+}
+
+function expect_equals () {
+ expect_run 0 test "${1:?}" = "${2:?}"
+}
+
+function expect_exists () {
+ expect_run 0 test -e "${1:?}"
+}
+
+function expect_run_sh () {
+ expect_run "${1:?}" bash -c -eu -o pipefail "${2:?}"
+}
+
+function expect_snapshot () {
+ local expected=${1:?}
+ local actual=${2:?}
+ if ! [ -e "$expected" ]; then
+ mkdir -p "${expected%/*}"
+ cp -R "$actual" "$expected"
+ fi
+ expect_run 0 diff -r -N "$expected" "$actual"
+}
+
+function expect_run () {
+ local expected_exit_code=$1
+ shift
+ local output=
+ set +e
+ if [[ -n "${SNAPSHOT_FILTER-}" ]]; then
+ output="$("$@" 2>&1 | "$SNAPSHOT_FILTER")"
+ else
+ output="$("$@" 2>&1)"
+ fi
+
+ local actual_exit_code=$?
+ if [[ "$actual_exit_code" == "$expected_exit_code" ]]; then
+ if [[ -n "${WITH_SNAPSHOT-}" ]]; then
+ local expected="$WITH_SNAPSHOT"
+ if ! [ -f "$expected" ]; then
+ mkdir -p "${expected%/*}"
+ echo -n "$output" > "$expected" || exit 1
+ fi
+ if ! diff "$expected" <(echo -n "$output"); then
+ echo 1>&2 "${RED} - FAIL"
+ echo 1>&2 "${WHITE}\$ $*"
+ echo 1>&2 "Output snapshot did not match snapshot at '$expected'"
+ echo 1>&2 "$output"
+ if [ -n "${ON_ERROR:-}" ]; then
+ eval "$ON_ERROR"
+ fi
+ exit 1
+ fi
+ fi
+ echo 1>&2
+ else
+ echo 1>&2 "${RED} - FAIL"
+ echo 1>&2 "${WHITE}\$ $*"
+ echo 1>&2 "${RED}Expected actual status $actual_exit_code to be $expected_exit_code"
+ echo 1>&2 "$output"
+ if [ -n "${ON_ERROR:-}" ]; then
+ eval "$ON_ERROR"
+ fi
+ exit 1
+ fi
+ set -e
+}