additional test coverage for missing lines #11
+2611
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
/// Additional tests for config module to improve coverage
|
||||
|
||||
use redshift_rebooted::config::{Config, LocationSource};
|
||||
use redshift_rebooted::types::Location;
|
||||
|
||||
#[test]
|
||||
fn test_config_path_creation() {
|
||||
let result = Config::config_path();
|
||||
assert!(result.is_ok(), "Should be able to determine config path");
|
||||
|
||||
let path = result.unwrap();
|
||||
assert!(path.to_string_lossy().contains("redshift"), "Path should contain 'redshift'");
|
||||
assert!(path.to_string_lossy().ends_with("config.toml"), "Path should end with 'config.toml'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_load_returns_default_on_missing_file() {
|
||||
// Test the default config behavior
|
||||
let config = Config::default();
|
||||
|
||||
assert!(config.location.is_none(), "Default config should have no location");
|
||||
assert!(config.last_geoclue_check.is_none(), "Default config should have no last check");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_save_and_load() {
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
// Create a config with data
|
||||
let mut config = Config::default();
|
||||
config.set_location(
|
||||
Location { lat: 48.8566, lon: 2.3522 },
|
||||
LocationSource::Manual,
|
||||
Some("Paris".to_string())
|
||||
);
|
||||
config.update_geoclue_check();
|
||||
|
||||
// Serialize to TOML string
|
||||
let toml_str = toml::to_string(&config).expect("Should serialize to TOML");
|
||||
|
||||
// Deserialize back
|
||||
let loaded: Config = toml::from_str(&toml_str).expect("Should deserialize from TOML");
|
||||
|
||||
// Verify data was preserved
|
||||
assert!(loaded.location.is_some(), "Loaded config should have location");
|
||||
let location = loaded.get_location().unwrap();
|
||||
assert_eq!(location.lat, 48.8566, "Latitude should match");
|
||||
assert_eq!(location.lon, 2.3522, "Longitude should match");
|
||||
|
||||
assert!(loaded.last_geoclue_check.is_some(), "Loaded config should have geoclue check timestamp");
|
||||
|
||||
if let Some(ref saved_loc) = loaded.location {
|
||||
assert_eq!(saved_loc.source, LocationSource::Manual, "Source should be Manual");
|
||||
assert_eq!(saved_loc.city_name, Some("Paris".to_string()), "City name should be preserved");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_path_has_parent_directory() {
|
||||
// Verify config path has a parent directory
|
||||
let config_path = Config::config_path();
|
||||
assert!(config_path.is_ok(), "Should be able to get config path");
|
||||
|
||||
let path = config_path.unwrap();
|
||||
assert!(path.parent().is_some(), "Config path should have a parent directory");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_update_geoclue_check() {
|
||||
let mut config = Config::default();
|
||||
|
||||
// Initially should be None
|
||||
assert!(config.last_geoclue_check.is_none());
|
||||
|
||||
// Update the check
|
||||
config.update_geoclue_check();
|
||||
|
||||
// Should now have a timestamp
|
||||
assert!(config.last_geoclue_check.is_some());
|
||||
let timestamp = config.last_geoclue_check.unwrap();
|
||||
|
||||
// Timestamp should be recent (within last minute)
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
|
||||
assert!(timestamp <= now, "Timestamp should not be in the future");
|
||||
assert!(now - timestamp < 60, "Timestamp should be recent");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_parse_invalid_toml() {
|
||||
// Test that invalid TOML fails to parse
|
||||
let invalid_toml = "this is not valid toml [[[";
|
||||
|
||||
let result: Result<Config, _> = toml::from_str(invalid_toml);
|
||||
assert!(result.is_err(), "Parsing invalid TOML should fail");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_location_source_serialization() {
|
||||
use serde_json;
|
||||
|
||||
// Test Manual source
|
||||
let manual_json = serde_json::to_string(&LocationSource::Manual).unwrap();
|
||||
assert_eq!(manual_json, r#""manual""#);
|
||||
|
||||
// Test Interactive source
|
||||
let interactive_json = serde_json::to_string(&LocationSource::Interactive).unwrap();
|
||||
assert_eq!(interactive_json, r#""interactive""#);
|
||||
|
||||
// Test GeoClue2 source
|
||||
let geoclue_json = serde_json::to_string(&LocationSource::GeoClue2).unwrap();
|
||||
assert_eq!(geoclue_json, r#""geoclue2""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_location_source_deserialization() {
|
||||
use serde_json;
|
||||
|
||||
let manual: LocationSource = serde_json::from_str(r#""manual""#).unwrap();
|
||||
assert_eq!(manual, LocationSource::Manual);
|
||||
|
||||
let interactive: LocationSource = serde_json::from_str(r#""interactive""#).unwrap();
|
||||
assert_eq!(interactive, LocationSource::Interactive);
|
||||
|
||||
let geoclue: LocationSource = serde_json::from_str(r#""geoclue2""#).unwrap();
|
||||
assert_eq!(geoclue, LocationSource::GeoClue2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saved_location_with_all_fields() {
|
||||
let mut config = Config::default();
|
||||
|
||||
config.set_location(
|
||||
Location { lat: 35.6762, lon: 139.6503 },
|
||||
LocationSource::GeoClue2,
|
||||
Some("Tokyo".to_string())
|
||||
);
|
||||
|
||||
let saved_loc = config.location.as_ref().unwrap();
|
||||
assert_eq!(saved_loc.lat, 35.6762);
|
||||
assert_eq!(saved_loc.lon, 139.6503);
|
||||
assert_eq!(saved_loc.source, LocationSource::GeoClue2);
|
||||
assert_eq!(saved_loc.city_name, Some("Tokyo".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saved_location_without_city_name() {
|
||||
let mut config = Config::default();
|
||||
|
||||
config.set_location(
|
||||
Location { lat: -33.8688, lon: 151.2093 },
|
||||
LocationSource::Interactive,
|
||||
None
|
||||
);
|
||||
|
||||
let saved_loc = config.location.as_ref().unwrap();
|
||||
assert_eq!(saved_loc.lat, -33.8688);
|
||||
assert_eq!(saved_loc.lon, 151.2093);
|
||||
assert_eq!(saved_loc.source, LocationSource::Interactive);
|
||||
assert!(saved_loc.city_name.is_none());
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/// Additional tests for gamma module to improve coverage
|
||||
|
||||
use redshift_rebooted::gamma::{DummyGammaMethod, GammaMethod};
|
||||
use redshift_rebooted::types::ColorSetting;
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_name() {
|
||||
let method = DummyGammaMethod::new();
|
||||
assert_eq!(method.name(), "dummy");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_print_help() {
|
||||
let method = DummyGammaMethod::new();
|
||||
|
||||
// Should not panic
|
||||
method.print_help();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_with_preserve_flag() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
let setting = ColorSetting {
|
||||
temperature: 3500,
|
||||
brightness: 1.0,
|
||||
gamma: [1.0, 1.0, 1.0],
|
||||
};
|
||||
|
||||
// Test with preserve = true
|
||||
let result = method.set_temperature(&setting, true);
|
||||
assert!(result.is_ok(), "set_temperature with preserve=true should succeed");
|
||||
|
||||
// Test with preserve = false
|
||||
let result = method.set_temperature(&setting, false);
|
||||
assert!(result.is_ok(), "set_temperature with preserve=false should succeed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_extreme_temperatures() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
// Very cool temperature
|
||||
let cool_setting = ColorSetting {
|
||||
temperature: 1000,
|
||||
brightness: 1.0,
|
||||
gamma: [1.0, 1.0, 1.0],
|
||||
};
|
||||
let result = method.set_temperature(&cool_setting, false);
|
||||
assert!(result.is_ok(), "Very cool temperature should succeed");
|
||||
|
||||
// Very warm temperature
|
||||
let warm_setting = ColorSetting {
|
||||
temperature: 25000,
|
||||
brightness: 1.0,
|
||||
gamma: [1.0, 1.0, 1.0],
|
||||
};
|
||||
let result = method.set_temperature(&warm_setting, false);
|
||||
assert!(result.is_ok(), "Very warm temperature should succeed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_various_brightness() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
let brightnesses = [0.1, 0.5, 0.8, 1.0];
|
||||
|
||||
for brightness in brightnesses {
|
||||
let setting = ColorSetting {
|
||||
temperature: 6500,
|
||||
brightness,
|
||||
gamma: [1.0, 1.0, 1.0],
|
||||
};
|
||||
let result = method.set_temperature(&setting, false);
|
||||
assert!(result.is_ok(), "Brightness {} should succeed", brightness);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_various_gamma_values() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
let gamma_values = [
|
||||
[0.5, 0.5, 0.5],
|
||||
[1.0, 1.0, 1.0],
|
||||
[1.5, 1.5, 1.5],
|
||||
[2.0, 2.0, 2.0],
|
||||
[1.0, 1.2, 0.8], // Asymmetric gamma
|
||||
];
|
||||
|
||||
for gamma in gamma_values {
|
||||
let setting = ColorSetting {
|
||||
temperature: 6500,
|
||||
brightness: 1.0,
|
||||
gamma,
|
||||
};
|
||||
let result = method.set_temperature(&setting, false);
|
||||
assert!(result.is_ok(), "Gamma {:?} should succeed", gamma);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_multiple_restore_calls() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
// Multiple restore calls should not panic
|
||||
method.restore();
|
||||
method.restore();
|
||||
method.restore();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_restore_without_start() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
|
||||
// Restore without start should not panic
|
||||
method.restore();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_as_trait_object() {
|
||||
let mut method: Box<dyn GammaMethod> = Box::new(DummyGammaMethod::new());
|
||||
|
||||
assert!(method.init().is_ok());
|
||||
assert!(method.start().is_ok());
|
||||
assert_eq!(method.name(), "dummy");
|
||||
|
||||
let setting = ColorSetting::default();
|
||||
assert!(method.set_temperature(&setting, false).is_ok());
|
||||
|
||||
method.restore();
|
||||
method.print_help();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_sequence_of_different_settings() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
// Sequence of different settings simulating a day cycle
|
||||
let settings = [
|
||||
ColorSetting { temperature: 6500, brightness: 0.5, gamma: [1.0, 1.0, 1.0] },
|
||||
ColorSetting { temperature: 5000, brightness: 0.7, gamma: [1.0, 1.0, 1.0] },
|
||||
ColorSetting { temperature: 4000, brightness: 0.9, gamma: [1.0, 1.0, 1.0] },
|
||||
ColorSetting { temperature: 3500, brightness: 1.0, gamma: [1.0, 1.0, 1.0] },
|
||||
ColorSetting { temperature: 4000, brightness: 0.9, gamma: [1.0, 1.0, 1.0] },
|
||||
ColorSetting { temperature: 5000, brightness: 0.7, gamma: [1.0, 1.0, 1.0] },
|
||||
ColorSetting { temperature: 6500, brightness: 0.5, gamma: [1.0, 1.0, 1.0] },
|
||||
];
|
||||
|
||||
for setting in &settings {
|
||||
let result = method.set_temperature(setting, false);
|
||||
assert!(result.is_ok(), "Setting temperature to {} should succeed", setting.temperature);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_init_multiple_times() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
|
||||
// Init multiple times should succeed
|
||||
assert!(method.init().is_ok());
|
||||
assert!(method.init().is_ok());
|
||||
assert!(method.init().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy_gamma_method_start_multiple_times() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
|
||||
// Start multiple times should succeed
|
||||
assert!(method.start().is_ok());
|
||||
assert!(method.start().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_color_setting_default_for_gamma_method() {
|
||||
let mut method = DummyGammaMethod::new();
|
||||
method.init().expect("Init should succeed");
|
||||
method.start().expect("Start should succeed");
|
||||
|
||||
// Test with default ColorSetting
|
||||
let setting = ColorSetting::default();
|
||||
let result = method.set_temperature(&setting, false);
|
||||
assert!(result.is_ok(), "Default ColorSetting should work");
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/// Additional tests for solar module to improve coverage
|
||||
|
||||
// Import private functions for testing by using path
|
||||
// Since these are in the main module, we need to test them indirectly
|
||||
|
||||
#[test]
|
||||
fn test_solar_constants_are_defined() {
|
||||
// Test that the solar constants are accessible and correct
|
||||
use redshift_rebooted::solar::{
|
||||
SOLAR_ATM_REFRAC, SOLAR_ASTRO_TWILIGHT_ELEV, SOLAR_CIVIL_TWILIGHT_ELEV,
|
||||
SOLAR_DAYTIME_ELEV, SOLAR_NAUT_TWILIGHT_ELEV,
|
||||
};
|
||||
|
||||
assert_eq!(SOLAR_ATM_REFRAC, 0.833);
|
||||
assert_eq!(SOLAR_ASTRO_TWILIGHT_ELEV, -18.0);
|
||||
assert_eq!(SOLAR_NAUT_TWILIGHT_ELEV, -12.0);
|
||||
assert_eq!(SOLAR_CIVIL_TWILIGHT_ELEV, -6.0);
|
||||
assert_eq!(SOLAR_DAYTIME_ELEV, 0.0 - SOLAR_ATM_REFRAC);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_is_computed() {
|
||||
// Test that solar elevation can be computed without errors
|
||||
// Use equator at noon UTC for simplicity
|
||||
|
||||
// March 20, 2024, ~12:00 UTC (approximate equinox)
|
||||
let date = 1710936000.0; // Unix timestamp
|
||||
let lat = 0.0; // Equator
|
||||
let lon = 0.0; // Prime meridian
|
||||
|
||||
let elevation = redshift_rebooted::solar::solar_elevation(date, lat, lon);
|
||||
|
||||
// Elevation should be in valid range
|
||||
assert!(elevation >= -90.0 && elevation <= 90.0, "Elevation should be in valid range");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_at_midnight() {
|
||||
// Test solar elevation at midnight (lowest point)
|
||||
// Should be negative (sun below horizon)
|
||||
|
||||
// March 20, 2024, ~00:00 UTC
|
||||
let date = 1710892800.0; // Unix timestamp
|
||||
let lat = 40.7;
|
||||
let lon = -74.0;
|
||||
|
||||
let elevation = redshift_rebooted::solar::solar_elevation(date, lat, lon);
|
||||
|
||||
// At midnight, sun should be below horizon
|
||||
assert!(elevation < 0.0, "Solar elevation at midnight should be negative");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_table_fill_returns_all_times() {
|
||||
// Test that solar_table_fill returns a complete table
|
||||
use redshift_rebooted::solar::solar_table_fill;
|
||||
|
||||
let date = 1710936000.0; // March 20, 2024, ~12:00 UTC
|
||||
let lat = 40.7;
|
||||
let lon = -74.0;
|
||||
|
||||
let table = solar_table_fill(date, lat, lon);
|
||||
|
||||
// Table should have 10 entries
|
||||
assert_eq!(table.len(), 10);
|
||||
|
||||
// Noon and midnight should always be valid
|
||||
assert!(!table[0].is_nan(), "Noon should be valid"); // Noon is index 0
|
||||
assert!(!table[1].is_nan(), "Midnight should be valid"); // Midnight is index 1
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_table_fill_has_valid_noon() {
|
||||
// Test that solar_table_fill returns a valid noon timestamp
|
||||
use redshift_rebooted::solar::solar_table_fill;
|
||||
|
||||
let date = 1710936000.0; // March 20, 2024
|
||||
let lat = 40.7;
|
||||
let lon = -74.0;
|
||||
|
||||
let table = solar_table_fill(date, lat, lon);
|
||||
|
||||
// Noon should always be valid
|
||||
let noon = table[0];
|
||||
assert!(!noon.is_nan(), "Noon should be valid");
|
||||
assert!(noon > 0.0, "Noon timestamp should be positive");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_table_fill_polar_latitudes() {
|
||||
// Test solar_table_fill at polar latitudes where some events may not occur
|
||||
use redshift_rebooted::solar::solar_table_fill;
|
||||
|
||||
// North pole in summer - midnight sun
|
||||
let date = 1718985600.0; // June 21, 2024 (summer solstice)
|
||||
let lat = 85.0; // Near north pole
|
||||
let lon = 0.0;
|
||||
|
||||
let table = solar_table_fill(date, lat, lon);
|
||||
|
||||
// Some twilight events may be NaN (sun never goes below certain elevations)
|
||||
// Just verify the function completes without panic
|
||||
assert_eq!(table.len(), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_table_fill_equator() {
|
||||
// Test solar_table_fill at the equator
|
||||
use redshift_rebooted::solar::solar_table_fill;
|
||||
|
||||
let date = 1710936000.0; // March 20, 2024 (equinox)
|
||||
let lat = 0.0; // Equator
|
||||
let lon = 0.0;
|
||||
|
||||
let table = solar_table_fill(date, lat, lon);
|
||||
|
||||
// All events should be valid at equator on equinox
|
||||
for (i, &time) in table.iter().enumerate() {
|
||||
assert!(!time.is_nan(), "Event {} should be valid at equator", i);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_changes_over_time() {
|
||||
// Test that solar elevation changes over a 24-hour period
|
||||
use redshift_rebooted::solar::solar_elevation;
|
||||
|
||||
let lat = 0.0; // Equator for simpler calculations
|
||||
let lon = 0.0;
|
||||
|
||||
// Sample at different times
|
||||
let time1 = 1710892800.0;
|
||||
let time2 = 1710935400.0; // 12 hours later
|
||||
|
||||
let el1 = solar_elevation(time1, lat, lon);
|
||||
let el2 = solar_elevation(time2, lat, lon);
|
||||
|
||||
// Elevations should be different
|
||||
assert_ne!(el1, el2, "Solar elevation should change over time");
|
||||
assert!(el1 >= -90.0 && el1 <= 90.0, "Elevation 1 should be in valid range");
|
||||
assert!(el2 >= -90.0 && el2 <= 90.0, "Elevation 2 should be in valid range");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_different_times_differ() {
|
||||
// Test that solar elevation differs at different times
|
||||
use redshift_rebooted::solar::solar_elevation;
|
||||
|
||||
let lat = 40.7;
|
||||
let lon = -74.0;
|
||||
|
||||
// Different times of day
|
||||
let time1 = 1710936000.0;
|
||||
let time2 = 1710946800.0; // Several hours later
|
||||
let time3 = 1710957600.0; // Several more hours later
|
||||
|
||||
let el1 = solar_elevation(time1, lat, lon);
|
||||
let el2 = solar_elevation(time2, lat, lon);
|
||||
let el3 = solar_elevation(time3, lat, lon);
|
||||
|
||||
// At least some values should differ
|
||||
assert!(el1 != el2 || el2 != el3, "Solar elevations should vary over time");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_southern_hemisphere() {
|
||||
// Test solar elevation in southern hemisphere
|
||||
use redshift_rebooted::solar::solar_elevation;
|
||||
|
||||
// Sydney, Australia (-33.9° S, 151.2° E)
|
||||
let date = 1710936000.0;
|
||||
let lat = -33.9;
|
||||
let lon = 151.2;
|
||||
|
||||
let elevation = solar_elevation(date, lat, lon);
|
||||
|
||||
// Should get a valid elevation
|
||||
assert!(elevation > -90.0 && elevation < 90.0, "Elevation should be in valid range");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_negative_longitude() {
|
||||
// Test with negative longitude (western hemisphere)
|
||||
use redshift_rebooted::solar::solar_elevation;
|
||||
|
||||
let date = 1710936000.0;
|
||||
let lat = 51.5; // London
|
||||
let lon = -0.1; // Slightly west of prime meridian
|
||||
|
||||
let elevation = solar_elevation(date, lat, lon);
|
||||
|
||||
// Should get a valid elevation
|
||||
assert!(elevation > -90.0 && elevation < 90.0, "Elevation should be in valid range");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_table_fill_midnight_after_noon() {
|
||||
// Verify that midnight timestamp is 12 hours after noon
|
||||
use redshift_rebooted::solar::solar_table_fill;
|
||||
|
||||
let date = 1710936000.0;
|
||||
let lat = 40.7;
|
||||
let lon = -74.0;
|
||||
|
||||
let table = solar_table_fill(date, lat, lon);
|
||||
|
||||
let noon = table[0];
|
||||
let midnight = table[1];
|
||||
|
||||
// Midnight should be approximately 12 hours (43200 seconds) after noon
|
||||
let diff = midnight - noon;
|
||||
assert!((diff - 43200.0).abs() < 60.0, "Midnight should be ~12 hours after noon");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_extreme_latitudes() {
|
||||
// Test solar elevation calculations at extreme latitudes
|
||||
use redshift_rebooted::solar::solar_elevation;
|
||||
|
||||
let date = 1710936000.0;
|
||||
|
||||
// Near north pole
|
||||
let el_north = solar_elevation(date, 89.0, 0.0);
|
||||
assert!(el_north > -90.0 && el_north < 90.0, "North pole elevation should be valid");
|
||||
|
||||
// Near south pole
|
||||
let el_south = solar_elevation(date, -89.0, 0.0);
|
||||
assert!(el_south > -90.0 && el_south < 90.0, "South pole elevation should be valid");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solar_elevation_full_day_cycle() {
|
||||
// Test that solar elevation follows expected pattern over 24 hours
|
||||
use redshift_rebooted::solar::solar_elevation;
|
||||
|
||||
let lat = 40.7;
|
||||
let lon = -74.0;
|
||||
let start_date = 1710892800.0; // Midnight
|
||||
|
||||
let mut max_elevation: f64 = -90.0;
|
||||
let mut min_elevation: f64 = 90.0;
|
||||
|
||||
// Sample every 2 hours for 24 hours
|
||||
for hour in 0..12 {
|
||||
let date = start_date + (hour as f64 * 7200.0);
|
||||
let el = solar_elevation(date, lat, lon);
|
||||
|
||||
max_elevation = max_elevation.max(el);
|
||||
min_elevation = min_elevation.min(el);
|
||||
}
|
||||
|
||||
// Max should be positive (daytime), min should be negative (nighttime)
|
||||
assert!(max_elevation > 0.0, "Max elevation during day should be positive");
|
||||
assert!(min_elevation < 0.0, "Min elevation during night should be negative");
|
||||
}
|
||||
Reference in New Issue
Block a user