1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::path::Path;

#[derive(Debug)]
pub struct ConfigurationError(pub &'static str);

pub trait LoadableFromEnvironment {
    fn load_from_env(&mut self) -> ();
}

pub trait Configuration where Self: Default + LoadableFromEnvironment {
    fn load() -> Self;
    fn load_from_file<P: AsRef<Path>>(p: P) -> Result<Self, ConfigurationError>;
}

#[cfg(test)]
mod tests {
    use super::*;
    use configurs_derive::{Configuration};

    use serde_derive::Deserialize;

    use serial_test::serial;

    #[derive(Configuration, Debug, Deserialize)]
    struct ConfigSub {
        #[env="CI"]
        #[default="bla"]
        ci: String,
    }

    #[derive(Configuration, Debug, Deserialize)]
    #[serde(default)]
    struct Config {
        #[env="PORT"]
        #[default="8088"]
        port: i16,

        #[env="CONFIGURATION_ITEM"]
        #[default="configuration_item"]
        configuration_item: String,

        #[env="CONFIGURATION_ITEM_OTHER"]
        #[default="configuration_item_other"]
        configuration_item_other: String,

        #[default]
        sub: ConfigSub,
    }

    #[test]
    #[serial]
    fn test_default_impl() {
        let c = Config::load();
        assert!(c.configuration_item == "configuration_item");
        assert!(c.sub.ci == "bla");
    }

    #[test]
    #[serial]
    fn test_env_var_override() {
        std::env::set_var("CONFIGURATION_ITEM", "test");
        let c = Config::load();

        assert!(c.configuration_item == "test");
        assert!(c.sub.ci == "bla");

        std::env::remove_var("CONFIGURATION_ITEM");
    }

    #[test]
    #[serial]
    fn test_file_loader() {
        let c = Config::load_from_file("./fixtures/Config.toml");
        assert!(c.is_ok());

        let config = c.unwrap();
        assert!(config.configuration_item == "TOML file entry");
        assert!(config.configuration_item_other == "configuration_item_other");
    }

    #[test]
    #[serial]
    fn test_file_loader_with_env_var_override() {
        std::env::set_var("PORT", "9001");

        let c = Config::load_from_file("./fixtures/Config.toml");
        assert!(c.is_ok());

        let config = c.unwrap();
        assert!(config.configuration_item == "TOML file entry");
        assert!(config.configuration_item_other == "configuration_item_other");
        assert!(config.port == 9001);

        std::env::remove_var("PORT");
    }
}