#![allow(dead_code, unused_variables)]
use lellm_agent::ToolArgs;
use lellm_core::ToolResult;
use lellm_derive::tool;
#[tool]
fn add_numbers(a: i32, b: i32) -> ToolResult {
Ok(serde_json::json!(a + b))
}
#[test]
fn test_basic_tool_args_trait() {
assert_eq!(AddNumbersArgs::NAME, "add_numbers");
assert_eq!(AddNumbersArgs::DESCRIPTION, "");
}
#[test]
fn test_basic_tool_factory() {
let reg = add_numbers_tool();
assert_eq!(reg.definition().name, "add_numbers");
}
#[test]
fn test_basic_tool_schema() {
let def = AddNumbersArgs::tool_definition();
let properties = def
.parameters
.get("properties")
.unwrap()
.as_object()
.unwrap();
assert_eq!(properties["a"]["type"], "integer");
assert_eq!(properties["b"]["type"], "integer");
let required = def.parameters.get("required").unwrap().as_array().unwrap();
assert!(required.iter().any(|v| v.as_str() == Some("a")));
assert!(required.iter().any(|v| v.as_str() == Some("b")));
}
#[tool(name = "custom_add", description = "自定义加法器")]
fn my_add(x: i64, y: i64) -> ToolResult {
Ok(serde_json::json!(x + y))
}
#[test]
fn test_tool_name_override() {
assert_eq!(MyAddArgs::NAME, "custom_add");
assert_eq!(MyAddArgs::DESCRIPTION, "自定义加法器");
let reg = my_add_tool();
assert_eq!(reg.definition().name, "custom_add");
assert_eq!(reg.definition().description, "自定义加法器");
}
#[tool]
fn subtract(minuend: i32, subtrahend: i32) -> ToolResult {
Ok(serde_json::json!(minuend - subtrahend))
}
#[test]
fn test_tool_doc_comment_description() {
assert_eq!(SubtractArgs::DESCRIPTION, "计算两个数的差值");
assert_eq!(SubtractArgs::NAME, "subtract");
}
#[tool(description = "显式描述优先")]
fn _multiply(a: i32, b: i32) -> ToolResult {
Ok(serde_json::json!(a * b))
}
#[test]
fn test_tool_description_attr_overrides_doc() {
assert_eq!(MultiplyArgs::DESCRIPTION, "显式描述优先");
}
#[tool(name = "typed_params", description = "测试各种类型")]
fn typed_function(
text: String,
count: u32,
flag: bool,
score: f64,
optional_text: Option<String>,
optional_number: Option<i64>,
tags: Vec<String>,
) -> ToolResult {
Ok(serde_json::json!(format!("{}-{}", text, count)))
}
#[test]
fn test_various_param_types_schema() {
let def = TypedFunctionArgs::tool_definition();
let properties = def
.parameters
.get("properties")
.unwrap()
.as_object()
.unwrap();
assert_eq!(properties["text"]["type"], "string");
assert_eq!(properties["count"]["type"], "integer");
assert_eq!(properties["flag"]["type"], "boolean");
assert_eq!(properties["score"]["type"], "number");
let opt_type = &properties["optional_text"]["type"];
assert!(
*opt_type == "string" || *opt_type == serde_json::json!(["string", "null"]),
"unexpected Option<String> type: {}",
opt_type
);
assert_eq!(properties["tags"]["type"], "array");
let required = def.parameters.get("required").unwrap().as_array().unwrap();
let required_set: std::collections::HashSet<&str> =
required.iter().filter_map(|v| v.as_str()).collect();
assert!(required_set.contains("text"));
assert!(required_set.contains("count"));
assert!(required_set.contains("flag"));
assert!(required_set.contains("score"));
assert!(required_set.contains("tags"));
assert!(!required_set.contains("optional_text"));
assert!(!required_set.contains("optional_number"));
}
#[tool]
fn get_timestamp() -> ToolResult {
Ok(serde_json::json!("1234567890"))
}
#[test]
fn test_no_param_tool() {
assert_eq!(GetTimestampArgs::NAME, "get_timestamp");
assert_eq!(GetTimestampArgs::DESCRIPTION, "获取当前时间戳");
let reg = get_timestamp_tool();
assert_eq!(reg.definition().name, "get_timestamp");
let def = GetTimestampArgs::tool_definition();
let properties = def.parameters.get("properties");
assert!(
properties.is_none()
|| properties
.unwrap()
.as_object()
.map_or(true, |obj| obj.is_empty())
);
}
#[test]
fn test_lazylock_schema_cache() {
let schema1 = AddNumbersArgs::schema();
let schema2 = AddNumbersArgs::schema();
let schema3 = AddNumbersArgs::schema();
assert_eq!(schema1, schema2);
assert_eq!(schema2, schema3);
let def_schema = AddNumbersArgs::tool_definition().parameters;
assert_eq!(schema1, def_schema);
}