ruwebframe 0.1.8

a simple webframe for rust actix-web, based on rudi and rbatis.
Documentation
use ruentity::BaseEntity;

use crate::rubase::get_self::GetSelf;
use crate::rubase::rudto::cfgdto;
use crate::rubase::ruentity;
use crate::rudomain::rudb::dbentity::dbexample;
use crate::{rucfg, rulog};
use std::fs::File;
use std::io::{BufReader, Read};
use std::sync::Arc;

#[cfg(test)]
mod tests {
    use super::*;
    use crate::rucfg::ru_config;

    // ==================== find_bean_ru_config 核心测试 ====================

    #[test]
    fn test_find_bean_ru_config_returns_some() {
        let result = rucfg::find_bean_ru_config();
        assert!(result.is_some(), "find_bean_ru_config should return Some");
    }

    #[test]
    fn test_find_bean_ru_config_returns_arc_mutex() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let _env: &str = &guard.find_env();
        println!("{:?}", guard);
    }

    #[test]
    fn test_find_bean_ru_config_singleton_same_instance() {
        let a = rucfg::find_bean_ru_config().unwrap();
        let b = rucfg::find_bean_ru_config().unwrap();
        assert!(Arc::ptr_eq(&a, &b), "should return the same singleton Arc");
    }

    #[test]
    fn test_find_bean_ru_config_singleton_shared_state() {
        let a = rucfg::find_bean_ru_config().unwrap();
        let b = rucfg::find_bean_ru_config().unwrap();
        let env_a = a.lock().unwrap().find_env();
        let env_b = b.lock().unwrap().find_env();
        assert_eq!(env_a, env_b, "shared singleton should have same env");
    }

    // ==================== lock / read / read_clone 测试 ====================

    #[test]
    fn test_lock_and_read_returns_reference() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let cfg: &cfgdto::CfgDto = guard.read();
        let _json = cfg.to_json().unwrap();
    }

    #[test]
    fn test_lock_and_read_clone_returns_owned() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let config: cfgdto::CfgDto = arc.lock().unwrap().read_clone();
        let _json = config.to_json().unwrap();
    }

    #[test]
    fn test_read_clone_is_independent() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let mut clone1 = arc.lock().unwrap().read_clone();
        let mut clone2 = arc.lock().unwrap().read_clone();

        clone1.gorm.dbType = "modified_1".to_string();
        clone2.gorm.dbType = "modified_2".to_string();

        assert_ne!(
            clone1.gorm.dbType, clone2.gorm.dbType,
            "clones should be independent"
        );

        let original = arc.lock().unwrap().read_clone();
        assert_ne!(
            original.gorm.dbType, "modified_1",
            "original should not be affected by clone mutation"
        );
    }

    #[test]
    fn test_get_self_returns_config_reference() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let cfg: &cfgdto::CfgDto = guard.get_self();
        let _ = cfg.to_json().unwrap();
    }

    #[test]
    fn test_read_json_alias() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let a: &cfgdto::CfgDto = guard.read();
        let b: &cfgdto::CfgDto = guard.read_json();
        assert!(std::ptr::eq(a, b), "read_json should be alias of read");
    }

    // ==================== 环境检测测试 ====================

    #[test]
    fn test_find_env_returns_string() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let env = arc.lock().unwrap().find_env();
        assert!(!env.is_empty(), "env should not be empty");
        println!("current env: {}", env);
    }

    #[test]
    fn test_if_env_matches_current() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let current_env = arc.lock().unwrap().find_env();
        let matched = arc.lock().unwrap().if_env(&current_env);
        assert!(matched, "if_env should match the current environment");
    }

    #[test]
    fn test_if_env_does_not_match_other() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let current_env = arc.lock().unwrap().find_env();
        let fake = format!("__not_real_env_{}", current_env);
        let matched = arc.lock().unwrap().if_env(&fake);
        assert!(!matched, "if_env should not match a fake environment");
    }

    #[test]
    fn test_global_if_dev() {
        let _ = rucfg::if_dev();
    }

    #[test]
    fn test_global_if_test() {
        let _ = rucfg::if_test();
    }

    #[test]
    fn test_global_find_env() {
        let env = rucfg::find_env();
        assert!(!env.is_empty());
    }

    // ==================== 序列化往返测试 ====================

    #[test]
    fn test_to_json_and_from_json_roundtrip() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let config = arc.lock().unwrap().read_clone();

        let json = config.to_json().unwrap();
        assert!(!json.is_empty(), "serialized JSON should not be empty");

        let restored: cfgdto::CfgDto = config.from_json(json).unwrap();
        let json2 = restored.to_json().unwrap();

        assert_eq!(config.gorm.dbType, restored.gorm.dbType);
        assert_eq!(config.software.env, restored.software.env);
    }

    #[test]
    fn test_to_json_is_valid_json() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let config = arc.lock().unwrap().read_clone();
        let json = config.to_json().unwrap();

        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
        assert!(
            parsed.is_object(),
            "serialized config should be a JSON object"
        );
    }

    // ==================== 配置字段完整性测试 ====================

    #[test]
    fn test_software_config_fields() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let sw = &guard.read().software;

        assert!(!sw.env.is_empty(), "software.env should be populated");
        assert!(
            !sw.projectName.is_empty(),
            "software.projectName should be populated"
        );
        assert!(!sw.author.is_empty(), "software.author should be populated");
    }

    #[test]
    fn test_web_server_config_fields() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let server = &guard.read().web.server;

        assert!(
            !server.port.is_empty(),
            "web.server.port should be populated"
        );
        assert!(
            !server.name.is_empty(),
            "web.server.name should be populated"
        );
    }

    #[test]
    fn test_web_client_config_fields() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let client = &guard.read().web.client;

        assert!(
            !client.name.is_empty(),
            "web.client.name should be populated"
        );
    }

    #[test]
    fn test_gorm_config_fields() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let gorm = &guard.read().gorm;

        assert!(!gorm.dbType.is_empty(), "gorm.dbType should be populated");
        assert!(!gorm.enable.is_empty(), "gorm.enable should be populated");
        assert!(
            gorm.maxOpenConns > 0,
            "gorm.maxOpenConns should be positive"
        );
        assert!(
            gorm.maxIdleConns > 0,
            "gorm.maxIdleConns should be positive"
        );
    }

    #[test]
    fn test_redis_config_fields() {
        let arc = rucfg::find_bean_ru_config().unwrap();
        let guard = arc.lock().unwrap();
        let redis = &guard.read().redis;

        assert!(!redis.addr.is_empty(), "redis.addr should be populated");
        assert!(redis.enable, "redis.enable should be true by default");
    }

    #[test]
    fn test_config_read_multiple_times_consistent() {
        let arc = rucfg::find_bean_ru_config().unwrap();

        let env1 = arc.lock().unwrap().find_env();
        let env2 = arc.lock().unwrap().find_env();
        let env3 = arc.lock().unwrap().find_env();

        assert_eq!(env1, env2);
        assert_eq!(env2, env3);
    }

    // ==================== RuConfig 工厂方法测试 ====================

    #[test]
    fn test_ru_config_new_mutex_returns_valid() {
        let mutex = ru_config::RuConfig::new_mutex();
        let guard = mutex.lock().unwrap();
        let _ = guard.read().to_json().unwrap();
    }

    // ==================== 原有保留测试(合并) ====================

    #[test]
    fn test_001_parse_config() {
        let config = rucfg::find_bean_ru_config().unwrap();
        println!("config:\n{:#?}", config);

        let file = File::open("./config/ichub-postgres.yml");
        let mut read = BufReader::new(file.unwrap());
        let mut yaml_str = String::new();
        read.read_to_string(&mut yaml_str).unwrap();

        let ret = serde_yaml::from_str::<cfgdto::cfg_dto::CfgDto>(&yaml_str);
        println!("{:#?}", ret);
    }

    #[test]
    fn test_004_parse_config() {
        let config = rucfg::find_bean_ru_config()
            .unwrap()
            .lock()
            .unwrap()
            .read_clone();

        rulog::info(config.to_json().unwrap());
    }

    #[test]
    fn test_006_from_json() {
        let person = dbexample::Person::default();

        let s = r##"{
            "id": 123,
            "name": "宋双艳",
            "age": 45,
            "active": false
        }"##;
        let p = person.from_json(s.to_string()).unwrap();
        println!("p:{:#?}", p);
        assert_eq!(p.id, 123);
        assert_eq!(p.name, "宋双艳");
    }

    #[test]
    fn test_007_parse_config() {
        let mut config = rucfg::find_bean_ru_config()
            .unwrap()
            .lock()
            .unwrap()
            .read_clone();
        println!("{:#?}", config);
        rulog::info(config.to_json().unwrap().as_str());
        config.gorm.dbType = "1111".to_string();
        let pp = config.from_json(config.to_json().unwrap());
        println!("pp:{:#?}", pp);
        assert!(pp.is_ok());
    }

    #[test]
    fn test_008_parse_config() {
        let mut config = rucfg::find_bean_ru_config()
            .unwrap()
            .lock()
            .unwrap()
            .read_clone();
        println!("{:#?}", config);
        rulog::info(config.to_json().unwrap().as_str());
        config.gorm.dbType = "1111".to_string();
        let pp = config.from_json(config.to_json().unwrap());
        println!("pp:{:#?}", pp);
        assert!(pp.is_ok());
    }

    #[test]
    fn test_010_parse_config() {
        let cfg = cfgdto::CfgDto::default();
        println!("{:#?}", cfg);
        assert!(cfg.software.env.is_empty());
    }

    #[test]
    fn test_012_parse_config() {
        let person = dbexample::find_bean_person().unwrap();
        let mut inst = person.lock().unwrap();
        inst.name = "leijmdas".to_string();
        rulog::info2("person:", inst.to_json().unwrap().as_str());

        let s = r#"
            {
                "id": 10,
                "name": "songlei",
                "age": 10,
                "active": true
            }
    "#;
        let pp = inst.from_json(s.to_string());
        let pp = pp.unwrap();
        rulog::info2("pp:", pp.to_json().unwrap().as_str());
        assert_eq!(pp.name, "songlei");
    }

    #[test]
    fn test_13_to_json() {
        let person = dbexample::find_bean_person().unwrap();
        person.lock().unwrap().name = "leijmdas".to_string();
        rulog::info2("person:", person.lock().unwrap());
    }

    #[test]
    fn test_016_cfg_to_json() {
        let cfg = rucfg::find_bean_ru_config()
            .unwrap()
            .lock()
            .unwrap()
            .read_clone();
        println!("config:\n{:#?}", cfg);
        assert!(!cfg.software.env.is_empty());
    }

    #[test]
    fn test_017_find_bean_ru_config() {
        let cfg = rucfg::find_bean_ru_config().unwrap();
        let c = cfg.lock().unwrap();
        let env = c.read().find_env();
        println!("{:#?}", env);
        assert!(!env.is_empty());
    }
}