use rsvici::{Client, Error};
use futures_util::{pin_mut, stream::TryStreamExt};
use pretty_assertions::assert_eq;
use serde::{Deserialize, Serialize};
use tokio_test::io::Builder;
#[derive(Debug, Deserialize, Eq, PartialEq)]
struct ControlLog {
group: String,
level: u32,
#[serde(rename = "ikesa-name")]
ikesa_name: String,
#[serde(rename = "ikesa-uniqueid")]
ikesa_uniqueid: u64,
msg: String,
}
#[derive(Debug, Serialize)]
struct Initiate {
ike: String,
child: String,
}
#[tokio::test]
async fn stream_request_with_success() {
#[rustfmt::skip]
let mock_stream = Builder::new()
.write(&[
0, 0, 0, 13,
3, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
])
.read(&[
0, 0, 0, 1,
5,
])
.write(&[
0, 0, 0, 38,
0, 8, b'i', b'n', b'i', b't', b'i', b'a', b't', b'e',
3, 3, b'i', b'k', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 5, b'c', b'h', b'i', b'l', b'd', 0, 7, b'n', b'e', b't', b'-', b'n', b'e', b't',
])
.read(&[
0, 0, 0, 107,
7, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
3, 5, b'g', b'r', b'o', b'u', b'p', 0, 3, b'I', b'K', b'E',
3, 5, b'l', b'e', b'v', b'e', b'l', 0, 1, b'1',
3, 10, b'i', b'k', b'e', b's', b'a', b'-', b'n', b'a', b'm', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 14, b'i', b'k', b'e', b's', b'a', b'-', b'u', b'n', b'i', b'q', b'u', b'e', b'i', b'd', 0, 2, b'1', b'2',
3, 3, b'm', b's', b'g', 0, 26, b'I', b'K', b'E', b'_', b'S', b'A', b' ', b'g', b'w', b'-', b'g', b'w', b'[', b'1', b'2', b']', b' ', b'i', b'n', b'i', b't', b'i', b'a', b't', b'e', b'd',
])
.read(&[
0, 0, 0, 103,
7, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
3, 5, b'g', b'r', b'o', b'u', b'p', 0, 3, b'E', b'N', b'C',
3, 5, b'l', b'e', b'v', b'e', b'l', 0, 1, b'1',
3, 10, b'i', b'k', b'e', b's', b'a', b'-', b'n', b'a', b'm', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 14, b'i', b'k', b'e', b's', b'a', b'-', b'u', b'n', b'i', b'q', b'u', b'e', b'i', b'd', 0, 2, b'1', b'2',
3, 3, b'm', b's', b'g', 0, 22, b'A', b'E', b'S', b'-', b'C', b'B', b'C', b'-', b'1', b'2', b'8', b' ', b'n', b'e', b'g', b'o', b't', b'i', b'a', b't', b'e', b'd',
])
.read(&[
0, 0, 0, 15,
1,
3, 7, b's', b'u', b'c', b'c', b'e', b's', b's', 0, 3, b'y', b'e', b's',
])
.write(&[
0, 0, 0, 13,
4, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
])
.read(&[
0, 0, 0, 1,
5,
])
.build();
let mut client = Client::new(mock_stream);
let initiate = Initiate {
ike: "gw-gw".to_string(),
child: "net-net".to_string(),
};
let stream = client.stream_request::<Initiate, ControlLog>("initiate", "control-log", initiate);
let actual: Vec<ControlLog> = stream.try_collect().await.unwrap();
assert_eq!(
actual,
vec![
ControlLog {
group: "IKE".to_string(),
level: 1,
ikesa_name: "gw-gw".to_string(),
ikesa_uniqueid: 12,
msg: "IKE_SA gw-gw[12] initiated".to_string(),
},
ControlLog {
group: "ENC".to_string(),
level: 1,
ikesa_name: "gw-gw".to_string(),
ikesa_uniqueid: 12,
msg: "AES-CBC-128 negotiated".to_string(),
},
]
);
}
#[tokio::test]
async fn stream_request_with_failure() {
#[rustfmt::skip]
let mock_stream = Builder::new()
.write(&[
0, 0, 0, 13,
3, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
])
.read(&[
0, 0, 0, 1,
5,
])
.write(&[
0, 0, 0, 38,
0, 8, b'i', b'n', b'i', b't', b'i', b'a', b't', b'e',
3, 3, b'i', b'k', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 5, b'c', b'h', b'i', b'l', b'd', 0, 7, b'n', b'e', b't', b'-', b'n', b'e', b't',
])
.read(&[
0, 0, 0, 100,
7, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
3, 5, b'g', b'r', b'o', b'u', b'p', 0, 3, b'E', b'N', b'C',
3, 5, b'l', b'e', b'v', b'e', b'l', 0, 1, b'1',
3, 10, b'i', b'k', b'e', b's', b'a', b'-', b'n', b'a', b'm', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 14, b'i', b'k', b'e', b's', b'a', b'-', b'u', b'n', b'i', b'q', b'u', b'e', b'i', b'd', 0, 2, b'1', b'2',
3, 3, b'm', b's', b'g', 0, 19, b'f', b'a', b'i', b'l', b'e', b'd', b' ', b't', b'o', b' ', b'n', b'e', b'g', b'o', b't', b'i', b'a', b't', b'e',
])
.read(&[
0, 0, 0, 55,
1,
3, 7, b's', b'u', b'c', b'c', b'e', b's', b's', 0, 2, b'n', b'o',
3, 6, b'e', b'r', b'r', b'm', b's', b'g', 0, 31, b'c', b'h', b'i', b'l', b'd', b' ', b'i', b'n', b'i', b't', b'i', b'a', b't', b'i', b'o', b'n', b' ', b'n', b'e', b't', b'-', b'n', b'e', b't', b' ', b'f', b'a', b'i', b'l', b'e', b'd',
])
.write(&[
0, 0, 0, 13,
4, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
])
.read(&[
0, 0, 0, 1,
5,
])
.build();
let mut client = Client::new(mock_stream);
let initiate = Initiate {
ike: "gw-gw".to_string(),
child: "net-net".to_string(),
};
let stream = client.stream_request::<Initiate, ControlLog>("initiate", "control-log", initiate);
pin_mut!(stream);
let mut items: Vec<ControlLog> = Vec::new();
let mut err: Option<Error> = None;
loop {
match stream.try_next().await {
Ok(Some(item)) => items.push(item),
Ok(None) => break,
Err(e) => {
err = Some(e);
break;
},
}
}
assert_eq!(
items,
vec![ControlLog {
group: "ENC".to_string(),
level: 1,
ikesa_name: "gw-gw".to_string(),
ikesa_uniqueid: 12,
msg: "failed to negotiate".to_string(),
}]
);
assert_eq!(err.map(|e| e.to_string()), Some("command failed: child initiation net-net failed".to_string()));
}
#[tokio::test]
async fn stream_request_with_failure_no_errmsg() {
#[rustfmt::skip]
let mock_stream = Builder::new()
.write(&[
0, 0, 0, 13,
3, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
])
.read(&[
0, 0, 0, 1,
5,
])
.write(&[
0, 0, 0, 38,
0, 8, b'i', b'n', b'i', b't', b'i', b'a', b't', b'e',
3, 3, b'i', b'k', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 5, b'c', b'h', b'i', b'l', b'd', 0, 7, b'n', b'e', b't', b'-', b'n', b'e', b't',
])
.read(&[
0, 0, 0, 100,
7, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
3, 5, b'g', b'r', b'o', b'u', b'p', 0, 3, b'E', b'N', b'C',
3, 5, b'l', b'e', b'v', b'e', b'l', 0, 1, b'1',
3, 10, b'i', b'k', b'e', b's', b'a', b'-', b'n', b'a', b'm', b'e', 0, 5, b'g', b'w', b'-', b'g', b'w',
3, 14, b'i', b'k', b'e', b's', b'a', b'-', b'u', b'n', b'i', b'q', b'u', b'e', b'i', b'd', 0, 2, b'1', b'2',
3, 3, b'm', b's', b'g', 0, 19, b'f', b'a', b'i', b'l', b'e', b'd', b' ', b't', b'o', b' ', b'n', b'e', b'g', b'o', b't', b'i', b'a', b't', b'e',
])
.read(&[
0, 0, 0, 14,
1,
3, 7, b's', b'u', b'c', b'c', b'e', b's', b's', 0, 2, b'n', b'o',
])
.write(&[
0, 0, 0, 13,
4, 11, b'c', b'o', b'n', b't', b'r', b'o', b'l', b'-', b'l', b'o', b'g',
])
.read(&[
0, 0, 0, 1,
5,
])
.build();
let mut client = Client::new(mock_stream);
let initiate = Initiate {
ike: "gw-gw".to_string(),
child: "net-net".to_string(),
};
let stream = client.stream_request::<Initiate, ControlLog>("initiate", "control-log", initiate);
pin_mut!(stream);
let mut items: Vec<ControlLog> = Vec::new();
let mut err: Option<Error> = None;
loop {
match stream.try_next().await {
Ok(Some(item)) => items.push(item),
Ok(None) => break,
Err(e) => {
err = Some(e);
break;
},
}
}
assert_eq!(
items,
vec![ControlLog {
group: "ENC".to_string(),
level: 1,
ikesa_name: "gw-gw".to_string(),
ikesa_uniqueid: 12,
msg: "failed to negotiate".to_string(),
}]
);
assert_eq!(err.map(|e| e.to_string()), Some("command failed".to_string()));
}