indy-sdk 0.1.1-53

This is the official SDK for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org). The major artifact of the SDK is a c-callable library.
Documentation
extern crate indy;

// Workaround to share some utils code based on indy sdk types between tests and indy sdk
use indy::api as api;

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate rust_base58;
#[macro_use]
extern crate serde_derive;
extern crate zmq_pw as zmq;

use std::sync::mpsc::channel;
use std::thread;

use indy::api::ErrorCode;

#[macro_use]
mod utils;

use utils::agent::AgentUtils;
use utils::ledger::LedgerUtils;
use utils::pool::PoolUtils;
use utils::signus::SignusUtils;
use utils::test::TestUtils;
use utils::timeout::TimeoutUtils;
use utils::wallet::WalletUtils;

mod high_cases {
    use super::*;

    #[test]
    fn indy_agent_listen_works_with_indy_agent_connect() {
        TestUtils::cleanup_storage();
        let wallet_handle = WalletUtils::create_and_open_wallet("pool3", None).unwrap();
        let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
        let endpoint = "127.0.0.1:9701";

        let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();
        AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();

        SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();

        AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();

        TestUtils::cleanup_storage();
    }

    mod indy_agent_connect {
        use super::*;
        use rust_base58::FromBase58;

        #[test]
        fn indy_agent_connect_works_for_remote_data() {
            TestUtils::cleanup_storage();

            let pool_handle = PoolUtils::create_and_open_pool_ledger_config("indy_agent_connect_works_for_remote_data").unwrap();

            let endpoint = "127.0.0.1:9710";
            let listener_wallet = WalletUtils::create_and_open_wallet("indy_agent_connect_works_for_remote_data", None).unwrap();
            let trustee_wallet = WalletUtils::create_and_open_wallet("indy_agent_connect_works_for_remote_data", None).unwrap();
            let (listener_did, listener_ver_key, listener_pub_key) = SignusUtils::create_and_store_my_did(listener_wallet, None).unwrap();
            let (trustee_did, _, _) = SignusUtils::create_and_store_my_did(trustee_wallet, Some("000000000000000000000000Trustee1")).unwrap();
            let sender_did = trustee_did.clone();
            let sender_wallet = trustee_wallet;

            let listener_nym_json = LedgerUtils::build_nym_request(trustee_did.as_str(), listener_did.as_str(), Some(listener_ver_key.as_str()), None, None).unwrap();
            LedgerUtils::sign_and_submit_request(pool_handle, trustee_wallet, trustee_did.as_str(), listener_nym_json.as_str()).unwrap();

            let listener_attrib_json =
                LedgerUtils::build_attrib_request(listener_did.as_str(), listener_did.as_str(), None,
                                                  Some(format!("{{\"endpoint\":{{\"ha\":\"{}\", \"verkey\":\"{}\"}}}}", endpoint, listener_pub_key).as_str()),
                                                  None).unwrap();
            LedgerUtils::sign_and_submit_request(pool_handle, listener_wallet, listener_did.as_str(), listener_attrib_json.as_str()).unwrap();

            let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();
            AgentUtils::add_identity(listener_handle, pool_handle, listener_wallet, listener_did.as_str()).unwrap();

            AgentUtils::connect(pool_handle, sender_wallet, sender_did.as_str(), listener_did.as_str(), None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn indy_agent_connect_works_for_all_data_in_wallet_present() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("pool1", None).expect("create wallet");

            let seed: Option<&str> = Some("sovrin_agent_connect_works_for_a");
            let (did, ver_key, pub_key) = SignusUtils::create_and_store_my_did(wallet_handle, seed).unwrap();
            let endpoint = "127.0.0.1:9702";

            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();

            //FIXME temporary code: replace by indy_agent_listen
            thread::spawn(move || {
                let secret_key = "6wBM7yEYWD7wGd3ZtNQX5r31uWuC8NoZS2Lr6HZvRTY4".from_base58().unwrap();
                let public_key = "2vTqP9QfNdvPr397QaFKtbVUPbhgqmAum2oDVkYsk4p9".from_base58().unwrap();
                let socket: zmq::Socket = zmq::Context::new().socket(zmq::SocketType::ROUTER).unwrap();
                socket.set_curve_server(true).unwrap();
                socket.add_curve_keypair([public_key, secret_key].concat().as_slice()).unwrap();
                socket.bind(format!("tcp://{}", endpoint).as_str()).unwrap();
                socket.poll(zmq::POLLIN, -1).unwrap();
                let identity = socket.recv_string(zmq::DONTWAIT).unwrap().unwrap();
                let msg = socket.recv_string(zmq::DONTWAIT).unwrap().unwrap();
                info!("Fake agent socket - recv - from {}, msg {}", identity, msg);
                if msg.eq(r#"{"did":{"sender_did":"L1Xk2qCV6uxEEsYhP7B4EP","receiver_did":"L1Xk2qCV6uxEEsYhP7B4EP"}}"#) {
                    info!("Fake agent socket send ACK");
                    socket.send_multipart(&[identity.as_bytes(), "DID_ACK".as_bytes()], zmq::DONTWAIT).unwrap();
                }
            });
            //FIXME /temporary code

            AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_listen {
        use super::*;

        #[test]
        fn indy_agent_listen_works_for_all_data_in_wallet_present() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("pool2", None).expect("create wallet");

            let seed: Option<&str> = Some("sovrin_agent_listen_works_for_al");
            let (did, ver_key, pub_key) = SignusUtils::create_and_store_my_did(wallet_handle, seed).unwrap();
            let endpoint = "127.0.0.1:9703";
            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();

            AgentUtils::listen(endpoint, None, None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_add_identity {
        use super::*;
        use rust_base58::FromBase58;

        #[test]
        fn indy_agent_add_identity_works() {
            TestUtils::cleanup_storage();

            let endpoint = "127.0.0.1:9711";
            let receiver_wallet = WalletUtils::create_and_open_wallet("ignore", None).unwrap();
            let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();

            let (receiver_did, _, receiver_pk) = SignusUtils::create_and_store_my_did(receiver_wallet, None).unwrap();
            AgentUtils::add_identity(listener_handle, -1, receiver_wallet, receiver_did.as_str()).unwrap();

            let sock = zmq::Context::new().socket(zmq::SocketType::DEALER).unwrap();
            let kp = zmq::CurveKeyPair::new().unwrap();
            sock.set_identity(zmq::z85_encode(&kp.public_key).unwrap().as_bytes()).unwrap();
            sock.set_curve_publickey(&kp.public_key).unwrap();
            sock.set_curve_secretkey(&kp.secret_key).unwrap();
            sock.set_curve_serverkey(receiver_pk.from_base58().unwrap().as_slice()).unwrap();
            sock.set_protocol_version(zmq::make_proto_version(1, 1)).unwrap();
            sock.connect(format!("tcp://{}", endpoint).as_str()).unwrap();
            sock.send("test", zmq::DONTWAIT).unwrap();
            sock.poll(zmq::POLLIN, 100).unwrap();
            assert_eq!(sock.recv_string(zmq::DONTWAIT).unwrap().unwrap(), "NOT_CONNECTED");

            TestUtils::cleanup_storage();
        }

        #[test]
        fn indy_agent_add_identity_works_for_multiply_keys() {
            TestUtils::cleanup_storage();

            let endpoint = "127.0.0.1:9714";
            let receiver_wallet = WalletUtils::create_and_open_wallet("ignore", None).unwrap();
            let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();

            let (receiver_did1, _, receiver_pk1) = SignusUtils::create_and_store_my_did(receiver_wallet, None).unwrap();
            let (receiver_did2, _, receiver_pk2) = SignusUtils::create_and_store_my_did(receiver_wallet, None).unwrap();
            for receiver_did in [receiver_did1, receiver_did2].iter() {
                AgentUtils::add_identity(listener_handle, -1, receiver_wallet, receiver_did.as_str()).unwrap();
            }

            for receiver_pk in [receiver_pk1, receiver_pk2].iter() {
                let sock = zmq::Context::new().socket(zmq::SocketType::DEALER).unwrap();
                let kp = zmq::CurveKeyPair::new().unwrap();
                sock.set_identity(zmq::z85_encode(&kp.public_key).unwrap().as_bytes()).unwrap();
                sock.set_curve_publickey(&kp.public_key).unwrap();
                sock.set_curve_secretkey(&kp.secret_key).unwrap();
                sock.set_curve_serverkey(receiver_pk.from_base58().unwrap().as_slice()).unwrap();
                sock.set_protocol_version(zmq::make_proto_version(1, 1)).unwrap();
                sock.connect(format!("tcp://{}", endpoint).as_str()).unwrap();
                sock.send("test", zmq::DONTWAIT).unwrap();
                sock.poll(zmq::POLLIN, 100).unwrap();
                assert_eq!(sock.recv_string(zmq::DONTWAIT).unwrap().unwrap(), "NOT_CONNECTED");
            }

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_rm_identity {
        use super::*;
        use rust_base58::FromBase58;

        #[test]
        fn indy_agent_rm_identity_works() {
            TestUtils::cleanup_storage();

            let endpoint = "127.0.0.1:9713";
            let receiver_wallet = WalletUtils::create_and_open_wallet("ignore", None).unwrap();
            let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();

            let (receiver_did, _, receiver_pk) = SignusUtils::create_and_store_my_did(receiver_wallet, None).unwrap();
            AgentUtils::add_identity(listener_handle, -1, receiver_wallet, receiver_did.as_str()).unwrap();

            let sock = zmq::Context::new().socket(zmq::SocketType::DEALER).unwrap();
            let kp = zmq::CurveKeyPair::new().unwrap();
            sock.set_linger(0).unwrap();
            sock.set_identity(zmq::z85_encode(&kp.public_key).unwrap().as_bytes()).unwrap();
            sock.set_curve_publickey(&kp.public_key).unwrap();
            sock.set_curve_secretkey(&kp.secret_key).unwrap();
            sock.set_curve_serverkey(receiver_pk.from_base58().unwrap().as_slice()).unwrap();
            sock.set_protocol_version(zmq::make_proto_version(1, 1)).unwrap();
            sock.connect(format!("tcp://{}", endpoint).as_str()).unwrap();
            sock.send("test", zmq::DONTWAIT).unwrap();
            sock.poll(zmq::POLLIN, 1000).unwrap();
            assert_eq!(sock.recv_string(zmq::DONTWAIT).unwrap().unwrap(), "NOT_CONNECTED");
            sock.disconnect(format!("tcp://{}", endpoint).as_str()).unwrap();

            AgentUtils::rm_identity(listener_handle, receiver_wallet, receiver_did.as_str()).unwrap();
            sock.connect(format!("tcp://{}", endpoint).as_str()).unwrap();
            sock.send("test", zmq::DONTWAIT).unwrap();
            sock.poll(zmq::POLLIN, 1000).unwrap();
            assert_eq!(sock.recv_string(zmq::DONTWAIT).unwrap_err(), zmq::Error::EAGAIN);
            sock.disconnect(format!("tcp://{}", endpoint).as_str()).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_send {
        use super::*;

        #[test]
        fn indy_agent_send_works_for_all_data_in_wallet_present() {
            TestUtils::cleanup_storage();

            let (wait_conn_send, wait_conn_recv) = channel();
            let (wait_msg_from_srv_send, wait_msg_from_srv_recv) = channel();
            let (wait_msg_from_cli_send, wait_msg_from_cli_recv) = channel();
            let wallet_handle = WalletUtils::create_and_open_wallet("pool4", None).unwrap();
            let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
            let endpoint = "127.0.0.1:9704";
            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();
            let listener_handle = AgentUtils::listen(endpoint,
                                                     Some(Box::new(move |_, conn_handle| {
                                                         wait_conn_send.send(conn_handle).unwrap();
                                                     })),
                                                     Some(Box::new(move |_, msg| {
                                                         wait_msg_from_cli_send.send(msg).unwrap();
                                                     }))).unwrap();
            AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();
            let cli_to_srv_connect_id = AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(),
                                                            Some(Box::new(move |_, msg| {
                                                                wait_msg_from_srv_send.send(msg).unwrap();
                                                            }))).unwrap();
            let srv_to_cli_connect_id = wait_conn_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap();
            let client_msg = "msg_from_client";
            let server_msg = "msg_from_server";

            info!("Sending message from client to server");
            AgentUtils::send(cli_to_srv_connect_id, client_msg).unwrap();
            assert_eq!(wait_msg_from_cli_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap(), client_msg);
            info!("Sending message from server to client");
            AgentUtils::send(srv_to_cli_connect_id, server_msg).unwrap();
            assert_eq!(wait_msg_from_srv_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap(), server_msg);

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_close_connection {
        use super::*;

        #[test]
        fn indy_agent_close_connection_works_for_outgoing() {
            TestUtils::cleanup_storage();
            let wallet_handle = WalletUtils::create_and_open_wallet("pool3", None).unwrap();
            let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
            let endpoint = "127.0.0.1:9705";

            let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();
            AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();

            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();

            let conn_handle = AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();

            AgentUtils::close_connection(conn_handle).unwrap();
            assert_eq!(AgentUtils::send(conn_handle, "").unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn indy_agent_close_connection_works_for_incoming_conn() {
            TestUtils::cleanup_storage();

            let (wait_conn_send, wait_conn_recv) = channel();
            let wallet_handle = WalletUtils::create_and_open_wallet("pool4", None).unwrap();
            let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
            let endpoint = "127.0.0.1:9706";
            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();
            let listener_handle = AgentUtils::listen(endpoint,
                                                     Some(Box::new(move |_, conn_handle| {
                                                         wait_conn_send.send(conn_handle).unwrap();
                                                     })),
                                                     None).unwrap();
            AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();
            AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();
            let srv_to_cli_connect_id = wait_conn_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

            AgentUtils::close_connection(srv_to_cli_connect_id).unwrap();

            let server_msg = "msg_from_server";
            assert_eq!(AgentUtils::send(srv_to_cli_connect_id, server_msg).unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_close_listener {
        use super::*;

        #[test]
        fn indy_agent_close_listener_works() {
            TestUtils::cleanup_storage();

            let (wait_conn_send, wait_conn_recv) = channel();
            let wallet_handle = WalletUtils::create_and_open_wallet("pool8", None).unwrap();
            let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
            let endpoint = "127.0.0.1:9708";
            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();
            let listener_handle = AgentUtils::listen(endpoint,
                                                     Some(Box::new(move |_, conn_handle| {
                                                         wait_conn_send.send(conn_handle).unwrap();
                                                     })),
                                                     None).unwrap();
            AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();
            AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();
            let srv_to_cli_connect_id = wait_conn_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

            AgentUtils::close_listener(listener_handle).unwrap();

            let server_msg = "msg_from_server";
            assert_eq!(AgentUtils::send(srv_to_cli_connect_id, server_msg).unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }
    }
}

mod medium_cases {
    use super::*;

    mod indy_agent_add_identity {
        use super::*;

        #[test]
        fn indy_agent_add_identity_works_for_incoming_connection_require_ledger_request_but_pool_handle_is_invalid() {
            TestUtils::cleanup_storage();

            let pool_handle = PoolUtils::create_and_open_pool_ledger_config("indy_agent_add_identity_works_for_incoming_connection_require_ledger_request_but_pool_handle_is_invalid").unwrap();

            let endpoint = "127.0.0.1:9712";
            let listener_wallet = WalletUtils::create_and_open_wallet("indy_agent_add_identity_works_for_incoming_connection_require_ledger_request_but_pool_handle_is_invalid", None).unwrap();
            let trustee_wallet = WalletUtils::create_and_open_wallet("indy_agent_add_identity_works_for_incoming_connection_require_ledger_request_but_pool_handle_is_invalid", None).unwrap();
            let (listener_did, listener_ver_key, listener_pub_key) = SignusUtils::create_and_store_my_did(listener_wallet, None).unwrap();
            let (trustee_did, _, _) = SignusUtils::create_and_store_my_did(trustee_wallet, Some("000000000000000000000000Trustee1")).unwrap();
            let sender_did = trustee_did.clone();
            let sender_wallet = trustee_wallet;

            let listener_nym_json = LedgerUtils::build_nym_request(trustee_did.as_str(), listener_did.as_str(), Some(listener_ver_key.as_str()), None, None).unwrap();
            LedgerUtils::sign_and_submit_request(pool_handle, trustee_wallet, trustee_did.as_str(), listener_nym_json.as_str()).unwrap();

            let listener_attrib_json =
                LedgerUtils::build_attrib_request(listener_did.as_str(), listener_did.as_str(), None,
                                                  Some(format!("{{\"endpoint\":{{\"ha\":\"{}\", \"verkey\":\"{}\"}}}}", endpoint, listener_pub_key).as_str()),
                                                  None).unwrap();
            LedgerUtils::sign_and_submit_request(pool_handle, listener_wallet, listener_did.as_str(), listener_attrib_json.as_str()).unwrap();

            let listener_handle = AgentUtils::listen(endpoint, None, None).unwrap();
            let invalid_pool_handle = listener_handle;
            AgentUtils::add_identity(listener_handle, invalid_pool_handle, listener_wallet, listener_did.as_str()).unwrap();

            /* TODO
             * Currently pool_handle and wallet_handle of add_identity will be checked only at required:
             * when listener will check incoming connection and go to ledger for info.
             * As result, add_identity will be successful but next connect will fail.
             * Possible the test should be split into two:
             * - add_identity_works_for_incompatible_pool_and_wallet
             *    with immediately check in the library
             * - connect_works_for_incorrect_connect_request
             *    actual info in ledger or listener_wallet, wrong public key in sender_wallet
             */

            assert_eq!(AgentUtils::connect(pool_handle, sender_wallet, sender_did.as_str(), listener_did.as_str(), None).unwrap_err(), ErrorCode::CommonInvalidState);

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_close_connection {
        use super::*;

        #[test]
        fn indy_agent_close_connection_works_for_incorrect_conn_handle() {
            TestUtils::cleanup_storage();

            let (wait_msg_from_cli_send, wait_msg_from_cli_recv) = channel();
            let wallet_handle = WalletUtils::create_and_open_wallet("pool6", None).unwrap();
            let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
            let endpoint = "127.0.0.1:9707";
            let listener_handle = AgentUtils::listen(endpoint, None,
                                                     Some(Box::new(move |_, msg| {
                                                         wait_msg_from_cli_send.send(msg).unwrap();
                                                     }))).unwrap();
            AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();
            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();
            let conn_handle = AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();

            assert_eq!(AgentUtils::close_connection(conn_handle + 100).unwrap_err(), ErrorCode::CommonInvalidStructure);

            let client_msg = "msg_from_cli_to_srv";
            AgentUtils::send(conn_handle, client_msg).unwrap();
            assert_eq!(wait_msg_from_cli_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap(), client_msg);

            TestUtils::cleanup_storage();
        }
    }

    mod indy_agent_close_listener {
        use super::*;

        #[test]
        fn indy_agent_close_listener_works_for_incorrect_handle() {
            TestUtils::cleanup_storage();

            let (wait_msg_from_cli_send, wait_msg_from_cli_recv) = channel();
            let wallet_handle = WalletUtils::create_and_open_wallet("pool9", None).unwrap();
            let (did, ver_key, pub_key): (String, String, String) = SignusUtils::create_and_store_my_did(wallet_handle, None).unwrap();
            let endpoint = "127.0.0.1:9709";
            let listener_handle = AgentUtils::listen(endpoint, None,
                                                     Some(Box::new(move |_, msg| {
                                                         wait_msg_from_cli_send.send(msg).unwrap();
                                                     }))).unwrap();
            AgentUtils::add_identity(listener_handle, -1, wallet_handle, did.as_str()).unwrap();
            SignusUtils::store_their_did_from_parts(wallet_handle, did.as_str(), pub_key.as_str(), ver_key.as_str(), endpoint).unwrap();
            let conn_handle = AgentUtils::connect(0, wallet_handle, did.as_str(), did.as_str(), None).unwrap();

            let incorrect_listener_handle = conn_handle;
            assert_eq!(AgentUtils::close_listener(incorrect_listener_handle).unwrap_err(), ErrorCode::CommonInvalidStructure);

            let client_msg = "msg_from_cli_to_srv";
            AgentUtils::send(conn_handle, client_msg).unwrap();
            assert_eq!(wait_msg_from_cli_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap(), client_msg);

            TestUtils::cleanup_storage();
        }
    }
}