1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! Access Door writes against its metadata: the command priority, the
//! Relinquish_Default gate, and the rows writable only out of service.
use super::*;
#[test]
fn property_metadata_access_door_writes_command_priority_and_gate_relinquish() {
for out_of_service in [false, true] {
let mut object = AccessDoorObject::new(1, "DOOR-1").unwrap();
object
.write_property(
P::OUT_OF_SERVICE,
None,
PropertyValue::Boolean(out_of_service),
None,
)
.unwrap();
// A priority write commands Present_Value; relinquishing the slot
// falls back to Relinquish_Default.
object
.write_property(
P::PRESENT_VALUE,
None,
PropertyValue::Enumerated(1),
Some(8),
)
.unwrap();
assert_eq!(
object.read_property(P::PRESENT_VALUE, None).unwrap(),
PropertyValue::Enumerated(1)
);
assert_eq!(
object.read_property(P::PRIORITY_ARRAY, Some(8)).unwrap(),
PropertyValue::Enumerated(1)
);
object
.write_property(P::PRESENT_VALUE, None, PropertyValue::Null, Some(8))
.unwrap();
assert_eq!(
object.read_property(P::PRESENT_VALUE, None).unwrap(),
PropertyValue::Enumerated(0)
);
// Relinquish_Default admits LOCK and UNLOCK (Clause 12.26.11)
// and resolves Present_Value anew from the empty array.
for raw in [0u32, 1] {
object
.write_property(
P::RELINQUISH_DEFAULT,
None,
PropertyValue::Enumerated(raw),
None,
)
.unwrap();
assert_eq!(
object.read_property(P::RELINQUISH_DEFAULT, None).unwrap(),
PropertyValue::Enumerated(raw)
);
assert_eq!(
object.read_property(P::PRESENT_VALUE, None).unwrap(),
PropertyValue::Enumerated(raw)
);
}
object
.write_property(
P::RELINQUISH_DEFAULT,
None,
PropertyValue::Enumerated(1),
None,
)
.unwrap();
for raw in [2, 3, 4] {
assert_error(
object
.write_property(
P::RELINQUISH_DEFAULT,
None,
PropertyValue::Enumerated(raw),
None,
)
.unwrap_err(),
ErrorCode::VALUE_OUT_OF_RANGE,
);
}
assert_eq!(
object.read_property(P::RELINQUISH_DEFAULT, None).unwrap(),
PropertyValue::Enumerated(1)
);
// Mistyped values are rejected without changing state.
for (p, value) in [
(P::PRESENT_VALUE, PropertyValue::Real(1.0)),
(P::RELINQUISH_DEFAULT, PropertyValue::Real(1.0)),
(P::DOOR_PULSE_TIME, PropertyValue::Real(1.0)),
(P::DESCRIPTION, PropertyValue::Unsigned(1)),
(P::OUT_OF_SERVICE, PropertyValue::Unsigned(1)),
] {
assert_error(
object.write_property(p, None, value, None).unwrap_err(),
ErrorCode::INVALID_DATA_TYPE,
);
}
assert_eq!(
object.read_property(P::PRESENT_VALUE, None).unwrap(),
PropertyValue::Enumerated(1)
);
// The footnote-1 status rows (#1131) and Reliability (#1149) take
// their own readback only while out of service.
for p in [
P::DOOR_STATUS,
P::LOCK_STATUS,
P::DOOR_ALARM_STATE,
P::RELIABILITY,
] {
let value = object.read_property(p, None).unwrap();
let result = object.write_property(p, None, value, None);
if out_of_service {
result.unwrap();
} else {
assert_error(result.unwrap_err(), ErrorCode::WRITE_ACCESS_DENIED);
}
assert!(object.is_writable_property(p));
}
// The other Table-O status rows and the readable-only rows deny
// even their own readback on write.
for p in [
P::SECURED_STATUS,
P::DOOR_MEMBERS,
P::PRIORITY_ARRAY,
P::EVENT_STATE,
P::STATUS_FLAGS,
P::CURRENT_COMMAND_PRIORITY,
P::ACKED_TRANSITIONS,
P::EVENT_TIME_STAMPS,
P::EVENT_MESSAGE_TEXTS,
] {
let value = object.read_property(p, None).unwrap();
assert_error(
object.write_property(p, None, value, None).unwrap_err(),
ErrorCode::WRITE_ACCESS_DENIED,
);
assert!(!object.is_writable_property(p));
}
}
}