#!/usr/bin/env bash
# Usage: bash test-ram.sh [GiB|auto] [seconds]; works with 128G or 64G.
set -euo pipefail
umask 077
command -v stress-ng >/dev/null || { echo 'Install stress-ng first'; exit 2; }
size=${1:-auto}; seconds=${2:-300}
[[ $seconds =~ ^[1-9][0-9]*$ ]] || exit 2
available=$(awk '/MemAvailable:/ {print int($2/1048576)}' /proc/meminfo)
limit=$((available * 3 / 4))
(( available-limit >= 16 )) || limit=$((available-16))
[[ $size != auto ]] || size=$limit
[[ $size =~ ^[1-9][0-9]*$ ]] && (( size <= limit )) || { echo "Unsafe size; max ${limit} GiB now"; exit 2; }
logdir="$HOME/memory-tests/$(date +%Y%m%d-%H%M%S)-$$"
mkdir -p "$logdir"
exec > >(tee "$logdir/report.txt") 2>&1
snapshot() { find /sys/devices/system/edac/mc -type f \( -name ce_count -o -name ue_count -o -name dimm_ce_count -o -name dimm_ue_count \) -print -exec cat {} \; 2>/dev/null || true; }
echo "Logs: $logdir; test ${size} GiB for ${seconds} seconds"
date -Is; cat /proc/sys/kernel/random/boot_id; free -h
snapshot > "$logdir/ecc-before.txt"
set +e
nice -n 10 stress-ng --vm 1 --vm-bytes "${size}G" --vm-keep --vm-method all --verify --timeout "${seconds}s" --metrics-brief 2>&1 | tee "$logdir/stress-ng.txt"
rc=${PIPESTATUS[0]}
set -e
snapshot > "$logdir/ecc-after.txt"
free -h
diff -u "$logdir/ecc-before.txt" "$logdir/ecc-after.txt" || true
echo "stress-ng exit=$rc"
echo 'Timed online sample: does not guarantee all RAM addresses or algorithms were tested.'
exit "$rc"
