demikernel 1.5.13

Kernel-Bypass LibOS Architecture
Documentation
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

//======================================================================================================================
// Imports
//======================================================================================================================

use ::anyhow::Result;
use ::demikernel::{
    LibOS,
    QDesc,
};

//======================================================================================================================
// Standalone Functions
//======================================================================================================================

/// Drives integration tests for pipe queues.
pub fn run(libos: &mut LibOS, pipe_name: &str) -> Vec<(String, String, Result<(), anyhow::Error>)> {
    let mut result: Vec<(String, String, Result<(), anyhow::Error>)> = Vec::new();

    demikernel::collect_test!(result, demikernel::run_test!(open_pipe_with_invalid_name(libos)));
    demikernel::collect_test!(
        result,
        demikernel::run_test!(open_pipe_that_does_not_exist(libos, pipe_name))
    );
    demikernel::collect_test!(
        result,
        demikernel::run_test!(open_pipe_multiple_times(libos, pipe_name))
    );

    result
}

/// Attempts to open a pipe with an invalid name.
fn open_pipe_with_invalid_name(libos: &mut LibOS) -> Result<()> {
    // Fail to create pipe with an invalid name.
    match libos.create_pipe(&format!("")) {
        Err(e) if e.errno == libc::EINVAL => Ok(()),
        Ok(_) => anyhow::bail!("create_pipe() with invalid name should fail"),
        Err(e) => anyhow::bail!("create_pipe() failed ({})", e),
    }
}

/// Attempts to open a pipe that does not exist.
fn open_pipe_that_does_not_exist(libos: &mut LibOS, pipe_name: &str) -> Result<()> {
    // Fail to open pipe that does not exist.
    match libos.open_pipe(&format!("{}-does-not-exist", pipe_name)) {
        Err(e) if e.errno == libc::ENOENT => Ok(()),
        Ok(_) => anyhow::bail!("open_pipe() that does not exist should fail"),
        Err(e) => anyhow::bail!("open_pipe() failed ({})", e),
    }
}

/// Attempts to open a pipe multiple times.
fn open_pipe_multiple_times(libos: &mut LibOS, pipe_name: &str) -> Result<()> {
    let mut ret: Result<(), anyhow::Error> = Ok(());

    // Create a pipe.
    let pipeqd: QDesc = match libos.create_pipe(pipe_name) {
        Ok(pipeqd) => pipeqd,
        Err(e) => anyhow::bail!("create_pipe() failed ({})", e),
    };

    // Succeed to open pipe multiple times. The number of iterations was set arbitrarily.
    for _ in 0..128 {
        let pipeqd: QDesc = match libos.open_pipe(pipe_name) {
            Ok(pipeqd) => pipeqd,
            Err(e) => {
                let errmsg: String = format!("open_pipe() failed ({})", e);
                demikernel::update_test_error!(ret, errmsg);
                println!("[ERROR] leaking pipeqd={:?}", pipeqd);
                break;
            },
        };

        match libos.close(pipeqd) {
            Ok(_) => (),
            Err(e) => {
                let errmsg: String = format!("close() failed ({})", e);
                demikernel::update_test_error!(ret, errmsg);
                println!("[ERROR] leaking pipeqd={:?}", pipeqd);
                break;
            },
        }
    }

    // Succeed to close pipe.
    match libos.close(pipeqd) {
        Ok(_) => (),
        Err(e) => {
            let errmsg: String = format!("close() failed ({})", e);
            demikernel::update_test_error!(ret, errmsg);
            println!("[ERROR] leaking pipeqd={:?}", pipeqd);
        },
    }

    ret
}