#!/usr/bin/env bash # SPDX-License-Identifier: LGPL-2.1-or-later set -eux set -o pipefail # shellcheck source=test/units/test-control.sh . "$(dirname "$0")"/test-control.sh SERVICE_TYPE_COUNT=10 SERVICE_COUNT=20 CONTAINER_ZONE="test-$RANDOM" CONTAINER_1="test-mdns-1" CONTAINER_2="test-mdns-2" # Prepare containers create_container() { local container="${1:?}" local stype sid svc # Prepare container's /etc # # Since we also need the various test suite related dropins from the host's /etc, # we'll overlay our customizations on top of that mkdir -p "/var/lib/machines/$container/etc/systemd/dnssd" # Create 20 test services for each service type (_testServiceX._udp) and number them sequentially, # i.e. create services 0-19 for _testService0._udp, services 20-39 for _testService1._udp, and so on for stype in $(seq 0 $((SERVICE_TYPE_COUNT - 1))); do for sid in $(seq 0 $((SERVICE_COUNT - 1))); do svc=$((stype * SERVICE_COUNT + sid)) cat >"/var/lib/machines/$container/etc/systemd/dnssd/test-service-$container-$svc.dnssd" <"/run/systemd/system/systemd-nspawn@$container.service.d/override.conf" <&2 "Found a record from an unreachable container" cat "$result_file" exit 1 fi done # We got all records and all of them are what we expect return 0 fi return 1 } run_and_check_services() { local service_id="${1:?}" local check_func="${2:?}" local unit_name="varlinkctl-$service_id-$SRANDOM.service" local i out_file parameters service_type svc tmp_file out_file="$(mktemp)" error_file="$(mktemp)" tmp_file="$(mktemp)" service_type="_testService$service_id._udp" parameters="{ \"domain\": \"$service_type.local\", \"type\": \"\", \"ifindex\": ${BRIDGE_INDEX:?}, \"flags\": 16785432 }" systemd-run --unit="$unit_name" --service-type=exec -p StandardOutput="file:$out_file" -p StandardError="file:$error_file" \ varlinkctl call --more /run/systemd/resolve/io.systemd.Resolve io.systemd.Resolve.BrowseServices "$parameters" # shellcheck disable=SC2064 # Note: unregister the trap once it's fired, otherwise it'll get propagated to functions that call this # one, *sigh* trap "trap - RETURN; systemctl stop $unit_name" RETURN for _ in {0..14}; do # The response format, for reference (it's JSON-SEQ): # # { # "browser_service_data": [ # { # "updateFlag": true, # "family": 10, # "name": "Test Service 13 on test-mdns-1", # "type": "_testService0._udp", # "domain": "local", # "interface": 3 # }, # ... # ] # } if [[ -s "$out_file" ]]; then # Extract the service name from each valid record... # jq --slurp --raw-output \ # ".[].browser_service_data[] | select(.updateFlag == true and .type == \"$service_type\" and .family == 10).name" "$out_file" | sort | tee "$tmp_file" grep -o '"name":"[^"]*"' "$out_file" | sed 's/"name":"//;s/"//g' | sort | tee "$tmp_file" # ...and compare them with what we expect if "$check_func" "$service_id" "$tmp_file"; then return 0 fi fi sleep 2 done cat "$out_file" cat "$error_file" return 1 } testcase_all_sequential() { : "Test each service type (sequentially)" resolvectl flush-caches for id in $(seq 0 $((SERVICE_TYPE_COUNT - 1))); do run_and_check_services "$id" check_both done echo testcase_end } testcase_all_parallel() { : "Test each service type (in parallel)" resolvectl flush-caches for id in $(seq 0 $((SERVICE_TYPE_COUNT - 1))); do run_and_check_services "$id" check_both & done wait } testcase_single_service_multiple_times() { : "Test one service type multiple times" resolvectl flush-caches for _ in {0..4}; do run_and_check_services 4 check_both done } testcase_second_unreachable() { : "Test each service type while the second container is unreachable" systemd-run -M "$CONTAINER_2" --wait --pipe -- networkctl down host0 resolvectl flush-caches for id in $(seq 0 $((SERVICE_TYPE_COUNT - 1))); do run_and_check_services "$id" check_first done : "Test each service type after bringing the second container back up again" systemd-run -M "$CONTAINER_2" --wait --pipe -- networkctl up host0 systemd-run -M "$CONTAINER_2" --wait --pipe -- \ /usr/lib/systemd/systemd-networkd-wait-online --ipv4 --ipv6 --interface=host0 --operational-state=degraded --timeout=30 for id in $(seq 0 $((SERVICE_TYPE_COUNT - 1))); do run_and_check_services "$id" check_both done } : "Setup host & containers" # Note: create the drop-in intentionally under /run/ and copy it manually into the containers mkdir -p /run/systemd/resolved.conf.d/ cat >/run/systemd/resolved.conf.d/99-mdns-llmnr.conf <