Skip to content

Commit fb9df82

Browse files
committed
testing should be OS agnostic now
1 parent aede0c8 commit fb9df82

File tree

6 files changed

+669
-476
lines changed

6 files changed

+669
-476
lines changed

ci-local.sh.sh

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env bash
2+
set -u
3+
set -o pipefail
4+
5+
# Mirror of GitHub Actions Rust CI, for local use.
6+
# Runs:
7+
# - cargo test (debug + release) on stable/beta/nightly (if installed)
8+
# - cargo fmt (nightly, --check)
9+
# - taplo fmt --check
10+
# - cargo clippy --all-targets --all-features -D warnings
11+
# - cargo doc with RUSTDOCFLAGS=-D warnings
12+
# - cargo tarpaulin (coverage) for package sql_docs
13+
#
14+
# Only prints full command output when a step fails.
15+
16+
CARGO_TERM_COLOR=always
17+
export CARGO_TERM_COLOR
18+
19+
LOG_DIR="$(mktemp -d -t rust-ci-logs-XXXXXX)"
20+
failed=0
21+
step_index=0
22+
23+
cleanup() {
24+
rm -rf "$LOG_DIR" 2>/dev/null || true
25+
}
26+
trap cleanup EXIT
27+
28+
run_step() {
29+
local name="$1"
30+
shift
31+
step_index=$((step_index + 1))
32+
local log="$LOG_DIR/${step_index}_${name//[^A-Za-z0-9_.-]/_}.log"
33+
34+
# Minimal noise on success: just a single line.
35+
echo "==> $name"
36+
if "$@" >"$log" 2>&1; then
37+
echo " OK"
38+
rm -f "$log"
39+
else
40+
echo " FAILED"
41+
echo "---- $name log ----"
42+
sed 's/^/ /' "$log"
43+
echo "-------------------"
44+
failed=1
45+
fi
46+
}
47+
48+
# --- Sanity checks ---------------------------------------------------------
49+
50+
if ! command -v rustup >/dev/null 2>&1; then
51+
echo "rustup is required to run this script."
52+
exit 1
53+
fi
54+
55+
if ! command -v cargo >/dev/null 2>&1; then
56+
echo "cargo is required to run this script."
57+
exit 1
58+
fi
59+
60+
# --- Test matrix: stable, beta, nightly -----------------------------------
61+
62+
for TOOLCHAIN in stable beta nightly; do
63+
if rustup toolchain list | grep -q "^$TOOLCHAIN"; then
64+
run_step "tests-${TOOLCHAIN}-debug" rustup run "$TOOLCHAIN" cargo test --verbose
65+
run_step "tests-${TOOLCHAIN}-release" rustup run "$TOOLCHAIN" cargo test --release --verbose
66+
else
67+
echo "==> Skipping tests for $TOOLCHAIN (toolchain not installed)"
68+
fi
69+
done
70+
71+
# --- Rustfmt (nightly) -----------------------------------------------------
72+
73+
if rustup toolchain list | grep -q "^nightly"; then
74+
run_step "rustfmt-install-nightly" rustup component add --toolchain nightly rustfmt
75+
run_step "rustfmt-check" rustup run nightly cargo fmt --all -- --check
76+
else
77+
echo "==> Skipping rustfmt check (nightly toolchain not installed)"
78+
fi
79+
80+
# --- Taplo (TOML formatting) ----------------------------------------------
81+
82+
if ! command -v taplo >/dev/null 2>&1; then
83+
# mirror GH action behavior: install taplo if missing
84+
run_step "install-taplo-cli" cargo install taplo-cli
85+
fi
86+
87+
if command -v taplo >/dev/null 2>&1; then
88+
run_step "taplo-fmt-check" taplo fmt --check
89+
else
90+
echo "==> Skipping taplo fmt check (taplo not available and install failed)"
91+
fi
92+
93+
# --- Clippy (stable) -------------------------------------------------------
94+
95+
if rustup toolchain list | grep -q "^stable"; then
96+
run_step "clippy-install" rustup component add --toolchain stable clippy
97+
run_step "clippy-check" rustup run stable cargo clippy --all-targets --all-features -- -D warnings
98+
else
99+
echo "==> Skipping clippy (stable toolchain not installed)"
100+
fi
101+
102+
# --- Docs (stable) ---------------------------------------------------------
103+
104+
if rustup toolchain list | grep -q "^stable"; then
105+
run_step "doc-check" env RUSTDOCFLAGS="-D warnings" rustup run stable cargo doc --no-deps --document-private-items
106+
else
107+
echo "==> Skipping doc check (stable toolchain not installed)"
108+
fi
109+
110+
# --- Coverage (tarpaulin) --------------------------------------------------
111+
112+
if ! command -v cargo-tarpaulin >/dev/null 2>&1; then
113+
run_step "install-tarpaulin" cargo install cargo-tarpaulin
114+
fi
115+
116+
if command -v cargo-tarpaulin >/dev/null 2>&1; then
117+
run_step "coverage-tarpaulin" cargo tarpaulin --verbose --engine=llvm --all-features --timeout 120 --out xml -p sql_docs
118+
else
119+
echo "==> Skipping coverage (cargo-tarpaulin not available and install failed)"
120+
fi
121+
122+
# --- Summary ---------------------------------------------------------------
123+
124+
if [[ "$failed" -ne 0 ]]; then
125+
echo
126+
echo "❌ One or more steps failed."
127+
else
128+
echo
129+
echo "✅ All steps passed."
130+
fi
131+
132+
exit "$failed"

src/ast.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,37 +93,37 @@ mod tests {
9393
use crate::files::{SqlFile, SqlFileSet};
9494

9595
#[test]
96-
fn parsed_sql_file_parses_single_statement() {
96+
fn parsed_sql_file_parses_single_statement() -> Result<(), Box<dyn std::error::Error>> {
9797
let base = env::temp_dir().join("parsed_sql_file_single_stmt_test");
9898
let _ = fs::remove_dir_all(&base);
99-
fs::create_dir_all(&base).unwrap_or_else(|e| panic!("panicked on {e}"));
99+
fs::create_dir_all(&base)?;
100100
let file_path = base.join("one.sql");
101101
let sql = "CREATE TABLE users (id INTEGER PRIMARY KEY);";
102-
fs::write(&file_path, sql).unwrap_or_else(|e| panic!("panicked on {e}"));
103-
let sql_file = SqlFile::new(&file_path).unwrap_or_else(|e| panic!("panicked on {e}"));
104-
let parsed = ParsedSqlFile::parse(sql_file).unwrap_or_else(|e| panic!("panicked on {e}"));
102+
fs::write(&file_path, sql)?;
103+
let sql_file = SqlFile::new(&file_path)?;
104+
let parsed = ParsedSqlFile::parse(sql_file)?;
105105
assert_eq!(parsed.path(), file_path.as_path());
106106
assert_eq!(parsed.content(), sql);
107107
assert_eq!(parsed.statements().len(), 1);
108108
let _ = fs::remove_dir_all(&base);
109+
Ok(())
109110
}
110111

111112
#[test]
112-
fn parsed_sql_file_set_parses_multiple_files() {
113+
fn parsed_sql_file_set_parses_multiple_files() -> Result<(), Box<dyn std::error::Error>> {
113114
let base = env::temp_dir().join("parsed_sql_file_set_multi_test");
114115
let _ = fs::remove_dir_all(&base);
115-
fs::create_dir_all(&base).unwrap_or_else(|e| panic!("panicked on {e}"));
116+
fs::create_dir_all(&base)?;
116117
let sub = base.join("subdir");
117-
fs::create_dir_all(&sub).unwrap_or_else(|e| panic!("panicked on {e}"));
118+
fs::create_dir_all(&sub)?;
118119
let file1 = base.join("one.sql");
119120
let file2 = sub.join("two.sql");
120121
let sql1 = "CREATE TABLE users (id INTEGER PRIMARY KEY);";
121122
let sql2 = "CREATE TABLE posts (id INTEGER PRIMARY KEY);";
122-
fs::write(&file1, sql1).unwrap_or_else(|e| panic!("panicked on {e}"));
123-
fs::write(&file2, sql2).unwrap_or_else(|e| panic!("panicked on {e}"));
124-
let set = SqlFileSet::new(&base, None).unwrap_or_else(|e| panic!("panicked on {e}"));
125-
let parsed_set =
126-
ParsedSqlFileSet::parse_all(set).unwrap_or_else(|e| panic!("panicked on {e}"));
123+
fs::write(&file1, sql1)?;
124+
fs::write(&file2, sql2)?;
125+
let set = SqlFileSet::new(&base, None)?;
126+
let parsed_set = ParsedSqlFileSet::parse_all(set)?;
127127
let existing_files = parsed_set.files();
128128
assert_eq!(existing_files.len(), 2);
129129
for parsed in existing_files {
@@ -136,5 +136,6 @@ mod tests {
136136
}
137137

138138
let _ = fs::remove_dir_all(&base);
139+
Ok(())
139140
}
140141
}

0 commit comments

Comments
 (0)