Skip to content

Instantly share code, notes, and snippets.

@jwmcglynn
Created January 29, 2018 06:09
Show Gist options
  • Save jwmcglynn/095fdb904e77cf2952736167bc544347 to your computer and use it in GitHub Desktop.
Save jwmcglynn/095fdb904e77cf2952736167bc544347 to your computer and use it in GitHub Desktop.
The tests below expose a bug/limitation of the Xmodem template code provided for CS140E assignment1.
//!
//! To fix this, the only byte that should handle a CAN is the packet receive response, which can be ACK, NAK, and CAN.
//! My fix for this required changing expect_byte, expect_byte_or_cancel, and read_byte.
/// Test sending a packet containing control characters, it should be received
/// intact.
#[test]
fn test_read_packet_control_characters() {
use std::io::{Read, Write};
let (mut tx, rx) = pipe();
let mut xmodem = Xmodem::new(rx);
let mut source_packet = [0u8; 128];
source_packet[0..5].copy_from_slice(&[SOH, EOT, ACK, NAK, CAN]);
let checksum: u8 = source_packet.iter().fold(0, |acc, &x| {
acc.wrapping_add(x)
});
tx.write(&[SOH, 1, 254]).expect("header");
tx.write(&source_packet).expect("packet");
tx.write(&[checksum]).expect("checksum");
let mut dest_packet = [0u8; 128];
xmodem.read_packet(&mut dest_packet).expect("read packet");
assert_eq!(&dest_packet[..], &source_packet[..]);
// We should get the NAK to indicate start of transmission, and then an ACK
// to indicate success.
let mut response = [0u8; 2];
tx.read(&mut response).expect("response");
assert_eq!(&response[..], &[NAK, ACK]);
}
/// Test sending with CAN as a checksum.
#[test]
fn test_read_packet_checksum_can() {
use std::io::{Read, Write};
let (mut tx, rx) = pipe();
let mut xmodem = Xmodem::new(rx);
let mut source_packet = [0u8; 128];
source_packet[0] = CAN;
tx.write(&[SOH, 1, 254]).expect("header");
tx.write(&source_packet).expect("packet");
tx.write(&[CAN]).expect("checksum");
let mut dest_packet = [0u8; 128];
xmodem.read_packet(&mut dest_packet).expect("read packet");
assert_eq!(&dest_packet[..], &source_packet[..]);
// We should get the NAK to indicate start of transmission, and then an ACK
// to indicate success.
let mut response = [0u8; 2];
tx.read(&mut response).expect("response");
assert_eq!(&response[..], &[NAK, ACK]);
}
/// Test large packet numbers and wrapping.
#[test]
fn test_read_packet_numbers() {
use std::io::{Read, Write};
let (mut tx, rx) = pipe();
let mut xmodem = Xmodem::new(rx);
let mut started = false;
for x in 1..512 {
let mut source_packet = [0u8; 128];
let packet_number: u8 = x as u8;
tx.write(&[SOH, packet_number, (255 - packet_number)]).expect("header");
tx.write(&source_packet).expect("packet");
tx.write(&[0]).expect("checksum");
let mut dest_packet = [0u8; 128];
xmodem.read_packet(&mut dest_packet).expect("read packet");
assert_eq!(&dest_packet[..], &source_packet[..]);
if !started {
started = true;
let mut start = [0u8; 1];
tx.read(&mut start).expect("start");
assert_eq!(&start[..], &[NAK]);
}
// We should get an ACK to indicate success.
let mut ack = [0u8; 1];
tx.read(&mut ack).expect("ack");
assert_eq!(&ack[..], &[ACK]);
}
// Don't validate the rest it's handled by test_read_packet.
}
/// Test sending a packet containing control characters, it should be received
/// intact.
#[test]
fn test_write_packet_control_characters() {
use std::io::{Read, Write};
let (tx, mut rx) = pipe();
let mut xmodem = Xmodem::new(tx);
// All the bytes sent from the receiver->transmitter, including start
// of transmission, packet ack, and EOT sequence response.
rx.write(&[NAK, ACK, NAK, ACK]).expect("responses");
let mut source_packet = [0u8; 128];
source_packet[0..5].copy_from_slice(&[SOH, EOT, ACK, NAK, CAN]);
xmodem.write_packet(&source_packet).expect("write packet");
xmodem.write_packet(&[]).expect("transmission end");
let mut header = [0u8; 3];
rx.read(&mut header).expect("read header");
assert_eq!(&header[..], &[SOH, 1, 254]);
let mut dest_packet = [0u8; 128];
rx.read(&mut dest_packet).expect("read packet");
assert_eq!(&dest_packet[..], &source_packet[..]);
// Don't validate the rest of the data, that is tested in test_write_packet.
}
// Test writing large packet numbers and wrapping.
#[test]
fn test_write_packet_numbers() {
use std::io::{Read, Write};
let (tx, mut rx) = pipe();
let mut xmodem = Xmodem::new(tx);
// All the bytes sent from the receiver->transmitter, including start
// of transmission, packet ack, and EOT sequence response.
rx.write(&[NAK]).expect("start");
for x in 1..512 {
rx.write(&[ACK]).expect("packet ack");
let mut source_packet = [0u8; 128];
xmodem.write_packet(&source_packet).expect("write packet");
let mut header = [0u8; 3];
rx.read(&mut header).expect("read header");
let packet_number: u8 = x as u8;
assert_eq!(&header[..], &[SOH, packet_number as u8, (255 - packet_number) as u8]);
let mut dest_packet = [0u8; 128];
rx.read(&mut dest_packet).expect("read packet");
assert_eq!(&dest_packet[..], &source_packet[..]);
let mut checksum = [0u8; 1];
rx.read(&mut checksum).expect("read checksum");
}
// Don't validate the rest, that's handled by test_write_packet.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment