1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #![allow(clippy::unwrap_used)]
16 
17 use alloc::boxed::Box;
18 
19 use crate::header::VERSION_HEADER_V0_UNENCRYPTED;
20 use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement};
21 use crate::legacy::serialize::{encode_de_header, AdvBuilder, UnencryptedEncoder};
22 use crate::legacy::Plaintext;
23 
24 use super::*;
25 
26 #[test]
dynamic_de_works()27 fn dynamic_de_works() {
28     let mut builder = AdvBuilder::new(UnencryptedEncoder);
29 
30     let actions: Box<dyn SerializeDataElement<Plaintext>> =
31         Box::new(ActionsDataElement::<Plaintext>::from(ActionBits::default()));
32     builder.add_data_element(DynamicSerializeDataElement::from(actions.as_ref())).unwrap();
33 
34     assert_eq!(
35         &[
36             VERSION_HEADER_V0_UNENCRYPTED,
37             encode_de_header(
38                 ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
39                 DeEncodedLength::from(1),
40             ),
41             0
42         ],
43         builder.into_advertisement().unwrap().as_slice()
44     );
45 }
46 
47 pub(in crate::legacy) mod macros {
48     use alloc::vec::Vec;
49 
50     use crate::legacy::data_elements::de_type::DataElementType;
51     use crate::legacy::deserialize::{DeIterator, DeserializedDataElement};
52     use crate::legacy::serialize::SerializedDataElement;
53     use crate::legacy::PacketFlavor;
54 
55     /// Test method body that creates an array, deserializes it into a DE, serializes it,
56     /// and asserts that the same bytes are produced.
57     ///
58     /// Evaluates to (the deserialized DE, the serialized form of the DE).
59     macro_rules! de_roundtrip_test {
60         ($de_type:ty, $type_variant:ident, $de_variant:ident, $flavor:ty,  $bytes:expr) => {{
61             let parsed_de_enum =
62                 crate::legacy::data_elements::tests::macros::construct_and_parse_de::<
63                     $flavor,
64                 >(crate::legacy::data_elements::de_type::DataElementType::$type_variant, &$bytes);
65             if let crate::legacy::deserialize::DeserializedDataElement::$de_variant(de) =
66                 parsed_de_enum
67             {
68                 // skip DE header byte
69                 let expected = <$de_type as crate::legacy::data_elements::DeserializeDataElement>
70                                     ::deserialize::<$flavor>(&$bytes.as_slice()[1..]).unwrap();
71                 assert_eq!(expected, de);
72 
73                 let serialized = crate::legacy::serialize::tests::serialize::<$flavor, _>(&de);
74                 assert_eq!($bytes.as_slice(), serialized.as_slice());
75 
76                 (de, serialized)
77             } else {
78                 panic!("Unexpected variant: {:?}", parsed_de_enum);
79             }
80         }};
81     }
82 
83     pub(in crate::legacy) use de_roundtrip_test;
84 
85     /// Construct the serialized DE and parse it
construct_and_parse_de<F>( de_type: DataElementType, contents: &SerializedDataElement, ) -> DeserializedDataElement<F> where F: PacketFlavor,86     pub(in crate::legacy) fn construct_and_parse_de<F>(
87         de_type: DataElementType,
88         contents: &SerializedDataElement,
89     ) -> DeserializedDataElement<F>
90     where
91         F: PacketFlavor,
92     {
93         let mut plain_des =
94             DeIterator::new(contents.as_slice()).collect::<Result<Vec<_>, _>>().unwrap();
95         assert_eq!(1, plain_des.len());
96         let de = plain_des.swap_remove(0);
97         assert_eq!(
98             de_type,
99             match de {
100                 DeserializedDataElement::Actions(_) => DataElementType::Actions,
101                 DeserializedDataElement::TxPower(_) => DataElementType::TxPower,
102             }
103         );
104         de
105     }
106 }
107 
108 mod coverage_gaming {
109     use alloc::format;
110 
111     use nom::error;
112     use nom::error::ParseError;
113 
114     use crate::legacy::data_elements::de_type::DeTypeCode;
115     use crate::legacy::data_elements::{DataElementDeserializeError, DataElementSerializeError};
116 
117     #[test]
data_element_serialize_error_debug_eq_clone()118     fn data_element_serialize_error_debug_eq_clone() {
119         let _ = format!("{:?}", DataElementSerializeError::InsufficientSpace.clone());
120         assert_eq!(
121             DataElementSerializeError::InsufficientSpace,
122             DataElementSerializeError::InsufficientSpace
123         );
124     }
125 
126     #[test]
data_element_deserialize_error_debug_clone()127     fn data_element_deserialize_error_debug_clone() {
128         let _ = format!("{:?}", DataElementDeserializeError::InvalidStructure.clone());
129     }
130 
131     #[test]
data_element_deserialize_error_append()132     fn data_element_deserialize_error_append() {
133         assert_eq!(
134             DataElementDeserializeError::InvalidStructure,
135             DataElementDeserializeError::append(
136                 &[0_u8],
137                 error::ErrorKind::CrLf,
138                 DataElementDeserializeError::InvalidDeType {
139                     de_type: DeTypeCode::try_from(10).unwrap()
140                 },
141             )
142         );
143     }
144 }
145 
146 pub(in crate::legacy) mod test_des {
147     use alloc::vec;
148 
149     use rand::distributions;
150     use strum_macros::EnumIter;
151 
152     use crate::legacy::data_elements::de_type::{
153         DeActualLength, DeEncodedLength, DeTypeCode, MAX_DE_ENCODED_LEN,
154     };
155     use crate::legacy::data_elements::{
156         DataElementDeserializeError, DataElementSerializationBuffer, DataElementSerializeError,
157         DeserializeDataElement, LengthMapper, SerializeDataElement,
158     };
159     use crate::legacy::deserialize::{DataElementDeserializer, LengthError, RawDataElement};
160     use crate::legacy::serialize::tests::helpers::{LongDataElement, ShortDataElement};
161     use crate::legacy::{PacketFlavor, NP_MAX_DE_CONTENT_LEN};
162     use crate::private::Sealed;
163 
164     /// A [DataElementDeserializer] that can deserialize the test stubs [ShortDataElement] and
165     /// [LongDataElement].
166     pub(in crate::legacy) struct TestDeDeserializer;
167 
168     impl DataElementDeserializer for TestDeDeserializer {
169         type DeTypeDisambiguator = TestDataElementType;
170         type Deserialized<F: PacketFlavor> = TestDataElement;
171 
map_encoded_len_to_actual_len( de_type: DeTypeCode, encoded_len: DeEncodedLength, ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError>172         fn map_encoded_len_to_actual_len(
173             de_type: DeTypeCode,
174             encoded_len: DeEncodedLength,
175         ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError> {
176             match de_type {
177                 ShortDataElement::DE_TYPE_CODE => {
178                     <ShortDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
179                         .map(|l| (TestDataElementType::Short, l))
180                         .map_err(|e| e.into())
181                 }
182                 LongDataElement::DE_TYPE_CODE => {
183                     <LongDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
184                         .map(|l| (TestDataElementType::Long, l))
185                         .map_err(|e| e.into())
186                 }
187                 _ => Err(LengthError::InvalidType),
188             }
189         }
190 
deserialize_de<F: PacketFlavor>( raw_de: RawDataElement<Self>, ) -> Result<Self::Deserialized<F>, DataElementDeserializeError>191         fn deserialize_de<F: PacketFlavor>(
192             raw_de: RawDataElement<Self>,
193         ) -> Result<Self::Deserialized<F>, DataElementDeserializeError> {
194             match raw_de.de_type {
195                 TestDataElementType::Short => {
196                     ShortDataElement::deserialize::<F>(raw_de.contents).map(TestDataElement::Short)
197                 }
198                 TestDataElementType::Long => {
199                     LongDataElement::deserialize::<F>(raw_de.contents).map(TestDataElement::Long)
200                 }
201             }
202         }
203     }
204 
205     #[derive(EnumIter, Debug, Clone, Copy)]
206     pub(in crate::legacy) enum TestDataElementType {
207         Short,
208         Long,
209     }
210 
211     #[derive(Debug, PartialEq, Eq, Clone)]
212     pub(in crate::legacy) enum TestDataElement {
213         Short(ShortDataElement),
214         Long(LongDataElement),
215     }
216 
217     impl From<ShortDataElement> for TestDataElement {
from(value: ShortDataElement) -> Self218         fn from(value: ShortDataElement) -> Self {
219             Self::Short(value)
220         }
221     }
222 
223     impl From<LongDataElement> for TestDataElement {
from(value: LongDataElement) -> Self224         fn from(value: LongDataElement) -> Self {
225             Self::Long(value)
226         }
227     }
228 
229     impl Sealed for TestDataElement {}
230 
231     // Not representative of how the main [DeserializedDataElement] would be used, but handy
232     // in tests to be able to directly serialize the deserialized representation
233     impl<F: PacketFlavor> SerializeDataElement<F> for TestDataElement {
de_type_code(&self) -> DeTypeCode234         fn de_type_code(&self) -> DeTypeCode {
235             match self {
236                 TestDataElement::Short(s) => {
237                     <ShortDataElement as SerializeDataElement<F>>::de_type_code(s)
238                 }
239                 TestDataElement::Long(l) => {
240                     <LongDataElement as SerializeDataElement<F>>::de_type_code(l)
241                 }
242             }
243         }
244 
map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength245         fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
246             match self {
247                 TestDataElement::Short(s) => {
248                     <ShortDataElement as SerializeDataElement<F>>::map_actual_len_to_encoded_len(
249                         s, actual_len,
250                     )
251                 }
252                 TestDataElement::Long(l) => {
253                     <LongDataElement as SerializeDataElement<F>>::map_actual_len_to_encoded_len(
254                         l, actual_len,
255                     )
256                 }
257             }
258         }
259 
serialize_contents( &self, sink: &mut DataElementSerializationBuffer, ) -> Result<(), DataElementSerializeError>260         fn serialize_contents(
261             &self,
262             sink: &mut DataElementSerializationBuffer,
263         ) -> Result<(), DataElementSerializeError> {
264             match self {
265                 TestDataElement::Short(s) => {
266                     <ShortDataElement as SerializeDataElement<F>>::serialize_contents(s, sink)
267                 }
268                 TestDataElement::Long(l) => {
269                     <LongDataElement as SerializeDataElement<F>>::serialize_contents(l, sink)
270                 }
271             }
272         }
273     }
274 
275     impl distributions::Distribution<ShortDataElement> for distributions::Standard {
sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> ShortDataElement276         fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> ShortDataElement {
277             let len = rng.gen_range(0_usize..MAX_DE_ENCODED_LEN.into());
278             let mut data = vec![0; len];
279             rng.fill(&mut data[..]);
280             ShortDataElement::new(data)
281         }
282     }
283 
284     impl distributions::Distribution<LongDataElement> for distributions::Standard {
sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> LongDataElement285         fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> LongDataElement {
286             let len = rng.gen_range(LongDataElement::OFFSET..NP_MAX_DE_CONTENT_LEN);
287             let mut data = vec![0; len];
288             rng.fill(&mut data[..]);
289             LongDataElement::new(data)
290         }
291     }
292 
293     /// Generate a random instance of the requested de type, or `None` if that type does not support
294     /// plaintext.
random_test_de<R>(de_type: TestDataElementType, rng: &mut R) -> TestDataElement where R: rand::Rng,295     pub(crate) fn random_test_de<R>(de_type: TestDataElementType, rng: &mut R) -> TestDataElement
296     where
297         R: rand::Rng,
298     {
299         match de_type {
300             TestDataElementType::Short => TestDataElement::Short(rng.gen()),
301             TestDataElementType::Long => TestDataElement::Long(rng.gen()),
302         }
303     }
304 }
305