首尾的控制字符不再被 trim 静默吞掉,统一按控制字符报错
- optional_text 原来先 trim 再查 is_control:`"prompt\n"`、`"\tprompt"` 这类落在首尾的控制字符被静默裁掉、当成合法值,而同一个字符出现在中间却会报错 - 改成先按原串查控制字符,再用 trim 做空值与长度判定:控制字符在哪个位置都报 has_control_characters - 纯空白值("\n\t"、" ")仍然算空值、报原来的 empty 错误;首尾的普通空格仍按原样裁掉 - 测试补三条断言:prompt 末尾带 \n 必须被拒、纯空白 brief 仍报空、brief 首尾普通空格仍会被裁剪 验证:cargo test --bin genarrative-ai-game-creator-shell -- agent:: 953 passed / 0 failed
This commit is contained in:
@@ -4860,6 +4860,38 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn non_text_field_values_report_a_type_error_instead_of_an_empty_value() {
|
||||
let trailing_newline = match resource_generation_input(&json!({
|
||||
"kind": "video",
|
||||
"mode": "create",
|
||||
"prompt": "生成过场\n",
|
||||
"assetName": "开场"
|
||||
})) {
|
||||
Ok(_) => panic!("落在首尾的控制字符不能被 trim 静默吞掉"),
|
||||
Err(error) => error.to_user_msg(),
|
||||
};
|
||||
assert!(
|
||||
trailing_newline.contains("prompt 含有控制字符"),
|
||||
"{trailing_newline}"
|
||||
);
|
||||
|
||||
let whitespace_only =
|
||||
required_text(&json!({ "brief": "\n\t" }), PrepareGameArtTextField::Brief)
|
||||
.expect_err("纯空白仍然按空值处理")
|
||||
.to_user_msg();
|
||||
assert!(
|
||||
whitespace_only.contains("brief 不能为空"),
|
||||
"{whitespace_only}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
required_text(
|
||||
&json!({ "brief": " 美术包 " }),
|
||||
PrepareGameArtTextField::Brief
|
||||
)
|
||||
.expect("首尾普通空格仍正常裁剪"),
|
||||
"美术包"
|
||||
);
|
||||
|
||||
let prompt_not_text = match resource_generation_input(&json!({
|
||||
"kind": "video",
|
||||
"mode": "create",
|
||||
|
||||
@@ -37,17 +37,19 @@ pub(crate) fn optional_text<F: ToolTextField<E>, E>(
|
||||
let Some(value) = value.as_str() else {
|
||||
return Err(field.not_text(value.to_string()));
|
||||
};
|
||||
let value = value.trim();
|
||||
if value.is_empty() {
|
||||
let trimmed = value.trim();
|
||||
if trimmed.is_empty() {
|
||||
return Err(field.empty());
|
||||
}
|
||||
if value.chars().count() > field.max_chars() {
|
||||
return Err(field.too_long(value.chars().count(), field.max_chars()));
|
||||
}
|
||||
// 控制字符必须按原串判定:否则落在首尾的 `\n`/`\t` 会被 trim 静默吞掉,
|
||||
// 同一个字符在中间报错、在边上通过。
|
||||
if value.chars().any(char::is_control) {
|
||||
return Err(field.has_control_characters());
|
||||
}
|
||||
Ok(Some(value.to_string()))
|
||||
if trimmed.chars().count() > field.max_chars() {
|
||||
return Err(field.too_long(trimmed.chars().count(), field.max_chars()));
|
||||
}
|
||||
Ok(Some(trimmed.to_string()))
|
||||
}
|
||||
|
||||
/// 一页列表结果:`offset` 是起始下标,`limit` 是这一次最多返回多少项。
|
||||
|
||||
Reference in New Issue
Block a user