diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/routes_acceptance.rs | 23 | ||||
| -rw-r--r-- | tests/vm_tun_acceptance.py | 46 |
2 files changed, 69 insertions, 0 deletions
diff --git a/tests/routes_acceptance.rs b/tests/routes_acceptance.rs new file mode 100644 index 0000000..608e309 --- /dev/null +++ b/tests/routes_acceptance.rs @@ -0,0 +1,23 @@ +#![cfg(feature = "linux-runtime")] + +use futures_util::TryStreamExt; +use rtnetlink::packet_route::link::LinkAttribute; + +// Run on the disposable ALT VM, including with no active roentgen0. A dump +// omits missing interfaces, whereas the production named lookup returns ENODEV. +#[tokio::test] +async fn tun_lookup_agrees_with_kernel_link_dump() -> anyhow::Result<()> { + let (connection, handle, _) = rtnetlink::new_connection()?; + tokio::spawn(connection); + let mut links = handle.link().get().execute(); + let mut expected = None; + while let Some(link) = links.try_next().await? { + if link.attributes.iter().any(|attribute| { + matches!(attribute, LinkAttribute::IfName(name) if name == "roentgen0") + }) { + expected = Some(link.header.index); + } + } + assert_eq!(roentgen::linux::routes::tun_index().await?, expected); + Ok(()) +} diff --git a/tests/vm_tun_acceptance.py b/tests/vm_tun_acceptance.py new file mode 100644 index 0000000..619459e --- /dev/null +++ b/tests/vm_tun_acceptance.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Verify a selected real configuration on the authorized disposable ALT VM.""" +import argparse +import ipaddress +import json +import os +import socket +import subprocess + + +def command(*args): + return subprocess.run(args, check=True, capture_output=True, text=True, timeout=35).stdout.strip() + + +def public_ipv4(): + value = command('curl', '-4', '--noproxy', '*', '--fail', '--silent', '--show-error', + '--connect-timeout', '5', '--max-time', '15', 'https://ifconfig.me') + return str(ipaddress.IPv4Address(value)) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--expected-ip', required=True, type=ipaddress.IPv4Address) + args = parser.parse_args() + assert os.geteuid() == 0 and socket.gethostname() == 'altctlrs' + binary = '/usr/local/bin/roentgen' + status = json.loads(command(binary, 'status', '--json')) + assert not status['requested_enabled'], 'Start with proxying disabled' + assert status['selected_configuration'], 'Select the real configuration before running' + direct = public_ipv4() + try: + command(binary, 'enable') + status = json.loads(command(binary, 'status', '--json')) + assert status['requested_enabled'] and status['routing'] == 'tun', status + proxied = public_ipv4() + assert proxied == str(args.expected_ip), (proxied, str(args.expected_ip)) + assert proxied != direct, 'Proxy IPv4 must differ from direct IPv4' + finally: + command(binary, 'disable') + restored = public_ipv4() + assert restored == direct, (restored, direct) + print(json.dumps({'direct_ipv4': direct, 'tun_ipv4': proxied, 'restored_ipv4': restored})) + + +if __name__ == '__main__': + main() |