| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use { |
| failure::Fail, |
| fuchsia_syslog::{fx_log_err, fx_log_info}, |
| serde_derive::Deserialize, |
| std::{ |
| fs::File, |
| io::{BufReader, Read}, |
| }, |
| }; |
| |
| /// Static service configuration options. |
| #[derive(Debug, Default, PartialEq, Eq)] |
| pub struct Config { |
| disable_dynamic_configuration: bool, |
| } |
| |
| impl Config { |
| pub fn disable_dynamic_configuration(&self) -> bool { |
| self.disable_dynamic_configuration |
| } |
| |
| pub fn load_from_config_data_or_default() -> Config { |
| let f = match File::open("/config/data/config.json") { |
| Ok(f) => f, |
| Err(e) => { |
| fx_log_info!("no config found, using defaults: {:?}", e.kind()); |
| return Config::default(); |
| } |
| }; |
| |
| Self::load(BufReader::new(f)).unwrap_or_else(|e| { |
| fx_log_err!("unable to load config, using defaults: {:?}", e); |
| Config::default() |
| }) |
| } |
| |
| fn load(r: impl Read) -> Result<Config, ConfigLoadError> { |
| #[derive(Debug, Deserialize)] |
| #[serde(deny_unknown_fields)] |
| struct ParseConfig { |
| disable_dynamic_configuration: bool, |
| } |
| |
| let parse_config = serde_json::from_reader::<_, ParseConfig>(r)?; |
| |
| Ok(Config { disable_dynamic_configuration: parse_config.disable_dynamic_configuration }) |
| } |
| } |
| |
| #[derive(Debug, Fail)] |
| enum ConfigLoadError { |
| #[fail(display = "parse error: {}", _0)] |
| Parse(#[cause] serde_json::Error), |
| } |
| |
| impl From<serde_json::Error> for ConfigLoadError { |
| fn from(e: serde_json::Error) -> Self { |
| Self::Parse(e) |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use {super::*, matches::assert_matches, serde_json::json}; |
| |
| fn verify_load(input: serde_json::Value, expected: Config) { |
| assert_eq!( |
| Config::load(input.to_string().as_bytes()).expect("json value to be valid"), |
| expected |
| ); |
| } |
| |
| #[test] |
| fn test_load_valid_configs() { |
| for val in [true, false].iter() { |
| verify_load( |
| json!({ |
| "disable_dynamic_configuration": *val, |
| }), |
| Config { disable_dynamic_configuration: *val }, |
| ); |
| } |
| } |
| |
| #[test] |
| fn test_load_errors_on_unknown_field() { |
| assert_matches!( |
| Config::load( |
| json!({ |
| "disable_dynamic_configuration": false, |
| "unknown_field": 3 |
| }) |
| .to_string() |
| .as_bytes() |
| ), |
| Err(ConfigLoadError::Parse(_)) |
| ); |
| } |
| |
| #[test] |
| fn test_no_config_data_is_default() { |
| assert_eq!(Config::load_from_config_data_or_default(), Config::default()); |
| } |
| |
| #[test] |
| fn test_default_does_not_disable_dynamic_configuraiton() { |
| assert_eq!(Config::default().disable_dynamic_configuration, false); |
| } |
| } |