mod test_pvxs_remote_enum_get_put {
use pvxs_sys::{Context, NTEnumMetadataBuilder, PvxsError, Server};
#[test]
fn test_pv_remote_enum_get_put() {
let timeout = 5.0;
let choices = vec!["DISABLED", "ENABLED", "TESTING"];
let initial_index = 0; let name = "remote:enum";
let srv = Server::start_from_env().expect("Failed to create server from env");
srv.create_pv_enum(
name,
choices.clone(),
initial_index,
NTEnumMetadataBuilder::new(),
)
.expect("Failed to create pv:enum on server");
let mut ctx = Context::from_env().expect("Failed to create client context from env");
let first_get: Result<pvxs_sys::Value, PvxsError> = ctx.get(name, timeout);
match first_get {
Ok(value) => {
let index = value.get_field_enum("value.index").unwrap();
assert_eq!(index, initial_index);
let retrieved_choices = value.get_field_string_array("value.choices").unwrap();
assert_eq!(retrieved_choices.len(), choices.len());
assert_eq!(retrieved_choices[0], "DISABLED");
assert_eq!(retrieved_choices[1], "ENABLED");
assert_eq!(retrieved_choices[2], "TESTING");
}
Err(e) => assert!(false, "Failed to get value from remote pv: {:?}", e),
}
srv.stop_drop().expect("Failed to stop server");
let failed_get: Result<pvxs_sys::Value, PvxsError> = ctx.get(name, timeout);
match failed_get {
Ok(_) => assert!(
false,
"Expected error when getting from stopped server, but got Ok"
),
Err(e) => {
assert!(e.to_string().contains("Timeout") || e.to_string().contains("Error"));
}
}
let srv = Server::start_from_env().expect("Failed to restart server");
srv.create_pv_enum(
name,
choices.clone(),
initial_index,
NTEnumMetadataBuilder::new(),
)
.expect("Failed to create pv:enum on server");
let new_index = 1; match ctx.put_enum(name, new_index, timeout) {
Ok(_) => (),
Err(e) => assert!(false, "Failed to put new enum value to remote pv: {:?}", e),
}
let second_get: Result<pvxs_sys::Value, PvxsError> = ctx.get(name, timeout);
match second_get {
Ok(value) => {
let index = value.get_field_enum("value.index").unwrap();
assert_eq!(index, new_index);
}
Err(e) => assert!(false, "Failed to get value from remote pv: {:?}", e),
}
srv.stop_drop().expect("Failed to stop server");
}
#[test]
fn test_pv_remote_enum_state_transitions() {
let timeout = 5.0;
let name = "remote:enum:states";
let choices = vec!["INIT", "READY", "ACTIVE", "PAUSED", "STOPPED"];
let srv = Server::start_from_env().expect("Failed to create server from env");
srv.create_pv_enum(name, choices.clone(), 0, NTEnumMetadataBuilder::new())
.expect("Failed to create pv:enum on server");
let mut ctx = Context::from_env().expect("Failed to create client context from env");
for (expected_index, expected_state) in choices.iter().enumerate() {
ctx.put_enum(name, expected_index as i16, timeout)
.expect(&format!("Failed to put state {}", expected_state));
let value = ctx
.get(name, timeout)
.expect(&format!("Failed to get state {}", expected_state));
let index = value.get_field_enum("value.index").unwrap();
assert_eq!(index as usize, expected_index);
let retrieved_choices = value.get_field_string_array("value.choices").unwrap();
assert_eq!(&retrieved_choices[index as usize], expected_state);
}
srv.stop_drop().expect("Failed to stop server");
}
#[test]
fn test_pv_remote_enum_invalid_index() {
let timeout = 5.0;
let name = "remote:enum:invalid";
let choices = vec!["OPTION_A", "OPTION_B", "OPTION_C"];
let srv = Server::start_from_env().expect("Failed to create server from env");
srv.create_pv_enum(name, choices.clone(), 0, NTEnumMetadataBuilder::new())
.expect("Failed to create pv:enum on server");
let mut ctx = Context::from_env().expect("Failed to create client context from env");
match ctx.put_enum(name, 99, timeout) {
Ok(_) => {
assert!(false, "Server accepted out-of-range enum index");
}
Err(_) => {
assert!(true, "Server did not reject invalid index"); }
}
match ctx.put_enum(name, -1, timeout) {
Ok(_) => assert!(false, "Server accepted negative enum index"),
Err(_) => {
assert!(true, "Server did not reject a negative index"); }
}
srv.stop_drop().expect("Failed to stop server");
}
#[test]
fn test_pv_remote_enum_choices_immutable() {
let timeout = 5.0;
let name = "remote:enum:immutable";
let choices = vec!["CHOICE_1", "CHOICE_2", "CHOICE_3", "CHOICE_4"];
let srv = Server::start_from_env().expect("Failed to create server from env");
srv.create_pv_enum(name, choices.clone(), 0, NTEnumMetadataBuilder::new())
.expect("Failed to create pv:enum on server");
let mut ctx = Context::from_env().expect("Failed to create client context from env");
let initial_value = ctx.get(name, timeout).expect("Failed to get initial value");
let initial_choices = initial_value
.get_field_string_array("value.choices")
.unwrap();
for idx in 0..choices.len() {
ctx.put_enum(name, idx as i16, timeout)
.expect(&format!("Failed to put index {}", idx));
}
let final_value = ctx.get(name, timeout).expect("Failed to get final value");
let final_choices = final_value.get_field_string_array("value.choices").unwrap();
assert_eq!(initial_choices.len(), final_choices.len());
for (i, (initial, final_choice)) in
initial_choices.iter().zip(final_choices.iter()).enumerate()
{
assert_eq!(initial, final_choice, "Choice at index {} changed", i);
}
srv.stop_drop().expect("Failed to stop server");
}
}