//! GLM-4 MoE Parser Integration Tests use sglang_router_rs::tool_parser::{Glm4MoeParser, ParseState, StreamResult, ToolParser}; #[tokio::test] async fn test_glm4_complete_parsing() { let parser = Glm4MoeParser::new(); // Test single tool call let input = r#"Let me search for that. get_weather city Beijing date 2024-12-25 The weather will be..."#; let result = parser.parse_complete(input).await.unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].function.name, "get_weather"); // Verify arguments let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap(); assert_eq!(args["city"], "Beijing"); assert_eq!(args["date"], "2024-12-25"); } #[tokio::test] async fn test_glm4_multiple_tools() { let parser = Glm4MoeParser::new(); let input = r#"search query rust tutorials translate text Hello World target_lang zh "#; let result = parser.parse_complete(input).await.unwrap(); assert_eq!(result.len(), 2); assert_eq!(result[0].function.name, "search"); assert_eq!(result[1].function.name, "translate"); } #[tokio::test] async fn test_glm4_type_conversion() { let parser = Glm4MoeParser::new(); // Test various value types let input = r#"process count 42 rate 1.5 enabled true data null text string value "#; let result = parser.parse_complete(input).await.unwrap(); assert_eq!(result.len(), 1); let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap(); assert_eq!(args["count"], 42); assert_eq!(args["rate"], 1.5); assert_eq!(args["enabled"], true); assert_eq!(args["data"], serde_json::Value::Null); assert_eq!(args["text"], "string value"); } #[tokio::test] async fn test_glm4_streaming() { let parser = Glm4MoeParser::new(); let mut state = ParseState::new(); // Simulate streaming chunks let chunks = vec![ "", "get_weather\n", "city\n", "Shanghai\n", "units\n", "celsius\n", "", ]; let mut found_name = false; let mut found_complete = false; for chunk in chunks { let result = parser.parse_incremental(chunk, &mut state).await.unwrap(); match result { StreamResult::ToolName { name, .. } => { assert_eq!(name, "get_weather"); found_name = true; } StreamResult::ToolComplete(tool) => { assert_eq!(tool.function.name, "get_weather"); found_complete = true; } _ => {} } } assert!(found_name || found_complete); } #[test] fn test_glm4_format_detection() { let parser = Glm4MoeParser::new(); // Should detect GLM-4 format assert!(parser.detect_format("")); assert!(parser.detect_format("text with marker")); // Should not detect other formats assert!(!parser.detect_format("[TOOL_CALLS]")); assert!(!parser.detect_format("<|tool▁calls▁begin|>")); assert!(!parser.detect_format("plain text")); } #[tokio::test] async fn test_glm4_python_literal_values() { let parser = Glm4MoeParser::new(); // Test Python-style boolean values let input = r#"config debug True verbose False optional None "#; let result = parser.parse_complete(input).await.unwrap(); assert_eq!(result.len(), 1); let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap(); assert_eq!(args["debug"], true); assert_eq!(args["verbose"], false); assert_eq!(args["optional"], serde_json::Value::Null); } #[tokio::test] async fn test_python_literals() { let parser = Glm4MoeParser::new(); let input = r#"test_func bool_true True bool_false False none_val None "#; let result = parser.parse_complete(input).await.unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].function.name, "test_func"); let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap(); assert_eq!(args["bool_true"], true); assert_eq!(args["bool_false"], false); assert_eq!(args["none_val"], serde_json::Value::Null); } #[tokio::test] async fn test_nested_values() { let parser = Glm4MoeParser::new(); let input = r#"process data {"nested": {"key": "value"}} list [1, 2, 3] "#; let result = parser.parse_complete(input).await.unwrap(); assert_eq!(result.len(), 1); let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap(); assert!(args["data"].is_object()); assert!(args["list"].is_array()); }