bt_rfcomm/frame/mux_commands/
test_command.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fuchsia_bluetooth::types::Channel;
6use packet_encoding::{Decodable, Encodable};
7
8use crate::frame::FrameParseError;
9
10/// The maximum size (in bytes) of a Test Command pattern.
11/// This is an arbitrarily chosen constant, and is not defined in the RFCOMM/GSM specs.
12/// This length is chosen as the maximum amount of data that can fit in a single
13/// packet of the underlying Channel.
14const TEST_COMMAND_MAX_PATTERN_LENGTH: usize = Channel::DEFAULT_MAX_TX;
15
16/// The Test Command is used to test the connection between two entities in a Session.
17/// The command can be arbitrarily sized, and contains a pattern that must be echoed
18/// back.
19/// See 7.10 Section GSM 5.4.6.3.4.
20#[derive(Clone, Debug, PartialEq)]
21pub struct TestCommandParams {
22    pub test_pattern: Vec<u8>,
23}
24
25impl Decodable for TestCommandParams {
26    type Error = FrameParseError;
27
28    fn decode(buf: &[u8]) -> Result<Self, FrameParseError> {
29        if buf.len() > TEST_COMMAND_MAX_PATTERN_LENGTH {
30            return Err(FrameParseError::InvalidFrame);
31        }
32        Ok(Self { test_pattern: buf.to_vec() })
33    }
34}
35
36impl Encodable for TestCommandParams {
37    type Error = FrameParseError;
38
39    fn encoded_len(&self) -> usize {
40        self.test_pattern.len()
41    }
42
43    fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
44        if buf.len() < self.encoded_len() {
45            return Err(FrameParseError::BufferTooSmall);
46        }
47        buf[..self.encoded_len()].copy_from_slice(&self.test_pattern);
48        Ok(())
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    use assert_matches::assert_matches;
57
58    #[test]
59    fn test_decode_test_command_with_empty_buf() {
60        let buf = [];
61        let expected = TestCommandParams { test_pattern: vec![] };
62        assert_eq!(TestCommandParams::decode(&buf[..]).unwrap(), expected);
63    }
64
65    #[test]
66    fn test_decode_test_command_with_nonempty_buf() {
67        let buf = [0x00, 0x01, 0x02, 0x03];
68        let expected = TestCommandParams { test_pattern: buf.to_vec() };
69        assert_eq!(TestCommandParams::decode(&buf[..]).unwrap(), expected);
70    }
71
72    #[test]
73    fn test_encode_buf_too_small() {
74        let mut small_buf = [];
75        let command = TestCommandParams { test_pattern: vec![0x01, 0x02] };
76        assert_matches!(command.encode(&mut small_buf[..]), Err(FrameParseError::BufferTooSmall));
77    }
78
79    #[test]
80    fn test_encode_larger_buf_is_ok() {
81        let mut buf = [0; 3];
82        let command = TestCommandParams { test_pattern: vec![0x01, 0x02] };
83        assert!(command.encode(&mut buf[..]).is_ok());
84        let expected = [0x01, 0x02, 0x00];
85        assert_eq!(buf, expected);
86    }
87
88    #[test]
89    fn test_encode_buf_success() {
90        let test_pattern = vec![0x01, 0x02, 0x03];
91
92        let mut buf = [0; 3];
93        let command = TestCommandParams { test_pattern: test_pattern.clone() };
94        assert!(command.encode(&mut buf[..]).is_ok());
95        assert_eq!(test_pattern, buf);
96    }
97}