use super::*;
const WRITES: [(PropertyIdentifier, Option<u32>, &[u8]); 9] = [
(
PropertyIdentifier::ASSIGNED_LANDING_CALLS,
None,
&[0x0E, 0x09, 0x03, 0x19, 0x04, 0x0F, 0x0E, 0x0F],
),
(
PropertyIdentifier::MAKING_CAR_CALL,
None,
&[0x21, 0x05, 0x21, 0x00],
),
(
PropertyIdentifier::REGISTERED_CAR_CALL,
Some(2),
&[0x0E, 0x21, 0x05, 0x21, 0x06, 0x0F],
),
(PropertyIdentifier::CAR_DOOR_COMMAND, Some(2), &[0x91, 0x01]),
(
PropertyIdentifier::CAR_ASSIGNED_DIRECTION,
None,
&[0x91, 0x04],
),
(PropertyIdentifier::CAR_DOOR_ZONE, None, &[0x11]),
(PropertyIdentifier::CAR_MODE, None, &[0x91, 0x06]),
(PropertyIdentifier::NEXT_STOPPING_FLOOR, None, &[0x21, 0x05]),
(PropertyIdentifier::CAR_DRIVE_STATUS, None, &[0x91, 0x05]),
];
fn two_door_lift() -> (ObjectDatabase, ObjectIdentifier) {
let mut lift = LiftObject::new(1, "LIFT-1", 6).unwrap();
lift.set_car_door_status(vec![DoorStatus::CLOSED, DoorStatus::CLOSED])
.unwrap();
db_with(Box::new(lift))
}
#[test]
fn wp_lift_call_arrays_and_car_state_take_simulation_writes_only_out_of_service() {
let (mut db, oid) = two_door_lift();
let read_all = |db: &ObjectDatabase| -> Vec<Vec<u8>> {
WRITES
.iter()
.map(|&(property, _, _)| read_wire(db, oid, property))
.collect()
};
let fresh = read_all(&db);
assert_eq!(
fresh,
[
vec![0x0E, 0x0F, 0x0E, 0x0F],
vec![0x21, 0x00, 0x21, 0x00],
vec![0x0E, 0x0F, 0x0E, 0x0F],
vec![0x91, 0x00, 0x91, 0x00],
vec![0x91, 0x00],
vec![0x10],
vec![0x91, 0x00],
vec![0x21, 0x01],
vec![0x91, 0x00],
]
);
for (property, index, value) in WRITES {
assert_property_error(
write_at(&mut db, oid, property, index, value),
ErrorCode::WRITE_ACCESS_DENIED,
&format!("in service {property:?}"),
);
}
assert_eq!(read_all(&db), fresh);
write(
&mut db,
oid,
PropertyIdentifier::OUT_OF_SERVICE,
PropertyValue::Boolean(true),
)
.unwrap();
for (property, index, value) in WRITES {
write_at(&mut db, oid, property, index, value)
.unwrap_or_else(|e| panic!("{property:?}: {e:?}"));
assert_eq!(
read_wire_at(&db, oid, property, index).unwrap(),
value,
"{property:?}"
);
}
assert_eq!(
read_wire(&db, oid, PropertyIdentifier::REGISTERED_CAR_CALL),
[0x0E, 0x0F, 0x0E, 0x21, 0x05, 0x21, 0x06, 0x0F]
);
assert_eq!(
read_wire(&db, oid, PropertyIdentifier::CAR_DOOR_COMMAND),
[0x91, 0x00, 0x91, 0x01]
);
}
#[test]
fn wp_lift_call_arrays_and_car_state_refuse_bad_values_out_of_service() {
let (mut db, oid) = two_door_lift();
write(
&mut db,
oid,
PropertyIdentifier::OUT_OF_SERVICE,
PropertyValue::Boolean(true),
)
.unwrap();
let before: Vec<_> = WRITES
.iter()
.map(|&(property, _, _)| read_wire(&db, oid, property))
.collect();
type Case = (
PropertyIdentifier,
Option<u32>,
&'static [u8],
ErrorCode,
&'static str,
);
let cases: &[Case] = &[
(
PropertyIdentifier::ASSIGNED_LANDING_CALLS,
Some(1),
&[0x0E, 0x09, 0x03, 0x19, 0x06, 0x0F],
ErrorCode::VALUE_OUT_OF_RANGE,
"reserved direction 6",
),
(
PropertyIdentifier::ASSIGNED_LANDING_CALLS,
Some(1),
&[0x0E, 0x0A, 0x01, 0x00, 0x19, 0x03, 0x0F],
ErrorCode::VALUE_OUT_OF_RANGE,
"floor 256",
),
(
PropertyIdentifier::ASSIGNED_LANDING_CALLS,
Some(1),
&[0x0E, 0x09, 0x03, 0x0F],
ErrorCode::INVALID_DATA_ENCODING,
"floor without direction",
),
(
PropertyIdentifier::ASSIGNED_LANDING_CALLS,
None,
&[0x0E, 0x0F],
ErrorCode::VALUE_OUT_OF_RANGE,
"one element for two car doors",
),
(
PropertyIdentifier::MAKING_CAR_CALL,
Some(1),
&[0x22, 0x01, 0x00],
ErrorCode::VALUE_OUT_OF_RANGE,
"floor 256",
),
(
PropertyIdentifier::MAKING_CAR_CALL,
Some(0),
&[0x21, 0x03],
ErrorCode::WRITE_ACCESS_DENIED,
"size",
),
(
PropertyIdentifier::REGISTERED_CAR_CALL,
Some(1),
&[0x0E, 0x22, 0x01, 0x00, 0x0F],
ErrorCode::VALUE_OUT_OF_RANGE,
"floor 256",
),
(
PropertyIdentifier::REGISTERED_CAR_CALL,
Some(3),
&[0x0E, 0x0F],
ErrorCode::INVALID_ARRAY_INDEX,
"door 3",
),
(
PropertyIdentifier::REGISTERED_CAR_CALL,
Some(1),
&[0x21, 0x05],
ErrorCode::INVALID_DATA_TYPE,
"bare floor",
),
(
PropertyIdentifier::CAR_DOOR_COMMAND,
Some(1),
&[0x91, 0x03],
ErrorCode::VALUE_OUT_OF_RANGE,
"command 3",
),
(
PropertyIdentifier::CAR_ASSIGNED_DIRECTION,
None,
&[0x92, 0x03, 0xFF],
ErrorCode::VALUE_OUT_OF_RANGE,
"reserved direction 1023",
),
(
PropertyIdentifier::CAR_DOOR_ZONE,
None,
&[0x91, 0x01],
ErrorCode::INVALID_DATA_TYPE,
"Enumerated zone",
),
(
PropertyIdentifier::CAR_MODE,
None,
&[0x91, 0x0E],
ErrorCode::VALUE_OUT_OF_RANGE,
"reserved mode 14",
),
(
PropertyIdentifier::NEXT_STOPPING_FLOOR,
None,
&[0x22, 0x01, 0x00],
ErrorCode::VALUE_OUT_OF_RANGE,
"floor 256",
),
(
PropertyIdentifier::CAR_DRIVE_STATUS,
None,
&[0x91, 0x0A],
ErrorCode::VALUE_OUT_OF_RANGE,
"reserved drive status 10",
),
(
PropertyIdentifier::CAR_DRIVE_STATUS,
None,
&[0x21, 0x01],
ErrorCode::INVALID_DATA_TYPE,
"Unsigned drive status",
),
];
for &(property, index, value, expected, context) in cases {
assert_property_error(
write_at(&mut db, oid, property, index, value),
expected,
&format!("{property:?} {index:?} {context}"),
);
}
let after: Vec<_> = WRITES
.iter()
.map(|&(property, _, _)| read_wire(&db, oid, property))
.collect();
assert_eq!(after, before);
}