Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ Each demo has automated smoke tests that verify the gateway starts and the REST

```bash
# Run smoke tests against a running demo (default: http://localhost:8080)
./tests/smoke_test.sh # Sensor diagnostics (21 tests, incl. fault injection)
./tests/smoke_test_turtlebot3.sh # TurtleBot3 (entity discovery)
./tests/smoke_test_moveit.sh # MoveIt pick-and-place (entity discovery)
./tests/smoke_test.sh # Sensor diagnostics (full API coverage + fault injection + beacons)
./tests/smoke_test_turtlebot3.sh # TurtleBot3 (discovery, data, operations, scripts, triggers, logs)
./tests/smoke_test_moveit.sh # MoveIt pick-and-place (discovery, data, operations, scripts, triggers, logs)
```

CI runs all 3 demos in parallel - each job builds the Docker image, starts the container, and runs the smoke tests against it. See [CI workflow](.github/workflows/ci.yml).
Expand Down
6 changes: 6 additions & 0 deletions demos/moveit_pick_place/config/medkit_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ diagnostics:
manifest_strict_validation: true
runtime:
create_synthetic_components: false # Manifest defines components
create_synthetic_areas: false # Manifest defines areas
merge_pipeline:
gap_fill:
allow_heuristic_areas: false # Manifest defines all areas
allow_heuristic_components: false # Manifest defines all components
allow_heuristic_apps: false # Manifest defines all apps

# Plugin configuration (set by launch file when .so paths are resolved)
plugins: [""]
Expand Down
6 changes: 6 additions & 0 deletions demos/sensor_diagnostics/config/medkit_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ diagnostics:
manifest_strict_validation: true
runtime:
create_synthetic_components: false # Manifest defines components
create_synthetic_areas: false # Manifest defines areas
merge_pipeline:
gap_fill:
allow_heuristic_areas: false # Manifest defines all areas
allow_heuristic_components: false # Manifest defines all components
allow_heuristic_apps: false # Manifest defines all apps

# Plugin configuration (set by launch file when .so paths are resolved)
plugins: [""]
Expand Down
6 changes: 6 additions & 0 deletions demos/turtlebot3_integration/config/medkit_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ diagnostics:
manifest_strict_validation: true
runtime:
create_synthetic_components: false # Manifest defines components
create_synthetic_areas: false # Manifest defines areas
merge_pipeline:
gap_fill:
allow_heuristic_areas: false # Manifest defines all areas
allow_heuristic_components: false # Manifest defines all components
allow_heuristic_apps: false # Manifest defines all apps

# Plugin configuration (set by launch file when .so paths are resolved)
plugins: [""]
Expand Down
197 changes: 195 additions & 2 deletions tests/smoke_lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,23 @@ test_entity_discovery() {
local entity_type="$1"
shift
local entity_ids=("$@")
local expected_count=${#entity_ids[@]}
local label
label="${entity_type^}"

section "Entity Discovery - ${label}"

if api_get "/${entity_type}"; then
# Verify exact count - catches duplicate/synthetic entities leaking through
local actual_count
actual_count=$(echo "$RESPONSE" | jq '.items | length')
if [ "$actual_count" = "$expected_count" ]; then
pass "${entity_type} count is ${expected_count}"
else
local actual_ids
actual_ids=$(echo "$RESPONSE" | jq -r '[.items[].id] | sort | join(", ")')
fail "${entity_type} count is ${expected_count}" "got ${actual_count}: ${actual_ids}"
fi
for entity_id in "${entity_ids[@]}"; do
if echo "$RESPONSE" | items_contain_id "$entity_id"; then
pass "${entity_type} contains '${entity_id}'"
Expand All @@ -162,8 +173,190 @@ test_entity_discovery() {
fi
}

# Print test summary and exit with appropriate code
# Test that procfs introspection data is available for an app
# Usage: assert_procfs_introspection "lidar-sim"
assert_procfs_introspection() {
local app_id="$1"
local endpoint="/apps/${app_id}/x-medkit-procfs"
if api_get "$endpoint"; then
if echo "$RESPONSE" | jq -e '.pid' > /dev/null 2>&1; then
pass "GET ${endpoint} returns procfs data with pid"
else
fail "GET ${endpoint} returns procfs data with pid" "pid field missing"
fi
else
fail "GET ${endpoint} returns 200" "unexpected status code"
fi
}

# Test that scripts are listed for a component
# Usage: assert_scripts_list "compute-unit" "run-diagnostics"
assert_scripts_list() {
local component_id="$1"
local expected_script="$2"
local endpoint="/components/${component_id}/scripts"
if api_get "$endpoint"; then
if echo "$RESPONSE" | jq -e '.items | length > 0' > /dev/null 2>&1; then
pass "GET ${endpoint} returns non-empty items"
else
fail "GET ${endpoint} returns non-empty items" "items is empty"
fi
if echo "$RESPONSE" | jq -e --arg s "$expected_script" '.items[] | select(.id == $s)' > /dev/null 2>&1; then
pass "scripts contains '${expected_script}'"
else
fail "scripts contains '${expected_script}'" "not found in response"
fi
else
fail "GET ${endpoint} returns 200" "unexpected status code"
fi
}

# Execute a script and verify it completes
# Usage: assert_script_execution "compute-unit" "run-diagnostics" [max_wait]
assert_script_execution() {
local component_id="$1"
local script_id="$2"
local max_wait="${3:-30}"
local exec_endpoint="/components/${component_id}/scripts/${script_id}/executions"

# Start execution
local exec_response
exec_response=$(curl -s -w "\n%{http_code}" -X POST "${API_BASE}${exec_endpoint}" \
-H "Content-Type: application/json" \
-d '{"execution_type": "now"}' 2>/dev/null) || true
local exec_http
exec_http=$(echo "$exec_response" | tail -1)
local exec_body
exec_body=$(echo "$exec_response" | sed '$d')

if [ "$exec_http" != "201" ] && [ "$exec_http" != "200" ] && [ "$exec_http" != "202" ]; then
fail "POST ${exec_endpoint} starts execution" "got HTTP ${exec_http}"
return
fi
pass "POST ${exec_endpoint} starts execution"

local exec_id
exec_id=$(echo "$exec_body" | jq -r '.id')
if [ -z "$exec_id" ] || [ "$exec_id" = "null" ]; then
fail "script execution returns valid id" "id is null or empty"
return
fi
pass "script execution returns valid id"

# Poll until completed
echo " Waiting for script '${script_id}' to complete (max ${max_wait}s)..."
local elapsed=0
while [ $elapsed -lt "$max_wait" ]; do
if api_get "${exec_endpoint}/${exec_id}"; then
local status
status=$(echo "$RESPONSE" | jq -r '.status')
case "$status" in
completed)
pass "script '${script_id}' completed successfully"
return
;;
failed|terminated)
fail "script '${script_id}' completed successfully" "status: ${status}"
return
;;
esac
fi
sleep 1
elapsed=$((elapsed + 1))
done
fail "script '${script_id}' completed successfully" "timed out after ${max_wait}s"
}

# Test trigger CRUD lifecycle on an entity
# Usage: assert_triggers_crud "apps" "diagnostic-bridge" "/api/v1/apps/diagnostic-bridge/faults"
assert_triggers_crud() {
local entity_type="$1"
local entity_id="$2"
local resource_uri="$3"
local triggers_endpoint="/${entity_type}/${entity_id}/triggers"

# Create trigger
echo " Creating OnChange trigger on ${entity_type}/${entity_id}..."
local payload
payload=$(jq -n --arg resource "$resource_uri" \
'{resource: $resource, trigger_condition: {condition_type: "OnChange"}, multishot: true, lifetime: 60}')
local create_response
create_response=$(curl -s -w "\n%{http_code}" -X POST "${API_BASE}${triggers_endpoint}" \
-H "Content-Type: application/json" \
-d "$payload" 2>/dev/null) || true

local create_http
create_http=$(echo "$create_response" | tail -1)
local create_body
create_body=$(echo "$create_response" | sed '$d')

if [ "$create_http" = "201" ]; then
pass "POST ${triggers_endpoint} returns 201"
else
fail "POST ${triggers_endpoint} returns 201" "got HTTP ${create_http}"
return
fi

local trigger_id
trigger_id=$(echo "$create_body" | jq -r '.id')
if [ -n "$trigger_id" ] && [ "$trigger_id" != "null" ]; then
pass "trigger response contains valid id"
else
fail "trigger response contains valid id" "id is null or empty"
return
fi

local trigger_status
trigger_status=$(echo "$create_body" | jq -r '.status')
if [ "$trigger_status" = "active" ]; then
pass "trigger status is 'active'"
else
fail "trigger status is 'active'" "got '${trigger_status}'"
fi

# List triggers - verify it appears
if api_get "${triggers_endpoint}"; then
if echo "$RESPONSE" | jq -e --arg id "$trigger_id" '.items[] | select(.id == $id)' > /dev/null 2>&1; then
pass "GET ${triggers_endpoint} lists created trigger"
else
fail "GET ${triggers_endpoint} lists created trigger" "trigger ${trigger_id} not found"
fi
else
fail "GET ${triggers_endpoint} returns 200" "unexpected status code"
fi

# Delete trigger
local delete_status
delete_status=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
"${API_BASE}${triggers_endpoint}/${trigger_id}" 2>/dev/null) || true

if [ "$delete_status" = "204" ]; then
pass "DELETE trigger ${trigger_id} returns 204"
else
fail "DELETE trigger ${trigger_id} returns 204" "got HTTP ${delete_status}"
fi

# Verify trigger is gone
if api_get "${triggers_endpoint}"; then
if ! echo "$RESPONSE" | jq -e --arg id "$trigger_id" '.items[] | select(.id == $id)' > /dev/null 2>&1; then
pass "trigger no longer listed after deletion"
else
fail "trigger no longer listed after deletion" "still found in list"
fi
else
fail "GET ${triggers_endpoint} returns 200 after delete" "unexpected status code"
fi
}

# Print test summary (called via EXIT trap - do not call exit here)
SUMMARY_PRINTED=false
print_summary() {
# Guard against double-printing when called as both trap and explicit call
if [ "$SUMMARY_PRINTED" = true ]; then
return
fi
SUMMARY_PRINTED=true

echo ""
echo -e "${BLUE}================================${NC}"
local total=$((PASS_COUNT + FAIL_COUNT))
Expand All @@ -172,7 +365,7 @@ print_summary() {
if [ "$FAIL_COUNT" -gt 0 ]; then
echo -e "\n ${RED}Failed tests:${FAILED_TESTS}${NC}"
echo -e "${BLUE}================================${NC}"
exit 1
return
fi

echo -e "${BLUE}================================${NC}"
Expand Down
Loading
Loading