docs/test for SafeReader
diff --git a/src/metadata.rs b/src/metadata.rs
index 1fbd10a..eda6908 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -1,4 +1,4 @@
-//! TUF metadata
+//! TUF metadata.
 
 use chrono::DateTime;
 use chrono::offset::Utc;
diff --git a/src/util.rs b/src/util.rs
index fa04ef4..6724d53 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -5,11 +5,16 @@
 
 use crypto::{HashAlgorithm, HashValue};
 
+/// Wrapper to verify a byte stream as it is read.
+///
 /// Wraps a `Read` to ensure that the consumer can't read more than a capped maximum number of
 /// bytes. Also, this ensures that a minimum bitrate and returns an `Err` if it is not. Finally,
 /// when the underlying `Read` is fully consumed, the hash of the data is optionally calculated. If
 /// the calculated hash does not match the given hash, it will return an `Err`. Consumers of a
 /// `SafeReader` should purge and untrust all read bytes if this ever returns an `Err`.
+///
+/// It is **critical** that none of the bytes from this struct are used until it has been fully
+/// consumed as the data is untrusted.
 pub struct SafeReader<R: Read> {
     inner: R,
     max_size: u64,
@@ -21,6 +26,11 @@
 
 impl<R: Read> SafeReader<R> {
     /// Create a new `SafeReader`.
+    ///
+    /// The argument `hash_data` takes a `HashAlgorithm` and expected `HashValue`. The given
+    /// algorithm is used to hash the data as it is read. At the end of the stream, the digest is
+    /// calculated and compared against `HashValue`. If the two are not equal, it means the data
+    /// stream has been tampered with in some way.
     pub fn new(
         read: R,
         max_size: u64,
@@ -103,3 +113,119 @@
         }
     }
 }
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn valid_read() {
+        let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03];
+        let mut reader = SafeReader::new(bytes, bytes.len() as u64, 0, None);
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_ok());
+        assert_eq!(buf, bytes);
+    }
+
+    #[test]
+    fn valid_read_large_data() {
+        let bytes: &[u8] = &[0x00; 64 * 1024];
+        let mut reader = SafeReader::new(bytes, bytes.len() as u64, 0, None);
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_ok());
+        assert_eq!(buf, bytes);
+    }
+
+    #[test]
+    fn valid_read_below_max_size() {
+        let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03];
+        let mut reader = SafeReader::new(bytes, (bytes.len() as u64) + 1, 0, None);
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_ok());
+        assert_eq!(buf, bytes);
+    }
+
+    #[test]
+    fn invalid_read_above_max_size() {
+        let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03];
+        let mut reader = SafeReader::new(bytes, (bytes.len() as u64) - 1, 0, None);
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_err());
+    }
+
+    #[test]
+    fn invalid_read_above_max_size_large_data() {
+        let bytes: &[u8] = &[0x00; 64 * 1024];
+        let mut reader = SafeReader::new(bytes, (bytes.len() as u64) - 1, 0, None);
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_err());
+    }
+
+    #[test]
+    fn valid_read_good_hash() {
+        let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03];
+        let mut context = digest::Context::new(&SHA256);
+        context.update(&bytes);
+        let hash_value = HashValue::new(context.finish().as_ref().to_vec());
+        let mut reader = SafeReader::new(
+            bytes,
+            bytes.len() as u64,
+            0,
+            Some((&HashAlgorithm::Sha256, hash_value)),
+        );
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_ok());
+        assert_eq!(buf, bytes);
+    }
+
+    #[test]
+    fn invalid_read_bad_hash() {
+        let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03];
+        let mut context = digest::Context::new(&SHA256);
+        context.update(&bytes);
+        context.update(&[0xFF]); // evil bytes
+        let hash_value = HashValue::new(context.finish().as_ref().to_vec());
+        let mut reader = SafeReader::new(
+            bytes,
+            bytes.len() as u64,
+            0,
+            Some((&HashAlgorithm::Sha256, hash_value)),
+        );
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_err());
+    }
+
+    #[test]
+    fn valid_read_good_hash_large_data() {
+        let bytes: &[u8] = &[0x00; 64 * 1024];
+        let mut context = digest::Context::new(&SHA256);
+        context.update(&bytes);
+        let hash_value = HashValue::new(context.finish().as_ref().to_vec());
+        let mut reader = SafeReader::new(
+            bytes,
+            bytes.len() as u64,
+            0,
+            Some((&HashAlgorithm::Sha256, hash_value)),
+        );
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_ok());
+        assert_eq!(buf, bytes);
+    }
+
+    #[test]
+    fn invalid_read_bad_hash_large_data() {
+        let bytes: &[u8] = &[0x00; 64 * 1024];
+        let mut context = digest::Context::new(&SHA256);
+        context.update(&bytes);
+        context.update(&[0xFF]); // evil bytes
+        let hash_value = HashValue::new(context.finish().as_ref().to_vec());
+        let mut reader = SafeReader::new(
+            bytes,
+            bytes.len() as u64,
+            0,
+            Some((&HashAlgorithm::Sha256, hash_value)),
+        );
+        let mut buf = Vec::new();
+        assert!(reader.read_to_end(&mut buf).is_err());
+    }
+}