extern crate modbus;
extern crate test_server;
mod connection_tests {
use modbus::tcp::{Config, Transport};
use std::time::{Duration, Instant};
#[test]
fn test_connect_timeout() {
let mut cfg = Config::default();
cfg.tcp_connect_timeout = Some(Duration::from_millis(1050));
let now = Instant::now();
if Transport::new_with_cfg("30.30.30.30", cfg).is_err() {
let elapsed = now.elapsed().as_secs();
assert_eq!(elapsed, 1, "Elapsed: {}", elapsed);
}
}
}
#[cfg(feature = "modbus-server-tests")]
mod modbus_server_tests {
use modbus::scoped::{CoilDropFunction, RegisterDropFunction, ScopedCoil, ScopedRegister};
use modbus::tcp::{Config, Transport};
use modbus::{Client, Coil};
use test_server::{start_dummy_server, ChildKiller};
fn start_dummy_server_with_cfg() -> (ChildKiller, Config) {
let (k, port) = start_dummy_server(None);
let mut cfg = Config::default();
cfg.tcp_port = port;
(k, cfg)
}
#[test]
fn test_read_coils() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert_eq!(trans.read_coils(0, 5).unwrap().len(), 5);
assert!(trans
.read_coils(0, 5)
.unwrap()
.iter()
.all(|c| *c == Coil::Off));
}
#[test]
fn test_read_discrete_inputs() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert_eq!(trans.read_discrete_inputs(0, 5).unwrap().len(), 5);
assert!(trans
.read_discrete_inputs(0, 5)
.unwrap()
.iter()
.all(|c| *c == Coil::Off));
}
#[test]
fn test_read_holding_registers() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert_eq!(trans.read_holding_registers(0, 5).unwrap().len(), 5);
assert!(trans
.read_holding_registers(0, 5)
.unwrap()
.iter()
.all(|c| *c == 0));
}
#[test]
fn test_read_input_registers() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert_eq!(trans.read_input_registers(0, 5).unwrap().len(), 5);
assert!(trans
.read_input_registers(0, 5)
.unwrap()
.iter()
.all(|c| *c == 0));
}
#[test]
fn test_write_single_coil() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_single_coil(0, Coil::On).is_ok());
}
#[test]
fn test_write_single_register() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_single_register(0, 1).is_ok());
}
#[test]
fn test_write_multiple_coils() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans
.write_multiple_coils(0, &[Coil::On, Coil::Off])
.is_ok());
}
#[test]
fn test_write_multiple_registers() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_multiple_registers(0, &[0, 1, 2, 3]).is_ok());
}
#[test]
fn test_write_read_single_coils() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_single_coil(1, Coil::On).is_ok());
assert!(trans.write_single_coil(3, Coil::On).is_ok());
assert_eq!(
trans.read_coils(0, 5).unwrap(),
vec![Coil::Off, Coil::On, Coil::Off, Coil::On, Coil::Off]
);
assert_eq!(
trans.read_coils(1, 5).unwrap(),
vec![Coil::On, Coil::Off, Coil::On, Coil::Off, Coil::Off]
);
assert!(trans.write_single_coil(10, Coil::On).is_ok());
assert!(trans.write_single_coil(11, Coil::On).is_ok());
assert_eq!(
trans.read_coils(9, 4).unwrap(),
vec![Coil::Off, Coil::On, Coil::On, Coil::Off]
);
assert!(trans.write_single_coil(10, Coil::Off).is_ok());
assert!(trans.write_single_coil(11, Coil::Off).is_ok());
assert_eq!(
trans.read_coils(9, 4).unwrap(),
vec![Coil::Off, Coil::Off, Coil::Off, Coil::Off]
);
}
#[test]
fn test_write_read_single_register() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_single_register(0, 23).is_ok());
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![23]);
assert!(trans.write_single_register(0, 0).is_ok());
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0]);
assert_eq!(trans.read_input_registers(0, 1).unwrap(), vec![0]);
assert!(trans.write_single_register(0, 23).is_ok());
assert!(trans.write_single_register(1, 24).is_ok());
assert_eq!(trans.read_holding_registers(0, 2).unwrap(), vec![23, 24]);
}
#[test]
fn test_write_read_multiple_coils() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans
.write_multiple_coils(0, &[Coil::Off, Coil::On])
.is_ok());
assert_eq!(
trans.read_coils(0, 3).unwrap(),
&[Coil::Off, Coil::On, Coil::Off]
);
assert!(trans.write_multiple_coils(0, &[Coil::On; 9]).is_ok());
assert_eq!(trans.read_coils(0, 9).unwrap(), &[Coil::On; 9]);
}
#[test]
fn test_write_read_multiple_registers() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_multiple_registers(0, &[23]).is_ok());
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), &[23]);
assert!(trans.write_multiple_registers(0, &[1, 2, 3]).is_ok());
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), &[1]);
assert_eq!(trans.read_holding_registers(1, 1).unwrap(), &[2]);
assert_eq!(trans.read_holding_registers(2, 1).unwrap(), &[3]);
assert_eq!(trans.read_holding_registers(0, 3).unwrap(), &[1, 2, 3]);
}
#[test]
fn test_write_too_big() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
assert!(trans.write_multiple_registers(0, &[0xdead; 123]).is_ok());
assert!(trans.write_multiple_registers(0, &[0xdead; 124]).is_err());
}
#[test]
fn test_scoped_coil() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
{
let mut auto = ScopedCoil::new(&mut trans, 0, CoilDropFunction::On).unwrap();
assert_eq!(
auto.mut_transport().read_coils(0, 1).unwrap(),
vec![Coil::Off]
);
}
assert_eq!(trans.read_coils(0, 1).unwrap(), vec![Coil::On]);
{
let mut auto = ScopedCoil::new(&mut trans, 0, CoilDropFunction::Off).unwrap();
assert_eq!(
auto.mut_transport().read_coils(0, 1).unwrap(),
vec![Coil::On]
);
}
assert_eq!(trans.read_coils(0, 1).unwrap(), vec![Coil::Off]);
{
let mut auto = ScopedCoil::new(&mut trans, 0, CoilDropFunction::Toggle).unwrap();
assert_eq!(
auto.mut_transport().read_coils(0, 1).unwrap(),
vec![Coil::Off]
);
}
assert_eq!(trans.read_coils(0, 1).unwrap(), vec![Coil::On]);
{
let mut auto = ScopedCoil::new(&mut trans, 0, CoilDropFunction::Toggle).unwrap();
assert_eq!(
auto.mut_transport().read_coils(0, 1).unwrap(),
vec![Coil::On]
);
}
assert_eq!(trans.read_coils(0, 1).unwrap(), vec![Coil::Off]);
{
let mut auto = ScopedCoil::new(&mut trans, 1, CoilDropFunction::Toggle).unwrap();
assert_eq!(
auto.mut_transport().read_coils(1, 1).unwrap(),
vec![Coil::Off]
);
}
assert_eq!(trans.read_coils(1, 1).unwrap(), vec![Coil::On]);
}
#[test]
fn test_scoped_register() {
let (_s, cfg) = start_dummy_server_with_cfg();
let mut trans = Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
{
let mut auto =
ScopedRegister::new(&mut trans, 0, RegisterDropFunction::Value(0xbeef)).unwrap();
assert_eq!(
auto.mut_transport().read_holding_registers(0, 1).unwrap(),
vec![0x0000]
);
}
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0xbeef]);
{
let mut auto = ScopedRegister::new(&mut trans, 0, RegisterDropFunction::Zero).unwrap();
assert_eq!(
auto.mut_transport().read_holding_registers(0, 1).unwrap(),
vec![0xbeef]
);
}
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0x0000]);
{
let mut auto =
ScopedRegister::new(&mut trans, 0, RegisterDropFunction::Increment).unwrap();
assert_eq!(
auto.mut_transport().read_holding_registers(0, 1).unwrap(),
vec![0x0000]
);
}
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0x0001]);
{
let mut auto =
ScopedRegister::new(&mut trans, 0, RegisterDropFunction::Increment).unwrap();
assert_eq!(
auto.mut_transport().read_holding_registers(0, 1).unwrap(),
vec![0x0001]
);
}
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0x0002]);
{
let mut auto =
ScopedRegister::new(&mut trans, 0, RegisterDropFunction::Decrement).unwrap();
assert_eq!(
auto.mut_transport().read_holding_registers(0, 1).unwrap(),
vec![0x0002]
);
}
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0x0001]);
{
let fun = |v| v + 0xbeee;
let mut auto =
ScopedRegister::new(&mut trans, 0, RegisterDropFunction::Fun(&fun)).unwrap();
assert_eq!(
auto.mut_transport().read_holding_registers(0, 1).unwrap(),
vec![0x0001]
);
}
assert_eq!(trans.read_holding_registers(0, 1).unwrap(), vec![0xbeef]);
}
}