use portus::lang::Scope; use portus::{DatapathTrait, Report}; use std::collections::HashMap; use std::time::Instant; use tracing::info; mod libccp_integration; use crate::libccp_integration::IntegrationTest; pub struct TestTwoFlows; static mut FLOW1_RECVD: u32 = 0; static mut FLOW2_RECVD: u32 = 0; impl IntegrationTest for TestTwoFlows { fn new() -> Self { TestTwoFlows {} } fn datapath_programs() -> HashMap<&'static str, String> { // compile and return any programs to be installed in the datapath let mut h = HashMap::default(); h.insert( "TestTwoFlows", "(def (Control.number 0) (Report.value 0)) (when (> Control.number 0) (:= Report.value Control.number) (:= Control.numer 0) (report) )" .to_owned(), ); h } fn install_test(&self, dp: &mut D) -> Option { let sc = dp.set_program("TestTwoFlows", None).ok()?; let flow_num = dp.get_sock_id(); dp.update_field(&sc, &[("Control.number", flow_num * 10)]) .unwrap(); Some(sc) } fn check_test(&mut self, sc: &Scope, _t: Instant, sock_id: u32, m: &Report) -> bool { unsafe { let num = m .get_field("Report.value", sc) .expect("expected datapath value field in returned measurement") as u32; match sock_id { 1 => FLOW1_RECVD = num, 2 => FLOW2_RECVD = num, _ => unreachable!(), }; match (FLOW1_RECVD, FLOW2_RECVD) { (10, 0) | (0, 20) => false, (0, _) | (_, 0) => false, (10, 20) => true, _ => { assert_eq!(FLOW1_RECVD, 10); assert_eq!(FLOW2_RECVD, 20); unreachable!(); } } } } } #[test] fn twoflow() { info!("starting twoflow test"); libccp_integration::run_test::(2); }