Add monster coverage and stack validation

This commit is contained in:
Rene De Ren
2026-03-12 10:32:09 +01:00
parent e580c93c84
commit c9bacb64c8
4 changed files with 162 additions and 12 deletions

View File

@@ -181,5 +181,124 @@
"x": 600,
"y": 200,
"wires": []
},
{
"id": "inject-monster-prediction",
"type": "inject",
"z": "e2e-flow-tab",
"name": "Monster prediction",
"props": [
{ "p": "payload" },
{ "p": "topic", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "4",
"topic": "model_prediction",
"payload": "120",
"payloadType": "num",
"x": 150,
"y": 320,
"wires": [["evolv-monster"]]
},
{
"id": "inject-monster-flow",
"type": "inject",
"z": "e2e-flow-tab",
"name": "Monster flow",
"props": [
{ "p": "payload" },
{ "p": "topic", "vt": "str" }
],
"repeat": "3",
"crontab": "",
"once": true,
"onceDelay": "5",
"topic": "i_flow",
"payload": "3600",
"payloadType": "num",
"x": 140,
"y": 360,
"wires": [["evolv-monster"]]
},
{
"id": "inject-monster-start",
"type": "inject",
"z": "e2e-flow-tab",
"name": "Monster start",
"props": [
{ "p": "payload" },
{ "p": "topic", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "6",
"topic": "start",
"payload": "",
"payloadType": "date",
"x": 140,
"y": 400,
"wires": [["evolv-monster"]]
},
{
"id": "evolv-monster",
"type": "monster",
"z": "e2e-flow-tab",
"name": "E2E-Monster",
"samplingtime": 1,
"minvolume": 5,
"maxweight": 23,
"emptyWeightBucket": 3,
"aquon_sample_name": "112100",
"supplier": "e2e-test",
"subType": "samplingCabinet",
"model": "e2e-virtual",
"unit": "m3/h",
"enableLog": false,
"logLevel": "error",
"x": 390,
"y": 360,
"wires": [
["debug-monster-process"],
["debug-monster-dbase"],
[],
[]
]
},
{
"id": "debug-monster-process",
"type": "debug",
"z": "e2e-flow-tab",
"name": "Monster Process Output",
"active": true,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 660,
"y": 340,
"wires": []
},
{
"id": "debug-monster-dbase",
"type": "debug",
"z": "e2e-flow-tab",
"name": "Monster Database Output",
"active": true,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 670,
"y": 380,
"wires": []
}
]

View File

@@ -13,6 +13,8 @@ COMPOSE_FILE="$PROJECT_ROOT/docker-compose.e2e.yml"
NODERED_URL="http://localhost:1880"
MAX_WAIT=120 # seconds to wait for Node-RED to become healthy
GRAFANA_URL="http://localhost:3000/api/health"
MAX_GRAFANA_WAIT=60
# EVOLV node types that must appear in the palette (from package.json node-red.nodes)
EXPECTED_NODES=(
@@ -38,10 +40,10 @@ log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
# Determine docker compose command (handle permission via sg docker if needed)
DOCKER_COMPOSE="docker compose"
USE_SG_DOCKER=false
if ! docker info >/dev/null 2>&1; then
if sg docker -c "docker info" >/dev/null 2>&1; then
DOCKER_COMPOSE="sg docker -c 'docker compose'"
USE_SG_DOCKER=true
log_info "Using sg docker for Docker access"
else
log_error "Docker is not accessible. Please ensure Docker is running and you have permissions."
@@ -49,9 +51,22 @@ if ! docker info >/dev/null 2>&1; then
fi
fi
run_compose() {
if [ "$USE_SG_DOCKER" = true ]; then
local cmd="docker compose -f $(printf '%q' "$COMPOSE_FILE")"
local arg
for arg in "$@"; do
cmd+=" $(printf '%q' "$arg")"
done
sg docker -c "$cmd"
else
docker compose -f "$COMPOSE_FILE" "$@"
fi
}
cleanup() {
log_info "Tearing down E2E stack..."
eval $DOCKER_COMPOSE -f "$COMPOSE_FILE" down --volumes --remove-orphans 2>/dev/null || true
run_compose down --volumes --remove-orphans 2>/dev/null || true
}
# Always clean up on exit
@@ -59,7 +74,7 @@ trap cleanup EXIT
# --- Step 1: Build and start the stack ---
log_info "Building and starting E2E stack..."
eval $DOCKER_COMPOSE -f "$COMPOSE_FILE" up -d --build
run_compose up -d --build
# --- Step 2: Wait for Node-RED to be healthy ---
log_info "Waiting for Node-RED to become healthy (max ${MAX_WAIT}s)..."
@@ -76,7 +91,7 @@ done
if [ $elapsed -ge $MAX_WAIT ]; then
log_error "Node-RED did not become healthy within ${MAX_WAIT}s"
log_error "Container logs:"
eval $DOCKER_COMPOSE -f "$COMPOSE_FILE" logs nodered
run_compose logs nodered
exit 1
fi
@@ -129,12 +144,15 @@ fi
# --- Step 5b: Verify Grafana is reachable ---
log_info "Checking Grafana health..."
GRAFANA_HEALTH=$(curl -sf "http://localhost:3000/api/health" 2>&1) || {
log_error "Failed to reach Grafana health endpoint"
FAILURES=$((FAILURES + 1))
}
GRAFANA_HEALTH=""
elapsed=0
while [ $elapsed -lt $MAX_GRAFANA_WAIT ]; do
GRAFANA_HEALTH=$(curl -sf "$GRAFANA_URL" 2>&1) && break
sleep 2
elapsed=$((elapsed + 2))
done
if echo "$GRAFANA_HEALTH" | grep -q '"database":"ok"'; then
if echo "$GRAFANA_HEALTH" | grep -Eq '"database"[[:space:]]*:[[:space:]]*"ok"'; then
log_info " [PASS] Grafana is healthy"
else
log_error " [FAIL] Grafana health check failed"
@@ -143,7 +161,7 @@ fi
# --- Step 5c: Verify EVOLV measurement node produced output ---
log_info "Checking EVOLV measurement node output in container logs..."
NODERED_LOGS=$(eval $DOCKER_COMPOSE -f "$COMPOSE_FILE" logs nodered 2>&1)
NODERED_LOGS=$(run_compose logs nodered 2>&1)
if echo "$NODERED_LOGS" | grep -q "Database Output"; then
log_info " [PASS] EVOLV measurement node produced database output"
@@ -157,6 +175,18 @@ else
log_warn " [WARN] EVOLV measurement process output not detected in logs"
fi
if echo "$NODERED_LOGS" | grep -q "Monster Process Output"; then
log_info " [PASS] EVOLV monster node produced process output"
else
log_warn " [WARN] EVOLV monster process output not detected in logs"
fi
if echo "$NODERED_LOGS" | grep -q "Monster Database Output"; then
log_info " [PASS] EVOLV monster node produced database output"
else
log_warn " [WARN] EVOLV monster database output not detected in logs"
fi
# --- Step 6: Summary ---
echo ""
if [ $FAILURES -eq 0 ]; then