feat: add signed integer filter condition with equal comparison
This commit is contained in:
@@ -6,6 +6,7 @@ pub fn run(filter: &Filter) -> Result<Vec<Box<dyn ToSql>>, FailedTo> {
|
|||||||
for condition in filter.conditions() {
|
for condition in filter.conditions() {
|
||||||
match condition.2 {
|
match condition.2 {
|
||||||
Condition::Bool(value) => params.push(Box::new(value)),
|
Condition::Bool(value) => params.push(Box::new(value)),
|
||||||
|
Condition::SignedInt(value) => params.push(Box::new(value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(params)
|
Ok(params)
|
||||||
@@ -14,7 +15,6 @@ pub fn run(filter: &Filter) -> Result<Vec<Box<dyn ToSql>>, FailedTo> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// Ensures that an empty vector is returned when the filter has no conditions.
|
// Ensures that an empty vector is returned when the filter has no conditions.
|
||||||
#[test]
|
#[test]
|
||||||
fn returns_empty_vec_for_empty_filter() {
|
fn returns_empty_vec_for_empty_filter() {
|
||||||
@@ -22,7 +22,6 @@ mod tests {
|
|||||||
let params = run(&filter).unwrap();
|
let params = run(&filter).unwrap();
|
||||||
assert!(params.is_empty());
|
assert!(params.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifies that a single boolean condition is correctly converted to a ToSql parameter.
|
// Verifies that a single boolean condition is correctly converted to a ToSql parameter.
|
||||||
#[test]
|
#[test]
|
||||||
fn returns_params_for_one_bool_condition() {
|
fn returns_params_for_one_bool_condition() {
|
||||||
@@ -34,7 +33,6 @@ mod tests {
|
|||||||
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(1))
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(1))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that multiple boolean conditions are correctly converted and ordered.
|
// Checks that multiple boolean conditions are correctly converted and ordered.
|
||||||
#[test]
|
#[test]
|
||||||
fn returns_params_for_multiple_bool_conditions() {
|
fn returns_params_for_multiple_bool_conditions() {
|
||||||
@@ -52,4 +50,51 @@ mod tests {
|
|||||||
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(0))
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(0))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Verifies that a single signed integer condition is correctly converted to a ToSql parameter.
|
||||||
|
#[test]
|
||||||
|
fn returns_params_for_one_signed_int_condition() {
|
||||||
|
let filter = Filter::new().with_signed_int("level", Comparison::Equal, -5);
|
||||||
|
let params = run(&filter).unwrap();
|
||||||
|
assert_eq!(params.len(), 1);
|
||||||
|
assert_eq!(
|
||||||
|
params[0].to_sql().unwrap(),
|
||||||
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(-5))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Checks that multiple signed integer conditions are correctly converted and ordered.
|
||||||
|
#[test]
|
||||||
|
fn returns_params_for_multiple_signed_int_conditions() {
|
||||||
|
let filter = Filter::new()
|
||||||
|
.with_signed_int("level", Comparison::Equal, -5)
|
||||||
|
.with_signed_int("score", Comparison::Equal, 100);
|
||||||
|
let params = run(&filter).unwrap();
|
||||||
|
assert_eq!(params.len(), 2);
|
||||||
|
assert_eq!(
|
||||||
|
params[0].to_sql().unwrap(),
|
||||||
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(-5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
params[1].to_sql().unwrap(),
|
||||||
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(100))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Tests conversion for a mix of boolean and signed integer conditions.
|
||||||
|
#[test]
|
||||||
|
fn returns_params_for_mixed_conditions() {
|
||||||
|
let filter = Filter::new().with_bool("is_active", true).with_signed_int(
|
||||||
|
"level",
|
||||||
|
Comparison::Equal,
|
||||||
|
-10,
|
||||||
|
);
|
||||||
|
let params = run(&filter).unwrap();
|
||||||
|
assert_eq!(params.len(), 2);
|
||||||
|
assert_eq!(
|
||||||
|
params[0].to_sql().unwrap(),
|
||||||
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(1))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
params[1].to_sql().unwrap(),
|
||||||
|
rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Integer(-10))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,18 @@ const BASE_SELECT: &str = r#"SELECT * FROM entity WHERE 1=1"#;
|
|||||||
pub fn run(filter: &Filter) -> Result<String, FailedTo> {
|
pub fn run(filter: &Filter) -> Result<String, FailedTo> {
|
||||||
let mut statement = String::from(BASE_SELECT);
|
let mut statement = String::from(BASE_SELECT);
|
||||||
for (i, (name, _comparison, condition)) in filter.conditions().enumerate() {
|
for (i, (name, _comparison, condition)) in filter.conditions().enumerate() {
|
||||||
let fragment = match *condition {
|
let fragment = match (_comparison, condition) {
|
||||||
Condition::Bool(_) => format!(
|
(_, Condition::Bool(_)) => format!(
|
||||||
" AND id IN (SELECT entity_id FROM attribute WHERE id = '{}' AND value_bool = ?{})",
|
" AND id IN (SELECT entity_id FROM attribute WHERE id = '{}' AND value_bool = ?{})",
|
||||||
name,
|
name,
|
||||||
i + 1
|
i + 1
|
||||||
),
|
),
|
||||||
|
(Comparison::Equal, Condition::SignedInt(_)) => format!(
|
||||||
|
" AND id IN (SELECT entity_id FROM attribute WHERE id = '{}' AND value_int = ?{})",
|
||||||
|
name,
|
||||||
|
i + 1
|
||||||
|
),
|
||||||
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
statement.push_str(&fragment);
|
statement.push_str(&fragment);
|
||||||
}
|
}
|
||||||
@@ -21,14 +27,12 @@ pub fn run(filter: &Filter) -> Result<String, FailedTo> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Filter;
|
use crate::Filter;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn builds_statement_with_no_conditions() {
|
fn builds_statement_with_no_conditions() {
|
||||||
let filter = Filter::new();
|
let filter = Filter::new();
|
||||||
let statement = run(&filter).unwrap();
|
let statement = run(&filter).unwrap();
|
||||||
assert_eq!(statement, BASE_SELECT);
|
assert_eq!(statement, BASE_SELECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn builds_statement_with_one_bool_condition() {
|
fn builds_statement_with_one_bool_condition() {
|
||||||
let filter = Filter::new().with_bool("is_active", true);
|
let filter = Filter::new().with_bool("is_active", true);
|
||||||
@@ -38,7 +42,6 @@ mod tests {
|
|||||||
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_active' AND value_bool = ?1)"
|
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_active' AND value_bool = ?1)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn builds_statement_with_multiple_bool_conditions() {
|
fn builds_statement_with_multiple_bool_conditions() {
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
@@ -50,4 +53,37 @@ mod tests {
|
|||||||
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_active' AND value_bool = ?1) AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_deleted' AND value_bool = ?2)"
|
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_active' AND value_bool = ?1) AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_deleted' AND value_bool = ?2)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn builds_statement_with_one_signed_int_equal_condition() {
|
||||||
|
let filter = Filter::new().with_signed_int("level", Comparison::Equal, 10);
|
||||||
|
let statement = run(&filter).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
statement,
|
||||||
|
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'level' AND value_int = ?1)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn builds_statement_with_multiple_signed_int_equal_conditions() {
|
||||||
|
let filter = Filter::new()
|
||||||
|
.with_signed_int("level", Comparison::Equal, 10)
|
||||||
|
.with_signed_int("score", Comparison::Equal, 100);
|
||||||
|
let statement = run(&filter).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
statement,
|
||||||
|
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'level' AND value_int = ?1) AND id IN (SELECT entity_id FROM attribute WHERE id = 'score' AND value_int = ?2)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn builds_statement_with_mixed_bool_and_signed_int_conditions() {
|
||||||
|
let filter = Filter::new().with_bool("is_active", true).with_signed_int(
|
||||||
|
"level",
|
||||||
|
Comparison::Equal,
|
||||||
|
5,
|
||||||
|
);
|
||||||
|
let statement = run(&filter).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
statement,
|
||||||
|
"SELECT * FROM entity WHERE 1=1 AND id IN (SELECT entity_id FROM attribute WHERE id = 'is_active' AND value_bool = ?1) AND id IN (SELECT entity_id FROM attribute WHERE id = 'level' AND value_int = ?2)"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ mod tests {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub price: u64,
|
pub price: u64,
|
||||||
|
pub sell_trend: i64,
|
||||||
pub in_stock: bool,
|
pub in_stock: bool,
|
||||||
}
|
}
|
||||||
impl EAV for Item {
|
impl EAV for Item {
|
||||||
@@ -245,6 +246,7 @@ mod tests {
|
|||||||
.with_id(&value.id)
|
.with_id(&value.id)
|
||||||
.with_attribute("name", value.name)
|
.with_attribute("name", value.name)
|
||||||
.with_attribute("price", value.price)
|
.with_attribute("price", value.price)
|
||||||
|
.with_attribute("sell_trend", value.sell_trend)
|
||||||
.with_attribute("in_stock", value.in_stock)
|
.with_attribute("in_stock", value.in_stock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,6 +256,9 @@ mod tests {
|
|||||||
id: entity.id.clone(),
|
id: entity.id.clone(),
|
||||||
name: entity.unwrap("name").expect("name is always present"),
|
name: entity.unwrap("name").expect("name is always present"),
|
||||||
price: entity.unwrap("price").expect("price is always present"),
|
price: entity.unwrap("price").expect("price is always present"),
|
||||||
|
sell_trend: entity
|
||||||
|
.unwrap("sell_trend")
|
||||||
|
.expect("sell_trend is always present"),
|
||||||
in_stock: entity
|
in_stock: entity
|
||||||
.unwrap("in_stock")
|
.unwrap("in_stock")
|
||||||
.expect("in_stock is always present"),
|
.expect("in_stock is always present"),
|
||||||
@@ -327,6 +332,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item_id = item.id.clone();
|
let item_id = item.id.clone();
|
||||||
@@ -337,6 +343,7 @@ mod tests {
|
|||||||
assert_eq!(entity.class, "item");
|
assert_eq!(entity.class, "item");
|
||||||
assert_eq!(entity.value_of("name"), Some(&Value::from("Test Item")));
|
assert_eq!(entity.value_of("name"), Some(&Value::from("Test Item")));
|
||||||
assert_eq!(entity.value_of("price"), Some(&Value::from(100u64)));
|
assert_eq!(entity.value_of("price"), Some(&Value::from(100u64)));
|
||||||
|
assert_eq!(entity.value_of("sell_trend"), Some(&Value::from(0i64)));
|
||||||
assert_eq!(entity.value_of("in_stock"), Some(&Value::from(true)));
|
assert_eq!(entity.value_of("in_stock"), Some(&Value::from(true)));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
@@ -347,6 +354,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "First Item".to_string(),
|
name: "First Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item_id = item1.id.clone();
|
let item_id = item1.id.clone();
|
||||||
@@ -355,6 +363,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "Second Item".to_string(),
|
name: "Second Item".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 10,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item2);
|
let _ = catalog.upsert(item2);
|
||||||
@@ -362,6 +371,7 @@ mod tests {
|
|||||||
let entity = catalog.items.get(&item_id).unwrap();
|
let entity = catalog.items.get(&item_id).unwrap();
|
||||||
assert_eq!(entity.value_of("name"), Some(&Value::from("Second Item")));
|
assert_eq!(entity.value_of("name"), Some(&Value::from("Second Item")));
|
||||||
assert_eq!(entity.value_of("price"), Some(&Value::from(200u64)));
|
assert_eq!(entity.value_of("price"), Some(&Value::from(200u64)));
|
||||||
|
assert_eq!(entity.value_of("sell_trend"), Some(&Value::from(10i64)));
|
||||||
assert_eq!(entity.value_of("in_stock"), Some(&Value::from(false)));
|
assert_eq!(entity.value_of("in_stock"), Some(&Value::from(false)));
|
||||||
assert_eq!(entity.state, EntityState::Updated);
|
assert_eq!(entity.state, EntityState::Updated);
|
||||||
}
|
}
|
||||||
@@ -374,12 +384,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item 1".to_string(),
|
name: "Item 1".to_string(),
|
||||||
price: 10,
|
price: 10,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
},
|
},
|
||||||
Item {
|
Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item 2".to_string(),
|
name: "Item 2".to_string(),
|
||||||
price: 20,
|
price: 20,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -388,9 +400,13 @@ mod tests {
|
|||||||
let entity1 = catalog.items.get("item-1").unwrap();
|
let entity1 = catalog.items.get("item-1").unwrap();
|
||||||
assert_eq!(entity1.state, EntityState::New);
|
assert_eq!(entity1.state, EntityState::New);
|
||||||
assert_eq!(entity1.value_of("name"), Some(&Value::from("Item 1")));
|
assert_eq!(entity1.value_of("name"), Some(&Value::from("Item 1")));
|
||||||
|
assert_eq!(entity1.value_of("price"), Some(&Value::from(10u64)));
|
||||||
|
assert_eq!(entity1.value_of("sell_trend"), Some(&Value::from(0i64)));
|
||||||
let entity2 = catalog.items.get("item-2").unwrap();
|
let entity2 = catalog.items.get("item-2").unwrap();
|
||||||
assert_eq!(entity2.state, EntityState::New);
|
assert_eq!(entity2.state, EntityState::New);
|
||||||
assert_eq!(entity2.value_of("name"), Some(&Value::from("Item 2")));
|
assert_eq!(entity2.value_of("name"), Some(&Value::from("Item 2")));
|
||||||
|
assert_eq!(entity2.value_of("price"), Some(&Value::from(20u64)));
|
||||||
|
assert_eq!(entity2.value_of("sell_trend"), Some(&Value::from(0i64)));
|
||||||
}
|
}
|
||||||
// ## 'get()'
|
// ## 'get()'
|
||||||
#[test]
|
#[test]
|
||||||
@@ -401,6 +417,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item.clone());
|
let _ = catalog.upsert(item.clone());
|
||||||
@@ -415,6 +432,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item.clone());
|
let _ = catalog.upsert(item.clone());
|
||||||
@@ -430,12 +448,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Unique Item".to_string(),
|
name: "Unique Item".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item1.clone());
|
let _ = catalog.upsert(item1.clone());
|
||||||
@@ -453,12 +473,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 250,
|
price: 250,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item1.clone());
|
let _ = catalog.upsert(item1.clone());
|
||||||
@@ -477,6 +499,11 @@ mod tests {
|
|||||||
.get_by_class_and_attribute("in_stock", true)
|
.get_by_class_and_attribute("in_stock", true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(retrieved_by_stock, Some(item1.clone()));
|
assert_eq!(retrieved_by_stock, Some(item1.clone()));
|
||||||
|
// Test with i64 for sell_trend attribute
|
||||||
|
let retrieved_by_sell_trend: Option<Item> = catalog
|
||||||
|
.get_by_class_and_attribute("sell_trend", 0i64)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(retrieved_by_sell_trend, Some(item1.clone()));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn get_by_class_and_attribute_should_return_none_if_no_match() {
|
fn get_by_class_and_attribute_should_return_none_if_no_match() {
|
||||||
@@ -486,6 +513,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item.clone());
|
let _ = catalog.upsert(item.clone());
|
||||||
@@ -509,12 +537,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item1.clone());
|
let _ = catalog.upsert(item1.clone());
|
||||||
@@ -546,18 +576,21 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let item3 = Item {
|
let item3 = Item {
|
||||||
id: "item-3".to_string(),
|
id: "item-3".to_string(),
|
||||||
name: "Item Three".to_string(),
|
name: "Item Three".to_string(),
|
||||||
price: 300,
|
price: 300,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item1.clone());
|
let _ = catalog.upsert(item1.clone());
|
||||||
@@ -580,6 +613,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item);
|
let _ = catalog.upsert(item);
|
||||||
@@ -612,6 +646,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item_id = item.id.clone();
|
let item_id = item.id.clone();
|
||||||
@@ -628,6 +663,7 @@ mod tests {
|
|||||||
id: "item-123".to_string(),
|
id: "item-123".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item);
|
let _ = catalog.upsert(item);
|
||||||
@@ -653,6 +689,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 123,
|
price: 123,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item1.clone());
|
let _ = catalog1.upsert(item1.clone());
|
||||||
@@ -682,6 +719,7 @@ mod tests {
|
|||||||
id: "item-to-delete".to_string(),
|
id: "item-to-delete".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 123,
|
price: 123,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item1.clone());
|
let _ = catalog1.upsert(item1.clone());
|
||||||
@@ -714,6 +752,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Original Name".to_string(),
|
name: "Original Name".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(original_item.clone());
|
let _ = catalog1.upsert(original_item.clone());
|
||||||
@@ -726,6 +765,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Updated Name".to_string(),
|
name: "Updated Name".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog2.upsert(updated_item.clone());
|
let _ = catalog2.upsert(updated_item.clone());
|
||||||
@@ -761,18 +801,21 @@ mod tests {
|
|||||||
id: "update-me".to_string(),
|
id: "update-me".to_string(),
|
||||||
name: "Original".to_string(),
|
name: "Original".to_string(),
|
||||||
price: 10,
|
price: 10,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item_to_delete = Item {
|
let item_to_delete = Item {
|
||||||
id: "delete-me".to_string(),
|
id: "delete-me".to_string(),
|
||||||
name: "Delete Me".to_string(),
|
name: "Delete Me".to_string(),
|
||||||
price: 20,
|
price: 20,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item_to_keep = Item {
|
let item_to_keep = Item {
|
||||||
id: "keep-me".to_string(),
|
id: "keep-me".to_string(),
|
||||||
name: "Keep Me".to_string(),
|
name: "Keep Me".to_string(),
|
||||||
price: 30,
|
price: 30,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog_setup.upsert(item_to_update_original.clone());
|
let _ = catalog_setup.upsert(item_to_update_original.clone());
|
||||||
@@ -787,6 +830,7 @@ mod tests {
|
|||||||
id: "add-me".to_string(),
|
id: "add-me".to_string(),
|
||||||
name: "Add Me".to_string(),
|
name: "Add Me".to_string(),
|
||||||
price: 40,
|
price: 40,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog_ops.upsert(item_to_add.clone()); // State: New
|
let _ = catalog_ops.upsert(item_to_add.clone()); // State: New
|
||||||
@@ -795,6 +839,7 @@ mod tests {
|
|||||||
id: "update-me".to_string(),
|
id: "update-me".to_string(),
|
||||||
name: "Updated".to_string(),
|
name: "Updated".to_string(),
|
||||||
price: 11,
|
price: 11,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog_ops.upsert(item_to_update_new.clone()); // State: Updated
|
let _ = catalog_ops.upsert(item_to_update_new.clone()); // State: Updated
|
||||||
@@ -834,6 +879,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Test".to_string(),
|
name: "Test".to_string(),
|
||||||
price: 10,
|
price: 10,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item);
|
let _ = catalog.upsert(item);
|
||||||
@@ -859,17 +905,23 @@ mod tests {
|
|||||||
let item_to_update = Item {
|
let item_to_update = Item {
|
||||||
id: "update-me".to_string(),
|
id: "update-me".to_string(),
|
||||||
name: "Original".to_string(),
|
name: "Original".to_string(),
|
||||||
..Default::default()
|
price: 0,
|
||||||
|
sell_trend: 0,
|
||||||
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let item_to_delete = Item {
|
let item_to_delete = Item {
|
||||||
id: "delete-me".to_string(),
|
id: "delete-me".to_string(),
|
||||||
name: "Delete Me".to_string(),
|
name: "Delete Me".to_string(),
|
||||||
..Default::default()
|
price: 0,
|
||||||
|
sell_trend: 0,
|
||||||
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let item_untouched = Item {
|
let item_untouched = Item {
|
||||||
id: "keep-me".to_string(),
|
id: "keep-me".to_string(),
|
||||||
name: "Keep Me".to_string(),
|
name: "Keep Me".to_string(),
|
||||||
..Default::default()
|
price: 0,
|
||||||
|
sell_trend: 0,
|
||||||
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item_to_update.clone());
|
let _ = catalog.upsert(item_to_update.clone());
|
||||||
let _ = catalog.upsert(item_to_delete.clone());
|
let _ = catalog.upsert(item_to_delete.clone());
|
||||||
@@ -894,14 +946,18 @@ mod tests {
|
|||||||
let item_new = Item {
|
let item_new = Item {
|
||||||
id: "add-me".to_string(),
|
id: "add-me".to_string(),
|
||||||
name: "Add Me".to_string(),
|
name: "Add Me".to_string(),
|
||||||
..Default::default()
|
price: 0,
|
||||||
|
sell_trend: 0,
|
||||||
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item_new.clone()); // State: New
|
let _ = catalog.upsert(item_new.clone()); // State: New
|
||||||
// An updated version of an existing item.
|
// An updated version of an existing item.
|
||||||
let item_updated = Item {
|
let item_updated = Item {
|
||||||
id: "update-me".to_string(),
|
id: "update-me".to_string(),
|
||||||
name: "Updated".to_string(),
|
name: "Updated".to_string(),
|
||||||
..Default::default()
|
price: 0,
|
||||||
|
sell_trend: 10,
|
||||||
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item_updated.clone()); // State: Updated
|
let _ = catalog.upsert(item_updated.clone()); // State: Updated
|
||||||
// An item to be deleted.
|
// An item to be deleted.
|
||||||
@@ -941,6 +997,10 @@ mod tests {
|
|||||||
updated_item_entity.value_of("name"),
|
updated_item_entity.value_of("name"),
|
||||||
Some(&Value::from("Updated"))
|
Some(&Value::from("Updated"))
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
updated_item_entity.value_of("sell_trend"),
|
||||||
|
Some(&Value::from(10i64))
|
||||||
|
);
|
||||||
let untouched_item_entity = catalog.items.get("keep-me").unwrap();
|
let untouched_item_entity = catalog.items.get("keep-me").unwrap();
|
||||||
assert_eq!(untouched_item_entity.state, EntityState::Loaded);
|
assert_eq!(untouched_item_entity.state, EntityState::Loaded);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -967,6 +1027,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 123,
|
price: 123,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item_to_persist.clone());
|
let _ = catalog1.upsert(item_to_persist.clone());
|
||||||
@@ -988,6 +1049,7 @@ mod tests {
|
|||||||
Some(&Value::from("Test Item"))
|
Some(&Value::from("Test Item"))
|
||||||
);
|
);
|
||||||
assert_eq!(loaded_entity.value_of("price"), Some(&Value::from(123u64)));
|
assert_eq!(loaded_entity.value_of("price"), Some(&Value::from(123u64)));
|
||||||
|
assert_eq!(loaded_entity.value_of("sell_trend"), Some(&Value::from(0i64)));
|
||||||
assert_eq!(loaded_entity.value_of("in_stock"), Some(&Value::from(true)));
|
assert_eq!(loaded_entity.value_of("in_stock"), Some(&Value::from(true)));
|
||||||
assert_eq!(loaded_entity.state, EntityState::Loaded); // Should be Synced after loading.
|
assert_eq!(loaded_entity.state, EntityState::Loaded); // Should be Synced after loading.
|
||||||
// 6. Also verify by using the public 'get' method.
|
// 6. Also verify by using the public 'get' method.
|
||||||
@@ -1012,6 +1074,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item from DB".to_string(),
|
name: "Item from DB".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item_in_db.clone());
|
let _ = catalog1.upsert(item_in_db.clone());
|
||||||
@@ -1022,6 +1085,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "In-memory version".to_string(),
|
name: "In-memory version".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog2.upsert(item_in_memory);
|
let _ = catalog2.upsert(item_in_memory);
|
||||||
@@ -1045,6 +1109,10 @@ mod tests {
|
|||||||
entity_after_load.value_of("price"),
|
entity_after_load.value_of("price"),
|
||||||
Some(&Value::from(100u64))
|
Some(&Value::from(100u64))
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
entity_after_load.value_of("sell_trend"),
|
||||||
|
Some(&Value::from(0i64))
|
||||||
|
);
|
||||||
// 5. Verify using the public 'get' method.
|
// 5. Verify using the public 'get' method.
|
||||||
let retrieved_item: Item = catalog2.get("item-1").unwrap().unwrap();
|
let retrieved_item: Item = catalog2.get("item-1").unwrap().unwrap();
|
||||||
assert_eq!(retrieved_item, item_in_db);
|
assert_eq!(retrieved_item, item_in_db);
|
||||||
@@ -1102,12 +1170,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item1.clone());
|
let _ = catalog1.upsert(item1.clone());
|
||||||
@@ -1150,6 +1220,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "DB Version".to_string(),
|
name: "DB Version".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item_in_db.clone());
|
let _ = catalog1.upsert(item_in_db.clone());
|
||||||
@@ -1160,6 +1231,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Memory Version".to_string(),
|
name: "Memory Version".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog2.upsert(item_in_memory);
|
let _ = catalog2.upsert(item_in_memory);
|
||||||
@@ -1203,6 +1275,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "In-memory only".to_string(),
|
name: "In-memory only".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item_in_memory.clone());
|
let _ = catalog.upsert(item_in_memory.clone());
|
||||||
@@ -1249,18 +1322,21 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
},
|
},
|
||||||
Item {
|
Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
},
|
},
|
||||||
Item {
|
Item {
|
||||||
id: "item-3".to_string(),
|
id: "item-3".to_string(),
|
||||||
name: "Item Three".to_string(),
|
name: "Item Three".to_string(),
|
||||||
price: 300,
|
price: 300,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -1290,12 +1366,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
},
|
},
|
||||||
Item {
|
Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -1325,12 +1403,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
},
|
},
|
||||||
Item {
|
Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -1357,6 +1437,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "DB Version".to_string(),
|
name: "DB Version".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
catalog_setup.upsert(item_in_db.clone()).unwrap();
|
catalog_setup.upsert(item_in_db.clone()).unwrap();
|
||||||
@@ -1366,6 +1447,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Memory Version".to_string(),
|
name: "Memory Version".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
catalog.upsert(item_in_memory).unwrap();
|
catalog.upsert(item_in_memory).unwrap();
|
||||||
@@ -1387,6 +1469,55 @@ mod tests {
|
|||||||
assert_eq!(result.unwrap_err(), FailedTo::LoadFromDB);
|
assert_eq!(result.unwrap_err(), FailedTo::LoadFromDB);
|
||||||
std::fs::remove_dir_all(invalid_path).unwrap();
|
std::fs::remove_dir_all(invalid_path).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn load_by_filter_should_load_matching_sell_trend() {
|
||||||
|
let db_path = "target/test_dbs/lbf_matching_sell_trend.db";
|
||||||
|
let path = std::path::Path::new(db_path);
|
||||||
|
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||||
|
if path.exists() {
|
||||||
|
std::fs::remove_file(path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut catalog_setup = Catalog::new(db_path);
|
||||||
|
catalog_setup.init().unwrap();
|
||||||
|
let items = vec![
|
||||||
|
Item {
|
||||||
|
id: "item-1".to_string(),
|
||||||
|
name: "Item One".to_string(),
|
||||||
|
price: 100,
|
||||||
|
sell_trend: 10,
|
||||||
|
in_stock: true,
|
||||||
|
},
|
||||||
|
Item {
|
||||||
|
id: "item-2".to_string(),
|
||||||
|
name: "Item Two".to_string(),
|
||||||
|
price: 200,
|
||||||
|
sell_trend: -5,
|
||||||
|
in_stock: false,
|
||||||
|
},
|
||||||
|
Item {
|
||||||
|
id: "item-3".to_string(),
|
||||||
|
name: "Item Three".to_string(),
|
||||||
|
price: 300,
|
||||||
|
sell_trend: 10,
|
||||||
|
in_stock: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
catalog_setup.insert_many(items).unwrap();
|
||||||
|
catalog_setup.persist().unwrap();
|
||||||
|
|
||||||
|
let mut catalog = Catalog::new(db_path);
|
||||||
|
let filter = Filter::new().with_signed_int("sell_trend", Comparison::Equal, 10);
|
||||||
|
assert!(catalog.load_by_filter(&filter).is_ok());
|
||||||
|
|
||||||
|
assert_eq!(catalog.items.len(), 2);
|
||||||
|
assert!(catalog.items.contains_key("item-1"));
|
||||||
|
assert!(catalog.items.contains_key("item-3"));
|
||||||
|
assert!(!catalog.items.contains_key("item-2"));
|
||||||
|
|
||||||
|
std::fs::remove_file(path).unwrap();
|
||||||
|
}
|
||||||
// ## Integration Tests
|
// ## Integration Tests
|
||||||
#[test]
|
#[test]
|
||||||
fn integration_test_init_insert_persist_load_get() {
|
fn integration_test_init_insert_persist_load_get() {
|
||||||
@@ -1404,6 +1535,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Integration Test Item".to_string(),
|
name: "Integration Test Item".to_string(),
|
||||||
price: 999,
|
price: 999,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item_to_insert.clone());
|
let _ = catalog1.upsert(item_to_insert.clone());
|
||||||
@@ -1434,12 +1566,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
},
|
},
|
||||||
Item {
|
Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -1478,6 +1612,7 @@ mod tests {
|
|||||||
id: "item-to-delete".to_string(),
|
id: "item-to-delete".to_string(),
|
||||||
name: "Test Item".to_string(),
|
name: "Test Item".to_string(),
|
||||||
price: 123,
|
price: 123,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog1.upsert(item_to_delete.clone());
|
let _ = catalog1.upsert(item_to_delete.clone());
|
||||||
@@ -1506,12 +1641,14 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "First Item".to_string(),
|
name: "First Item".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Second Item".to_string(),
|
name: "Second Item".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let _ = catalog.upsert(item1.clone());
|
let _ = catalog.upsert(item1.clone());
|
||||||
@@ -1532,18 +1669,21 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Item One".to_string(),
|
name: "Item One".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let item2 = Item {
|
let item2 = Item {
|
||||||
id: "item-2".to_string(),
|
id: "item-2".to_string(),
|
||||||
name: "Item Two".to_string(),
|
name: "Item Two".to_string(),
|
||||||
price: 200,
|
price: 200,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: false,
|
in_stock: false,
|
||||||
};
|
};
|
||||||
let item3 = Item {
|
let item3 = Item {
|
||||||
id: "item-3".to_string(),
|
id: "item-3".to_string(),
|
||||||
name: "Item Three".to_string(),
|
name: "Item Three".to_string(),
|
||||||
price: 150,
|
price: 150,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog.insert_many(vec![item1.clone(), item2.clone(), item3.clone()]);
|
let _ = catalog.insert_many(vec![item1.clone(), item2.clone(), item3.clone()]);
|
||||||
@@ -1579,6 +1719,7 @@ mod tests {
|
|||||||
id: "item-1".to_string(),
|
id: "item-1".to_string(),
|
||||||
name: "Original".to_string(),
|
name: "Original".to_string(),
|
||||||
price: 100,
|
price: 100,
|
||||||
|
sell_trend: 0,
|
||||||
in_stock: true,
|
in_stock: true,
|
||||||
};
|
};
|
||||||
let _ = catalog_setup.upsert(initial_item);
|
let _ = catalog_setup.upsert(initial_item);
|
||||||
@@ -1611,8 +1752,8 @@ mod tests {
|
|||||||
catalog_verify.load_by_id("item-1").unwrap();
|
catalog_verify.load_by_id("item-1").unwrap();
|
||||||
let final_item: Item = catalog_verify.get("item-1").unwrap().unwrap();
|
let final_item: Item = catalog_verify.get("item-1").unwrap().unwrap();
|
||||||
// The final state depends on which thread persisted last. One update will have been lost.
|
// The final state depends on which thread persisted last. One update will have been lost.
|
||||||
let thread1_won = final_item.name == "Updated by Thread 1" && final_item.price == 100;
|
let thread1_won = final_item.name == "Updated by Thread 1" && final_item.price == 100 && final_item.sell_trend == 0;
|
||||||
let thread2_won = final_item.name == "Original" && final_item.price == 200;
|
let thread2_won = final_item.name == "Original" && final_item.price == 200 && final_item.sell_trend == 0;
|
||||||
assert!(
|
assert!(
|
||||||
thread1_won || thread2_won,
|
thread1_won || thread2_won,
|
||||||
"Final state must be the result of one of the threads winning the race."
|
"Final state must be the result of one of the threads winning the race."
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
|
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
|
||||||
pub enum E {
|
pub enum E {
|
||||||
Equal,
|
Equal,
|
||||||
|
Greater,
|
||||||
|
GreaterOrEqual,
|
||||||
|
Lesser,
|
||||||
|
LesserOrEqual,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
|
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
|
||||||
pub enum E {
|
pub enum E {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
|
SignedInt(i64),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,19 @@ impl Filter {
|
|||||||
));
|
));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn with_signed_int(
|
||||||
|
mut self,
|
||||||
|
attribute_name: &str,
|
||||||
|
comparison: Comparison,
|
||||||
|
value: i64,
|
||||||
|
) -> Self {
|
||||||
|
self.conditions.push((
|
||||||
|
attribute_name.to_string(),
|
||||||
|
comparison,
|
||||||
|
Condition::SignedInt(value),
|
||||||
|
));
|
||||||
|
self
|
||||||
|
}
|
||||||
pub(crate) fn conditions(&self) -> impl Iterator<Item = &(String, Comparison, Condition)> {
|
pub(crate) fn conditions(&self) -> impl Iterator<Item = &(String, Comparison, Condition)> {
|
||||||
self.conditions.iter()
|
self.conditions.iter()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user