use assert_cmd::cargo::CommandCargoExt;
use predicates::prelude::PredicateBooleanExt;
use predicates::str::contains;
use serde_json::Value;
use std::process::Command;
mod common;
use common::fez_fake;
#[test]
fn list_json_hides_unmanaged_veth() {
fez_fake()
.args(["network", "list", "--json"])
.assert()
.success()
.stdout(contains("\"kind\":\"NetworkDeviceList\""))
.stdout(contains("enp1s0"))
.stdout(contains("enp2s0"))
.stdout(contains("lo"))
.stdout(contains("veth0").not());
}
#[test]
fn list_all_includes_veth() {
fez_fake()
.args(["network", "list", "--all", "--json"])
.assert()
.success()
.stdout(contains("veth0"));
}
#[test]
fn list_human_decodes_enums() {
fez_fake()
.args(["network", "list"])
.assert()
.success()
.stdout(contains("ethernet"))
.stdout(contains("activated"))
.stdout(contains("loopback"));
}
#[test]
fn show_json_resolves_full_detail() {
fez_fake()
.args(["network", "show", "enp1s0", "--json"])
.assert()
.success()
.stdout(contains("\"kind\":\"NetworkDeviceDetail\""))
.stdout(contains("192.168.10.20"))
.stdout(contains("192.168.10.1"))
.stdout(contains("52:54:00:12:34:56"))
.stdout(contains("802-3-ethernet"))
.stdout(contains("fd00::20"))
.stdout(contains("\"routers\":\"192.168.10.1\""));
}
#[test]
fn show_device_without_ip_config_does_not_panic() {
fez_fake()
.args(["network", "show", "enp2s0"])
.assert()
.success()
.stdout(contains("enp2s0"))
.stdout(contains("unavailable"));
}
#[test]
fn show_unknown_device_exits_4() {
fez_fake()
.args(["network", "show", "doesnotexist"])
.assert()
.code(4);
}
#[test]
fn list_json_shape_stays_stable() {
let output = Command::cargo_bin("fez")
.unwrap()
.env("FEZ_BRIDGE", env!("CARGO_BIN_EXE_fez-fake-bridge"))
.args(["network", "list", "--json"])
.output()
.unwrap();
assert!(output.status.success());
let envelope: Value = serde_json::from_slice(&output.stdout).unwrap();
assert_eq!(
envelope,
serde_json::json!({
"apiVersion": "fez/v1",
"kind": "NetworkDeviceList",
"host": "localhost",
"status": "ok",
"data": {
"columns": ["interface", "type", "state", "ip4", "ip6", "mac"],
"count": 3,
"rows": [
[
"enp1s0",
"ethernet",
"activated",
"192.168.10.20",
"fd00::20",
"52:54:00:12:34:56"
],
["enp2s0", "ethernet", "unavailable", "", "", "52:54:00:12:34:56"],
["lo", "loopback", "unmanaged", "", "", "52:54:00:12:34:56"]
]
}
})
);
}
#[test]
fn show_json_shape_stays_stable() {
let output = Command::cargo_bin("fez")
.unwrap()
.env("FEZ_BRIDGE", env!("CARGO_BIN_EXE_fez-fake-bridge"))
.args(["network", "show", "enp1s0", "--json"])
.output()
.unwrap();
assert!(output.status.success());
let envelope: Value = serde_json::from_slice(&output.stdout).unwrap();
assert_eq!(
envelope,
serde_json::json!({
"apiVersion": "fez/v1",
"kind": "NetworkDeviceDetail",
"host": "localhost",
"status": "ok",
"data": {
"connection": {
"default": true,
"id": "enp1s0",
"type": "802-3-ethernet"
},
"dhcp4": {
"ip_address": "192.168.10.20",
"routers": "192.168.10.1"
},
"interface": "enp1s0",
"ipv4": {
"addresses": ["192.168.10.20/24"],
"dns": ["192.168.10.1", "1.1.1.1"],
"domains": ["lan"],
"gateway": "192.168.10.1"
},
"ipv6": {
"addresses": ["fd00::20/64"]
},
"mac": "52:54:00:12:34:56",
"mtu": 1500,
"state": "activated",
"type": "ethernet"
}
})
);
}