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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
acceptance_tests:
needs: unit_tests
uses: ./.github/workflows/acceptance_tests.yml
reactor_tests:
needs: unit_tests
uses: ./.github/workflows/reactor_tests.yml
macos_unit_tests:
needs: unit_tests
uses: ./.github/workflows/macos_unit_tests.yml
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/reactor_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Reactor Tests

on:
workflow_call

jobs:
reactor_tests:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Install dependencies
run: ./ci/dependencies.sh
- name: Run autotools / configure
run: ./autogen.sh --enable-debug
- name: Compile and link (make)
run: make -j8 CFLAGS="-Werror -Wall"
- name: Run reactor tests
run: |
mkdir -p "$RUNNER_TEMP/bin"
ln -s "$PWD/cf-reactor/cf-reactor" "$PWD/cf-promises/cf-promises" "$RUNNER_TEMP/bin/"
cd tests/reactor
chmod -R go-w .
CF_BINDIR="$RUNNER_TEMP/bin" sh run.sh
5 changes: 5 additions & 0 deletions cf-reactor/file_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ WatcherCheckResult FileWatcherCheckFileDeleted(void *state)
return WATCHER_CHECK_ERROR;
}

if (exists && !fws->last_exists)
{
Log(LOG_LEVEL_VERBOSE, "File '%s' is present, watching for its deletion", fws->path);
}

bool deleted = fws->last_exists && !exists;
return FileWatcherRecordObservation(fws, exists, deleted, "deletion");
}
Expand Down
7 changes: 7 additions & 0 deletions tests/reactor/lib.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bundle agent record_event(file, message)
{
reports:
"$(with): $(message)"
with => strftime("localtime", "%Y-%m-%d %H:%M:%S", now()),
report_to_file => "$(file)";
}
54 changes: 54 additions & 0 deletions tests/reactor/lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Helpers sourced by the tests. Expects CF_BINDIR and LOG to be exported by
# run.sh.

# number of log lines already consumed by wait_for_log
log_offset=0

# Wait until the reactor log contains $1 in a line after the last match, then
# skip past that line, so that the next wait only sees newer output.
wait_for_log() {
if ! match=$(timeout 60 sh -c '
until tail -n "+$(($2 + 1))" "$1" | grep -n -F -m 1 -- "$3"; do
sleep 0.1
done' _ "$LOG" "$log_offset" "$1")
then
echo "Timed out waiting for '$1' in reactor log:" >&2
cat "$LOG" >&2
return 1
fi
log_offset=$((log_offset + ${match%%:*}))
}

# Wait until file $1 has at least $2 lines, then fail if it has more than $2.
wait_for_lines() {
if ! timeout 60 sh -c '
until [ "$(cat "$1" 2>/dev/null | wc -l)" -ge "$2" ]; do
sleep 0.1
done' _ "$1" "$2"
then
echo "Timed out waiting for $2 line(s) in '$1', reactor log:" >&2
cat "$LOG" >&2
return 1
fi

lines=$(wc -l < "$1")
if [ "$lines" -ne "$2" ]
then
echo "Expected $2 line(s) in '$1', got $lines" >&2
return 1
fi
}

# Start cf-reactor in the background with policy file $1, logging to $LOG.
# It is stopped when the test exits.
start_reactor() {
"$CF_BINDIR/cf-reactor" --no-fork --verbose -f "$1" >>"$LOG" 2>&1 &
reactor_pid=$!
trap stop_reactor EXIT
}

stop_reactor() {
echo "Exiting cf-reactor..."
kill -TERM "$reactor_pid" 2>/dev/null || true
wait "$reactor_pid" 2>/dev/null || true
}
43 changes: 43 additions & 0 deletions tests/reactor/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/sh

fail=0

banner() {
name=" $(basename "$1") "
width=72
left=$(( (width - ${#name}) / 2 ))
right=$(( width - ${#name} - left ))
[ "$left" -lt 0 ] && left=0
[ "$right" -lt 0 ] && right=0
printf '%s%s%s\n' \
"$(printf "%${left}s" '' | tr ' ' '=')" \
"$name" \
"$(printf "%${right}s" '' | tr ' ' '=')"
}

error() {
echo "test '$1' FAILED" >&2
fail=1
}

CF_BINDIR=${CF_BINDIR:-/var/cfengine/bin}
export CF_BINDIR

for t in "$PWD"/tests/*.sh; do
banner "$t"

# create throwaway work dir
WORKDIR=$(mktemp -d)
mkdir -p "$WORKDIR/bin" "$WORKDIR/tmp"
ln -s "$CF_BINDIR/cf-promises" "$WORKDIR/bin/"
CFENGINE_TEST_OVERRIDE_WORKDIR="$WORKDIR"
LOG="$WORKDIR/reactor.log"
PROMISE_NAME=$(basename "$t" .sh)
export WORKDIR CFENGINE_TEST_OVERRIDE_WORKDIR LOG PROMISE_NAME

sh "$t" "${t%.sh}.cf" || error "$t"

rm -rf "$WORKDIR"
done

exit $fail
24 changes: 24 additions & 0 deletions tests/reactor/tests/001_vars.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
body common control
{
inputs => { "../lib.cf" };
bundlesequence => { "test" };
version => "1.0";
}

body when deleted(file)
{
file_deleted => "$(file)";
}

bundle reactor test
{
vars:
"test" string => getenv("TESTFILE", 999);
"events_file" string => getenv("EVENTS_FILE", 999);
"promise_name" string => basename("$(this.promise_filename)", ".cf");

events:
"$(promise_name)"
when => deleted("$(test)"),
then => record_event("$(events_file)", "$(test) was deleted");
}
24 changes: 24 additions & 0 deletions tests/reactor/tests/001_vars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh
Comment thread
victormlg marked this conversation as resolved.

set -ex

. "$(dirname "$0")/../lib.sh"

TESTFILE="$WORKDIR/tmp/test"
EVENTS_FILE="$WORKDIR/tmp/events"
export TESTFILE EVENTS_FILE

# create initial file
touch "$TESTFILE"

start_reactor "$1"

wait_for_log "File '$TESTFILE' is present, watching for its deletion"
rm "$TESTFILE"
wait_for_lines "$EVENTS_FILE" 1

# recreate the file and wait for the watcher to see it before deleting it again
touch "$TESTFILE"
wait_for_log "File '$TESTFILE' is present, watching for its deletion"
rm "$TESTFILE"
wait_for_lines "$EVENTS_FILE" 2
Loading