<commit_before>use std::ffi;
use std::io;
use std::path::{Path, PathBuf};
use std::vec;

use env::Env;

/// Provides inspection and manipulation of a simulated process's environment.
#[derive(Default)]
pub struct SimulatedEnv {
    args: Vec<String>,
    args_os: Vec<ffi::OsString>,
    current_dir: PathBuf,
}

impl SimulatedEnv {
    /// Creates a new virtual environment.
    pub fn new() -> SimulatedEnv {
        SimulatedEnv {
            args: Vec::new(),
            args_os: Vec::new(),
            current_dir: PathBuf::from("/"),
        }
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args(&mut self, args: Vec<String>) {
        self.args = args;
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args_os(&mut self, args: Vec<ffi::OsString>) {
        self.args_os = args;
    }
}

impl Env for SimulatedEnv {
    type ArgsIter = vec::IntoIter<String>;
    type ArgsOsIter = vec::IntoIter<ffi::OsString>;

    fn args(&self) -> Self::ArgsIter {
        self.args.clone().into_iter()
    }

    fn args_os(&self) -> Self::ArgsOsIter {
        self.args_os.clone().into_iter()
    }

    fn current_dir(&self) -> io::Result<PathBuf> {
        Ok(self.current_dir.clone())
    }

    fn set_current_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<()> {
        self.current_dir = PathBuf::from(path.as_ref());
        Ok(())
    }
}

#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
    use std::ffi::OsString;
    use std::path::{Path, PathBuf};
    use super::SimulatedEnv;
    use env::Env;

    #[test]
    fn current_dir__default__returns_root() {
        let provider = SimulatedEnv::new();
        let result = provider.current_dir().unwrap();
        assert_eq!(PathBuf::from("/"), result);
    }

    #[test]
    fn current_dir__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let path = Path::new("/foo/bar");

        provider.set_current_dir(path).unwrap();
        let result = provider.current_dir().unwrap();

        assert_eq!(path, result.as_path());
    }

    #[test]
    fn args__default__returns_empty() {
        let provider = SimulatedEnv::new();
        let result = provider.args();
        assert_eq!(0, result.len());
    }

    #[test]
    fn args__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let args = vec!["app".to_string(), "arg1".to_string(), "arg2".to_string()];

        provider.set_args(args.clone());
        let result: Vec<String> = provider.args().collect();

        assert_eq!(args, result);
    }

    #[test]
    fn args_os__default__returns_empty() {
        let provider = SimulatedEnv::new();
        let result = provider.args_os();
        assert_eq!(0, result.len());
    }

    #[test]
    fn args_os__set_and_get__success() {<commit_msg>Make SimulatedEnv panic if something is used before a fake value is set for it<commit_after>use std::ffi;
use std::io;
use std::path::{Path, PathBuf};
use std::vec;

use env::Env;

/// Provides inspection and manipulation of a simulated process's environment.
#[derive(Default)]
pub struct SimulatedEnv {
    args: Option<Vec<String>>,
    args_os: Option<Vec<ffi::OsString>>,
    current_dir: Option<PathBuf>,
}

impl SimulatedEnv {
    /// Creates a new virtual environment.
    pub fn new() -> SimulatedEnv {
        SimulatedEnv {
            args: None,
            args_os: None,
            current_dir: None,
        }
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args(&mut self, args: Vec<String>) {
        self.args = Some(args);
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args_os(&mut self, args: Vec<ffi::OsString>) {
        self.args_os = Some(args);
    }
}

impl Env for SimulatedEnv {
    type ArgsIter = vec::IntoIter<String>;
    type ArgsOsIter = vec::IntoIter<ffi::OsString>;

    fn args(&self) -> Self::ArgsIter {
        self.args.clone()
            .expect("Env::args() was called before a simulated value was set")
            .into_iter()
    }

    fn args_os(&self) -> Self::ArgsOsIter {
        self.args_os.clone()
            .expect("Env::args_os() was called before a simulated value was set")
            .into_iter()
    }

    fn current_dir(&self) -> io::Result<PathBuf> {
        Ok(self.current_dir.clone()
            .expect("Env::current_dir() was called before a simulated value was set"))
    }

    fn set_current_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<()> {
        self.current_dir = Some(PathBuf::from(path.as_ref()));
        Ok(())
    }
}

#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
    use std::ffi::OsString;
    use std::path::Path;
    use super::SimulatedEnv;
    use env::Env;

    #[test]
    #[should_panic]
    fn current_dir__called_before_set__panics() {
        let provider = SimulatedEnv::new();
        let _ = provider.current_dir().unwrap();
    }

    #[test]
    fn current_dir__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let path = Path::new("/foo/bar");

        provider.set_current_dir(path).unwrap();
        let result = provider.current_dir().unwrap();

        assert_eq!(path, result.as_path());
    }

    #[test]
    #[should_panic]
    fn args__called_before_set__panics() {
        let provider = SimulatedEnv::new();
        let _ = provider.args();
    }

    #[test]
    fn args__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let args = vec!["app".to_string(), "arg1".to_string(), "arg2".to_string()];

        provider.set_args(args.clone());
        let result: Vec<String> = provider.args().collect();

        assert_eq!(args, result);
    }

    #[test]
    #[should_panic]
    fn args_os__called_before_set__panics() {
        let provider = SimulatedEnv::new();
        let _ = provider.args_os();
    }

    #[test]
    fn args_os__set_and_get__success() {
{'fraction_non_alphanumeric': 0.14604922279792745, 'fraction_numerical': 0.0009715025906735751, 'mean_word_length': 2.6921697549312613, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '769635', 'n_tokens_mistral': 1973, 'n_tokens_neox': 1967, 'n_words': 456}