Relicense as dual Apache-2.0 + MIT
[rust-lightning] / fuzz / src / msg_targets / utils.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 #![macro_use]
11
12 use lightning::util::ser::Writer;
13 pub struct VecWriter(pub Vec<u8>);
14 impl Writer for VecWriter {
15         fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
16                 assert!(self.0.capacity() >= self.0.len() + buf.len());
17                 self.0.extend_from_slice(buf);
18                 Ok(())
19         }
20         fn size_hint(&mut self, size: usize) {
21                 self.0.reserve_exact(size);
22         }
23 }
24
25 // We attempt to test the strictest behavior we can for a given message, however, some messages
26 // have different expected behavior. You can see which messages have which behavior in
27 // gen_target.sh, but, in general, the *_announcement messages have to round-trip exactly (as
28 // otherwise we'd invalidate the signatures), most messages just need to round-trip up to the
29 // amount of data we know how to interpret, and some messages we may throw out invalid stuff (eg
30 // if an error message isn't valid UTF-8 we cant String-ize it), so they wont roundtrip correctly.
31
32 // Tests a message that must survive roundtrip exactly, though may not empty the read buffer
33 // entirely
34 #[macro_export]
35 macro_rules! test_msg {
36         ($MsgType: path, $data: ident) => {
37                 {
38                         use lightning::util::ser::{Writeable, Readable};
39                         let mut r = ::std::io::Cursor::new($data);
40                         if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
41                                 let p = r.position() as usize;
42                                 let mut w = VecWriter(Vec::new());
43                                 msg.write(&mut w).unwrap();
44
45                                 assert_eq!(w.0.len(), p);
46                                 assert_eq!(&r.into_inner()[..p], &w.0[..p]);
47                         }
48                 }
49         }
50 }
51
52 // Tests a message that may lose data on roundtrip, but shoulnd't lose data compared to our
53 // re-serialization.
54 #[macro_export]
55 macro_rules! test_msg_simple {
56         ($MsgType: path, $data: ident) => {
57                 {
58                         use lightning::util::ser::{Writeable, Readable};
59                         let mut r = ::std::io::Cursor::new($data);
60                         if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
61                                 let mut w = VecWriter(Vec::new());
62                                 msg.write(&mut w).unwrap();
63
64                                 let msg = <$MsgType as Readable>::read(&mut ::std::io::Cursor::new(&w.0)).unwrap();
65                                 let mut w_two = VecWriter(Vec::new());
66                                 msg.write(&mut w_two).unwrap();
67                                 assert_eq!(&w.0[..], &w_two.0[..]);
68                         }
69                 }
70         }
71 }
72
73 // Tests a message that must survive roundtrip exactly, and must exactly empty the read buffer and
74 // split it back out on re-serialization.
75 #[macro_export]
76 macro_rules! test_msg_exact {
77         ($MsgType: path, $data: ident) => {
78                 {
79                         use lightning::util::ser::{Writeable, Readable};
80                         let mut r = ::std::io::Cursor::new($data);
81                         if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
82                                 let mut w = VecWriter(Vec::new());
83                                 msg.write(&mut w).unwrap();
84                                 assert_eq!(&r.into_inner()[..], &w.0[..]);
85                         }
86                 }
87         }
88 }
89
90 // Tests a message that must survive roundtrip exactly, modulo one "hole" which may be set to
91 // any value on re-serialization.
92 #[macro_export]
93 macro_rules! test_msg_hole {
94         ($MsgType: path, $data: ident, $hole: expr, $hole_len: expr) => {
95                 {
96                         use lightning::util::ser::{Writeable, Readable};
97                         let mut r = ::std::io::Cursor::new($data);
98                         if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
99                                 let mut w = VecWriter(Vec::new());
100                                 msg.write(&mut w).unwrap();
101                                 let p = w.0.len() as usize;
102
103                                 assert_eq!(w.0.len(), p);
104                                 assert_eq!(&r.get_ref()[..$hole], &w.0[..$hole]);
105                                 assert_eq!(&r.get_ref()[$hole+$hole_len..p], &w.0[$hole+$hole_len..]);
106                         }
107                 }
108         }
109 }