update grid4 & heroledger models
This commit is contained in:
@@ -1,7 +1,38 @@
|
||||
use heromodels_derive::model;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// Define the necessary structs and traits for testing
|
||||
// Make the current crate visible as an extern crate named `heromodels_core`
|
||||
extern crate self as heromodels_core;
|
||||
extern crate serde_json; // ensure ::serde_json path resolves
|
||||
|
||||
// Mock the heromodels_core API at crate root (visible via the alias above)
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IndexKey {
|
||||
pub name: &'static str,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
pub trait Model: std::fmt::Debug + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static {
|
||||
fn db_prefix() -> &'static str
|
||||
where
|
||||
Self: Sized;
|
||||
fn get_id(&self) -> u32;
|
||||
fn base_data_mut(&mut self) -> &mut BaseModelData;
|
||||
fn db_keys(&self) -> Vec<IndexKey> {
|
||||
Vec::new()
|
||||
}
|
||||
fn indexed_fields() -> Vec<&'static str> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Index {
|
||||
type Model: Model;
|
||||
type Key: ToString + ?Sized;
|
||||
fn key() -> &'static str;
|
||||
fn field_name() -> &'static str;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BaseModelData {
|
||||
pub id: u32,
|
||||
@@ -11,41 +42,18 @@ pub struct BaseModelData {
|
||||
}
|
||||
|
||||
impl BaseModelData {
|
||||
pub fn new(id: u32) -> Self {
|
||||
let now = 1000; // Mock timestamp
|
||||
Self {
|
||||
id,
|
||||
created_at: now,
|
||||
modified_at: now,
|
||||
comments: Vec::new(),
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
let now = 1000;
|
||||
Self { id: 0, created_at: now, modified_at: now, comments: Vec::new() }
|
||||
}
|
||||
pub fn update_modified(&mut self) { self.modified_at += 1; }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IndexKey {
|
||||
pub name: &'static str,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
pub trait Model: std::fmt::Debug + Clone {
|
||||
fn db_prefix() -> &'static str;
|
||||
fn get_id(&self) -> u32;
|
||||
fn base_data_mut(&mut self) -> &mut BaseModelData;
|
||||
fn db_keys(&self) -> Vec<IndexKey>;
|
||||
}
|
||||
|
||||
pub trait Index {
|
||||
type Model: Model;
|
||||
type Key: ?Sized;
|
||||
fn key() -> &'static str;
|
||||
}
|
||||
|
||||
// Test struct using the model macro
|
||||
// Top-level field index tests
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[model]
|
||||
struct TestUser {
|
||||
base_data: BaseModelData,
|
||||
pub struct TestUser {
|
||||
base_data: heromodels_core::BaseModelData,
|
||||
|
||||
#[index]
|
||||
username: String,
|
||||
@@ -54,25 +62,12 @@ struct TestUser {
|
||||
is_active: bool,
|
||||
}
|
||||
|
||||
// Test struct with custom index name
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[model]
|
||||
struct TestUserWithCustomIndex {
|
||||
base_data: BaseModelData,
|
||||
|
||||
#[index(name = "custom_username")]
|
||||
username: String,
|
||||
|
||||
#[index]
|
||||
is_active: bool,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic_model() {
|
||||
assert_eq!(TestUser::db_prefix(), "test_user");
|
||||
|
||||
let user = TestUser {
|
||||
base_data: BaseModelData::new(1),
|
||||
base_data: heromodels_core::BaseModelData::new(),
|
||||
username: "test".to_string(),
|
||||
is_active: true,
|
||||
};
|
||||
@@ -85,22 +80,47 @@ fn test_basic_model() {
|
||||
assert_eq!(keys[1].value, "true");
|
||||
}
|
||||
|
||||
// Nested path index tests (including vector traversal)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
struct GPU { gpu_brand: String }
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
struct CPU { cpu_brand: String }
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
struct DeviceInfo { vendor: String, cpu: Vec<CPU>, gpu: Vec<GPU> }
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[model]
|
||||
pub struct NodeLike {
|
||||
base_data: heromodels_core::BaseModelData,
|
||||
|
||||
#[index(path = "vendor")]
|
||||
#[index(path = "cpu.cpu_brand")]
|
||||
#[index(path = "gpu.gpu_brand")]
|
||||
devices: DeviceInfo,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_index_name() {
|
||||
let user = TestUserWithCustomIndex {
|
||||
base_data: BaseModelData::new(1),
|
||||
username: "test".to_string(),
|
||||
is_active: true,
|
||||
fn test_nested_indexes() {
|
||||
let n = NodeLike {
|
||||
base_data: heromodels_core::BaseModelData::new(),
|
||||
devices: DeviceInfo {
|
||||
vendor: "SuperVendor".to_string(),
|
||||
cpu: vec![CPU { cpu_brand: "Intel".into() }, CPU { cpu_brand: "AMD".into() }],
|
||||
gpu: vec![GPU { gpu_brand: "NVIDIA".into() }, GPU { gpu_brand: "AMD".into() }],
|
||||
},
|
||||
};
|
||||
|
||||
// Check that the Username struct uses the custom index name
|
||||
assert_eq!(Username::key(), "custom_username");
|
||||
let mut keys = n.db_keys();
|
||||
// Sort for deterministic assertions
|
||||
keys.sort_by(|a,b| a.name.cmp(b.name).then(a.value.cmp(&b.value)));
|
||||
|
||||
// Check that the db_keys method returns the correct keys
|
||||
let keys = user.db_keys();
|
||||
assert_eq!(keys.len(), 2);
|
||||
assert_eq!(keys[0].name, "custom_username");
|
||||
assert_eq!(keys[0].value, "test");
|
||||
assert_eq!(keys[1].name, "is_active");
|
||||
assert_eq!(keys[1].value, "true");
|
||||
// Expect 1 (vendor) + 2 (cpu brands) + 2 (gpu brands) = 5 keys
|
||||
assert_eq!(keys.len(), 5);
|
||||
assert!(keys.iter().any(|k| k.name == "vendor" && k.value == "SuperVendor"));
|
||||
assert!(keys.iter().any(|k| k.name == "cpu.cpu_brand" && k.value == "Intel"));
|
||||
assert!(keys.iter().any(|k| k.name == "cpu.cpu_brand" && k.value == "AMD"));
|
||||
assert!(keys.iter().any(|k| k.name == "gpu.gpu_brand" && k.value == "NVIDIA"));
|
||||
assert!(keys.iter().any(|k| k.name == "gpu.gpu_brand" && k.value == "AMD"));
|
||||
}
|
||||
|
Reference in New Issue
Block a user