continuous-testing 0.0.4

A continue testing library
Documentation
///
/// # Represent a test environment
///
pub mod continuous {
    use std::fs;
    use std::fs::File;
    use std::io::Write;
    use std::ops::Add;
    use std::path::Path;
    use std::process::Command;
    use std::thread::sleep;
    use std::time::{Duration, Instant};

    ///
    ///
    /// # Run command in a virtual machine
    ///
    /// - `directory`   The path to store the configuration
    /// - [**os**](https://app.vagrantup.com/boxes/search)          The box os
    /// - `memory`      The memory for the virtual machine
    /// - `cpus`        The cpus for the virtual machine
    /// - `command`     The test commands
    ///
    #[macro_export]
    macro_rules! install {
        ($directory:expr,$os:expr,$memory:expr,$cpus:expr,$command:expr) => {
            continuous::testing::Again::on($directory, $os, $memory, $cpus, $command)
        };
    }

    ///
    ///
    /// # Generate and run the configuration
    ///
    pub struct Again {}

    impl Again {
        ///
        ///
        /// - `directory`   The path to store the configuration
        /// - [**os**](https://app.vagrantup.com/boxes/search)          The box os
        /// - `memory`      The memory for the virtual machine
        /// - `cpus`        The cpus for the virtual machine
        /// - `command`     The test commands
        ///
        ///
        pub fn on(
            directory: &String,
            os: &String,
            memory: &String,
            cpus: &String,
            command: &String,
        ) -> Result<String, String> {
            if String::from(directory).is_empty() {
                return Err(String::from("Missing directory name"));
            }

            if String::from(os).is_empty() {
                return Err(String::from("Missing os url"));
            }

            if String::from(memory).is_empty() {
                return Err(String::from("Missing memory size"));
            }

            if String::from(cpus).is_empty() {
                return Err(String::from("Missing cpus size"));
            }

            if String::from(command).is_empty() {
                return Err(String::from("Missing commands"));
            }

            println!("\nDirectory : {}\nOperating system : {}\nMemory used : {}\nCpus used : {}\nCommand to run : {}\n", directory, os, memory, cpus, command);

            println!("Waiting...Press CTRL-C to cancel");

            sleep(Duration::from_secs(5));

            Command::new("clear").spawn().expect("linux");

            println!("[  OK  ] Starting configuration creation");

            if Path::new(directory.as_str()).is_dir() {
                fs::remove_dir_all(directory.as_str()).expect("failed to remove the directory");
                fs::create_dir(directory.as_str()).expect("Failed to create the directory");
            } else {
                fs::create_dir(directory.as_str()).expect("Failed to create the directory");
            }

            println!("[  OK  ] Directory has been created successfully");

            let binding = String::from(directory.as_str()).add("/").add("Vagrantfile");

            let mut f = File::create(binding.as_str()).expect("");

            f.write_all(format!("Vagrant.configure(\"2\") do |config|\n\tconfig.vm.box = \"{}\"\n\tconfig.vm.disk :disk, size: \"100GB\", primary: true\n\n\tconfig.vm.provider \"virtualbox\" do |vb|\n\t\tvb.gui = false\n\t\tvb.memory = \"{}\"\n\t\tvb.cpus =  {}\n\tend\n\n\tconfig.vm.provision \"shell\", path: \"bootstrap.sh\"\nend", os, memory, cpus).as_bytes()).expect("failed to create vagrant fie content");

            println!("[  OK  ] Vagrantfile has been created successfully");

            let bootstrap = String::from(directory.as_str())
                .add("/")
                .add("bootstrap.sh");

            let boot = bootstrap.as_str();

            File::create(boot).expect("");

            let mut b = File::options().append(true).open(boot).expect("");

            writeln!(&mut b, "#!/bin/bash").expect("");

            writeln!(&mut b, "{}", command).expect("");

            println!("[  OK  ] bootstrap.sh has been created successfully");

            Command::new("chmod")
                .arg("+x")
                .arg(boot)
                .spawn()
                .expect("")
                .wait()
                .expect("");

            println!("[  OK  ] bootstrap.sh is now executable");

            println!("[  OK  ] Configuration ready to use");

            println!("[  OK  ] Running the virtual machine");

            Command::new("vagrant")
                .arg("up")
                .arg("--no-color")
                .current_dir(directory.as_str())
                .spawn()
                .expect("")
                .wait()
                .expect("");

            println!("[  OK  ] Removing temporary files");

            Command::new("vagrant")
                .arg("destroy")
                .arg("-f")
                .current_dir(directory.as_str())
                .spawn()
                .expect("")
                .wait()
                .expect("");

            fs::remove_dir_all(directory.as_str()).expect("a");

            println!("[  OK  ] Temporary files removed successfully");

            Ok(String::from("success"))
        }
    }

    ///
    /// # A Vm builder
    ///
    pub struct Encore {
        started: Instant,
        directory: String,
        os: String,
        memory: String,
        cpus: String,
        command: String,
    }

    impl Default for Encore {
        fn default() -> Self {
            Self::new()
        }
    }

    impl Encore {
        ///
        /// # Constructor
        ///
        pub fn new() -> Encore {
            Self {
                started: Instant::now(),
                directory: "".to_string(),
                os: "".to_string(),
                memory: "".to_string(),
                cpus: "".to_string(),
                command: "".to_string(),
            }
        }

        ///
        /// # Set the dirname to store Vagrantfile and bootstrap.sh files
        ///
        /// - `dir` The dirname
        ///
        ///
        pub fn set_directory(&mut self, dir: &str) -> &mut Encore {
            self.directory = dir.to_string();
            self
        }

        ///
        /// # Get the defined user's directory
        ///
        pub fn get_directory(self) -> String {
            self.directory
        }

        ///
        /// # Set the os to install inside the vm
        ///
        /// - `os` The os box to use
        ///
        ///
        pub fn set_os(&mut self, os: &str) -> &mut Encore {
            self.os = os.to_string();
            self
        }

        ///
        /// # Get the defined user's os
        ///
        pub fn get_os(self) -> String {
            self.os
        }

        ///
        /// # Set the memory to use from the host
        ///
        /// - `memory` The host memory to use
        ///
        ///
        pub fn set_memory(&mut self, memory: &str) -> &mut Encore {
            self.memory = memory.to_string();
            self
        }

        ///
        /// # Get the defined user's memory size
        ///
        pub fn get_memory(self) -> String {
            self.memory
        }

        ///
        /// # Set the all cpus used by the host to run the test
        ///
        /// - `cpus` The host cpus to use
        ///
        ///
        pub fn set_cpus(&mut self, cpus: &str) -> &mut Encore {
            self.cpus = cpus.to_string();
            self
        }

        ///
        /// # Get the defined user's cpus usage
        ///
        pub fn get_cpus(self) -> String {
            self.cpus
        }

        ///
        /// # Set the command to run inside the vm
        ///
        /// - `command` The command to install and test the project
        ///
        pub fn set_command(&mut self, command: &str) -> &mut Encore {
            self.command = command.to_string();
            self
        }

        ///
        /// # Get the defined user's install command
        ///
        pub fn get_commands(self) -> String {
            self.command
        }

        ///
        /// # Build and run the configuration os
        ///
        pub fn run(self) -> Result<String, String> {
            let r = Again::on(
                &self.directory,
                &self.os,
                &self.memory,
                &self.cpus,
                &self.command,
            );

            println!(
                "Execution time : {} min",
                self.started.elapsed().as_secs() / 60
            );
            r
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::continuous::Encore;

    #[test]
    pub fn ok() -> Result<(), String> {
        let mut encore = Encore::new();

        encore.set_cpus("1");
        encore.set_directory("Encore");
        encore.set_os("generic/arch");
        encore.set_memory("1024");
        encore.set_command("pacman -Syyu git base base-devel virtualbox xterm vagrant libvirt --noconfirm && git clone https://github.com/taishingi/zuu && cd zuu && cargo build");
        encore.run().expect("failed");

        Ok(())
    }
}