summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-11-18 15:47:33 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-11-18 15:47:33 +0100
commiteaa6885f184d864dbd5f33d83134b35a74831d77 (patch)
treefec0877e7fff9665d2aad2846cb7946cdec0b73a /openpgp
parentdf9251ae12f937aa16645e143e06be647a690cfd (diff)
openpgp: Add mutation tests for key packets.
Diffstat (limited to 'openpgp')
-rw-r--r--openpgp/src/packet/key.rs75
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)
+ }
+ }
}