use mini_bitcoin_script::engine::execute;
use mini_bitcoin_script::error::ScriptError;
use mini_bitcoin_script::opcode::Opcode;
use mini_bitcoin_script::token::Token;
fn run(tokens: &[Token]) -> Result<bool, ScriptError> {
execute(tokens)
}
#[test]
fn if_true_executes_body() {
let tokens = vec![
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpEndIf),
];
assert!(run(&tokens).unwrap());
}
#[test]
fn if_false_skips_body() {
let tokens = vec![
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpEndIf),
];
assert!(!run(&tokens).unwrap());
}
#[test]
fn if_true_else_takes_true_branch() {
let tokens = vec![
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpElse),
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpEndIf),
];
assert!(run(&tokens).unwrap());
}
#[test]
fn if_false_else_takes_else_branch() {
let tokens = vec![
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpElse),
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpEndIf),
];
assert!(!run(&tokens).unwrap());
}
#[test]
fn notif_true_skips_body() {
let tokens = vec![
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpNotIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpElse),
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpEndIf),
];
assert!(!run(&tokens).unwrap());
}
#[test]
fn notif_false_executes_body() {
let tokens = vec![
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpNotIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpElse),
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpEndIf),
];
assert!(run(&tokens).unwrap());
}
#[test]
fn nested_if_both_true() {
let tokens = vec![
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpEndIf),
Token::Op(Opcode::OpEndIf),
];
assert!(run(&tokens).unwrap());
}
#[test]
fn if_without_endif() {
let tokens = vec![
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
];
let err = run(&tokens).unwrap_err();
assert_eq!(err, ScriptError::UnbalancedConditional);
}
#[test]
fn endif_without_if() {
let tokens = vec![Token::Op(Opcode::OpEndIf)];
let err = run(&tokens).unwrap_err();
assert_eq!(err, ScriptError::UnbalancedConditional);
}
#[test]
fn else_without_if() {
let tokens = vec![Token::Op(Opcode::OpElse)];
let err = run(&tokens).unwrap_err();
assert_eq!(err, ScriptError::UnbalancedConditional);
}
#[test]
fn three_level_nesting() {
let tokens = vec![
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpEndIf),
Token::Op(Opcode::OpElse),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpEndIf),
Token::Op(Opcode::OpEndIf),
];
assert!(run(&tokens).unwrap());
}
#[test]
fn false_outer_skips_inner() {
let tokens = vec![
Token::Op(Opcode::Op0),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpIf),
Token::Op(Opcode::Op1),
Token::Op(Opcode::OpEndIf),
Token::Op(Opcode::OpEndIf),
];
assert!(!run(&tokens).unwrap());
}