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

Commit 3c8164a9 authored by Luke Huang's avatar Luke Huang
Browse files

Add more unit test for doh

Test: atest doh_unit_test
Bug: 155855709
Change-Id: Ieb1fa2ed1965e7c93211e00e1d285544dc4ed3a3
Merged-In: I616933251aec49c60c850198c0594861009c2bb8
parent 8f58a580
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -288,6 +288,13 @@ cc_library_static {
    min_sdk_version: "29",
}

filegroup {
    name: "resolv_rust_test_config_template",
    srcs: [
        "resolv_rust_test_config_template.xml",
    ],
}

filegroup {
    name: "resolv_test_config_template",
    srcs: [
@@ -368,6 +375,9 @@ rust_test {
    edition: "2018",
    test_suites: ["general-tests"],
    auto_gen_config: true,
    // Used to enable root permission for the test.
    // TODO: remove after 'require_root' is supported in rust_test.
    test_config_template: ":resolv_rust_test_config_template",
    rustlibs: [
        "libandroid_logger",
        "libanyhow",
+93 −1
Original line number Diff line number Diff line
@@ -475,10 +475,102 @@ pub unsafe extern "C" fn doh_query(

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

    const TEST_MARK: u32 = 0xD0033;
    const LOOPBACK_ADDR: &str = "127.0.0.1";

    #[test]
    fn dohdispatcher_invalid_args() {
        let test_args = [
            // Bad url
            ("foo", "bar"),
            ("https://1", "bar"),
            ("https:/", "bar"),
            // Bad ip
            ("https://dns.google", "bar"),
            ("https://dns.google", "256.256.256.256"),
        ];
        for args in &test_args {
            assert!(
                DohDispatcher::new(args.0, args.1, 0, None).is_err(),
                "doh dispatcher should not be created"
            )
        }
    }

    #[test]
    fn make_doh_udp_socket() {
        // Bad ip
        for ip in &["foo", "1", "333.333.333.333"] {
            assert!(super::make_doh_udp_socket(ip, 0).is_err(), "udp socket should not be created");
        }
        // Make a socket connecting to loopback with a test mark.
        let sk = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap();
        // Check if the socket is connected to loopback.
        assert_eq!(
            sk.peer_addr().unwrap(),
            SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), DOH_PORT))
        );

        // Check if the socket mark is correct.
        let fd: RawFd = sk.as_raw_fd();

        let mut mark: u32 = 50;
        let mut size = std::mem::size_of::<u32>() as libc::socklen_t;
        unsafe {
            // Safety: fd must be valid.
            assert_eq!(
                libc::getsockopt(
                    fd,
                    libc::SOL_SOCKET,
                    libc::SO_MARK,
                    &mut mark as *mut _ as *mut libc::c_void,
                    &mut size as *mut _ as *mut libc::socklen_t,
                ),
                0
            );
        }
        assert_eq!(mark, TEST_MARK);

        // Check if the socket is non-blocking.
        unsafe {
            // Safety: fd must be valid.
            assert_eq!(libc::fcntl(fd, libc::F_GETFL, 0) & libc::O_NONBLOCK, libc::O_NONBLOCK);
        }
    }

    #[test]
    fn create_quiche_config() {
        assert!(
            super::create_quiche_config(None).is_ok(),
            "quiche config without cert creating failed"
        );
        assert!(
            super::create_quiche_config(Some("data/local/tmp/")).is_ok(),
            "quiche config with cert creating failed"
        );
    }

    const GOOGLE_DNS_URL: &str = "https://dns.google/dns-query";
    const GOOGLE_DNS_IP: &str = "8.8.8.8";
    // qtype: A, qname: www.example.com
    const SAMPLE_QUERY: &str = "q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB";
    #[test]
    fn close_doh() {
        let doh = DohDispatcher::new(GOOGLE_DNS_URL, GOOGLE_DNS_IP, 0, None).unwrap();
        let (resp_tx, resp_rx) = oneshot::channel();
        let cmd = Command::DohQuery { query: SAMPLE_QUERY.as_bytes().to_vec(), resp: resp_tx };
        assert!(doh.query(cmd).is_ok(), "Send query failed");
        doh.abort_handler();
        assert!(RUNTIME_STATIC.block_on(resp_rx).is_err(), "channel should already be closed");
    }

    #[test]
    fn doh_init() {
        unsafe {
            // Safety: the returned pointer from doh_init() must be a null terminated string.
            // Safety: the returned pointer of doh_init() must be a null terminated string.
            assert_eq!(std::ffi::CStr::from_ptr(super::doh_init()).to_str().unwrap(), "1.0");
        }
    }
+26 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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.
-->
<configuration description="Configuration for {MODULE} Rust tests">
   <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
   <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
       <option name="cleanup" value="true" />
       <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
   </target_preparer>
   <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
       <option name="test-device-path" value="/data/local/tmp" />
       <option name="module-name" value="{MODULE}" />
   </test>
</configuration>