//! Test for parametrisation on the number of roles //! Checks that "generate!" macro works: //! check that the generated "send" and "recv", //! as well as the generated "offer_mpst!" and //! "choose_mpst!" macros work accordingly to the //! specifications in a non-recursive //! multiparty protocol. use rand::{thread_rng, Rng}; use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::message::Message; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use mpstthree::{choose_mpst_create_multi_to_all, generate}; use std::error::Error; use Option::None; // use Option::{None, Some}; // Create new roles generate!("basic", MeshedChannels, A, B, D); // Test our usecase // Simple types // Client = D // Authenticator = A // Server = B type AtoDClose = End; type AtoBClose = End; type AtoBVideo = Send>, Recv>, End>>; type AtoDVideo = Recv>, Send>, RecursAtoD>>; type InitA = Recv, Send, RecursAtoD>>; type BtoAClose = ::Dual; type BtoDClose = End; type BtoAVideo = ::Dual; type RecursAtoD = ::Dual; type RecursBtoD = ::Dual; enum Branches0AtoD { End(MeshedChannels), Video(MeshedChannels), } enum Branches0BtoD { End(MeshedChannels), Video(MeshedChannels), } type Choose0fromCtoA = Send; type Choose0fromCtoB = Send; type InitD = Send, Recv, Choose0fromCtoA>>; // Stacks type StackAEnd = RoleEnd; type StackAVideo = RoleD>>>>; type StackARecurs = RoleD; type StackAInit = RoleD>>; type StackBEnd = RoleEnd; type StackBVideo = RoleA>>; type StackBRecurs = RoleD; type StackDRecurs = RoleBroadcast; type StackDFull = RoleA>; // Creating the MP sessions // For D type EndpointDVideo = MeshedChannels< ::Dual, ::Dual, RoleA>, NameD, >; type EndpointDRecurs = MeshedChannels; type EndpointDFull = MeshedChannels; // For A type EndpointARecurs = MeshedChannels; type EndpointAFull = MeshedChannels; // For B type EndpointBRecurs = MeshedChannels; choose_mpst_create_multi_to_all!(choose_mpst_client_to_all, NameD, MeshedChannels, 3); // Functions related to endpoints fn server(s: EndpointBRecurs) -> Result<(), Box> { offer_mpst!(s, { Branches0BtoD::End(s) => { s.close() }, Branches0BtoD::Video(s) => { let (_, s) = s.recv(); let s = s.send(Message { label: "video".to_string(), payload: None, }); server(s) }, }) } fn authenticator(s: EndpointAFull) -> Result<(), Box> { let (id, s) = s.recv(); let s = s.send(id); authenticator_recurs(s) } fn authenticator_recurs(s: EndpointARecurs) -> Result<(), Box> { offer_mpst!(s, { Branches0AtoD::End(s) => { s.close() }, Branches0AtoD::Video(s) => { let (_, s) = s.recv(); let (_, s) = s.send(Message { label: "request".to_string(), payload: None, }).recv(); let s = s.send(Message { label: "video".to_string(), payload: Some(0), }); authenticator_recurs(s) }, }) } fn client(s: EndpointDFull) -> Result<(), Box> { let mut rng = thread_rng(); let xs: Vec = (1..100).map(|_| rng.gen()).collect(); let (_, s) = s .send(Message { label: String::from("Start"), payload: 0, }) .recv(); client_recurs(s, xs, 1) } fn client_recurs(s: EndpointDRecurs, mut xs: Vec, index: i32) -> Result<(), Box> { match xs.pop() { Some(_) => { let s: EndpointDVideo = choose_mpst_client_to_all!(s, Branches0AtoD::Video, Branches0BtoD::Video); let (_, s) = s .send(Message { label: format!("Loop number {index}"), payload: Some(index), }) .recv(); client_recurs(s, xs, index + 1) } None => { let s = choose_mpst_client_to_all!(s, Branches0AtoD::End, Branches0BtoD::End); assert_eq!(index, 100); s.close() } } } //////////////////////////////////////// pub fn new_run_usecase_recursive() { let (thread_a, thread_b, thread_c) = fork_mpst(authenticator, server, client); assert!(thread_a.join().is_ok()); assert!(thread_b.join().is_ok()); assert!(thread_c.join().is_ok()); }