Skip to content

Commit

Permalink
Merge pull request #264 from artichoke/dev/lopopolo-100%-coverage
Browse files Browse the repository at this point in the history
Add additional decode tests for uncovered branches
  • Loading branch information
lopopolo authored Feb 1, 2025
2 parents 416e23a + 2cc0b4e commit dde9071
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 0 deletions.
156 changes: 156 additions & 0 deletions src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,159 @@ fn decode_3_tuple(byte1: u8, byte2: u8, byte3: u8, checksum: u8) -> Result<u8, D
fn decode_2_tuple(byte1: u8, byte2: u8) -> u8 {
(byte1 << 4) | byte2
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_index_from_consonant_valid() {
// Valid consonants should correctly map to their respective indices.
let cases = [
(b'b', 0),
(b'c', 1),
(b'd', 2),
(b'f', 3),
(b'g', 4),
(b'h', 5),
(b'k', 6),
(b'l', 7),
(b'm', 8),
(b'n', 9),
(b'p', 10),
(b'r', 11),
(b's', 12),
(b't', 13),
(b'v', 14),
(b'z', 15),
];
for &(input, expected) in &cases {
assert_eq!(index_from_consonant(input), Some(expected));
}
}

#[test]
fn test_index_from_consonant_invalid() {
// Non-consonant characters should return None.
for &input in b"aeiouyx-" {
assert_eq!(index_from_consonant(input), None);
}
}

#[test]
fn test_index_from_vowel_valid() {
// Valid vowels should correctly map to their respective indices.
let cases = [
(b'a', 0),
(b'e', 1),
(b'i', 2),
(b'o', 3),
(b'u', 4),
(b'y', 5),
];
for &(input, expected) in &cases {
assert_eq!(index_from_vowel(input), Some(expected));
}
}

#[test]
fn test_index_from_vowel_invalid() {
// Non-vowel characters should return None.
for &input in b"bcdfghklmnpqrstvxz-" {
assert_eq!(index_from_vowel(input), None);
}
}

#[test]
fn test_index_from_consonant_exhaustive() {
// Iterate over all ASCII characters (0–127) and verify that valid
// consonants are mapped to the expected index, while any other character
// returns None.
for byte in 0u8..=127 {
let expected = match byte {
b'b' => Some(0),
b'c' => Some(1),
b'd' => Some(2),
b'f' => Some(3),
b'g' => Some(4),
b'h' => Some(5),
b'k' => Some(6),
b'l' => Some(7),
b'm' => Some(8),
b'n' => Some(9),
b'p' => Some(10),
b'r' => Some(11),
b's' => Some(12),
b't' => Some(13),
b'v' => Some(14),
b'z' => Some(15),
_ => None,
};
assert_eq!(index_from_consonant(byte), expected);
}
}

#[test]
fn test_index_from_vowel_exhaustive() {
// Iterate over all ASCII characters (0–127) and verify that valid
// vowels are mapped to the expected index, while any other character returns None.
for byte in 0u8..=127 {
let expected = match byte {
b'a' => Some(0),
b'e' => Some(1),
b'i' => Some(2),
b'o' => Some(3),
b'u' => Some(4),
b'y' => Some(5),
_ => None,
};
assert_eq!(index_from_vowel(byte), expected);
}
}

#[test]
fn test_decode_2_tuple() {
// Verify that two 4‑bit values are correctly combined.
// For example, (1,2) should produce (1 << 4) | 2 = 18,
// and the maximum (15,15) yields 255.
assert_eq!(decode_2_tuple(0, 0), 0);
assert_eq!(decode_2_tuple(1, 2), (1 << 4) | 2);
assert_eq!(decode_2_tuple(15, 15), 255);
}

#[test]
fn test_decode_3_tuple_success() {
// Test a successful three-tuple decoding.
// With vowel index 1, consonant index 2, vowel index 1, and checksum 1:
// high = (1 + 6 - (1 % 6)) % 6 = (7 - 1) % 6 = 6 % 6 = 0,
// low = (1 + 6 - ((1 / 6) % 6)) % 6 = (7 - 0) % 6 = 7 % 6 = 1,
// final byte = (0 << 6) | (2 << 2) | 1 = 0 | 8 | 1 = 9.
assert_eq!(decode_3_tuple(1, 2, 1, 1), Ok(9));
}

#[test]
fn test_decode_3_tuple_valid_with_checksum() {
// Test a valid decoding where the checksum adjusts the values.
// For inputs: vowel index 2, consonant index 3, vowel index 2, and checksum 7:
// high = (2 + 6 - (7 % 6)) % 6 = (8 - 1) % 6 = 7 % 6 = 1,
// low = (2 + 6 - ((7 / 6) % 6)) % 6 = (8 - 1) % 6 = 7 % 6 = 1,
// final byte = (1 << 6) | (3 << 2) | 1 = 64 | 12 | 1 = 77.
assert_eq!(decode_3_tuple(2, 3, 2, 7), Ok(77));
}

#[test]
fn test_decode_3_tuple_error_high() {
// Test that an invalid 'high' component causes an error.
// For instance, using vowel index 4 with checksum 0 gives:
// high = (4 + 6 - 0) % 6 = 10 % 6 = 4 (>= 4 is invalid).
assert_eq!(decode_3_tuple(4, 0, 0, 0), Err(DecodeError::Corrupted));
}

#[test]
fn test_decode_3_tuple_error_low() {
// Test that an invalid 'low' component causes an error.
// For example, using vowel index 4 for the third value with checksum 0 yields:
// low = (4 + 6 - 0) % 6 = 10 % 6 = 4 (invalid since it must be < 4).
assert_eq!(decode_3_tuple(0, 0, 4, 0), Err(DecodeError::Corrupted));
}
}
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,18 @@ mod tests {
assert!(!buf.is_empty());
}
}

#[test]
fn test_inner_triggers_decode_3_tuple_corrupted() {
// This encoded input is designed to trigger a DecodeError::Corrupted.
// It consists of a header and trailer ('x') framing the 6-byte chunk
// "abab-b". Within the chunk, the first three-tuple decodes to a value
// where the computed 'high' component is 5 (>= 4), which violates the
// valid range and causes an error.
let encoded = b"xabab-bx";
let result = decode(encoded);
assert_eq!(result, Err(DecodeError::Corrupted));
}
}

// Ensure code blocks in `README.md` compile.
Expand Down

0 comments on commit dde9071

Please sign in to comment.