use bashkit::Bash;
async fn stdout_of(script: &str) -> String {
let mut bash = Bash::new();
bash.exec(script)
.await
.unwrap_or_else(|e| panic!("{script:?} failed to run: {e}"))
.stdout
.to_string()
}
#[tokio::test]
async fn close_brace_stays_inside_a_word() {
assert_eq!(stdout_of("echo a}b").await, "a}b\n");
assert_eq!(stdout_of("echo a}").await, "a}\n");
assert_eq!(stdout_of("echo }b").await, "}b\n");
assert_eq!(stdout_of("echo a}b}c").await, "a}b}c\n");
assert_eq!(stdout_of("echo }}").await, "}}\n");
assert_eq!(stdout_of("echo a}{b").await, "a}{b\n");
}
#[tokio::test]
async fn close_brace_does_not_split_fields() {
assert_eq!(stdout_of("echo 1}2 3}4").await, "1}2 3}4\n");
}
#[tokio::test]
async fn lone_close_brace_is_still_a_word() {
assert_eq!(stdout_of("echo }").await, "}\n");
}
#[tokio::test]
async fn close_brace_in_assignment_value() {
assert_eq!(stdout_of("v=a}b; echo $v").await, "a}b\n");
}
#[tokio::test]
async fn close_brace_in_for_list() {
assert_eq!(stdout_of("for i in a}b; do echo $i; done").await, "a}b\n");
}
#[tokio::test]
async fn close_brace_in_case_pattern() {
assert_eq!(stdout_of("case x} in x}) echo m;; esac").await, "m\n");
assert_eq!(stdout_of("case a}b in a}b) echo M;; esac").await, "M\n");
}
#[tokio::test]
async fn brace_group_and_function_body_still_close() {
assert_eq!(stdout_of("{ echo grp; }").await, "grp\n");
assert_eq!(stdout_of("{ echo one; echo two; }").await, "one\ntwo\n");
assert_eq!(stdout_of("f() { echo fn; }; f").await, "fn\n");
assert_eq!(stdout_of("f(){ echo z; }; f").await, "z\n");
assert_eq!(stdout_of("if true; then { echo n; }; fi").await, "n\n");
}
#[tokio::test]
async fn expansions_are_unaffected() {
assert_eq!(stdout_of("x=1; echo ${x}").await, "1\n");
assert_eq!(stdout_of("echo ${x}y").await, "y\n");
assert_eq!(stdout_of("a=(1 2); echo ${a[@]}").await, "1 2\n");
assert_eq!(stdout_of("echo {1..3}").await, "1 2 3\n");
assert_eq!(stdout_of("echo {a,b}").await, "a b\n");
assert_eq!(stdout_of("echo x{a,b}y").await, "xay xby\n");
assert_eq!(stdout_of("echo a{b}c").await, "a{b}c\n");
}
#[tokio::test]
async fn quoted_and_escaped_close_brace_unchanged() {
assert_eq!(stdout_of("echo \"a}b\"").await, "a}b\n");
assert_eq!(stdout_of("echo 'a}b'").await, "a}b\n");
assert_eq!(stdout_of("echo a\\}b").await, "a}b\n");
}
#[tokio::test]
async fn metacharacter_after_close_brace_still_terminates() {
assert_eq!(stdout_of("echo a}b >/dev/null; echo ok").await, "ok\n");
}