You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: connection_commands.rs
    path of file: ./repos/rustis/src/tests
    
    the code of the file until where you have to start completion: use crate::{
    client::{BatchPreparedCommand, Client, ClientPreparedCommand},
    commands::{
        ClientCachingMode, ClientKillOptions, ClientListOptions, ClientPauseMode, ClientReplyMode,
        ClientTrackingOptions, ClientTrackingStatus, ClientUnblockMode, ConnectionCommands,
        FlushingMode, GenericCommands, HelloOptions, PingOptions, ServerCommands,
        StringCommands,
    },
    network::spawn,
    sleep,
    tests::{get_test_client, log_try_init},
    Error, RedisError, RedisErrorKind, Result,
};
use futures_util::StreamExt;
use serial_test::serial;

#[cfg_attr(feature = "tokio-runtime", tokio::test)]
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
#[serial]
async fn auth() -> Result<()> {
    let client = get_test_client().await?;

    let result = client.auth(Some("username"), "password").await;
    assert!(matches!(
        result,
        Err(Error::Redis(RedisError {
            kind: RedisErrorKind::WrongPass,
            description: _
        }))
    ));

    let result = client.auth::<&str, &str>(None, "password").await;
    assert!(matches!(
        result,
        Err(Error::Redis(RedisError {
            kind: RedisErrorKind::Err,
            description: _
        }))
    ));

    Ok(())
}

#[cfg_attr(feature = "tokio-runtime", tokio::test)]
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
#[serial]
async fn client_getredir() -> Result<()> {
    let client1 = get_test_client().await?;
    let client2 = get_test_client().await?;

    let client1_id = client1.client_id().await?;

    client2
        .client_tracking(
            ClientTrackingStatus::On,
            ClientTrackingOptions::default().redirect(client1_id),
        )
        .await?;

    let redir_id = client2.client_getredir().await?;
    assert_eq!(client1_id, redir_id);

    client2
        .clie
    
async fn client_tracking() -> Result<()> {
    log_try_init();
    let client1 = Client::connect("redis://127.0.0.1?connection_name=client1").await?;
    let client1_invalidations =
        Client::connect("redis://127.0.0.1?connection_name=client1_invalidations").await?;
    let client2 = Client::connect("redis://127.0.0.1?connection_name=client2").await?;

    // prepare invalidations
    let invalidation_id = client1_invalidations.client_id().await?;
    let mut invalidation_stream =
        client1_invalidations.create_client_tracking_invalidation_stream()?;

    client1.set("key", "value").await?;

    client1
        .client_tracking(
            ClientTrackingStatus::On,
            ClientTrackingOptions::default().redirect(invalidation_id),
        )
        .await?;

    // Redis track our local caching
    let _value: String = client1.get("key").await?;

    client2.set("key", "new_value").await?;

    let keys_to_invalidate: Vec<String> = invalidation_stream.next().await.unwrap();
    assert_eq!(1, keys_to_invalidate.len());
    assert_eq!("key", keys_to_invalidate[0]);

    client1
        .client_tracking(ClientTrackingStatus::Off, ClientTrackingOptions::default())
        .await?;

    // optin
    client1
        .client_tracking(
            ClientTrackingStatus::On,
            ClientTrackingOptions::default()
                .redirect(invalidation_id)
                .optin(),
        )
        .await?;

    // Redis will not track our local caching because we are optin
    let _value: String = client1.get("key").await?;

    client2.set("key", "new_value2").await?;

    // Redis will track our local caching because of the client_caching command
    client1.client_caching(ClientCachingMode::Yes).await?;
    let _value: String = client1.get("key").await?;

    client2.set("key", "new_value3").await?;

    let keys_to_invalidate: Vec<String> = invalidation_stream.next().await.unwrap();
    assert_eq!(1, keys_to_invalidate.len());
    assert_eq!("key", keys_to_invalidate[0]);

    // broadcasting mode
    client1
        .client_tracking(ClientTrackingStatus::Off, ClientTrackingOptions::default())
        .await?;

    client1
        .client_tracking(
            ClientTrackingStatus::On,
            ClientTrackingOptions::default()
                .redirect(invalidation_id)
                .prefix("k")
                .broadcasting(),
        )
        .await?;

    // Redis will track our local caching because key is in the prefix pattern we just set
    let _value: String = client1.get("key").await?;

    client2.set("key", "new_value4").await?;

    let keys_to_invalidate: Vec<String> = invalidation_stream.next().await.unwrap();
    assert_eq!(1, keys_to_invalidate.len());
    assert_eq!("key", keys_to_invalidate[0]);

    Ok(())
}