diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-11-18 15:47:33 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-11-18 15:47:33 +0100 |
commit | eaa6885f184d864dbd5f33d83134b35a74831d77 (patch) | |
tree | fec0877e7fff9665d2aad2846cb7946cdec0b73a /openpgp | |
parent | df9251ae12f937aa16645e143e06be647a690cfd (diff) |
openpgp: Add mutation tests for key packets.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/src/packet/key.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index 43aba868..b45b196d 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -1532,6 +1532,20 @@ impl<P, R> Arbitrary for super::Key<P, R> } #[cfg(test)] +impl Arbitrary for Key4<PublicParts, PrimaryRole> { + fn arbitrary<G: Gen>(g: &mut G) -> Self { + Key4::<PublicParts, UnspecifiedRole>::arbitrary(g).into() + } +} + +#[cfg(test)] +impl Arbitrary for Key4<PublicParts, SubordinateRole> { + fn arbitrary<G: Gen>(g: &mut G) -> Self { + Key4::<PublicParts, UnspecifiedRole>::arbitrary(g).into() + } +} + +#[cfg(test)] impl Arbitrary for Key4<PublicParts, UnspecifiedRole> { fn arbitrary<G: Gen>(g: &mut G) -> Self { let mpis = mpi::PublicKey::arbitrary(g); @@ -1549,6 +1563,20 @@ impl Arbitrary for Key4<PublicParts, UnspecifiedRole> { } #[cfg(test)] +impl Arbitrary for Key4<SecretParts, PrimaryRole> { + fn arbitrary<G: Gen>(g: &mut G) -> Self { + Key4::<SecretParts, UnspecifiedRole>::arbitrary(g).into() + } +} + +#[cfg(test)] +impl Arbitrary for Key4<SecretParts, SubordinateRole> { + fn arbitrary<G: Gen>(g: &mut G) -> Self { + Key4::<SecretParts, UnspecifiedRole>::arbitrary(g).into() + } +} + +#[cfg(test)] impl Arbitrary for Key4<SecretParts, UnspecifiedRole> { fn arbitrary<G: Gen>(g: &mut G) -> Self { use rand::Rng; @@ -1969,4 +1997,51 @@ mod tests { Ok(()) } + + fn mutate_eq_discriminates_key<P, R>(key: Key<P, R>, i: usize) -> bool + where P: KeyParts, + R: KeyRole, + Key<P, R>: Into<Packet>, + { + use crate::serialize::MarshalInto; + let p: Packet = key.into(); + let mut buf = p.to_vec().unwrap(); + // Avoid first two bytes so that we don't change the + // type and reduce the chance of changing the length. + let bit = i.saturating_add(2 * 8) % (buf.len() * 8); + buf[bit / 8] ^= 1 << (bit % 8); + match Packet::from_bytes(&buf) { + Ok(q) => p != q, + Err(_) => true, // Packet failed to parse. + } + } + + // Given a packet and a position, induces a bit flip in the + // serialized form, then checks that PartialEq detects that. + // Recall that for packets, PartialEq is defined using the + // serialized form. + quickcheck! { + fn mutate_eq_discriminates_pp(key: Key<PublicParts, PrimaryRole>, + i: usize) -> bool { + mutate_eq_discriminates_key(key, i) + } + } + quickcheck! { + fn mutate_eq_discriminates_ps(key: Key<PublicParts, SubordinateRole>, + i: usize) -> bool { + mutate_eq_discriminates_key(key, i) + } + } + quickcheck! { + fn mutate_eq_discriminates_sp(key: Key<SecretParts, PrimaryRole>, + i: usize) -> bool { + mutate_eq_discriminates_key(key, i) + } + } + quickcheck! { + fn mutate_eq_discriminates_ss(key: Key<SecretParts, SubordinateRole>, + i: usize) -> bool { + mutate_eq_discriminates_key(key, i) + } + } } |