mirror of
https://github.com/SeCherkasov/util-linux-cal.git
synced 2026-03-30 16:01:50 +03:00
Bump to 0.1.1: fix bugs, rewrite tests
Bug fixes: - Fix Zeller's formula for Julian calendar (separate branch without century correction) and use rem_euclid for negative modulo safety - Pass country code (cc=) to isdayoff.ru API in holiday plugin - Sync clap --version with Cargo.toml (was hardcoded "1.0.0") Tests: - Rename integration_tests.rs to unit_tests.rs (they are unit tests) - Fix race condition on env vars in plugin tests (Mutex + remove_var) - Fix incorrect assertions (color tty detection, locale fallback) - Add missing test cases: Julian/Gregorian Zeller, display date parsing, Sunday offset, week numbers, edge cases (87 tests total) - Remove brittle version-checking tests
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "holiday_highlighter"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
edition = "2024"
|
||||
description = "Holiday highlighting plugin for cal using isdayoff.ru API"
|
||||
|
||||
|
||||
@@ -157,8 +157,14 @@ pub unsafe extern "C" fn plugin_get_year_holidays(
|
||||
}
|
||||
|
||||
/// Fetch holiday data for a month from isdayoff.ru API.
|
||||
fn fetch_holidays(year: i32, month: u32, _country: &str) -> Option<String> {
|
||||
let url = format!("{}?year={}&month={:02}&pre=1", API_URL_MONTH, year, month);
|
||||
fn fetch_holidays(year: i32, month: u32, country: &str) -> Option<String> {
|
||||
let url = format!(
|
||||
"{}?year={}&month={:02}&cc={}&pre=1",
|
||||
API_URL_MONTH,
|
||||
year,
|
||||
month,
|
||||
country.to_lowercase()
|
||||
);
|
||||
|
||||
match ureq::get(&url).call() {
|
||||
Ok(response) => response.into_body().read_to_string().ok(),
|
||||
@@ -167,8 +173,13 @@ fn fetch_holidays(year: i32, month: u32, _country: &str) -> Option<String> {
|
||||
}
|
||||
|
||||
/// Fetch holiday data for entire year from isdayoff.ru API.
|
||||
pub fn fetch_holidays_year(year: i32, _country: &str) -> Option<String> {
|
||||
let url = format!("{}?year={}&pre=1", API_URL_YEAR, year);
|
||||
pub fn fetch_holidays_year(year: i32, country: &str) -> Option<String> {
|
||||
let url = format!(
|
||||
"{}?year={}&cc={}&pre=1",
|
||||
API_URL_YEAR,
|
||||
year,
|
||||
country.to_lowercase()
|
||||
);
|
||||
|
||||
match ureq::get(&url).call() {
|
||||
Ok(response) => response.into_body().read_to_string().ok(),
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
//! Integration tests for holiday_highlighter plugin.
|
||||
|
||||
use holiday_highlighter::{
|
||||
PLUGIN_NAME, PLUGIN_VERSION, get_country_from_locale, plugin_get_name, plugin_get_version,
|
||||
};
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
fn test_get_country_from_locale_ru() {
|
||||
unsafe {
|
||||
std::env::set_var("LC_ALL", "ru_RU.UTF-8");
|
||||
}
|
||||
assert_eq!(get_country_from_locale(), "RU");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_country_from_locale_us() {
|
||||
unsafe {
|
||||
std::env::set_var("LC_ALL", "en_US.UTF-8");
|
||||
}
|
||||
assert_eq!(get_country_from_locale(), "US");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_country_from_locale_by() {
|
||||
unsafe {
|
||||
std::env::set_var("LC_ALL", "be_BY.UTF-8");
|
||||
}
|
||||
assert_eq!(get_country_from_locale(), "BY");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_country_from_locale_fallback() {
|
||||
unsafe {
|
||||
std::env::set_var("LC_ALL", "");
|
||||
std::env::set_var("LC_TIME", "");
|
||||
std::env::set_var("LANG", "");
|
||||
}
|
||||
assert_eq!(get_country_from_locale(), "RU");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plugin_metadata_from_cargo() {
|
||||
assert_eq!(PLUGIN_NAME, "holiday_highlighter");
|
||||
assert_eq!(PLUGIN_VERSION, "0.1.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plugin_get_name_version() {
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(plugin_get_name()).to_str().unwrap();
|
||||
let version = CStr::from_ptr(plugin_get_version()).to_str().unwrap();
|
||||
assert_eq!(name, "holiday_highlighter");
|
||||
assert_eq!(version, "0.1.0");
|
||||
}
|
||||
}
|
||||
80
plugins/holiday_highlighter/tests/unit_tests.rs
Normal file
80
plugins/holiday_highlighter/tests/unit_tests.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
//! Unit tests for holiday_highlighter plugin.
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
use holiday_highlighter::get_country_from_locale;
|
||||
|
||||
/// Mutex to serialize tests that modify environment variables.
|
||||
/// `set_var` is not thread-safe, so locale tests must not run in parallel.
|
||||
/// We use `lock().unwrap_or_else(|e| e.into_inner())` to recover from poison.
|
||||
static ENV_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
fn lock_env() -> std::sync::MutexGuard<'static, ()> {
|
||||
ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner())
|
||||
}
|
||||
|
||||
/// Reset all locale env vars to a clean state, then set `LC_ALL` to the given value.
|
||||
fn set_locale(lc_all: &str) {
|
||||
unsafe {
|
||||
std::env::set_var("LC_ALL", lc_all);
|
||||
std::env::remove_var("LC_TIME");
|
||||
std::env::remove_var("LANG");
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove all locale env vars.
|
||||
fn clear_locale() {
|
||||
unsafe {
|
||||
std::env::remove_var("LC_ALL");
|
||||
std::env::remove_var("LC_TIME");
|
||||
std::env::remove_var("LANG");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Country detection from locale
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn country_from_locale_ru() {
|
||||
let _guard = lock_env();
|
||||
set_locale("ru_RU.UTF-8");
|
||||
assert_eq!(get_country_from_locale(), "RU");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn country_from_locale_us() {
|
||||
let _guard = lock_env();
|
||||
set_locale("en_US.UTF-8");
|
||||
assert_eq!(get_country_from_locale(), "US");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn country_from_locale_by() {
|
||||
let _guard = lock_env();
|
||||
set_locale("be_BY.UTF-8");
|
||||
assert_eq!(get_country_from_locale(), "BY");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn country_from_locale_kz() {
|
||||
let _guard = lock_env();
|
||||
set_locale("kk_KZ.UTF-8");
|
||||
assert_eq!(get_country_from_locale(), "KZ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn country_from_locale_fallback_to_us() {
|
||||
let _guard = lock_env();
|
||||
clear_locale();
|
||||
// When no locale vars are set, the function defaults to "en_US.UTF-8" -> "US"
|
||||
assert_eq!(get_country_from_locale(), "US");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn country_from_locale_lc_time_fallback() {
|
||||
let _guard = lock_env();
|
||||
clear_locale();
|
||||
unsafe { std::env::set_var("LC_TIME", "tr_TR.UTF-8") };
|
||||
assert_eq!(get_country_from_locale(), "TR");
|
||||
}
|
||||
Reference in New Issue
Block a user