Skip to content

Commit 9ac6126

Browse files
committed
tests: configure compliance tests
1 parent 610b3bb commit 9ac6126

File tree

6 files changed

+305
-0
lines changed

6 files changed

+305
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Compliance Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
compliance-tests:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Build compliance test image
17+
run: docker build -f compliance-tests/Dockerfile -t net-tools-compliance .
18+
19+
- name: Run compliance tests
20+
run: |
21+
docker run --rm \
22+
--privileged \
23+
--cap-add=NET_ADMIN \
24+
--cap-add=SYS_ADMIN \
25+
net-tools-compliance

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
# net-tools-rs
22

33
Rust implementation of [net-tools](https://sourceforge.net/projects/net-tools/).
4+
5+
The status of implemented commands is tracked in
6+
https://github.com/rust-swifties/net-tools-rs/issues/3
7+
8+
## Testing
9+
10+
Compliance tests verify that net-tools-rs commands behave identically to the original
11+
net-tools implementation. See [compliance-tests/README.md](compliance-tests/README.md) for
12+
details on running the tests.

compliance-tests/Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM rust:1-trixie
2+
3+
RUN apt-get update && apt-get install -y \
4+
net-tools \
5+
iproute2
6+
7+
WORKDIR /workspace
8+
COPY . /workspace/
9+
10+
RUN cargo build --release
11+
12+
RUN chmod +x compliance-tests/tests/*.sh
13+
WORKDIR /workspace/compliance-tests
14+
15+
CMD ["./run-tests.sh"]

compliance-tests/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Compliance Tests
2+
3+
This directory contains compliance tests that verify net-tools-rs commands behave identically to the original net-tools implementation.
4+
5+
## Structure
6+
7+
- `tests/` - Individual test scripts for each command
8+
- `Dockerfile` - Test environment with both implementations installed
9+
- `run-tests.sh` - Runner script to execute all tests
10+
11+
## Running Tests
12+
13+
### Using Docker (recommended)
14+
15+
```bash
16+
cd compliance-tests
17+
18+
# Build the test image (build context is parent directory)
19+
docker build -f Dockerfile -t net-tools-compliance ..
20+
21+
# Run all tests
22+
docker run --rm --privileged net-tools-compliance
23+
24+
# Run specific test
25+
docker run --rm --privileged net-tools-compliance ./tests/nameif_test.sh
26+
```
27+
28+
### Local testing (requires root)
29+
30+
```bash
31+
cd ../
32+
cargo build --release
33+
34+
# Run tests
35+
sudo ./run-tests.sh
36+
```
37+
38+
## Writing Tests
39+
40+
Each test script should:
41+
1. Set up test environment (create dummy interfaces, config files, etc.)
42+
2. Run the original command and capture output/behavior
43+
3. Reset environment
44+
4. Run the Rust implementation and capture output/behavior
45+
5. Compare results
46+
6. Clean up
47+
48+
Tests run in isolated network namespaces when possible to avoid interfering with the host system.
49+
50+
## CI Integration
51+
52+
These tests run in GitHub Actions using Docker containers with `--privileged` flag to allow network interface manipulation.

compliance-tests/run-tests.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/bash
2+
set -e
3+
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
TESTS_DIR="$SCRIPT_DIR/tests"
6+
7+
RED='\033[0;31m'
8+
GREEN='\033[0;32m'
9+
NC='\033[0m' # No Color
10+
11+
TOTAL_FAILED=0
12+
TOTAL_PASSED=0
13+
14+
echo "========================================"
15+
echo "Running net-tools compliance tests"
16+
echo "========================================"
17+
echo
18+
19+
for test_script in "$TESTS_DIR"/*_test.sh; do
20+
if [ -f "$test_script" ]; then
21+
if ! bash "$test_script"; then
22+
TOTAL_FAILED=$((TOTAL_FAILED + 1))
23+
fi
24+
echo
25+
fi
26+
done
27+
28+
if [ $TOTAL_FAILED -gt 0 ]; then
29+
exit 1
30+
fi
31+
32+
exit 0
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
ORIGINAL_NAMEIF="${ORIGINAL_NAMEIF:-/sbin/nameif}"
6+
RUST_NAMEIF="${RUST_NAMEIF:-/workspace/target/release/nameif}"
7+
8+
FAILED=0
9+
PASSED=0
10+
FAILED_TESTS=()
11+
12+
# Colors
13+
RED='\033[0;31m'
14+
GREEN='\033[0;32m'
15+
NC='\033[0m' # No Color
16+
17+
fail() {
18+
echo -e "${RED}FAILED${NC}"
19+
FAILED=$((FAILED + 1))
20+
FAILED_TESTS+=("$1")
21+
}
22+
23+
pass() {
24+
echo -e "${GREEN}ok${NC}"
25+
PASSED=$((PASSED + 1))
26+
}
27+
28+
cleanup() {
29+
ip link delete dummy0 2>/dev/null || true
30+
ip link delete testif0 2>/dev/null || true
31+
ip link delete testif1 2>/dev/null || true
32+
rm -f /tmp/test_mactab
33+
}
34+
35+
setup_interface() {
36+
local name=$1
37+
local mac=$2
38+
ip link add "$name" type dummy
39+
ip link set "$name" address "$mac"
40+
}
41+
42+
test_basic_rename() {
43+
echo -n "test nameif::test_basic_rename ... "
44+
cleanup
45+
46+
setup_interface dummy0 "00:11:22:33:44:55"
47+
48+
set +e
49+
$ORIGINAL_NAMEIF testif0 00:11:22:33:44:55 2>/tmp/original_stderr
50+
ORIG_EXIT=$?
51+
set -e
52+
ORIG_EXISTS=$(ip link show testif0 2>/dev/null && echo "yes" || echo "no")
53+
54+
if [ "$ORIG_EXISTS" = "yes" ]; then
55+
ip link set testif0 name dummy0 2>/dev/null || true
56+
fi
57+
58+
set +e
59+
$RUST_NAMEIF testif0 00:11:22:33:44:55 2>/tmp/rust_stderr
60+
RUST_EXIT=$?
61+
set -e
62+
RUST_EXISTS=$(ip link show testif0 2>/dev/null && echo "yes" || echo "no")
63+
64+
if [ "$ORIG_EXIT" -eq "$RUST_EXIT" ] && [ "$ORIG_EXISTS" = "$RUST_EXISTS" ]; then
65+
pass
66+
else
67+
fail "nameif::test_basic_rename"
68+
fi
69+
70+
cleanup
71+
}
72+
73+
test_config_file() {
74+
echo -n "test nameif::test_config_file ... "
75+
cleanup
76+
77+
setup_interface dummy0 "aa:bb:cc:dd:ee:ff"
78+
79+
cat > /tmp/test_mactab <<EOF
80+
testif1 aa:bb:cc:dd:ee:ff
81+
EOF
82+
83+
set +e
84+
$ORIGINAL_NAMEIF -c /tmp/test_mactab 2>/tmp/original_stderr
85+
ORIG_EXIT=$?
86+
set -e
87+
ORIG_EXISTS=$(ip link show testif1 2>/dev/null && echo "yes" || echo "no")
88+
89+
if [ "$ORIG_EXISTS" = "yes" ]; then
90+
ip link set testif1 name dummy0 2>/dev/null || true
91+
fi
92+
93+
set +e
94+
$RUST_NAMEIF -c /tmp/test_mactab 2>/tmp/rust_stderr
95+
RUST_EXIT=$?
96+
set -e
97+
RUST_EXISTS=$(ip link show testif1 2>/dev/null && echo "yes" || echo "no")
98+
99+
if [ "$ORIG_EXIT" -eq "$RUST_EXIT" ] && [ "$ORIG_EXISTS" = "$RUST_EXISTS" ]; then
100+
pass
101+
else
102+
fail "nameif::test_config_file"
103+
fi
104+
105+
cleanup
106+
}
107+
108+
test_missing_interface() {
109+
echo -n "test nameif::test_missing_interface ... "
110+
cleanup
111+
112+
set +e
113+
$ORIGINAL_NAMEIF testnonexist 00:00:00:00:00:00 2>/tmp/original_stderr
114+
ORIG_EXIT=$?
115+
116+
$RUST_NAMEIF testnonexist 00:00:00:00:00:00 2>/tmp/rust_stderr
117+
RUST_EXIT=$?
118+
set -e
119+
120+
if [ "$ORIG_EXIT" -eq "$RUST_EXIT" ]; then
121+
pass
122+
else
123+
fail "nameif::test_missing_interface"
124+
fi
125+
126+
cleanup
127+
}
128+
129+
test_invalid_mac() {
130+
echo -n "test nameif::test_invalid_mac ... "
131+
cleanup
132+
133+
set +e
134+
$ORIGINAL_NAMEIF testif0 "invalid:mac" 2>/tmp/original_stderr
135+
ORIG_EXIT=$?
136+
137+
$RUST_NAMEIF testif0 "invalid:mac" 2>/tmp/rust_stderr
138+
RUST_EXIT=$?
139+
set -e
140+
141+
# Both should fail
142+
if [ "$ORIG_EXIT" -ne 0 ] && [ "$RUST_EXIT" -ne 0 ]; then
143+
pass
144+
else
145+
fail "nameif::test_invalid_mac"
146+
fi
147+
148+
cleanup
149+
}
150+
151+
echo "running nameif tests"
152+
test_basic_rename
153+
test_config_file
154+
test_missing_interface
155+
test_invalid_mac
156+
157+
echo
158+
if [ $FAILED -gt 0 ]; then
159+
echo "failures:"
160+
for test in "${FAILED_TESTS[@]}"; do
161+
echo " $test"
162+
done
163+
echo
164+
fi
165+
166+
if [ $FAILED -eq 0 ]; then
167+
echo -e "test result: ${GREEN}ok${NC}. $PASSED passed; $FAILED failed"
168+
exit 0
169+
else
170+
echo -e "test result: ${RED}FAILED${NC}. $PASSED passed; $FAILED failed"
171+
exit 1
172+
fi

0 commit comments

Comments
 (0)