//! Robustness against malformed input. The function must return a result and
//! never panic, whatever bytes it receives.
//!
//! This uses a small deterministic generator so the run is reproducible and
//! needs no extra dependency.

use ttf2eot::ttf2eot;

/// A tiny linear congruential generator for reproducible pseudo-random bytes.
struct Lcg(u64);

impl Lcg {
    fn next_u32(&mut self) -> u32 {
        // Numerical Recipes constants.
        self.0 = self
            .0
            .wrapping_mul(6364136223846793005)
            .wrapping_add(1442695040888963407);
        (self.0 >> 32) as u32
    }

    fn fill(&mut self, buf: &mut [u8]) {
        for b in buf.iter_mut() {
            *b = (self.next_u32() & 0xff) as u8;
        }
    }
}

/// Random byte vectors of varied lengths never panic. They return Ok or Err.
#[test]
fn random_bytes_never_panic() {
    let mut rng = Lcg(0x1234_5678_9abc_def0);
    for len in [0usize, 1, 2, 4, 12, 13, 16, 28, 64, 256, 1024] {
        for _ in 0..200 {
            let mut buf = vec![0u8; len];
            rng.fill(&mut buf);
            // The result is ignored. The point is that the call returns.
            let _ = ttf2eot(&buf);
        }
    }
}

/// A plausible SFNT header with a large `numTables` and no real tables must
/// error rather than read past the end.
#[test]
fn bogus_numtables_errors() {
    let mut buf = vec![0u8; 12];
    // sfntVersion 0x00010000.
    buf[0..4].copy_from_slice(&[0x00, 0x01, 0x00, 0x00]);
    // numTables = 0xffff at offset 4.
    buf[4] = 0xff;
    buf[5] = 0xff;
    assert!(ttf2eot(&buf).is_err());
}
