Create syscall recorder and write first test
diff --git a/src/leds.rs b/src/leds.rs
index e0f420c..c505cf9 100644
--- a/src/leds.rs
+++ b/src/leds.rs
@@ -127,3 +127,35 @@
         }
     }
 }
+
+#[cfg(test)]
+mod test {
+    use super::command_nr;
+    use super::DRIVER_NUMBER;
+    use crate::result::TockResult;
+    use crate::syscalls;
+    use crate::syscalls::raw::Event;
+
+    #[test]
+    pub fn single_led_can_be_enabled() {
+        let events = syscalls::raw::run_recording_events::<TockResult<()>, _>(|next_return| {
+            let mut drivers = unsafe { crate::drivers::retrieve_drivers_unsafe() };
+
+            next_return.set(1);
+
+            let leds_driver = drivers.leds.init_driver()?;
+            next_return.set(0);
+
+            let led = leds_driver.get(0)?;
+            led.on()?;
+            Ok(())
+        });
+        assert_eq!(
+            events,
+            vec![
+                Event::Command(DRIVER_NUMBER, command_nr::COUNT, 0, 0),
+                Event::Command(DRIVER_NUMBER, command_nr::ON, 0, 0),
+            ]
+        );
+    }
+}
diff --git a/src/syscalls/platform_mock.rs b/src/syscalls/platform_mock.rs
index 30c528f..66e79f0 100644
--- a/src/syscalls/platform_mock.rs
+++ b/src/syscalls/platform_mock.rs
@@ -1,49 +1,103 @@
+use core::cell::Cell;
+use core::cell::RefCell;
+use std::vec::Vec;
+
 /// yield for a callback fired by the kernel
 /// # Safety
 /// Yielding inside a callback conflicts with Rust's safety guarantees. For example,
 /// a FnMut closure could be triggered multiple times making a &mut a shared reference.
-pub unsafe fn yieldk() {}
+pub unsafe fn yieldk() {
+    EVENTS.with(|e| e.borrow_mut().push(Event::YieldK));
+}
 
 /// Subscribe a callback to the kernel
 /// # Safety
 /// Unsafe as passed callback is dereferenced and called.
 pub unsafe fn subscribe(
-    _: usize,
-    _: usize,
-    _: *const unsafe extern "C" fn(usize, usize, usize, usize),
-    _: usize,
+    arg1: usize,
+    arg2: usize,
+    arg3: *const unsafe extern "C" fn(usize, usize, usize, usize),
+    arg4: usize,
 ) -> isize {
-    unimplemented()
+    EVENTS.with(|e| {
+        e.borrow_mut()
+            .push(Event::Subscribe(arg1, arg2, arg3, arg4))
+    });
+    NEXT_OUTPUT.with(|e| e.get())
 }
 
 /// Send a command to the tock kernel
 /// # Safety
 /// This function usually involves assembly calls which are unsafe.
-pub unsafe fn command(_: usize, _: usize, _: usize, _: usize) -> isize {
-    unimplemented()
+pub unsafe fn command(arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> isize {
+    EVENTS.with(|e| e.borrow_mut().push(Event::Command(arg1, arg2, arg3, arg4)));
+    NEXT_OUTPUT.with(|e| e.get())
 }
 
 /// Call a command only taking into accoun the first argument
 /// # Safety
 /// Unsafe as ignored arguments cause leaking of registers to the kernel
-pub unsafe fn command1(_: usize, _: usize, _: usize) -> isize {
-    unimplemented()
+pub unsafe fn command1(arg1: usize, arg2: usize, arg3: usize) -> isize {
+    EVENTS.with(|e| e.borrow_mut().push(Event::Command1(arg1, arg2, arg3)));
+    NEXT_OUTPUT.with(|e| e.get())
 }
 
 /// Share a memory region with the kernel
 /// # Safety
 /// Unsafe as the pointer to the shared buffer is potentially dereferenced by the kernel.
-pub unsafe fn allow(_: usize, _: usize, _: *mut u8, _: usize) -> isize {
-    unimplemented()
+pub unsafe fn allow(arg1: usize, arg2: usize, arg3: *mut u8, arg4: usize) -> isize {
+    EVENTS.with(|e| e.borrow_mut().push(Event::Allow(arg1, arg2, arg3, arg4)));
+    NEXT_OUTPUT.with(|e| e.get())
 }
 
 /// Generic operations on the app's memory as requesting more memory
 /// # Safety
 /// Allows the kernel to do generic operations on the app's memory which can cause memory corruption.
-pub unsafe fn memop(_: u32, _: usize) -> isize {
-    unimplemented()
+pub unsafe fn memop(arg1: u32, arg2: usize) -> isize {
+    EVENTS.with(|e| e.borrow_mut().push(Event::Memop(arg1, arg2)));
+    NEXT_OUTPUT.with(|e| e.get())
 }
 
-fn unimplemented() -> ! {
-    unimplemented!("Unimplemented for tests");
+/// For tests: Run the closure recording the syscalls which are invoked in during the run of the closure.
+pub fn run_recording_events<R, C: FnMut(&NextReturn) -> R>(mut f: C) -> Vec<Event> {
+    NEXT_OUTPUT.with(|n| n.set(0));
+    NEXT_OUTPUT.with(|n| f(n));
+    let mut output = Vec::new();
+    EVENTS.with(|e| output.append(&mut e.borrow_mut()));
+    output
+}
+
+thread_local!(static EVENTS: RefCell<Vec<Event>> = RefCell::new(Vec::new()));
+thread_local!(static NEXT_OUTPUT: NextReturn = NextReturn { next_return: Cell::new(0) });
+
+#[derive(Clone, Debug, PartialEq)]
+/// For tests: syscall event
+pub enum Event {
+    YieldK,
+    Subscribe(
+        usize,
+        usize,
+        *const unsafe extern "C" fn(usize, usize, usize, usize),
+        usize,
+    ),
+    Command(usize, usize, usize, usize),
+    Command1(usize, usize, usize),
+    Allow(usize, usize, *mut u8, usize),
+    Memop(u32, usize),
+}
+
+/// For tests: controls the next return value of any syscall
+pub struct NextReturn {
+    next_return: Cell<isize>,
+}
+
+impl NextReturn {
+    /// Set the next return value
+    pub fn set(&self, value: isize) {
+        self.next_return.set(value);
+    }
+
+    fn get(&self) -> isize {
+        self.next_return.get()
+    }
 }