Add Watchdog unit tests

Cover watchdog driver implementation with unit tests.

Change-Id: Ib273892bf5202cfb5e57849f34dd52cca983dbff
Signed-off-by: Imre Kis <imre.kis@arm.com>
diff --git a/src/lib.rs b/src/lib.rs
index 5156f77..0126c94 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,10 +15,12 @@
 };
 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
 
+/// Control Register
 #[repr(transparent)]
 #[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
 struct ControlRegister(u32);
 
+/// Interrupt register.
 #[repr(transparent)]
 #[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
 struct Interrupts(u32);
@@ -39,7 +41,7 @@
     }
 }
 
-/// SP805 register map
+/// SP805 register map.
 #[derive(Clone, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
 #[repr(C, align(4))]
 pub struct SP805Registers {
@@ -85,7 +87,7 @@
     wdog_pcell_id3: ReadPure<u32>,
 }
 
-/// SP805 Watchdog implementation
+/// SP805 Watchdog driver implementation.
 pub struct Watchdog<'a> {
     regs: UniqueMmioPointer<'a, SP805Registers>,
     load_value: u32,
@@ -135,3 +137,86 @@
         field!(self.regs, wdog_lock).write(Self::LOCK);
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use zerocopy::transmute_mut;
+
+    const LOAD_VALUE : u32 = 0xabcd_ef01;
+
+    #[repr(align(4096))]
+    pub struct FakeSp805Registers {
+        regs: [u32; 1024],
+    }
+
+    impl FakeSp805Registers {
+        pub fn new() -> Self {
+            Self { regs: [0u32; 1024] }
+        }
+
+        pub fn clear(&mut self) {
+            self.regs.fill(0);
+        }
+
+        pub fn reg_write(&mut self, offset: usize, value: u32) {
+            self.regs[offset / 4] = value;
+        }
+
+        pub fn reg_read(&self, offset: usize) -> u32 {
+            self.regs[offset / 4]
+        }
+
+        fn get(&mut self) -> UniqueMmioPointer<SP805Registers> {
+            UniqueMmioPointer::from(transmute_mut!(&mut self.regs))
+        }
+
+        pub fn system_for_test(&mut self) -> Watchdog {
+            Watchdog::new(self.get(), LOAD_VALUE)
+        }
+    }
+
+    #[test]
+    fn register_block_size() {
+        assert_eq!(0x1000, core::mem::size_of::<SP805Registers>());
+    }
+
+    #[test]
+    fn enable() {
+          let mut regs = FakeSp805Registers::new();
+
+        {
+            // Enable
+            regs.reg_write(0x0c, 0xffff_ffff);
+            let mut wdt = regs.system_for_test();
+            wdt.enable();
+        }
+
+        assert_eq!(LOAD_VALUE, regs.reg_read(0x00));
+        assert_eq!(0x0000_0003, regs.reg_read(0x08));
+        assert!(regs.reg_read(0x0c) != 0);
+        assert_eq!(Watchdog::LOCK, regs.reg_read(0xc00));
+
+        regs.clear();
+
+        {
+            // Disable
+            regs.reg_write(0x08, 0x0000_0003);
+            let mut wdt = regs.system_for_test();
+            wdt.disable();
+        }
+
+        assert_eq!(0x0000_0000, regs.reg_read(0x08));
+        assert_eq!(Watchdog::LOCK, regs.reg_read(0xc00));
+
+        regs.clear();
+
+        {
+            // Update
+            let mut wdt = regs.system_for_test();
+            wdt.update();
+        }
+
+        assert_eq!(LOAD_VALUE, regs.reg_read(0x00));
+    }
+}
\ No newline at end of file