Browse Source

multiboot2: tests for parsing strings from tags

Philipp Schuster 2 years ago
parent
commit
fd0cfd2cae

+ 39 - 0
multiboot2/src/boot_loader_name.rs

@@ -29,8 +29,47 @@ impl BootLoaderNameTag {
     /// ```
     pub fn name(&self) -> Result<&str, Utf8Error> {
         use core::{mem, slice, str};
+        // strlen without null byte
         let strlen = self.size as usize - mem::size_of::<BootLoaderNameTag>();
         let bytes = unsafe { slice::from_raw_parts((&self.string) as *const u8, strlen) };
         str::from_utf8(bytes)
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::TagType;
+
+    const MSG: &str = "hello";
+
+    /// Returns the tag structure in bytes in native endian format.
+    fn get_bytes() -> std::vec::Vec<u8> {
+        // size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
+        let size = (4 + 4 + MSG.as_bytes().len() + 1) as u32;
+        [
+            &((TagType::BootLoaderName as u32).to_ne_bytes()),
+            &size.to_ne_bytes(),
+            MSG.as_bytes(),
+            // Null Byte
+            &[0],
+        ]
+        .iter()
+        .flat_map(|bytes| bytes.iter())
+        .copied()
+        .collect()
+    }
+
+    /// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
+    #[test]
+    fn test_parse_str() {
+        let tag = get_bytes();
+        let tag = unsafe {
+            tag.as_ptr()
+                .cast::<super::BootLoaderNameTag>()
+                .as_ref()
+                .unwrap()
+        };
+        assert_eq!({ tag.typ }, TagType::BootLoaderName);
+        assert_eq!(tag.name().expect("must be valid UTF-8"), MSG);
+    }
+}

+ 42 - 3
multiboot2/src/command_line.rs

@@ -3,7 +3,7 @@
 use crate::TagType;
 use core::mem;
 use core::slice;
-use core::str::Utf8Error;
+use core::str;
 
 /// This tag contains the command line string.
 ///
@@ -31,9 +31,48 @@ impl CommandLineTag {
     ///     assert_eq!("/bootarg", command_line);
     /// }
     /// ```
-    pub fn command_line(&self) -> Result<&str, Utf8Error> {
+    pub fn command_line(&self) -> Result<&str, str::Utf8Error> {
+        // strlen without null byte
         let strlen = self.size as usize - mem::size_of::<CommandLineTag>();
         let bytes = unsafe { slice::from_raw_parts((&self.string) as *const u8, strlen) };
-        core::str::from_utf8(bytes)
+        str::from_utf8(bytes)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::TagType;
+
+    const MSG: &str = "hello";
+
+    /// Returns the tag structure in bytes in native endian format.
+    fn get_bytes() -> std::vec::Vec<u8> {
+        // size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
+        let size = (4 + 4 + MSG.as_bytes().len() + 1) as u32;
+        [
+            &((TagType::Cmdline as u32).to_ne_bytes()),
+            &size.to_ne_bytes(),
+            MSG.as_bytes(),
+            // Null Byte
+            &[0],
+        ]
+        .iter()
+        .flat_map(|bytes| bytes.iter())
+        .copied()
+        .collect()
+    }
+
+    /// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
+    #[test]
+    fn test_parse_str() {
+        let tag = get_bytes();
+        let tag = unsafe {
+            tag.as_ptr()
+                .cast::<super::CommandLineTag>()
+                .as_ref()
+                .unwrap()
+        };
+        assert_eq!({ tag.typ }, TagType::Cmdline);
+        assert_eq!(tag.command_line().expect("must be valid UTF-8"), MSG);
     }
 }

+ 2 - 0
multiboot2/src/elf_sections.rs

@@ -190,6 +190,8 @@ impl ElfSection {
         use core::{slice, str};
 
         let name_ptr = unsafe { self.string_table().offset(self.get().name_index() as isize) };
+
+        // strlen without null byte
         let strlen = {
             let mut len = 0;
             while unsafe { *name_ptr.offset(len) } != 0 {

+ 37 - 0
multiboot2/src/module.rs

@@ -25,6 +25,7 @@ impl ModuleTag {
     /// will return `--test cmdline-option`.
     pub fn cmdline(&self) -> Result<&str, Utf8Error> {
         use core::{mem, slice, str};
+        // strlen without null byte
         let strlen = self.size as usize - mem::size_of::<ModuleTag>();
         let bytes = unsafe { slice::from_raw_parts((&self.cmdline_str) as *const u8, strlen) };
         str::from_utf8(bytes)
@@ -88,3 +89,39 @@ impl<'a> Debug for ModuleIter<'a> {
         list.finish()
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::TagType;
+
+    const MSG: &str = "hello";
+
+    /// Returns the tag structure in bytes in native endian format.
+    fn get_bytes() -> std::vec::Vec<u8> {
+        // size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
+        //          4 bytes mod_start + 4 bytes mod_end
+        let size = (4 + 4 + 4 + 4 + MSG.as_bytes().len() + 1) as u32;
+        [
+            &((TagType::Module as u32).to_ne_bytes()),
+            &size.to_ne_bytes(),
+            &0_u32.to_ne_bytes(),
+            &0_u32.to_ne_bytes(),
+            MSG.as_bytes(),
+            // Null Byte
+            &[0],
+        ]
+        .iter()
+        .flat_map(|bytes| bytes.iter())
+        .copied()
+        .collect()
+    }
+
+    /// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
+    #[test]
+    fn test_parse_str() {
+        let tag = get_bytes();
+        let tag = unsafe { tag.as_ptr().cast::<super::ModuleTag>().as_ref().unwrap() };
+        assert_eq!({ tag.typ }, TagType::Module);
+        assert_eq!(tag.cmdline().expect("must be valid UTF-8"), MSG);
+    }
+}