Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions stdlib/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,166 @@ impl StdlibRegistry {
);
}
}

#[cfg(test)]
mod tests {
use super::*;
use techscript_runtime::context::{RuntimeConfig, RuntimeContext};

#[test]
fn test_register_cache() {
let mut registry = StdlibRegistry::default();
registry.register_cache();

let module = registry
.modules
.get("std.cache")
.expect("Module std.cache should be registered");
assert_eq!(module.name, "std.cache");
assert_eq!(module.version, "1.0.0");
assert!(module.exports.contains_key("set"));
assert!(module.exports.contains_key("set_ttl"));
assert!(module.exports.contains_key("get"));
assert!(module.exports.contains_key("remove"));
assert!(module.exports.contains_key("clear"));
}

#[test]
fn test_cache_set_and_get() {
let mut registry = StdlibRegistry::default();
registry.register_cache();

let module = registry.modules.get("std.cache").unwrap();
let set_fn = module.exports.get("set").unwrap();
let get_fn = module.exports.get("get").unwrap();

let mut ctx = RuntimeContext::new(RuntimeConfig::default());

// Test non-existent key
let res = get_fn
.call(&mut ctx, vec![RuntimeValue::Str("missing".to_string())])
.unwrap();
assert_eq!(res, RuntimeValue::Null);

// Test setting a value
let set_res = set_fn
.call(
&mut ctx,
vec![
RuntimeValue::Str("k1".to_string()),
RuntimeValue::Str("v1".to_string()),
],
)
.unwrap();
assert_eq!(set_res, RuntimeValue::Null);

// Test getting the set value
let get_res = get_fn
.call(&mut ctx, vec![RuntimeValue::Str("k1".to_string())])
.unwrap();
assert_eq!(get_res, RuntimeValue::Str("v1".to_string()));
}

#[test]
fn test_cache_set_ttl() {
let mut registry = StdlibRegistry::default();
registry.register_cache();

let module = registry.modules.get("std.cache").unwrap();
let set_ttl_fn = module.exports.get("set_ttl").unwrap();
let get_fn = module.exports.get("get").unwrap();

let mut ctx = RuntimeContext::new(RuntimeConfig::default());

// Set key with TTL of 10 seconds
set_ttl_fn
.call(
&mut ctx,
vec![
RuntimeValue::Str("ttl_key".to_string()),
RuntimeValue::Int(100),
RuntimeValue::Int(10),
],
)
.unwrap();

let val = get_fn
.call(&mut ctx, vec![RuntimeValue::Str("ttl_key".to_string())])
.unwrap();
assert_eq!(val, RuntimeValue::Int(100));

// Set key with TTL of 1 second and sleep 2.1 seconds to test expiration
set_ttl_fn
.call(
&mut ctx,
vec![
RuntimeValue::Str("exp_key".to_string()),
RuntimeValue::Str("exp_val".to_string()),
RuntimeValue::Int(1),
],
)
.unwrap();

std::thread::sleep(std::time::Duration::from_millis(2100));

let expired_val = get_fn
.call(&mut ctx, vec![RuntimeValue::Str("exp_key".to_string())])
.unwrap();
assert_eq!(expired_val, RuntimeValue::Null);
}

#[test]
fn test_cache_remove_and_clear() {
let mut registry = StdlibRegistry::default();
registry.register_cache();

let module = registry.modules.get("std.cache").unwrap();
let set_fn = module.exports.get("set").unwrap();
let get_fn = module.exports.get("get").unwrap();
let remove_fn = module.exports.get("remove").unwrap();
let clear_fn = module.exports.get("clear").unwrap();

let mut ctx = RuntimeContext::new(RuntimeConfig::default());

set_fn
.call(
&mut ctx,
vec![RuntimeValue::Str("a".to_string()), RuntimeValue::Int(1)],
)
.unwrap();
set_fn
.call(
&mut ctx,
vec![RuntimeValue::Str("b".to_string()), RuntimeValue::Int(2)],
)
.unwrap();

// Remove key "a"
remove_fn
.call(&mut ctx, vec![RuntimeValue::Str("a".to_string())])
.unwrap();

assert_eq!(
get_fn
.call(&mut ctx, vec![RuntimeValue::Str("a".to_string())])
.unwrap(),
RuntimeValue::Null
);
assert_eq!(
get_fn
.call(&mut ctx, vec![RuntimeValue::Str("b".to_string())])
.unwrap(),
RuntimeValue::Int(2)
);

// Clear all keys
clear_fn.call(&mut ctx, vec![]).unwrap();

assert_eq!(
get_fn
.call(&mut ctx, vec![RuntimeValue::Str("b".to_string())])
.unwrap(),
RuntimeValue::Null
);
}
}
64 changes: 64 additions & 0 deletions stdlib/tests/stdlib_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,3 +1331,67 @@ fn test_uuid_module() {
assert!(!uuid_str.is_empty());
assert!(uuid_str.contains("-"));
}

#[test]
fn test_cache_module() {
let registry = StdlibRegistry::new();
let cache = registry.get_module("std.cache").unwrap();

let mut ctx = RuntimeContext::new(RuntimeConfig::default());

let set = cache.exports.get("set").unwrap();
let set_ttl = cache.exports.get("set_ttl").unwrap();
let get = cache.exports.get("get").unwrap();
let remove = cache.exports.get("remove").unwrap();
let clear = cache.exports.get("clear").unwrap();

// Test set and get
set.call(
&mut ctx,
vec![
RuntimeValue::Str("session_1".to_string()),
RuntimeValue::Str("user_42".to_string()),
],
)
.unwrap();

let res = get
.call(&mut ctx, vec![RuntimeValue::Str("session_1".to_string())])
.unwrap();
assert_eq!(res.as_string(), Some("user_42"));

// Test set_ttl
set_ttl
.call(
&mut ctx,
vec![
RuntimeValue::Str("temp_token".to_string()),
RuntimeValue::Str("abc123".to_string()),
RuntimeValue::Int(300),
],
)
.unwrap();

let token = get
.call(&mut ctx, vec![RuntimeValue::Str("temp_token".to_string())])
.unwrap();
assert_eq!(token.as_string(), Some("abc123"));

// Test remove
remove
.call(&mut ctx, vec![RuntimeValue::Str("session_1".to_string())])
.unwrap();

let res = get
.call(&mut ctx, vec![RuntimeValue::Str("session_1".to_string())])
.unwrap();
assert_eq!(res, RuntimeValue::Null);

// Test clear
clear.call(&mut ctx, vec![]).unwrap();

let res = get
.call(&mut ctx, vec![RuntimeValue::Str("temp_token".to_string())])
.unwrap();
assert_eq!(res, RuntimeValue::Null);
}