use rand::{thread_rng, Rng}; use either::Either; use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::role::end::RoleEnd; use mpstthree::role::Role; use std::error::Error; use mpstthree::generate; // Create new roles generate!("basic", MeshedChannels, A, B, D); // Those types will be code generated type OfferMpstThree = Recv, MeshedChannels>, End>; type ChooseMpstThree = Send< Either< MeshedChannels<::Dual, ::Dual, ::Dual, N0>, MeshedChannels<::Dual, ::Dual, ::Dual, N0>, >, End, >; // Types type AtoCClose = End; type AtoBClose = End; type AtoCVideo = Recv>; type AtoBVideo = Send>; type BtoAClose = ::Dual; type BtoCClose = End; type BtoAVideo = as Session>::Dual; type CtoBClose = ::Dual; type CtoAClose = ::Dual; type CtoAVideo = as Session>::Dual; // Stacks type StackAEnd = RoleEnd; type StackAVideo = RoleD>>>; type StackAVideoDual = ::Dual; type StackAFull = RoleD>>; type StackBEnd = RoleEnd; type StackBVideo = RoleA>; type StackBVideoDual = ::Dual; type StackBFull = RoleAlltoD; type StackCEnd = RoleEnd; type StackCVideo = RoleA>; type StackCChoice = RoleDtoAll; type StackCFull = RoleA>; // Creating the MP sessions // For C type ChooseCtoA = ChooseMpstThree< BtoAVideo, CtoAVideo, BtoAClose, CtoAClose, StackAVideoDual, StackAEnd, NameA, >; type ChooseCtoB = ChooseMpstThree< AtoBVideo, CtoBClose, AtoBClose, CtoBClose, StackBVideoDual, StackBEnd, NameB, >; type InitC = Send>>; type EndpointCFull = MeshedChannels, ChooseCtoB, StackCFull, NameD>; // For A type EndpointAVideo = MeshedChannels, AtoCVideo, StackAVideo, NameA>; type EndpointAEnd = MeshedChannels; type OfferA = OfferMpstThree, AtoCVideo, AtoBClose, AtoCClose, StackAVideo, StackAEnd, NameA>; type InitA = Recv>>; type EndpointAFull = MeshedChannels, StackAFull, NameA>; // For B type EndpointBVideo = MeshedChannels, BtoCClose, StackBVideo, NameB>; type EndpointBEnd = MeshedChannels; type OfferB = OfferMpstThree, BtoCClose, BtoAClose, BtoCClose, StackBVideo, StackBEnd, NameB>; type EndpointBFull = MeshedChannels, StackBFull, NameB>; // Functions related to endpoints fn server(s: EndpointBFull) -> Result<(), Box> { s.offer( |s: EndpointBVideo| { let (request, s) = s.recv(); s.send(request + 1).close() }, |s: EndpointBEnd| s.close(), ) } fn authenticator(s: EndpointAFull) -> Result<(), Box> { let (id, s) = s.recv(); s.send(id + 1).offer( |s: EndpointAVideo| { let (request, s) = s.recv(); let (video, s) = s.send(request + 1).recv(); assert_eq!(request, id + 1); assert_eq!(video, id + 3); s.send(video + 1).close() }, |s: EndpointAEnd| s.close(), ) } fn client_video(s: EndpointCFull) -> Result<(), Box> { let mut rng = thread_rng(); let id: i32 = rng.gen(); let (accept, s) = s.send(id).recv(); assert_eq!(accept, id + 1); let (result, s) = s.choose_left().send(accept).recv(); assert_eq!(result, accept + 3); s.close() } fn client_close(s: EndpointCFull) -> Result<(), Box> { let mut rng = thread_rng(); let id: i32 = rng.gen(); let (accept, s) = s.send(id).recv(); assert_eq!(accept, id + 1); s.choose_right().close() } //////////////////////////////////////// pub fn test_new_choice_full() { // Test video branch. let (thread_a, thread_pawn, thread_d) = fork_mpst(authenticator, server, client_video); assert!(thread_a.join().is_ok()); assert!(thread_pawn.join().is_ok()); assert!(thread_d.join().is_ok()); } pub fn test_new_choice_close() { // Test end branch. let (thread_a, thread_pawn, thread_d) = fork_mpst(authenticator, server, client_close); assert!(thread_a.join().is_ok()); assert!(thread_pawn.join().is_ok()); assert!(thread_d.join().is_ok()); }