cpg-test.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Test the CPG library. Requires that corosync is running and that we are root.
  2. extern crate rust_corosync as corosync;
  3. use corosync::{cpg, NodeId};
  4. use std::str;
  5. fn deliver_fn(
  6. _handle: &cpg::Handle,
  7. group_name: String,
  8. nodeid: NodeId,
  9. pid: u32,
  10. msg: &[u8],
  11. msg_len: usize,
  12. ) {
  13. println!(
  14. "TEST deliver_fn called for {group_name}, from nodeid/pid {nodeid}/{pid}. len={msg_len}"
  15. );
  16. // Print as text if it's valid UTF8
  17. match str::from_utf8(msg) {
  18. Ok(s) => println!(" {s}"),
  19. Err(_) => {
  20. for i in msg {
  21. print!("{i:02x} ");
  22. }
  23. println!();
  24. }
  25. }
  26. }
  27. fn confchg_fn(
  28. _handle: &cpg::Handle,
  29. group_name: &str,
  30. member_list: Vec<cpg::Address>,
  31. left_list: Vec<cpg::Address>,
  32. joined_list: Vec<cpg::Address>,
  33. ) {
  34. println!("TEST confchg_fn called for {group_name}");
  35. println!(" members: {member_list:?}");
  36. println!(" left: {left_list:?}");
  37. println!(" joined: {joined_list:?}");
  38. }
  39. fn totem_confchg_fn(_handle: &cpg::Handle, ring_id: cpg::RingId, member_list: Vec<NodeId>) {
  40. println!(
  41. "TEST totem_confchg_fn called for {}/{}",
  42. ring_id.nodeid, ring_id.seq
  43. );
  44. println!(" members: {member_list:?}");
  45. }
  46. fn main() -> Result<(), corosync::CsError> {
  47. // Initialise the model data
  48. let md = cpg::ModelData::ModelV1(cpg::Model1Data {
  49. flags: cpg::Model1Flags::None,
  50. deliver_fn: Some(deliver_fn),
  51. confchg_fn: Some(confchg_fn),
  52. totem_confchg_fn: Some(totem_confchg_fn),
  53. });
  54. let handle = match cpg::initialize(&md, 99_u64) {
  55. Ok(h) => h,
  56. Err(e) => {
  57. println!("Error in CPG init: {e}");
  58. return Err(e);
  59. }
  60. };
  61. if let Err(e) = cpg::join(&handle, "TEST") {
  62. println!("Error in CPG join: {e}");
  63. return Err(e);
  64. }
  65. match cpg::local_get(&handle) {
  66. Ok(n) => {
  67. println!("Local nodeid is {n}");
  68. }
  69. Err(e) => {
  70. println!("Error in CPG local_get: {e}");
  71. return Err(e);
  72. }
  73. }
  74. // Test membership_get()
  75. match cpg::membership_get(&handle, "TEST") {
  76. Ok(m) => {
  77. println!(" members: {m:?}");
  78. println!();
  79. }
  80. Err(e) => {
  81. println!("Error in CPG membership_get: {e}");
  82. return Err(e);
  83. }
  84. }
  85. // Test context APIs
  86. let set_context: u64 = 0xabcdbeefcafe;
  87. if let Err(e) = cpg::context_set(&handle, set_context) {
  88. println!("Error in CPG context_set: {e}");
  89. return Err(e);
  90. }
  91. // NOTE This will fail on 32 bit systems because void* is not u64
  92. match cpg::context_get(&handle) {
  93. Ok(c) => {
  94. if c != set_context {
  95. println!("Error: context_get() returned {c:x}, context should be {set_context:x}");
  96. }
  97. }
  98. Err(e) => {
  99. println!("Error in CPG context_get: {e}");
  100. return Err(e);
  101. }
  102. }
  103. // Test iterator
  104. match cpg::CpgIterStart::new(&handle, "", cpg::CpgIterType::All) {
  105. Ok(cpg_iter) => {
  106. for i in cpg_iter {
  107. println!("ITER: {i:?}");
  108. }
  109. println!();
  110. }
  111. Err(e) => {
  112. println!("Error in CPG iter start: {e}");
  113. return Err(e);
  114. }
  115. }
  116. // We should receive our own message (at least) in the event loop
  117. if let Err(e) = cpg::mcast_joined(
  118. &handle,
  119. cpg::Guarantee::TypeAgreed,
  120. &"This is a test".to_string().into_bytes(),
  121. ) {
  122. println!("Error in CPG mcast_joined: {e}");
  123. return Err(e);
  124. }
  125. // Check that fd_get returns a valid FD
  126. match cpg::fd_get(&handle) {
  127. Ok(fd) => {
  128. println!("FD is {fd}");
  129. // Arbitrary upper limit but FDs should always be low
  130. // and we're mainly checking addresses being returned
  131. if !(0..=0xFFFF).contains(&fd) {
  132. println!("Error - bad fd returned from fd_get: {fd}");
  133. return Err(corosync::CsError::CsErrRustCompat);
  134. }
  135. }
  136. Err(e) => {
  137. println!("Error in CPG fd_get: {e}");
  138. return Err(e);
  139. }
  140. }
  141. // Quick test of dispatch
  142. if let Err(e) = cpg::dispatch(&handle, corosync::DispatchFlags::OneNonblocking) {
  143. println!("Error in CPG dispatch: {e}");
  144. return Err(e);
  145. }
  146. Ok(())
  147. }