Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84f14c9c authored by Sonny Sasaka's avatar Sonny Sasaka
Browse files

floss: Add dbus_projection unit test

As PropMap conversion gets more complex, unit tests will help
maintaining this.

Bug: 193685325
Tag: #floss
Test: Build floss on Linux and AOSP

Change-Id: Ic808f05230b66c9ccd9188d17c01733cb5d25995
parent 3a8d94ec
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4,4 +4,6 @@ version = "0.1.0"
edition = "2018"

[dependencies]
dbus_macros = { path = "dbus_macros" }
dbus = "0.9.2"
dbus-tokio = "0.7.3"
+1 −1
Original line number Diff line number Diff line
@@ -7,6 +7,6 @@ edition = "2018"
proc-macro = true

[dependencies]
syn = "1.0"
syn = { version = "1.0.58", features = ['default', 'full'] }
quote = "1.0"
proc-macro2 = "1.0"
+18 −10
Original line number Diff line number Diff line
@@ -183,13 +183,13 @@ pub fn generate_dbus_exporter(attr: TokenStream, item: TokenStream) -> TokenStre

        pub fn #fn_ident<T: 'static + #api_iface_ident + Send + ?Sized, P: Into<dbus::Path<'static>>>(
            path: P,
            conn: std::sync::Arc<SyncConnection>,
            conn: std::sync::Arc<dbus::nonblock::SyncConnection>,
            cr: &mut dbus_crossroads::Crossroads,
            obj: #obj_type,
            disconnect_watcher: std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
        ) {
            fn get_iface_token<T: #api_iface_ident + Send + ?Sized>(
                conn: std::sync::Arc<SyncConnection>,
                conn: std::sync::Arc<dbus::nonblock::SyncConnection>,
                cr: &mut dbus_crossroads::Crossroads,
                disconnect_watcher: std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
            ) -> dbus_crossroads::IfaceToken<#obj_type> {
@@ -314,7 +314,7 @@ pub fn dbus_propmap(attr: TokenStream, item: TokenStream) -> TokenStream {

            fn from_dbus(
                data__: dbus::arg::PropMap,
                conn__: Option<std::sync::Arc<SyncConnection>>,
                conn__: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>,
                remote__: Option<dbus::strings::BusName<'static>>,
                disconnect_watcher__: Option<std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>>,
            ) -> Result<#struct_ident, Box<dyn std::error::Error>> {
@@ -440,7 +440,7 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {
        }

        struct #struct_ident {
            conn: std::sync::Arc<SyncConnection>,
            conn: std::sync::Arc<dbus::nonblock::SyncConnection>,
            remote: dbus::strings::BusName<'static>,
            objpath: Path<'static>,
            disconnect_watcher: std::sync::Arc<std::sync::Mutex<DisconnectWatcher>>,
@@ -465,7 +465,7 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {

            fn from_dbus(
                objpath__: Path<'static>,
                conn__: Option<std::sync::Arc<SyncConnection>>,
                conn__: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>,
                remote__: Option<dbus::strings::BusName<'static>>,
                disconnect_watcher__: Option<std::sync::Arc<std::sync::Mutex<DisconnectWatcher>>>,
            ) -> Result<Box<dyn #trait_ + Send>, Box<dyn std::error::Error>> {
@@ -559,10 +559,18 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {
            type RustType = dbus::arg::PropMap;
            fn ref_arg_to_rust(
                arg: &(dyn dbus::arg::RefArg + 'static),
                _name: String,
                name: String,
            ) -> Result<Self::RustType, Box<dyn Error>> {
                let mut map: dbus::arg::PropMap = std::collections::HashMap::new();
                let mut iter = arg.as_iter().unwrap();
                let mut iter = match arg.as_iter() {
                    None => {
                        return Err(Box::new(DBusArgError::new(String::from(format!(
                            "{} is not iterable",
                            name,
                        )))))
                    }
                    Some(item) => item,
                };
                let mut key = iter.next();
                let mut val = iter.next();
                while !key.is_none() && !val.is_none() {
@@ -602,7 +610,7 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

            fn from_dbus(
                x: Self::DBusType,
                conn: Option<Arc<SyncConnection>>,
                conn: Option<Arc<dbus::nonblock::SyncConnection>>,
                remote: Option<BusName<'static>>,
                disconnect_watcher: Option<Arc<Mutex<DisconnectWatcher>>>,
            ) -> Result<Self, Box<dyn Error>>
@@ -627,7 +635,7 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

            fn from_dbus(
                data: T,
                _conn: Option<Arc<SyncConnection>>,
                _conn: Option<Arc<dbus::nonblock::SyncConnection>>,
                _remote: Option<BusName<'static>>,
                _disconnect_watcher: Option<Arc<Mutex<DisconnectWatcher>>>,
            ) -> Result<T, Box<dyn Error>> {
@@ -644,7 +652,7 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

            fn from_dbus(
                data: Vec<T::DBusType>,
                conn: Option<Arc<SyncConnection>>,
                conn: Option<Arc<dbus::nonblock::SyncConnection>>,
                remote: Option<BusName<'static>>,
                disconnect_watcher: Option<Arc<Mutex<DisconnectWatcher>>>,
            ) -> Result<Vec<T>, Box<dyn Error>> {
+176 −0
Original line number Diff line number Diff line
use core::any::Any;

use dbus_macros::{dbus_propmap, generate_dbus_arg};

use dbus::arg::{Arg, ArgType, IterAppend, RefArg};
use dbus::Signature;

generate_dbus_arg!();

#[derive(Debug, Default, Clone, PartialEq)]
struct OtherStruct {
    address: String,
}

#[dbus_propmap(OtherStruct)]
struct OtherStructDBus {
    address: String,
}

#[derive(Debug, Default, Clone, PartialEq)]
struct SomeStruct {
    name: String,
    number: i32,
    other_struct: OtherStruct,
    bytes: Vec<u8>,
    nested: Vec<Vec<String>>,
    recursive: Vec<SomeStruct>,
}

#[dbus_propmap(SomeStruct)]
struct SomeStructDBus {
    name: String,
    number: i32,
    other_struct: OtherStruct,
    bytes: Vec<u8>,
    nested: Vec<Vec<String>>,
    recursive: Vec<SomeStruct>,
}

// Pretends to be a D-Bus dictionary.
#[derive(Debug)]
struct FakeDictionary {
    items: Vec<(String, Box<dyn RefArg>)>,
}

impl RefArg for FakeDictionary {
    fn arg_type(&self) -> ArgType {
        todo!()
    }
    fn signature(&self) -> dbus::Signature<'static> {
        todo!()
    }
    fn append(&self, _: &mut IterAppend<'_>) {
        todo!()
    }
    fn as_any(&self) -> &(dyn Any + 'static) {
        todo!()
    }
    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static) {
        todo!()
    }
    fn box_clone(&self) -> Box<dyn RefArg + 'static> {
        Box::new(FakeDictionary {
            items: self.items.iter().map(|(k, v)| (k.clone(), v.box_clone())).collect(),
        })
    }

    fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item = &'b dyn RefArg> + 'b>> {
        Some(Box::new(
            self.items
                .iter()
                .flat_map(|(k, v)| vec![k as &dyn RefArg, v as &dyn RefArg].into_iter()),
        ))
    }
}

impl Arg for FakeDictionary {
    const ARG_TYPE: ArgType = ArgType::Array;
    fn signature() -> dbus::Signature<'static> {
        Signature::from("a{sv}")
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_dbus_propmap_error() {
        let data_dbus = String::from("some data");
        let result = <dbus::arg::PropMap as RefArgToRust>::ref_arg_to_rust(
            &data_dbus,
            String::from("Some Variable"),
        );
        assert!(result.is_err());
        assert_eq!("Some Variable is not iterable", result.unwrap_err().to_string());
    }

    #[test]
    fn test_dbus_propmap_success() {
        let data_dbus = FakeDictionary {
            items: vec![
                (String::from("name"), Box::new(String::from("foo"))),
                (String::from("number"), Box::new(100)),
                (
                    String::from("other_struct"),
                    Box::new(FakeDictionary {
                        items: vec![(
                            String::from("address"),
                            Box::new(String::from("aa:bb:cc:dd:ee:ff")),
                        )],
                    }),
                ),
                (String::from("bytes"), Box::new(vec![1 as u8, 2, 3])),
                (
                    String::from("nested"),
                    Box::new(vec![
                        vec![
                            String::from("string a"),
                            String::from("string b"),
                            String::from("string c"),
                        ],
                        vec![String::from("string 1"), String::from("string 2")],
                    ]),
                ),
                (
                    String::from("recursive"),
                    Box::new(vec![FakeDictionary {
                        items: vec![
                            (String::from("name"), Box::new(String::from("bar"))),
                            (String::from("number"), Box::new(200)),
                            (
                                String::from("other_struct"),
                                Box::new(FakeDictionary {
                                    items: vec![(
                                        String::from("address"),
                                        Box::new(String::from("xx")),
                                    )],
                                }),
                            ),
                            (String::from("bytes"), Box::new(Vec::<u8>::new())),
                            (String::from("nested"), Box::new(Vec::<Vec<u8>>::new())),
                            (String::from("recursive"), Box::new(Vec::<FakeDictionary>::new())),
                        ],
                    }]),
                ),
            ],
        };
        let result = <dbus::arg::PropMap as RefArgToRust>::ref_arg_to_rust(
            &data_dbus,
            String::from("Some Variable"),
        );
        assert!(result.is_ok());
        let result = result.unwrap();
        let result_struct = <SomeStruct as DBusArg>::from_dbus(result, None, None, None).unwrap();
        let expected_struct = SomeStruct {
            name: String::from("foo"),
            number: 100,
            other_struct: OtherStruct { address: String::from("aa:bb:cc:dd:ee:ff") },
            bytes: vec![1, 2, 3],
            nested: vec![
                vec![String::from("string a"), String::from("string b"), String::from("string c")],
                vec![String::from("string 1"), String::from("string 2")],
            ],
            recursive: vec![SomeStruct {
                name: String::from("bar"),
                number: 200,
                other_struct: OtherStruct { address: String::from("xx") },
                bytes: vec![],
                nested: vec![],
                recursive: vec![],
            }],
        };
        assert_eq!(expected_struct, result_struct);
    }
}
+0 −1
Original line number Diff line number Diff line
use dbus::arg::RefArg;
use dbus::nonblock::SyncConnection;
use dbus::strings::Path;
use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter};
use dbus_projection::DisconnectWatcher;
Loading