use std::collections::HashMap;
use sz_orm_core::Value;
use sz_orm_core::{Model, ModelExt};
#[derive(Debug, Clone, Default)]
#[allow(dead_code)]
struct User {
id: i64,
name: String,
email: String,
}
impl Model for User {
type PrimaryKey = i64;
fn table_name() -> &'static str {
"users"
}
fn pk(&self) -> Self::PrimaryKey {
self.id
}
fn set_pk(&mut self, pk: Self::PrimaryKey) {
self.id = pk;
}
}
impl ModelExt for User {
fn columns() -> Vec<&'static str> {
vec!["id", "name", "email"]
}
fn fillable() -> Vec<&'static str> {
vec!["name", "email"]
}
fn hidden() -> Vec<&'static str> {
vec!["email"]
}
fn get_column_value(&self, column: &str) -> Option<Value> {
match column {
"id" => Some(Value::I64(self.id)),
"name" => Some(Value::String(self.name.clone())),
"email" => Some(Value::String(self.email.clone())),
_ => None,
}
}
fn from_value(&mut self, map: std::collections::HashMap<String, Value>) {
if let Some(Value::I64(id)) = map.get("id") {
self.id = *id;
}
if let Some(Value::String(name)) = map.get("name") {
self.name = name.clone();
}
if let Some(Value::String(email)) = map.get("email") {
self.email = email.clone();
}
}
}
#[test]
fn test_model_table_name_contract() {
assert_eq!(User::table_name(), "users");
}
#[test]
fn test_model_pk_name_default_contract() {
assert_eq!(User::pk_name(), "id");
}
#[test]
fn test_model_pk_get_set_contract() {
let mut u = User::default();
assert_eq!(u.pk(), 0);
u.set_pk(42);
assert_eq!(u.pk(), 42);
}
#[test]
fn test_model_primary_key_default_contract() {
let pk = <User as Model>::PrimaryKey::default();
assert_eq!(pk, 0);
}
#[test]
fn test_model_foreign_key_default_contract() {
assert_eq!(User::foreign_key("post"), "post_id");
assert_eq!(User::foreign_key("Order"), "order_id"); assert_eq!(User::foreign_key("USER"), "user_id");
}
#[test]
fn test_model_timestamp_fields_default_contract() {
assert!(User::timestamp_fields().is_none());
}
#[test]
fn test_model_soft_delete_field_default_contract() {
assert!(User::soft_delete_field().is_none());
}
#[test]
fn test_model_ext_columns_contract() {
let cols = User::columns();
assert_eq!(cols, vec!["id", "name", "email"]);
}
#[test]
fn test_model_ext_fillable_contract() {
let fillable = User::fillable();
assert_eq!(fillable, vec!["name", "email"]);
}
#[test]
fn test_model_ext_hidden_contract() {
let hidden = User::hidden();
assert_eq!(hidden, vec!["email"]);
}
#[test]
fn test_model_ext_guarded_includes_pk_by_default_contract() {
let guarded = User::guarded();
assert!(
guarded.contains(&"id"),
"guarded 默认应包含主键列,实际: {:?}",
guarded
);
}
#[test]
fn test_model_ext_relations_default_empty_contract() {
let relations = User::relations();
assert!(relations.is_empty(), "默认 relations 应为空");
}
#[test]
fn test_model_ext_fill_skips_guarded_contract() {
let mut u = User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
let mut data = HashMap::new();
data.insert("id".to_string(), Value::I64(999));
data.insert("name".to_string(), Value::String("Bob".to_string()));
u.fill(data);
assert_eq!(u.id, 1);
assert_eq!(u.name, "Bob");
}
#[test]
fn test_model_ext_to_json_contract() {
let u = User {
id: 42,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
let json = u.to_json();
assert!(json.is_object());
assert!(
json.get("email").is_none(),
"hidden 字段不应出现在 to_json 输出中"
);
}
#[test]
fn test_model_primary_key_trait_bounds_contract() {
fn assert_pk_bounds<T>()
where
T: Send + Sync + std::fmt::Debug + std::fmt::Display + Clone + Default,
{
}
assert_pk_bounds::<<User as Model>::PrimaryKey>();
}
#[test]
fn test_model_send_sync_sized_static_bounds_contract() {
fn assert_model_bounds<T: Model>() {}
assert_model_bounds::<User>();
}