test_plugin.sh (4006B)
1 #!/bin/sh 2 # Plugin subsystem: handshake, config delivery, broadcast, failure semantics. 3 # 4 # Driven by tests/fixtures/plugin-echo.sh, a plugin written in POSIX shell. 5 # That is deliberate: if the suite passes with a shell plugin, the claim that 6 # plugins need no particular language is tested rather than asserted. 7 set -eu 8 HERE=$(cd "$(dirname "$0")" && pwd) 9 ROOT=$(cd "${HERE}/../.." && pwd) 10 . "${HERE}/../helpers.sh" 11 12 echo "==> test_plugin: RESP plugin subsystem" 13 14 BUILD_DIR=$(ensure_built "${ROOT}") 15 BIN="${BUILD_DIR}/linkd" 16 FIXTURE="${ROOT}/tests/fixtures/plugin-echo.sh" 17 assert_path_exists "${FIXTURE}" "shell plugin fixture present" 18 19 T=$(mktemp -d) 20 trap 'rm -rf "${T}"' EXIT 21 mkdir -p "${T}/net" 22 23 # No `auto`: nothing is applied, so the daemon needs no CAP_NET_ADMIN and 24 # cannot modify the host. The plugin still sees real PORT/RIF/NEIGH events, 25 # because the startup resync dumps the interfaces that already exist -- and 26 # reading them is unprivileged. 27 cat > "${T}/net/interfaces" <<EOF 28 iface lo 29 address 127.0.0.1/8 30 EOF 31 32 cat > "${T}/net/ports" <<EOF 33 port swp1 34 speed 25000 35 fec rs 36 autoneg 0 37 EOF 38 39 # Runs linkd to completion against a config, returning its log. 40 run_linkd() { 41 # run_linkd <config> [env assignments...] 42 _cfg=$1; shift 43 env "$@" PLUGIN_LOG="${T}/plugin.log" \ 44 timeout 15 "${BIN}" --config "${_cfg}" --resync-interval 0 \ 45 >"${T}/linkd.log" 2>&1 || true 46 cat "${T}/linkd.log" 47 } 48 49 # --- handshake + config delivery ------------------------------------------- 50 cat > "${T}/full.cnf" <<EOF 51 config_iface ${T}/net/interfaces 52 config_ports ${T}/net/ports 53 listen unix://${T}/linkd.sock 54 plugin ${FIXTURE} 55 echo-setting value1 value2 56 EOF 57 58 : > "${T}/plugin.log" 59 run_linkd "${T}/full.cnf" >/dev/null 60 61 assert_file_contains "${T}/plugin.log" "COMMAND" "plugin asked for COMMAND" 62 assert_file_contains "${T}/plugin.log" "INFO" "plugin asked for INFO" 63 assert_file_contains "${T}/plugin.log" "CONFIG LIST" "plugin asked for CONFIG LIST" 64 assert_file_contains "${T}/plugin.log" "CONFIG SET echo-setting value1 value2" \ 65 "unknown sub-directive delivered as CONFIG SET" 66 67 # Operations reach the plugin in the documented subcommand form. 68 assert_file_contains "${T}/plugin.log" "PORT APPLY swp1 speed 25000 fec rs autoneg 0" \ 69 "ports config broadcast as PORT APPLY" 70 assert_file_contains "${T}/plugin.log" "PORT ADMIN lo up" "netlink link event broadcast" 71 assert_file_contains "${T}/plugin.log" "RIF ADD lo 127.0.0.1/8" "address event broadcast as RIF ADD" 72 73 # --- hardware_detected gates the plugin ------------------------------------ 74 : > "${T}/plugin.log" 75 out=$(run_linkd "${T}/full.cnf" PLUGIN_HARDWARE=0) 76 assert_contains "${out}" "no supported hardware" "plugin reporting no hardware is refused" 77 78 # --- failure semantics ------------------------------------------------------ 79 # A required plugin failing an operation fails that operation. 80 : > "${T}/plugin.log" 81 out=$(run_linkd "${T}/full.cnf" PLUGIN_FAIL_VERB=PORT) 82 assert_contains "${out}" "port_admin lo failed" "required plugin failure fails the operation" 83 84 # The same plugin marked optional does not. 85 cat > "${T}/opt.cnf" <<EOF 86 config_iface ${T}/net/interfaces 87 listen unix://${T}/linkd.sock 88 plugin ${FIXTURE} 89 optional 90 EOF 91 : > "${T}/plugin.log" 92 out=$(run_linkd "${T}/opt.cnf" PLUGIN_FAIL_VERB=PORT) 93 case "${out}" in 94 *"port_admin lo failed"*) 95 echo "FAIL: optional plugin failure still failed the operation" >&2; exit 1 ;; 96 *"deliberate failure"*) 97 echo "PASS: optional plugin failure logged but not fatal" ;; 98 *) 99 echo "FAIL: optional plugin was not consulted at all" >&2; exit 1 ;; 100 esac 101 102 # --- no plugins configured -------------------------------------------------- 103 cat > "${T}/none.cnf" <<EOF 104 config_iface ${T}/net/interfaces 105 listen unix://${T}/linkd.sock 106 EOF 107 out=$(run_linkd "${T}/none.cnf") 108 case "${out}" in 109 *"ERROR"*plugin*) echo "FAIL: plugin errors without any plugin configured" >&2; exit 1 ;; 110 *) echo "PASS: no plugins configured is not an error" ;; 111 esac 112 113 echo "==> test_plugin done"