Add some tests.
[crypto_lab1.git] / src / end_point.rs
index 77af33d..199fff7 100644 (file)
@@ -21,11 +21,11 @@ struct EndPoint {
 impl Server {
    pub fn new(interface: &str, port: u16) -> IoResult<Server> {
       let mut acceptor = try!(TcpListener::bind(interface, port).listen());
-      
-      let server = Server { 
+
+      let server = Server {
          acceptor: acceptor.clone()
       };
-      
+
       spawn(proc() {
          loop {
             for stream in acceptor.incoming() {
@@ -38,17 +38,17 @@ impl Server {
             }
          }
       });
-      
+
       Ok(server)
    }
-   
+
    pub fn close(&mut self) -> IoResult<()> {
       self.acceptor.close_accept()
    }
-   
-   fn handle_client(mut end_point: EndPoint) {      
+
+   fn handle_client(mut end_point: EndPoint) {
       loop {
-         match end_point.read() {         
+         match end_point.read() {
             Ok(packet@Packet { t: Command(..), .. }) => {
                println!("[Server] Valid command received: {}", packet);
                let answer = Answer(Packet::random_packet_data([]));
@@ -67,7 +67,7 @@ impl Server {
             other =>
                println!("[Server] Error or invalid packet: {}", other)
          }
-      }         
+      }
    }
 }
 
@@ -78,11 +78,11 @@ impl Client {
          current_timestamp: 0
       }})
    }
-   
+
    pub fn close(&mut self) -> IoResult<()> {
       self.end_point.close()
    }
-   
+
    pub fn send(&mut self, packet: PacketType) {
       match packet {
          Command(_) => {
@@ -102,7 +102,7 @@ impl Client {
             println!("[Client] Cannot send this type of packet: {}", other)
       }
    }
-   
+
    /// Send some valid and not-valid packets to the server and check the result.
    pub fn start_tests(address: &str, port: u16) {
       let execute = |f: &mut |&mut Client| -> bool| -> bool {
@@ -114,68 +114,140 @@ impl Client {
             }
          }
       };
-   
+
+      fn raw_packet(timestamp: u64) -> Vec<u8> {
+         let mut m = MemWriter::new();
+         match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: timestamp }).write(&mut m) {
+            Err(e) => vec!(),
+            _ => m.unwrap()
+         }
+      }
+
       let mut tests = vec!(
          |client: &mut Client| -> bool {
             println!("Send a valid packet...");
             match client.end_point.send_with_result(Command(Packet::random_packet_data([42]))) {
-               Ok(Ok(packet@Packet { t: Answer(..), .. })) =>
-                  true,
+               Ok(Ok(packet@Packet { t: Answer(..), .. })) => true,
                other => {
                   println!("Error: {}", other);
                   false
                }
             }
          },
-         
+
          |client: &mut Client| -> bool {
             println!("Send a packet with an unknown type...");
             client.end_point.current_timestamp += 1;
-            let mut m = MemWriter::new(); 
-            match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: client.end_point.current_timestamp }).write(&mut m) {
-               Err(e) => {
-                  println!("Error: {}", e)
+            let mut raw_packet = raw_packet(client.end_point.current_timestamp);
+            raw_packet[2] = 0xEE; // Alter the type.
+            match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
+               Ok(Err(packet::IOReadError( IoError { kind: TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               other => {
+                  println!("Error: {}", other);
                   false
-               },
-               _ => {
-                  let mut raw_packet = m.unwrap();
-                  raw_packet[2] = 0xEE; // Alter the type.
-                        
-                  match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
-                     Ok(Err(packet::IOReadError( IoError { kind: TimedOut, .. }))) => true, // The server should not send a packet.
-                     other => {
-                        println!("Error: {}", other);
-                        false
-                     }
-                  }                  
                }
             }
-         }
+         },
+
+         |client: &mut Client| -> bool {
+            println!("Send a packet with an old timestamp...");
+            client.end_point.current_timestamp += 1;
+            let raw_packet = raw_packet(0);
+            match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
+               Ok(Err(packet::IOReadError( IoError { kind: TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               other => {
+                  println!("Error: {}", other);
+                  false
+               }
+            }
+         },
+
+         |client: &mut Client| -> bool {
+            println!("Send a packet with altered crypted data...");
+            client.end_point.current_timestamp += 1;
+            let mut raw_packet = raw_packet(client.end_point.current_timestamp);
+            raw_packet[11] = 0xDE;
+            raw_packet[12] = 0xAD;
+            raw_packet[13] = 0xBE;
+            raw_packet[14] = 0xEF;
+            match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
+               Ok(Ok(packet@Packet { t: Error(packet::AuthError), .. })) => true,
+               other => {
+                  println!("Error: {}", other);
+                  false
+               }
+            }
+         },
+
+         |client: &mut Client| -> bool {
+            println!("Send a packet with too small data...");
+            let mut command = Command(Packet::new_packet_data(0, Vec::from_elem(6, 0x00)));
+            match client.end_point.send_with_result(command) {
+               Ok(Err(packet::IOReadError( IoError { kind: TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               other => {
+                  println!("Error: {}", other);
+                  false
+               }
+            }
+         },
+
+         |client: &mut Client| -> bool {
+            println!("Send a packet with too large data...");
+            let mut command = Command(Packet::new_packet_data(0, Vec::from_elem(40, 0x00)));
+            match client.end_point.send_with_result(command) {
+               Ok(Err(packet::IOReadError( IoError { kind: TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               other => {
+                  println!("Error: {}", other);
+                  false
+               }
+            }
+         },
+
+         |client: &mut Client| -> bool {
+            println!("Send a packet with wrong padding...");
+            client.end_point.current_timestamp += 1;
+            let mut m = MemWriter::new();
+            let raw_packet = match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: client.end_point.current_timestamp }).write_with_padding_fun(&mut m, |_, _| -> u8 { 0 }) {
+               Err(e) => vec!(),
+               _ => m.unwrap()
+            };
+
+            match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
+               Ok(Ok(packet@Packet { t: Error(packet::CryptError), .. })) => true,
+               other => {
+                  println!("Error: {}", other);
+                  false
+               }
+            }
+         },
       );
-      
-      for (i, test) in range(0, tests.len()).zip(tests.iter_mut()) {
+
+      let mut nb_test_passed = 0;
+      for (i, test) in range(1, tests.len()+1).zip(tests.iter_mut()) {
          println!("===== Test case #{}:", i)
          if execute(test) {
+            nb_test_passed += 1;
             println!("===== Test passed");
          } else {
             println!("===== Test failed");
-            break;
          }
-      }     
-      
-      // Send a packet with a wrong timestamp.
-      // Send a packet with a maximum timestamp.
-      // Send a packet with altered encrypted data.
+      }
+
+      if nb_test_passed == tests.len() {
+         println!("All tests passed");
+      } else {
+         println!("#{} test(s) failed", tests.len() - nb_test_passed);
+      }
    }
 }
 
-impl EndPoint {   
+impl EndPoint {
    fn close(&mut self) -> IoResult<()> {
       try!(self.socket.close_read());
       try!(self.socket.close_write());
       Ok(())
    }
-   
+
    /// Send a packet and wait for an answer synchronously.
    fn send_with_result(&mut self, p: PacketType) -> IoResult<ReadingResult> {
       match self.send(p) {
@@ -183,7 +255,7 @@ impl EndPoint {
          _ => Ok(self.read())
       }
    }
-   
+
    /// Send arbitrary data and wait for an answer synchronously.
    /// Do not increment the current timestamp.
    fn send_raw_with_result(&mut self, p: &[u8]) -> IoResult<ReadingResult> {
@@ -193,7 +265,7 @@ impl EndPoint {
          _ => Ok(self.read())
       }
    }
-   
+
    fn send(&mut self, p: PacketType) -> IoResult<()> {
       self.socket.set_timeout(DEFAULT_TIMEOUT);
       self.current_timestamp += 1;
@@ -202,7 +274,7 @@ impl EndPoint {
          _ => Ok(())
       }
    }
-   
+
    fn read(&mut self) -> ReadingResult {
       fn send_error(ep: &mut EndPoint, error_type: packet::ErrorType) {
          match ep.send(Error(error_type)) {
@@ -210,8 +282,8 @@ impl EndPoint {
             Ok(_) => ()
          };
       };
-   
-      self.socket.set_timeout(DEFAULT_TIMEOUT);      
+
+      self.socket.set_timeout(DEFAULT_TIMEOUT);
       match Packet::read(&mut self.socket) {
          Ok(packet) => {
             if packet.timestamp <= self.current_timestamp {
@@ -223,10 +295,12 @@ impl EndPoint {
             }
          },
          e @ Err(packet::PaddingError) => {
+            self.current_timestamp += 1;
             send_error(self, packet::CryptError);
             e
          },
          e @ Err(packet::MACMismatchError) => {
+            self.current_timestamp += 1;
             send_error(self, packet::AuthError);
             e
          },