tests.rs raw

use super::*;
use crate::sexpr;

fn parse(source: &str) -> Result<String, Diagnostic> {
    let doc = sexpr::read(source).expect("reads");
    let form = &doc.values[0];
    parse_asset_form(form.as_list().expect("list"), form.span()).expect("an asset form")
}

#[test]
fn an_asset_carries_its_path_verbatim() {
    assert_eq!(
        parse(r#"(asset "icons/logo.png")"#).unwrap(),
        "icons/logo.png"
    );
}

#[test]
fn a_non_asset_head_is_not_claimed() {
    let doc = sexpr::read("(path (move 0 0))").expect("reads");
    let form = &doc.values[0];
    assert!(parse_asset_form(form.as_list().unwrap(), form.span()).is_none());
}

#[test]
fn wrong_arity_is_an_error() {
    assert!(
        parse("(asset)")
            .unwrap_err()
            .message
            .contains("exactly one")
    );
    assert!(
        parse(r#"(asset "a.png" "b.png")"#)
            .unwrap_err()
            .message
            .contains("exactly one")
    );
}

#[test]
fn a_non_string_path_is_pointed() {
    assert!(parse("(asset 3)").unwrap_err().message.contains("string"));
}

#[test]
fn an_empty_path_is_rejected() {
    assert!(
        parse(r#"(asset "")"#)
            .unwrap_err()
            .message
            .contains("empty")
    );
}

#[test]
fn machine_dependent_paths_are_rejected() {
    assert!(
        parse(r#"(asset "/etc/passwd")"#)
            .unwrap_err()
            .message
            .contains("not absolute")
    );
    assert!(
        parse(r#"(asset "../../secrets.png")"#)
            .unwrap_err()
            .message
            .contains("climb out")
    );
}

#[test]
fn an_interpolated_path_is_rejected() {
    // A `.gdc` author writing `{name}` means interpolation, but this form is
    // read from the raw s-expression, so it would otherwise become a literal
    // filename with braces in it. The bytes are found at build time.
    assert!(
        parse(r#"(asset "icons/{name}.png")"#)
            .unwrap_err()
            .message
            .contains("interpolation")
    );
}