Skip to content

Commit a4915bb

Browse files
authored
Merge pull request #4 from project-chip/feature/timed_request_tests
Add tests for timed requests
2 parents bb23396 + 91b451d commit a4915bb

File tree

13 files changed

+537
-264
lines changed

13 files changed

+537
-264
lines changed

matter/src/interaction_model/core.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use super::{messages::msg::TimedReq, InteractionConsumer};
4444
/* Interaction Model ID as per the Matter Spec */
4545
const PROTO_ID_INTERACTION_MODEL: usize = 0x01;
4646

47-
#[derive(FromPrimitive, Debug, Copy, Clone)]
47+
#[derive(FromPrimitive, Debug, Copy, Clone, PartialEq)]
4848
pub enum OpCode {
4949
Reserved = 0,
5050
StatusResponse = 1,

matter/src/interaction_model/messages.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,35 +71,44 @@ pub mod msg {
7171
tlv::{FromTLV, TLVArray, TLVElement, TLVWriter, TagType, ToTLV},
7272
};
7373

74-
use super::ib::{AttrData, AttrPath, AttrResp, CmdData, DataVersionFilter};
74+
use super::ib::{self, AttrData, AttrPath, AttrResp, AttrStatus, CmdData, DataVersionFilter};
7575

76-
#[derive(FromTLV)]
76+
#[derive(FromTLV, ToTLV)]
7777
pub struct TimedReq {
7878
pub timeout: u16,
7979
}
8080

81-
#[derive(ToTLV)]
81+
#[derive(FromTLV, ToTLV)]
8282
pub struct StatusResp {
8383
pub status: IMStatusCode,
8484
}
8585

86-
#[derive(FromTLV)]
86+
pub enum InvReqTag {
87+
SupressResponse = 0,
88+
TimedReq = 1,
89+
InvokeRequests = 2,
90+
}
91+
92+
#[derive(FromTLV, ToTLV)]
8793
#[tlvargs(lifetime = "'a")]
8894
pub struct InvReq<'a> {
8995
pub suppress_response: Option<bool>,
9096
pub timed_request: Option<bool>,
9197
pub inv_requests: Option<TLVArray<'a, CmdData<'a>>>,
9298
}
9399

100+
// This enum is helpful when we are constructing the response
101+
// step by step in incremental manner
94102
pub enum InvRespTag {
95103
SupressResponse = 0,
96104
InvokeResponses = 1,
97105
}
98106

99-
pub enum InvReqTag {
100-
SupressResponse = 0,
101-
TimedReq = 1,
102-
InvokeRequests = 2,
107+
#[derive(FromTLV, ToTLV, Debug)]
108+
#[tlvargs(lifetime = "'a")]
109+
pub struct InvResp<'a> {
110+
pub suppress_response: Option<bool>,
111+
pub inv_responses: Option<TLVArray<'a, ib::InvResp<'a>>>,
103112
}
104113

105114
#[derive(Default, ToTLV, FromTLV)]
@@ -171,6 +180,12 @@ pub mod msg {
171180
}
172181

173182
// Write Response
183+
#[derive(ToTLV, FromTLV)]
184+
#[tlvargs(lifetime = "'a")]
185+
pub struct WriteResp<'a> {
186+
pub write_responses: TLVArray<'a, AttrStatus>,
187+
}
188+
174189
pub enum WriteRespTag {
175190
WriteResponses = 0,
176191
}
@@ -190,7 +205,7 @@ pub mod ib {
190205
use super::GenericPath;
191206

192207
// Command Response
193-
#[derive(Clone, Copy, FromTLV, ToTLV)]
208+
#[derive(Clone, Copy, FromTLV, ToTLV, Debug)]
194209
#[tlvargs(lifetime = "'a")]
195210
pub enum InvResp<'a> {
196211
Cmd(CmdData<'a>),

matter/src/tlv/traits.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use super::{ElementType, TLVContainerIterator, TLVElement, TLVWriter, TagType};
1919
use crate::error::Error;
2020
use core::slice::Iter;
2121
use log::error;
22+
use std::fmt::Debug;
2223

2324
pub trait FromTLV<'a> {
2425
fn from_tlv(t: &TLVElement<'a>) -> Result<Self, Error>
@@ -282,6 +283,7 @@ impl<T> TLVArrayOwned<T> {
282283
}
283284
}
284285

286+
#[derive(Copy, Clone)]
285287
pub enum TLVArray<'a, T> {
286288
// This is used for the to-tlv path
287289
Slice(&'a [T]),
@@ -342,6 +344,27 @@ impl<'a, T: FromTLV<'a> + Copy> Iterator for TLVArrayIter<'a, T> {
342344
}
343345
}
344346

347+
impl<'a, T> PartialEq<&[T]> for TLVArray<'a, T>
348+
where
349+
T: ToTLV + FromTLV<'a> + Copy + PartialEq,
350+
{
351+
fn eq(&self, other: &&[T]) -> bool {
352+
let mut iter1 = self.iter();
353+
let mut iter2 = other.into_iter();
354+
loop {
355+
match (iter1.next(), iter2.next()) {
356+
(None, None) => return true,
357+
(Some(x), Some(y)) => {
358+
if x != *y {
359+
return false;
360+
}
361+
}
362+
_ => return false,
363+
}
364+
}
365+
}
366+
}
367+
345368
impl<'a, T: ToTLV> ToTLV for TLVArray<'a, T> {
346369
fn to_tlv(&self, tw: &mut TLVWriter, tag_type: TagType) -> Result<(), Error> {
347370
match *self {
@@ -364,6 +387,15 @@ impl<'a, T> FromTLV<'a> for TLVArray<'a, T> {
364387
}
365388
}
366389

390+
impl<'a, T: Debug + ToTLV + FromTLV<'a> + Copy> Debug for TLVArray<'a, T> {
391+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
392+
for i in self.iter() {
393+
writeln!(f, "{:?}", i)?;
394+
}
395+
writeln!(f, "")
396+
}
397+
}
398+
367399
#[cfg(test)]
368400
mod tests {
369401
use super::{FromTLV, OctetStr, TLVElement, TLVWriter, TagType, ToTLV};

matter/tests/common/attributes.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use matter::interaction_model::{messages::ib::AttrResp, messages::msg::ReportDat
2121
pub fn assert_attr_report(received: &ReportDataMsg, expected: &[AttrResp]) {
2222
let mut index = 0;
2323

24+
// We can't use assert_eq because it will also try to match data-version
2425
for inv_response in received.attr_reports.as_ref().unwrap().iter() {
2526
println!("Validating index {}", index);
2627
match expected[index] {
@@ -34,14 +35,7 @@ pub fn assert_attr_report(received: &ReportDataMsg, expected: &[AttrResp]) {
3435
panic!("Invalid response, expected AttrRespIn::Data");
3536
}
3637
},
37-
AttrResp::Status(e_s) => match inv_response {
38-
AttrResp::Status(s) => {
39-
assert_eq!(e_s, s);
40-
}
41-
_ => {
42-
panic!("Invalid response, expected AttrRespIn::Status");
43-
}
44-
},
38+
AttrResp::Status(s) => assert_eq!(AttrResp::Status(s), inv_response),
4539
}
4640
println!("Index {} success", index);
4741
index += 1;

matter/tests/common/commands.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
use matter::{
19+
data_model::objects::EncodeValue,
20+
interaction_model::{
21+
messages::ib::{CmdPath, CmdStatus, InvResp},
22+
messages::msg,
23+
},
24+
};
25+
26+
pub enum ExpectedInvResp {
27+
Cmd(CmdPath, u8),
28+
Status(CmdStatus),
29+
}
30+
31+
pub fn assert_inv_response(resp: &msg::InvResp, expected: &[ExpectedInvResp]) {
32+
let mut index = 0;
33+
for inv_response in resp.inv_responses.unwrap().iter() {
34+
println!("Validating index {}", index);
35+
match expected[index] {
36+
ExpectedInvResp::Cmd(e_c, e_d) => match inv_response {
37+
InvResp::Cmd(c) => {
38+
assert_eq!(e_c, c.path);
39+
match c.data {
40+
EncodeValue::Tlv(t) => {
41+
assert_eq!(e_d, t.find_tag(0).unwrap().u8().unwrap())
42+
}
43+
_ => panic!("Incorrect CmdDataType"),
44+
}
45+
}
46+
_ => {
47+
panic!("Invalid response, expected InvResponse::Cmd");
48+
}
49+
},
50+
ExpectedInvResp::Status(e_status) => match inv_response {
51+
InvResp::Status(status) => {
52+
assert_eq!(e_status, status);
53+
}
54+
_ => {
55+
panic!("Invalid response, expected InvResponse::Status");
56+
}
57+
},
58+
}
59+
println!("Index {} success", index);
60+
index += 1;
61+
}
62+
assert_eq!(index, expected.len());
63+
}
64+
65+
#[macro_export]
66+
macro_rules! cmd_data {
67+
($path:ident, $data:literal) => {
68+
CmdData::new($path, EncodeValue::Value(&($data as u32)))
69+
};
70+
}
71+
72+
#[macro_export]
73+
macro_rules! echo_req {
74+
($endpoint:literal, $data:literal) => {
75+
CmdData::new(
76+
CmdPath::new(
77+
Some($endpoint),
78+
Some(echo_cluster::ID),
79+
Some(echo_cluster::Commands::EchoReq as u16),
80+
),
81+
EncodeValue::Value(&($data as u32)),
82+
)
83+
};
84+
}
85+
86+
#[macro_export]
87+
macro_rules! echo_resp {
88+
($endpoint:literal, $data:literal) => {
89+
ExpectedInvResp::Cmd(
90+
CmdPath::new(
91+
Some($endpoint),
92+
Some(echo_cluster::ID),
93+
Some(echo_cluster::Commands::EchoResp as u16),
94+
),
95+
$data,
96+
)
97+
};
98+
}

0 commit comments

Comments
 (0)