/src/lib/device_tree/tests/integration_test.rs

https://github.com/oreboot/oreboot · Rust · 151 lines · 135 code · 15 blank · 1 comment · 6 complexity · 48aaa46c728e1e604c7e46c241e2d942 MD5 · raw file

  1. extern crate device_tree;
  2. use device_tree::{Entry, FdtReader};
  3. use model::Driver;
  4. use std::io::Write;
  5. use std::process::{Command, Stdio};
  6. use wrappers::SliceReader;
  7. fn assert_node<D: Driver>(entry: Entry<D>, name: &str, depth: usize) {
  8. if let Entry::Node { path } = entry {
  9. assert_eq!(path.name(), name);
  10. assert_eq!(path.depth(), depth);
  11. } else {
  12. panic!("Expected Node!")
  13. }
  14. }
  15. fn assert_property<D: Driver>(entry: Entry<D>, expected_name: &str, expected_depth: usize, expected_value: &[u8]) {
  16. if let Entry::Property { path, value } = entry {
  17. assert_eq!(path.name(), expected_name);
  18. assert_eq!(path.depth(), expected_depth);
  19. assert_eq!(read_all(&value), expected_value);
  20. } else {
  21. panic!("Expected Node!")
  22. }
  23. }
  24. fn dts_to_dtb(dts: &str) -> std::vec::Vec<u8> {
  25. let mut dtc = Command::new("dtc").arg("-O").arg("dtb").stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn().unwrap();
  26. dtc.stdin.as_mut().unwrap().write_all(dts.as_bytes()).unwrap();
  27. let output = dtc.wait_with_output().unwrap();
  28. if output.status.success() {
  29. return output.stdout;
  30. }
  31. panic!("dtc command failed: {:?}", String::from_utf8_lossy(&output.stderr))
  32. }
  33. fn read_all(d: &impl Driver) -> std::vec::Vec<u8> {
  34. let mut data = [0; 500];
  35. let size = match d.pread(&mut data, 0) {
  36. Ok(x) => Ok(x),
  37. Err("EOF") => Ok(0),
  38. Err(other) => Err(other),
  39. }
  40. .unwrap();
  41. let mut result = std::vec::Vec::new();
  42. result.extend_from_slice(&data[0..size]);
  43. return result;
  44. }
  45. #[test]
  46. fn test_reads_empty_device_tree() {
  47. let data = dts_to_dtb("/dts-v1/; / { };");
  48. let slice_reader = &SliceReader::new(&data);
  49. let reader = FdtReader::new(slice_reader).unwrap();
  50. let mut it = reader.walk();
  51. assert_node(it.next().unwrap(), "", 1);
  52. assert!(it.next().is_none());
  53. }
  54. #[test]
  55. fn test_reads_properties() {
  56. let data = dts_to_dtb(
  57. r#"
  58. /dts-v1/;
  59. / {
  60. #address-cells = <1>;
  61. };"#,
  62. );
  63. let slice_reader = &SliceReader::new(&data);
  64. let reader = FdtReader::new(slice_reader).unwrap();
  65. let mut it = reader.walk();
  66. assert_node(it.next().unwrap(), "", 1);
  67. assert_property(it.next().unwrap(), "#address-cells", 2, &vec![0, 0, 0, 1]);
  68. assert!(it.next().is_none());
  69. }
  70. #[test]
  71. fn test_reads_empty_properties() {
  72. let data = dts_to_dtb(
  73. r#"
  74. /dts-v1/;
  75. / {
  76. #address-cells;
  77. };"#,
  78. );
  79. let slice_reader = &SliceReader::new(&data);
  80. let reader = FdtReader::new(slice_reader).unwrap();
  81. let mut it = reader.walk();
  82. assert_node(it.next().unwrap(), "", 1);
  83. assert_property(it.next().unwrap(), "#address-cells", 2, &vec![]);
  84. assert!(it.next().is_none());
  85. }
  86. #[test]
  87. fn test_reads_nested_nodes() {
  88. let data = dts_to_dtb(
  89. r#"
  90. /dts-v1/;
  91. / {
  92. node1 {
  93. #address-cells = "ok";
  94. node2 {
  95. };
  96. };
  97. node3 {
  98. };
  99. };"#,
  100. );
  101. let slice_reader = &SliceReader::new(&data);
  102. let reader = FdtReader::new(slice_reader).unwrap();
  103. let mut it = reader.walk();
  104. assert_node(it.next().unwrap(), "", 1);
  105. assert_node(it.next().unwrap(), "node1", 2);
  106. assert_property(it.next().unwrap(), "#address-cells", 3, &vec![111, 107, 0]);
  107. assert_node(it.next().unwrap(), "node2", 3);
  108. assert_node(it.next().unwrap(), "node3", 2);
  109. assert!(it.next().is_none());
  110. }
  111. #[test]
  112. fn test_returns_error_when_magic_is_invalid() {
  113. let mut data = dts_to_dtb(
  114. r#"
  115. /dts-v1/;
  116. / {
  117. #address-cells = "ok";
  118. };"#,
  119. );
  120. // Magic is a first number
  121. data[0] = 1;
  122. let slice_reader = &SliceReader::new(&data);
  123. assert_eq!(FdtReader::new(slice_reader).err(), Some("invalid magic in device tree header"));
  124. }
  125. #[test]
  126. fn test_returns_error_when_header_is_too_short() {
  127. let data = dts_to_dtb(
  128. r#"
  129. /dts-v1/;
  130. / {
  131. #address-cells = "ok";
  132. };"#,
  133. );
  134. let slice_reader = &SliceReader::new(&data[0..4]);
  135. assert_eq!(FdtReader::new(slice_reader).err(), Some("not enough data to read device tree header"));
  136. }