/*
==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--

Namaste

Copyright (C) 2019, 2021-2025  Anonymous

There are several releases over multiple years,
they are listed as ranges, such as: "2021-2025".

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
*/

//! # Tests

#![cfg(any(target_os="linux", target_os="l4re", target_os="android"))]
#![cfg(not(feature="tokio"))]

use {
    std::{
        io::{ErrorKind, Read, Write},
        os::{
            fd::AsRawFd,
            linux::net::SocketAddrExt,
            unix::net::{SocketAddr, UnixListener, UnixStream},
        },
        thread,
    },
    namaste::{Result, UdsxUnixStream},
};

#[test]
fn abstract_uds() -> Result<()> {
    const ADDRESS: &[u8] = &[
        0xac, 0x4b, 0x2d, 0x48, 0x05, 0xb9, 0x64, 0x6f, 0x75, 0x88, 0x4e, 0xe2, 0xe7, 0x75, 0x93, 0x36, 0x22, 0x39, 0x85, 0x5b, 0x78, 0x5c,
        0x94, 0x4b, 0x44, 0x8e, 0x2e, 0xd2, 0xd3, 0xf7, 0x28, 0xd8, 0xdf, 0x90, 0x4c, 0x56, 0xfd, 0x7c, 0x33, 0xe8, 0x43, 0x47, 0xa5, 0xd6,
        0x93, 0x3c, 0x8b, 0xd0, 0x05, 0x52, 0xec, 0xb8, 0x08, 0xbd, 0x80, 0xfe, 0x21, 0xc2, 0xf5, 0xc4, 0x03, 0xa4, 0xeb, 0xe8,
    ];

    let address = SocketAddr::from_abstract_name(&ADDRESS)?;
    {
        let _tmp = {
            let tmp = UnixListener::bind_addr(&address)?;
            tmp.try_clone()?
        };
        assert_eq!(UnixListener::bind_addr(&address).unwrap_err().kind(), ErrorKind::AddrInUse);
    }
    {
        let _tmp = {
            let unix_listener = UnixListener::bind_addr(&address)?;
            let thread = thread::spawn(move || {
                let mut stream = unix_listener.accept()?.0;
                stream.send_streams(ADDRESS, [unix_listener.as_raw_fd()])?;
                let mut buf = [0];
                stream.read_exact(&mut buf)?;
                assert_eq!(buf[0], u8::MAX);
                Result::Ok(())
            });

            let mut stream = UnixStream::connect_addr(&address)?;
            let unix_listener = unsafe {
                stream.recv_streams::<_, UnixListener, 1>(ADDRESS)?
            };
            stream.write_all(&[u8::MAX])?;
            stream.flush()?;
            thread.join().unwrap()?;

            unix_listener
        };
        assert_eq!(UnixListener::bind_addr(&address).unwrap_err().kind(), ErrorKind::AddrInUse);
    }

    Ok(())
}
