Skip to content

Commit caf2d80

Browse files
committed
Initial load-generator -> 5 homeserver and load-generator -> 1 proxy -> 2 homeserver multi-server tests and environment.
1 parent 260540c commit caf2d80

30 files changed

Lines changed: 1797 additions & 0 deletions
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
name: Multi-Server CI Tests
2+
3+
on:
4+
push:
5+
branches-ignore:
6+
- coverity_scan
7+
- run-fuzzer**
8+
- debug-fuzzer-**
9+
pull_request:
10+
paths:
11+
- '.github/workflows/ci-multi-server-tests.yml'
12+
- 'src/tests/multi-server/**'
13+
workflow_dispatch:
14+
15+
jobs:
16+
pre-test:
17+
runs-on: ubuntu-latest
18+
outputs:
19+
#selfhosted: 0
20+
selfhosted: ${{ (github.repository_owner == 'FreeRADIUS') && '1' || '0' }}
21+
steps:
22+
- run: echo "Pre-test job; checking if using self-hosted runners"
23+
24+
# Job only runs on GitHub-hosted runners
25+
test-5hs-autoaccept:
26+
needs: pre-test
27+
runs-on: ubuntu-24.04
28+
if: ${{ needs.pre-test.outputs.selfhosted != '1' }}
29+
30+
env:
31+
MULTI_SERVER_ENV_DOCKER_BUILD_OS: ubuntu24
32+
MULTI_SERVER_TEST_LOG: build/tests/multi-server/freeradius-multi-server/multi_server_test.log
33+
MULTI_SERVER_TEST_LISTENER_LOG: build/tests/multi-server/freeradius-listener-logs/custom_test-env-5hs-autoaccept.txt.bak
34+
35+
steps:
36+
# Checkout, but defer pulling LFS objects until we've restored the cache
37+
- uses: actions/checkout@v4
38+
with:
39+
lfs: false
40+
41+
- name: Package manager performance improvements
42+
run: |
43+
sudo sh -c 'echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02speedup'
44+
echo 'man-db man-db/auto-update boolean false' | sudo debconf-set-selections
45+
sudo dpkg-reconfigure man-db
46+
sudo sed -i 's/^update_initramfs=.*/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf
47+
48+
- name: NetworkRADIUS signing key
49+
shell: bash
50+
run: |
51+
sudo install -d -o root -g root -m 0755 /etc/apt/keyrings
52+
curl -s 'https://packages.inkbridgenetworks.com/pgp/packages.networkradius.com.asc' | sudo tee /etc/apt/keyrings/packages.networkradius.com.asc > /dev/null
53+
54+
- name: Set up NetworkRADIUS extras repository
55+
shell: bash
56+
run: |
57+
DIST=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
58+
RELEASE=$(lsb_release -cs)
59+
sudo /bin/sh -c "echo \"deb [arch=amd64 signed-by=/etc/apt/keyrings/packages.networkradius.com.asc] http://packages.networkradius.com/extras/${DIST}/${RELEASE} ${RELEASE} main\" \
60+
> /etc/apt/sources.list.d/networkradius-extras.list"
61+
sudo apt-get update
62+
63+
# Remove pre-installed package which conflicts with dependency installation
64+
- name: Remove package conflicts
65+
run: |
66+
sudo apt-get remove -y libhashkit2
67+
68+
# Installing build dependencies requires a ubuntu-24.04 runner
69+
- name: Install build dependencies
70+
run: |
71+
sudo apt-get install -y --no-install-recommends build-essential devscripts equivs quilt
72+
debian/rules debian/control
73+
sudo mk-build-deps -irt"apt-get -y --no-install-recommends" debian/control
74+
sudo mk-build-deps -irt"apt-get -y --no-install-recommends" scripts/ci/extra-packages.debian.control
75+
76+
- name: Build Docker image for multi-server test environment
77+
run: |
78+
./configure
79+
make docker.${MULTI_SERVER_ENV_DOCKER_BUILD_OS}.build
80+
81+
# List all images
82+
docker images --all
83+
84+
# Tag freeradius build image using using a non-OS specific name to be used with the multi-server docker compose environment.
85+
docker tag freeradius4/${MULTI_SERVER_ENV_DOCKER_BUILD_OS}:latest freeradius-build:latest
86+
87+
- name: Run test-5hs-autoaccept test
88+
run: |
89+
if ! docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^freeradius-build:latest$"; then
90+
echo "Error: freeradius-build:latest Docker image not found and required for multi-server test environment."
91+
exit 1
92+
fi
93+
make -f src/tests/multi-server/all.mk test-5hs-autoaccept VERBOSE=4
94+
95+
- name: Verify test results
96+
shell: bash
97+
run: |
98+
set -euo pipefail
99+
100+
echo "============ ${MULTI_SERVER_TEST_LOG} ============"
101+
cat "${MULTI_SERVER_TEST_LOG}"
102+
103+
if grep -q '\[Failed\]' "${MULTI_SERVER_TEST_LOG}"; then
104+
echo "TEST FAILED: Found [Failed] in log"
105+
grep '\[Failed\]' "${MULTI_SERVER_TEST_LOG}"
106+
107+
# Display the framework's listener log for debugging purposes
108+
echo "============ ${MULTI_SERVER_TEST_LISTENER_LOG} ============"
109+
cat "${MULTI_SERVER_TEST_LISTENER_LOG}"
110+
exit 1
111+
fi
112+
113+
if grep -Eq '\(Failures:[[:space:]]*[1-9][0-9]*[[:space:]]*\)' "${MULTI_SERVER_TEST_LOG}"; then
114+
echo "TEST FAILED: Found Failures > 0 in log"
115+
grep -E '\(Failures:[[:space:]]*[1-9][0-9]*[[:space:]]*\)' "${MULTI_SERVER_TEST_LOG}"
116+
117+
# Display the framework's listener log for debugging purposes
118+
echo "============ ${MULTI_SERVER_TEST_LISTENER_LOG} ============"
119+
cat "${MULTI_SERVER_TEST_LISTENER_LOG}"
120+
exit 1
121+
fi
122+
123+
log="${MULTI_SERVER_TEST_LOG}"
124+
if awk '
125+
BEGIN { found=0; n1=0; n2=0; line="" }
126+
index($0,"Matched:") {
127+
orig=$0
128+
s=$0
129+
gsub(/[[:space:]]/, "", s)
130+
sub(/^.*Matched:/, "", s)
131+
sub(/\(.*/, "", s)
132+
n = split(s, parts, "/")
133+
if (n == 2) {
134+
a = parts[1] + 0
135+
b = parts[2] + 0
136+
if (a > 0 && a == b) { found=1; n1=a; n2=b; line=orig }
137+
}
138+
}
139+
END {
140+
if (found) { printf "MATCH: %d / %d\nMatched line: %s\n", n1, n2, line; exit 0 }
141+
exit 1
142+
}
143+
' "$log"
144+
then
145+
: # PASS
146+
else
147+
echo "TEST FAILED: No Matched line found with equal non-zero counts"
148+
# Display the framework's listener log for debugging purposes
149+
echo "============ ${MULTI_SERVER_TEST_LISTENER_LOG} ============"
150+
cat "${MULTI_SERVER_TEST_LISTENER_LOG}"
151+
exit 1
152+
fi
153+
154+
# Job only runs on self-hosted runners
155+
test-5hs-autoaccept-selfhosted:
156+
needs: pre-test
157+
runs-on: self-hosted
158+
if: ${{ needs.pre-test.outputs.selfhosted == '1' }}
159+
160+
env:
161+
MULTI_SERVER_TEST_LOG: build/tests/multi-server/freeradius-multi-server/multi_server_test.log
162+
MULTI_SERVER_TEST_LISTENER_LOG: build/tests/multi-server/freeradius-listener-logs/custom_test-env-5hs-autoaccept.txt.bak
163+
steps:
164+
165+
# Need git installed for checkout to behave normally
166+
- name: Install multi-server framework test environment dependencies
167+
run: |
168+
apt-get update
169+
apt-get install -y build-essential
170+
apt-get install -y --no-install-recommends git git-lfs ca-certificates
171+
make --version
172+
173+
# Checkout, but defer pulling LFS objects until we've restored the cache
174+
- uses: actions/checkout@v4
175+
with:
176+
lfs: false
177+
178+
- name: Get pre-built Docker image for self-hosted runner test
179+
shell: bash
180+
env:
181+
DOCKER_REGISTRY: docker.internal.networkradius.com
182+
DOCKER_IMAGE: self-hosted-ubuntu24
183+
run: |
184+
docker pull "${DOCKER_REGISTRY}/${DOCKER_IMAGE}"
185+
186+
# Tag freeradius build image using using a non-OS specific name to be used with the multi-server docker compose environment.
187+
docker tag "${DOCKER_REGISTRY}/${DOCKER_IMAGE}" freeradius-build:latest
188+
189+
# Display all docker images for debugging purposes
190+
docker images --all
191+
192+
- name: Configure and build freeradius-server from src
193+
shell: bash
194+
run: |
195+
# The multi-server test framework requires the availability of the $BUILD_DIR, hence why
196+
# the following is needed before running multi-server tests.
197+
./configure
198+
make -j"$(nproc)" all
199+
200+
- name: Run test-5hs-autoaccept test
201+
shell: bash
202+
run: |
203+
if ! docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^freeradius-build:latest$"; then
204+
echo "Error: freeradius-build:latest Docker image not found and required for multi-server test environment."
205+
exit 1
206+
fi
207+
208+
ls -l
209+
which make
210+
make -f src/tests/multi-server/all.mk test-5hs-autoaccept
211+
212+
- name: Verify test results
213+
shell: bash
214+
run: |
215+
set -euo pipefail
216+
217+
echo "============ ${MULTI_SERVER_TEST_LOG} ============"
218+
cat "${MULTI_SERVER_TEST_LOG}"
219+
220+
if grep -q '\[Failed\]' "${MULTI_SERVER_TEST_LOG}"; then
221+
echo "TEST FAILED: Found [Failed] in log"
222+
grep '\[Failed\]' "${MULTI_SERVER_TEST_LOG}"
223+
224+
# Display the framework's listener log for debugging purposes
225+
echo "============ ${MULTI_SERVER_TEST_LISTENER_LOG} ============"
226+
cat "${MULTI_SERVER_TEST_LISTENER_LOG}"
227+
exit 1
228+
fi
229+
230+
if grep -Eq '\(Failures:[[:space:]]*[1-9][0-9]*[[:space:]]*\)' "${MULTI_SERVER_TEST_LOG}"; then
231+
echo "TEST FAILED: Found Failures > 0 in log"
232+
grep -E '\(Failures:[[:space:]]*[1-9][0-9]*[[:space:]]*\)' "${MULTI_SERVER_TEST_LOG}"
233+
234+
# Display the framework's listener log for debugging purposes
235+
echo "============ ${MULTI_SERVER_TEST_LISTENER_LOG} ============"
236+
cat "${MULTI_SERVER_TEST_LISTENER_LOG}"
237+
exit 1
238+
fi
239+
240+
log="${MULTI_SERVER_TEST_LOG}"
241+
if awk '
242+
BEGIN { found=0; n1=0; n2=0; line="" }
243+
index($0,"Matched:") {
244+
orig=$0
245+
s=$0
246+
gsub(/[[:space:]]/, "", s)
247+
sub(/^.*Matched:/, "", s)
248+
sub(/\(.*/, "", s)
249+
n = split(s, parts, "/")
250+
if (n == 2) {
251+
a = parts[1] + 0
252+
b = parts[2] + 0
253+
if (a > 0 && a == b) { found=1; n1=a; n2=b; line=orig }
254+
}
255+
}
256+
END {
257+
if (found) { printf "MATCH: %d / %d\nMatched line: %s\n", n1, n2, line; exit 0 }
258+
exit 1
259+
}
260+
' "$log"
261+
then
262+
: # PASS
263+
else
264+
echo "TEST FAILED: No Matched line found with equal non-zero counts"
265+
266+
# Display the framework's listener log for debugging purposes
267+
echo "============ ${MULTI_SERVER_TEST_LISTENER_LOG} ============"
268+
cat "${MULTI_SERVER_TEST_LISTENER_LOG}"
269+
exit 1
270+
fi
271+
272+
#
273+
# If the CI has failed and the branch is loadgen-5hs-tests then we start a tmate
274+
# session to provide interactive shell access to the session.
275+
#
276+
# The SSH rendezvous point will be emited continuously in the job output,
277+
# which will look something like:
278+
#
279+
# SSH: ssh VfuX8SrNuU5pGPMyZcz7TpJTa@sfo2.tmate.io
280+
#
281+
# For example:
282+
#
283+
# git push origin loadgen-5hs-tests --force
284+
#
285+
# Look at the job output in: https://github.com/FreeRADIUS/freeradius-server/actions
286+
#
287+
# ssh VfuX8SrNuU5pGPMyZcz7TpJTa@sfo2.tmate.io
288+
#
289+
# Access requires that you have the private key corresponding to the
290+
# public key of the GitHub user that initiated the job.
291+
#
292+
- name: "Debug: Start tmate"
293+
uses: mxschmitt/action-tmate@v3
294+
with:
295+
limit-access-to-actor: true
296+
if: ${{ github.ref == 'refs/heads/loadgen-5hs-tests' && failure() }}

src/tests/multi-server/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
If you are reading this, you are probably wondering how to run a multi-server test. Here's a quick overview.
2+
3+
## Run Test With Makefile
4+
5+
1. Build an image of freeradius-server and tag it as "freeradius-build:latest". All docker compose files for the multi-server tests use "freeradius-build:latest".
6+
```bash
7+
% cd ${FREERADIUS-SERVER-LOCAL-REPO}
8+
% make docker.ubuntu24.build
9+
% docker tag <your-freeradius-build-tag> freeradius-build:latest
10+
```
11+
2. Run make target based on the test name. All testcase config files start with "test-*".
12+
```bash
13+
% cd ${FREERADIUS-SERVER-LOCAL-REPO}/src/tests/multi-server
14+
% make -f all.mk test-5hs-autoaccept
15+
```
16+
or
17+
```bash
18+
% cd ${FREERADIUS-SERVER-LOCAL-REPO}/src/tests/multi-server
19+
% make -f all.mk test-5hs-autoaccept-5min
20+
```
21+
22+
## Run Multi-Server Tests Manually
23+
24+
### Clone Multi-Server Framework Repo
25+
```bash
26+
git clone git@github.com:InkbridgeNetworks/freeradius-multi-server.git
27+
cd ${FREERADIUS-MULTI-SERVER-LOCAL-REPO}
28+
./configure
29+
source .venv/bin/activate
30+
```
31+
32+
### Render Jinja Templates (e.g. test-5hs-autoaccept):
33+
34+
Homeserver config:
35+
```bash
36+
% python3 src/config_builder.py \
37+
--vars-file "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml" \
38+
--aux-file "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/configs/freeradius/homeserver/radiusd.conf.j2" \
39+
--include-path "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/"
40+
```
41+
Load-generator config:
42+
```bash
43+
python3 src/config_builder.py \
44+
--vars-file "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml" \
45+
--aux-file "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/configs/freeradius/load-generator/radiusd.conf.j2" \
46+
--include-path "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/"
47+
```
48+
Test Environment Docker compose:
49+
```bash
50+
python3 src/config_builder.py \
51+
--vars-file "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml" \
52+
--aux-file "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml.j2" \
53+
--include-path "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/"
54+
```
55+
56+
### Run test (e.g. test-5hs-autoaccept):
57+
```bash
58+
% DATA_PATH="${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/configs" \
59+
make test-framework -- -x -v \
60+
--compose "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml" \
61+
--test "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/src/tests/multi-server/test-5hs-autoaccept.yml" \
62+
--use-files \
63+
--listener-dir "${FREERADIUS-SERVER-LOCAL-REPO-PATH-ABS}/build/tests/multi-server/freeradius-listener-logs/test-5hs-autoaccept"
64+
```

0 commit comments

Comments
 (0)