//! Тесты на правильное поведение.
use crate::codegen_tests::helper::compile;

#[test]
fn encode_push_wrong_operand_count() {
    let err = compile("push").unwrap_err();
    assert!(err.contains("expects"));
    assert!(err.contains("operand"));
}

#[test]
fn encode_pop_wrong_operand_count() {
    let err = compile("pop rax, rbx").unwrap_err();
    assert!(err.contains("expects"));
}

#[test]
fn encode_mov_wrong_operand_count() {
    let err = compile("mov rax").unwrap_err();
    assert!(err.contains("Mov expects"));
}

#[test]
fn encode_jmp_wrong_operand_count() {
    let err = compile("jmp").unwrap_err();
    assert!(err.contains("Jmp expects"));
}

#[test]
fn encode_call_wrong_operand_count() {
    let err = compile("call rax, rbx").unwrap_err();
    assert!(err.contains("Call expects"));
}

#[test]
fn encode_add_wrong_operand_count() {
    let err = compile("add rax").unwrap_err();
    assert!(err.contains("Add expects"));
}

#[test]
fn encode_push_unsupported_operand() {
    let err = compile("push [rax]").unwrap_err();
    assert!(err.contains("unsupported operand combination"));
}

#[test]
fn encode_jmp_unsupported_operand() {
    let err = compile("jmp [rax]").unwrap_err();
    assert!(err.contains("unsupported operand combination"));
}

#[test]
fn encode_mov_unsupported_operand() {
    let err = compile("mov rax, [rax], rbx").unwrap_err();
    assert!(err.contains("Mov expects"));
}

#[test]
fn encode_undefined_label() {
    let err = compile("jmp undefined_label").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_call_undefined_label() {
    let err = compile("call nowhere").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jcc_undefined_label() {
    let err = compile("je missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jg_undefined_label() {
    let err = compile("jg missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jge_undefined_label() {
    let err = compile("jge missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jl_undefined_label() {
    let err = compile("jl missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jle_undefined_label() {
    let err = compile("jle missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_ja_undefined_label() {
    let err = compile("ja missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jae_undefined_label() {
    let err = compile("jae missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jb_undefined_label() {
    let err = compile("jb missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_jbe_undefined_label() {
    let err = compile("jbe missing").unwrap_err();
    assert!(err.contains("undefined label"));
}

#[test]
fn encode_imul_unsupported_operand() {
    let err = compile("imul rax, [rbx], rcx, rdx").unwrap_err();
    assert!(err.contains("Imul expects"));
}

#[test]
fn encode_shl_wrong_operand_count() {
    let err = compile("shl rax").unwrap_err();
    assert!(err.contains("Shl expects"));
}

#[test]
fn encode_shr_wrong_operand_count() {
    let err = compile("shr rax, rbx, rcx").unwrap_err();
    assert!(err.contains("Shr expects"));
}

#[test]
fn encode_inc_wrong_operand_count() {
    let err = compile("inc rax, rbx").unwrap_err();
    assert!(err.contains("Inc expects"));
}

#[test]
fn encode_test_wrong_operand_count() {
    let err = compile("test rax").unwrap_err();
    assert!(err.contains("Test expects"));
}

#[test]
fn encode_div_wrong_operand_count() {
    let err = compile("div").unwrap_err();
    assert!(err.contains("Div expects"));
}

#[test]
fn encode_push_imm64_truncation() {
    let output = compile("push 0x123456789").unwrap();
    assert_eq!(output.code, &[0x68, 0x89, 0x67, 0x45, 0x23]);
}

#[test]
fn encode_mov_r64_to_imm() {
    let err = compile("mov 0x42, rax").unwrap_err();
    assert!(err.contains("unsupported operand combination"));
}

#[test]
fn encode_unary_unsupported_operand() {
    let err = compile("not 0x42").unwrap_err();
    assert!(err.contains("unsupported operand combination"));
}
