Merge "Add libdts for comparing DTs" into main
diff --git a/tests/libs/libdts/Android.bp b/tests/libs/libdts/Android.bp
new file mode 100644
index 0000000..512c50b
--- /dev/null
+++ b/tests/libs/libdts/Android.bp
@@ -0,0 +1,17 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_library_rlib {
+ name: "libdts",
+ crate_name: "dts",
+ defaults: ["avf_build_flags_rust"],
+ srcs: ["src/lib.rs"],
+ edition: "2021",
+ prefer_rlib: true,
+ rustlibs: [
+ "libanyhow",
+ "liblibfdt",
+ ],
+ apex_available: ["com.android.virt"],
+}
diff --git a/tests/libs/libdts/README.md b/tests/libs/libdts/README.md
new file mode 100644
index 0000000..ed63bd0
--- /dev/null
+++ b/tests/libs/libdts/README.md
@@ -0,0 +1,16 @@
+Device tree source (DTS) decompiler on Android device.
+
+This is alternative to dtdiff, which only support bash.
+
+How to use for rust_test
+========================
+
+Following dependencies are needed in addition to libdts.
+
+```
+rust_test {
+ ...
+ data_bins: ["dtc_static"],
+ compile_multilib: "first",
+}
+```
diff --git a/tests/libs/libdts/src/lib.rs b/tests/libs/libdts/src/lib.rs
new file mode 100644
index 0000000..0ee9b66
--- /dev/null
+++ b/tests/libs/libdts/src/lib.rs
@@ -0,0 +1,75 @@
+// Copyright 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Device tree source (dts) for comparing device tree contents
+//! i.e. sorted dts decompiled by `dtc -s -O dts`.
+
+use anyhow::{anyhow, Result};
+use libfdt::Fdt;
+use std::io::Write;
+use std::path::Path;
+use std::process::{Command, Stdio};
+
+/// Device tree source (dts)
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct Dts {
+ dts: String,
+}
+
+impl Dts {
+ /// Creates a device tree source from /proc/device-tree style directory
+ pub fn from_fs(path: &Path) -> Result<Self> {
+ let path = path.to_str().unwrap();
+ let res = Command::new("./dtc_static")
+ .args(["-f", "-s", "-I", "fs", "-O", "dts", path])
+ .output()?;
+ if !res.status.success() {
+ return Err(anyhow!("Failed to run dtc_static, res={res:?}"));
+ }
+ Ok(Self { dts: String::from_utf8(res.stdout)? })
+ }
+
+ /// Creates a device tree source from dtb
+ pub fn from_dtb(path: &Path) -> Result<Self> {
+ let path = path.to_str().unwrap();
+ let res = Command::new("./dtc_static")
+ .args(["-f", "-s", "-I", "dtb", "-O", "dts", path])
+ .output()?;
+ if !res.status.success() {
+ return Err(anyhow!("Failed to run dtc_static, res={res:?}"));
+ }
+ Ok(Self { dts: String::from_utf8(res.stdout)? })
+ }
+
+ /// Creates a device tree source from Fdt
+ pub fn from_fdt(fdt: &Fdt) -> Result<Self> {
+ let mut dtc = Command::new("./dtc_static")
+ .args(["-f", "-s", "-I", "dtb", "-O", "dts"])
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .spawn()?;
+
+ {
+ let mut stdin = dtc.stdin.take().unwrap();
+ stdin.write_all(fdt.as_slice())?;
+ // Explicitly drop stdin to avoid indefinite blocking
+ }
+
+ let res = dtc.wait_with_output()?;
+ if !res.status.success() {
+ return Err(anyhow!("Failed to run dtc_static, res={res:?}"));
+ }
+ Ok(Self { dts: String::from_utf8(res.stdout)? })
+ }
+}
diff --git a/virtualizationmanager/fsfdt/Android.bp b/virtualizationmanager/fsfdt/Android.bp
index 7a1e5ed..1d03522 100644
--- a/virtualizationmanager/fsfdt/Android.bp
+++ b/virtualizationmanager/fsfdt/Android.bp
@@ -41,6 +41,7 @@
defaults: ["libfsfdt_default"],
data: ["testdata/**/*"],
data_bins: ["dtc_static"],
- rustlibs: ["libtempfile"],
+ prefer_rlib: true,
+ rustlibs: ["libdts"],
compile_multilib: "first",
}
diff --git a/virtualizationmanager/fsfdt/src/lib.rs b/virtualizationmanager/fsfdt/src/lib.rs
index 84e50c1..e176b7b 100644
--- a/virtualizationmanager/fsfdt/src/lib.rs
+++ b/virtualizationmanager/fsfdt/src/lib.rs
@@ -114,51 +114,20 @@
#[cfg(test)]
mod test {
use super::*;
- use std::io::Write;
- use std::process::Command;
- use tempfile::NamedTempFile;
+ use dts::Dts;
const TEST_FS_FDT_ROOT_PATH: &str = "testdata/fs";
const BUF_SIZE_MAX: usize = 1024;
- fn dts_from_fs(path: &Path) -> String {
- let path = path.to_str().unwrap();
- let res = Command::new("./dtc_static")
- .args(["-f", "-s", "-I", "fs", "-O", "dts", path])
- .output()
- .unwrap();
- assert!(res.status.success(), "{res:?}");
- String::from_utf8(res.stdout).unwrap()
- }
-
- fn dts_from_dtb(path: &Path) -> String {
- let path = path.to_str().unwrap();
- let res = Command::new("./dtc_static")
- .args(["-f", "-s", "-I", "dtb", "-O", "dts", path])
- .output()
- .unwrap();
- assert!(res.status.success(), "{res:?}");
- String::from_utf8(res.stdout).unwrap()
- }
-
- fn to_temp_file(fdt: &Fdt) -> Result<NamedTempFile> {
- let mut file = NamedTempFile::new()?;
- file.as_file_mut().write_all(fdt.as_slice())?;
- file.as_file_mut().sync_all()?;
-
- Ok(file)
- }
-
#[test]
fn test_from_fs() {
let fs_path = Path::new(TEST_FS_FDT_ROOT_PATH);
let mut data = vec![0_u8; BUF_SIZE_MAX];
let fdt = Fdt::from_fs(fs_path, &mut data).unwrap();
- let file = to_temp_file(fdt).unwrap();
- let expected = dts_from_fs(fs_path);
- let actual = dts_from_dtb(file.path());
+ let expected = Dts::from_fs(fs_path).unwrap();
+ let actual = Dts::from_fdt(fdt).unwrap();
assert_eq!(&expected, &actual);
// Again append fdt from TEST_FS_FDT_ROOT_PATH at root & ensure it succeeds when some