use sqlite_vdbe::{Connection, Insn, StepResult, Value, ffi};
#[test]
fn test_simple_integer_program() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let result = program.step().expect("Failed to step");
assert_eq!(result, StepResult::Row);
assert_eq!(program.column_int(0), 42);
let result = program.step().expect("Failed to step");
assert_eq!(result, StepResult::Done);
}
#[test]
fn test_c_simple_vdbe() {
let conn = Connection::open_in_memory().expect("Failed to open connection");
let result = unsafe { ffi::sqlite3_vdbe_test_simple(conn.raw_ptr()) };
assert_eq!(result, 42);
}
#[test]
fn test_addition_program() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 10,
dest: r1,
});
builder.add(Insn::Integer {
value: 32,
dest: r2,
});
builder.add(Insn::Add {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let result = program.step().expect("Failed to step");
assert_eq!(result, StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_multiple_rows() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Integer { value: 2, dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Integer { value: 3, dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let mut results = Vec::new();
loop {
match program.step().expect("Failed to step") {
StepResult::Row => results.push(program.column_int(0)),
StepResult::Done => break,
}
}
assert_eq!(results, vec![1, 2, 3]);
}
#[test]
fn test_multiple_columns() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 100,
dest: r1,
});
builder.add(Insn::Integer {
value: 200,
dest: r2,
});
builder.add(Insn::Integer {
value: 300,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r1,
count: 3,
});
builder.add(Insn::Halt);
let mut program = builder.finish(3).expect("Failed to finish program");
let result = program.step().expect("Failed to step");
assert_eq!(result, StepResult::Row);
assert_eq!(program.column_count(), 3);
assert_eq!(program.column_int(0), 100);
assert_eq!(program.column_int(1), 200);
assert_eq!(program.column_int(2), 300);
}
#[test]
fn test_arithmetic_operations() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_add = builder.alloc_register();
let r_sub = builder.alloc_register();
let r_mul = builder.alloc_register();
let r_div = builder.alloc_register();
let r_rem = builder.alloc_register();
builder.add(Insn::Integer {
value: 17,
dest: r1,
});
builder.add(Insn::Integer { value: 5, dest: r2 });
builder.add(Insn::Add {
lhs: r1,
rhs: r2,
dest: r_add,
});
builder.add(Insn::Subtract {
lhs: r1,
rhs: r2,
dest: r_sub,
});
builder.add(Insn::Multiply {
lhs: r1,
rhs: r2,
dest: r_mul,
});
builder.add(Insn::Divide {
lhs: r1,
rhs: r2,
dest: r_div,
});
builder.add(Insn::Remainder {
lhs: r1,
rhs: r2,
dest: r_rem,
});
builder.add(Insn::ResultRow {
start: r_add,
count: 5,
});
builder.add(Insn::Halt);
let mut program = builder.finish(5).expect("Failed to finish program");
let result = program.step().expect("Failed to step");
assert_eq!(result, StepResult::Row);
assert_eq!(program.column_int(0), 22); assert_eq!(program.column_int(1), 12); assert_eq!(program.column_int(2), 85); assert_eq!(program.column_int(3), 3); assert_eq!(program.column_int(4), 2); }
#[test]
fn test_program_reset() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 123,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 123);
assert_eq!(program.step().unwrap(), StepResult::Done);
program.reset();
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 123);
assert_eq!(program.step().unwrap(), StepResult::Done);
}
#[test]
fn test_null_value() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Null { dest: r1, count: 1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let value = program.column_value(0);
assert!(value.is_null());
}
#[test]
fn test_jump_here() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let jump_addr = builder.add(Insn::Goto { target: 0 });
builder.add(Insn::Integer {
value: 999,
dest: r1,
}); builder.jump_here(jump_addr);
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_comparison_eq() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: 5, dest: r1 });
builder.add(Insn::Integer { value: 5, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let eq_addr = builder.add(Insn::Eq {
lhs: r1,
rhs: r2,
target: 0,
});
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(eq_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_copy_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::SCopy { src: r1, dest: r2 });
builder.add(Insn::ResultRow {
start: r2,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_integer_max_value() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: i32::MAX,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), i32::MAX);
}
#[test]
fn test_integer_min_value() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: i32::MIN,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), i32::MIN);
}
#[test]
fn test_int64_large_values() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Int64 {
value: i64::MAX,
dest: r1,
});
builder.add(Insn::Int64 {
value: i64::MIN,
dest: r2,
});
builder.add(Insn::ResultRow {
start: r1,
count: 2,
});
builder.add(Insn::Halt);
let mut program = builder.finish(2).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int64(0), i64::MAX);
assert_eq!(program.column_int64(1), i64::MIN);
}
#[test]
fn test_integer_zero() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_negative_integers() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: -1,
dest: r1,
});
builder.add(Insn::Integer {
value: -100,
dest: r2,
});
builder.add(Insn::Integer {
value: -999999,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r1,
count: 3,
});
builder.add(Insn::Halt);
let mut program = builder.finish(3).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), -1);
assert_eq!(program.column_int(1), -100);
assert_eq!(program.column_int(2), -999999);
}
#[test]
fn test_add_negative_numbers() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: -10,
dest: r1,
});
builder.add(Insn::Integer {
value: -20,
dest: r2,
});
builder.add(Insn::Add {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), -30);
}
#[test]
fn test_subtract_to_negative() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 5, dest: r1 });
builder.add(Insn::Integer {
value: 10,
dest: r2,
});
builder.add(Insn::Subtract {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), -5);
}
#[test]
fn test_multiply_by_zero() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 1000000,
dest: r1,
});
builder.add(Insn::Integer { value: 0, dest: r2 });
builder.add(Insn::Multiply {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_multiply_negative_numbers() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
let r4 = builder.alloc_register();
builder.add(Insn::Integer {
value: -5,
dest: r1,
});
builder.add(Insn::Integer { value: 3, dest: r2 });
builder.add(Insn::Integer {
value: -4,
dest: r3,
});
builder.add(Insn::Multiply {
lhs: r1,
rhs: r2,
dest: r4,
});
builder.add(Insn::ResultRow {
start: r4,
count: 1,
});
builder.add(Insn::Multiply {
lhs: r1,
rhs: r3,
dest: r4,
});
builder.add(Insn::ResultRow {
start: r4,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), -15);
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 20);
}
#[test]
fn test_divide_by_zero_returns_null() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Integer { value: 0, dest: r2 });
builder.add(Insn::Divide {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!(program.column_value(0).is_null());
}
#[test]
fn test_remainder_by_zero_returns_null() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Integer { value: 0, dest: r2 });
builder.add(Insn::Remainder {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!(program.column_value(0).is_null());
}
#[test]
fn test_remainder_with_negatives() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: -17,
dest: r1,
});
builder.add(Insn::Integer { value: 5, dest: r2 });
builder.add(Insn::Remainder {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), -2);
}
#[test]
fn test_integer_division_truncates() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 7, dest: r1 });
builder.add(Insn::Integer { value: 3, dest: r2 });
builder.add(Insn::Divide {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 2); }
#[test]
fn test_bitwise_and() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 0b1100,
dest: r1,
}); builder.add(Insn::Integer {
value: 0b1010,
dest: r2,
}); builder.add(Insn::BitAnd {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0b1000); }
#[test]
fn test_bitwise_or() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 0b1100,
dest: r1,
}); builder.add(Insn::Integer {
value: 0b1010,
dest: r2,
}); builder.add(Insn::BitOr {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0b1110); }
#[test]
fn test_bitwise_not() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 });
builder.add(Insn::BitNot { src: r1, dest: r2 });
builder.add(Insn::ResultRow {
start: r2,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), -1); }
#[test]
fn test_shift_left() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 });
builder.add(Insn::Integer { value: 4, dest: r2 });
builder.add(Insn::ShiftLeft {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 16); }
#[test]
fn test_shift_right() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 32,
dest: r1,
});
builder.add(Insn::Integer { value: 2, dest: r2 });
builder.add(Insn::ShiftRight {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 8); }
#[test]
fn test_null_multiple_registers() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let _r2 = builder.alloc_register();
let _r3 = builder.alloc_register();
builder.add(Insn::Null { dest: r1, count: 3 });
builder.add(Insn::ResultRow {
start: r1,
count: 3,
});
builder.add(Insn::Halt);
let mut program = builder.finish(3).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!(program.column_value(0).is_null());
assert!(program.column_value(1).is_null());
assert!(program.column_value(2).is_null());
}
#[test]
fn test_add_with_null() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Null { dest: r2, count: 1 });
builder.add(Insn::Add {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!(program.column_value(0).is_null());
}
#[test]
fn test_is_null_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Null { dest: r1, count: 1 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let is_null_addr = builder.add(Insn::IsNull { src: r1, target: 0 });
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(is_null_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1); }
#[test]
fn test_not_null_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let not_null_addr = builder.add(Insn::NotNull { src: r1, target: 0 });
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(not_null_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1); }
#[test]
fn test_if_true() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 }); builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let if_addr = builder.add(Insn::If {
src: r1,
target: 0,
jump_if_null: false,
});
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(if_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_if_false() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 }); builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let if_addr = builder.add(Insn::If {
src: r1,
target: 0,
jump_if_null: false,
});
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(if_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0); }
#[test]
fn test_ifnot_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 }); builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let ifnot_addr = builder.add(Insn::IfNot {
src: r1,
target: 0,
jump_if_null: false,
});
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(ifnot_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1); }
#[test]
fn test_loop_with_ifnotzero() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_counter = builder.alloc_register();
let r_sum = builder.alloc_register();
builder.add(Insn::Integer {
value: 5,
dest: r_counter,
});
builder.add(Insn::Integer {
value: 0,
dest: r_sum,
});
let loop_start = builder.current_addr();
builder.add(Insn::Add {
lhs: r_sum,
rhs: r_counter,
dest: r_sum,
});
builder.add(Insn::IfNotZero {
src: r_counter,
target: loop_start.raw(),
});
builder.add(Insn::ResultRow {
start: r_sum,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 15);
}
#[test]
fn test_ifpos_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: 5, dest: r1 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let ifpos_addr = builder.add(Insn::IfPos {
src: r1,
target: 0,
decrement: 0,
});
let goto_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(ifpos_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(goto_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1); }
#[test]
fn test_ifnotzero_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_counter = builder.alloc_register();
let r_sum = builder.alloc_register();
builder.add(Insn::Integer {
value: 3,
dest: r_counter,
});
builder.add(Insn::Integer {
value: 0,
dest: r_sum,
});
let loop_start = builder.current_addr();
builder.add(Insn::Add {
lhs: r_sum,
rhs: r_counter,
dest: r_sum,
});
builder.add(Insn::IfNotZero {
src: r_counter,
target: loop_start.raw(),
});
builder.add(Insn::ResultRow {
start: r_sum,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 6);
}
#[test]
fn test_all_comparisons() {
fn test_cmp(
a: i32,
b: i32,
expected_eq: bool,
expected_ne: bool,
expected_lt: bool,
expected_le: bool,
expected_gt: bool,
expected_ge: bool,
) {
{
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let eq_addr = builder.add(Insn::Eq {
lhs: r1,
rhs: r2,
target: 0,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(eq_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(
program.column_int(0) != 0,
expected_eq,
"Eq failed for {} == {}",
a,
b
);
}
{
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let ne_addr = builder.add(Insn::Ne {
lhs: r1,
rhs: r2,
target: 0,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(ne_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(
program.column_int(0) != 0,
expected_ne,
"Ne failed for {} != {}",
a,
b
);
}
{
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let lt_addr = builder.add(Insn::Lt {
lhs: r1,
rhs: r2,
target: 0,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(lt_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(
program.column_int(0) != 0,
expected_lt,
"Lt failed for {} < {}",
a,
b
);
}
{
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let le_addr = builder.add(Insn::Le {
lhs: r1,
rhs: r2,
target: 0,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(le_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(
program.column_int(0) != 0,
expected_le,
"Le failed for {} <= {}",
a,
b
);
}
{
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let gt_addr = builder.add(Insn::Gt {
lhs: r1,
rhs: r2,
target: 0,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(gt_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(
program.column_int(0) != 0,
expected_gt,
"Gt failed for {} > {}",
a,
b
);
}
{
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let ge_addr = builder.add(Insn::Ge {
lhs: r1,
rhs: r2,
target: 0,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(ge_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(
program.column_int(0) != 0,
expected_ge,
"Ge failed for {} >= {}",
a,
b
);
}
}
test_cmp(5, 10, false, true, true, true, false, false);
test_cmp(10, 5, false, true, false, false, true, true);
test_cmp(7, 7, true, false, false, true, false, true);
}
#[test]
fn test_comparison_equal_values() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r_eq = builder.alloc_register();
let r_le = builder.alloc_register();
let r_ge = builder.alloc_register();
builder.add(Insn::Integer { value: 7, dest: r1 });
builder.add(Insn::Integer { value: 7, dest: r2 });
builder.add(Insn::Integer {
value: 0,
dest: r_eq,
});
builder.add(Insn::Integer {
value: 0,
dest: r_le,
});
builder.add(Insn::Integer {
value: 0,
dest: r_ge,
});
let eq_addr = builder.add(Insn::Eq {
lhs: r1,
rhs: r2,
target: 0,
});
let eq_skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(eq_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_eq,
});
builder.jump_here(eq_skip);
let le_addr = builder.add(Insn::Le {
lhs: r1,
rhs: r2,
target: 0,
});
let le_skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(le_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_le,
});
builder.jump_here(le_skip);
let ge_addr = builder.add(Insn::Ge {
lhs: r1,
rhs: r2,
target: 0,
});
let ge_skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(ge_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_ge,
});
builder.jump_here(ge_skip);
builder.add(Insn::ResultRow {
start: r_eq,
count: 3,
});
builder.add(Insn::Halt);
let mut program = builder.finish(3).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1); assert_eq!(program.column_int(1), 1); assert_eq!(program.column_int(2), 1); }
#[test]
fn test_copy_range() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
let r4 = builder.alloc_register();
let _r5 = builder.alloc_register();
let _r6 = builder.alloc_register();
builder.add(Insn::Integer {
value: 10,
dest: r1,
});
builder.add(Insn::Integer {
value: 20,
dest: r2,
});
builder.add(Insn::Integer {
value: 30,
dest: r3,
});
builder.add(Insn::Copy {
src: r1,
dest: r4,
count: 3,
});
builder.add(Insn::ResultRow {
start: r4,
count: 3,
});
builder.add(Insn::Halt);
let mut program = builder.finish(3).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 10);
assert_eq!(program.column_int(1), 20);
assert_eq!(program.column_int(2), 30);
}
#[test]
fn test_move_clears_source() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Move {
src: r1,
dest: r2,
count: 1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 2,
});
builder.add(Insn::Halt);
let mut program = builder.finish(2).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!(program.column_value(0).is_null()); assert_eq!(program.column_int(1), 42); }
#[test]
fn test_addimm() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 100,
dest: r1,
});
builder.add(Insn::AddImm {
dest: r1,
value: 50,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 150);
}
#[test]
fn test_addimm_negative() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 100,
dest: r1,
});
builder.add(Insn::AddImm {
dest: r1,
value: -30,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 70);
}
#[test]
fn test_real_values() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Real {
value: 3.14159,
dest: r1,
});
builder.add(Insn::Real {
value: -2.5,
dest: r2,
});
builder.add(Insn::ResultRow {
start: r1,
count: 2,
});
builder.add(Insn::Halt);
let mut program = builder.finish(2).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v1 = program.column_value(0);
let v2 = program.column_value(1);
assert!((v1.as_real().unwrap() - 3.14159).abs() < 0.00001);
assert!((v2.as_real().unwrap() - (-2.5)).abs() < 0.00001);
}
#[test]
fn test_real_arithmetic() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Real {
value: 10.5,
dest: r1,
});
builder.add(Insn::Real {
value: 3.0,
dest: r2,
});
builder.add(Insn::Divide {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v = program.column_value(0);
assert!((v.as_real().unwrap() - 3.5).abs() < 0.00001);
}
#[test]
fn test_string_values() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::String8 {
value: "Hello, World!".to_string(),
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v = program.column_value(0);
assert_eq!(v.as_text(), Some("Hello, World!"));
}
#[test]
fn test_string_concat() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::String8 {
value: "Hello, ".to_string(),
dest: r1,
});
builder.add(Insn::String8 {
value: "World!".to_string(),
dest: r2,
});
builder.add(Insn::Concat {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v = program.column_value(0);
assert_eq!(v.as_text(), Some("Hello, World!"));
}
#[test]
fn test_empty_string() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::String8 {
value: "".to_string(),
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v = program.column_value(0);
assert_eq!(v.as_text(), Some(""));
}
#[test]
fn test_string_with_special_chars() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::String8 {
value: "Line1\nLine2\tTab".to_string(),
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v = program.column_value(0);
assert_eq!(v.as_text(), Some("Line1\nLine2\tTab"));
}
#[test]
fn test_string_with_unicode() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::String8 {
value: "Hello, 世界! 🎉".to_string(),
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let v = program.column_value(0);
assert_eq!(v.as_text(), Some("Hello, 世界! 🎉"));
}
#[test]
fn test_gosub_return() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_return = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
let gosub_addr = builder.add(Insn::Gosub {
return_reg: r_return,
target: 0,
});
builder.add(Insn::Integer {
value: 3,
dest: r_result,
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
builder.jump_here(gosub_addr);
builder.add(Insn::Integer {
value: 2,
dest: r_result,
});
builder.add(Insn::Return {
return_reg: r_return,
});
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 3);
}
#[test]
fn test_not_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
let r4 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 }); builder.add(Insn::Integer { value: 1, dest: r2 }); builder.add(Insn::Not { src: r1, dest: r3 }); builder.add(Insn::Not { src: r2, dest: r4 }); builder.add(Insn::ResultRow {
start: r3,
count: 2,
});
builder.add(Insn::Halt);
let mut program = builder.finish(2).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_many_registers() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let first_reg = builder.alloc_register();
for i in 1..10 {
let _ = builder.alloc_register();
builder.add(Insn::Integer {
value: i as i32,
dest: first_reg + i,
});
}
builder.add(Insn::Integer {
value: 0,
dest: first_reg,
});
builder.add(Insn::ResultRow {
start: first_reg,
count: 10,
});
builder.add(Insn::Halt);
let mut program = builder.finish(10).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_count(), 10);
for i in 0..10 {
assert_eq!(program.column_int(i), i);
}
}
#[test]
fn test_noop_instruction() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Noop);
builder.add(Insn::Noop);
builder.add(Insn::Noop);
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_value_type_conversions() {
let v: Value = 42i64.into();
assert_eq!(v, Value::Integer(42));
assert_eq!(v.as_integer(), Some(42));
assert!((v.as_real().unwrap() - 42.0).abs() < 0.001);
let v: Value = 3.14f64.into();
assert_eq!(v.as_integer(), Some(3));
let v: Value = "123".into();
assert_eq!(v.as_integer(), Some(123));
let v: Value = "not a number".into();
assert_eq!(v.as_integer(), None);
let v: Value = None::<i64>.into();
assert!(v.is_null());
}
#[test]
fn test_value_to_string_lossy() {
assert_eq!(Value::Null.to_string_lossy(), "NULL");
assert_eq!(Value::Integer(42).to_string_lossy(), "42");
assert_eq!(Value::Real(3.14).to_string_lossy(), "3.14");
assert_eq!(Value::Text("hello".to_string()).to_string_lossy(), "hello");
assert_eq!(Value::Blob(vec![0xDE, 0xAD]).to_string_lossy(), "X'DEAD'");
}
#[test]
fn test_factorial_5() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_n = builder.alloc_register(); let r_result = builder.alloc_register(); let r_one = builder.alloc_register();
builder.add(Insn::Integer {
value: 5,
dest: r_n,
});
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.add(Insn::Integer {
value: 1,
dest: r_one,
});
let loop_start = builder.current_addr();
builder.add(Insn::Multiply {
lhs: r_result,
rhs: r_n,
dest: r_result,
});
builder.add(Insn::Subtract {
lhs: r_n,
rhs: r_one,
dest: r_n,
});
builder.add(Insn::Gt {
lhs: r_n,
rhs: r_one,
target: loop_start.raw(),
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 120); }
#[test]
fn test_fibonacci_sequence() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_a = builder.alloc_register(); let r_b = builder.alloc_register(); let r_next = builder.alloc_register(); let r_count = builder.alloc_register();
builder.add(Insn::Integer {
value: 0,
dest: r_a,
});
builder.add(Insn::Integer {
value: 1,
dest: r_b,
});
builder.add(Insn::Integer {
value: 10,
dest: r_count,
});
builder.add(Insn::ResultRow {
start: r_a,
count: 1,
});
builder.add(Insn::AddImm {
dest: r_count,
value: -1,
});
let loop_start = builder.current_addr();
builder.add(Insn::ResultRow {
start: r_b,
count: 1,
});
builder.add(Insn::Add {
lhs: r_a,
rhs: r_b,
dest: r_next,
});
builder.add(Insn::SCopy {
src: r_b,
dest: r_a,
});
builder.add(Insn::SCopy {
src: r_next,
dest: r_b,
});
builder.add(Insn::AddImm {
dest: r_count,
value: -1,
});
builder.add(Insn::IfPos {
src: r_count,
target: loop_start.raw(),
decrement: 0,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let expected = vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
let mut results = Vec::new();
loop {
match program.step().unwrap() {
StepResult::Row => results.push(program.column_int(0)),
StepResult::Done => break,
}
}
assert_eq!(results, expected);
}
struct SimpleRng {
state: u64,
}
impl SimpleRng {
fn new(seed: u64) -> Self {
Self { state: seed }
}
fn next(&mut self) -> u64 {
self.state ^= self.state << 13;
self.state ^= self.state >> 7;
self.state ^= self.state << 17;
self.state
}
fn next_i32(&mut self) -> i32 {
self.next() as i32
}
fn range(&mut self, min: i32, max: i32) -> i32 {
let range = (max - min) as u64;
(self.next() % range) as i32 + min
}
}
#[test]
fn test_fuzz_arithmetic_programs() {
let mut rng = SimpleRng::new(12345);
for _ in 0..100 {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
let a = rng.next_i32() % 10000;
let b = rng.range(1, 10000);
builder.add(Insn::Integer { value: a, dest: r1 });
builder.add(Insn::Integer { value: b, dest: r2 });
match rng.range(0, 5) {
0 => {
builder.add(Insn::Add {
lhs: r1,
rhs: r2,
dest: r3,
});
}
1 => {
builder.add(Insn::Subtract {
lhs: r1,
rhs: r2,
dest: r3,
});
}
2 => {
builder.add(Insn::Multiply {
lhs: r1,
rhs: r2,
dest: r3,
});
}
3 => {
builder.add(Insn::Divide {
lhs: r1,
rhs: r2,
dest: r3,
});
}
_ => {
builder.add(Insn::Remainder {
lhs: r1,
rhs: r2,
dest: r3,
});
}
}
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let result = program.step();
assert!(result.is_ok());
}
}
#[test]
fn test_fuzz_random_integer_values() {
let mut rng = SimpleRng::new(67890);
for _ in 0..100 {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let value = match rng.range(0, 5) {
0 => i32::MAX,
1 => i32::MIN,
2 => 0,
3 => -1,
_ => rng.next_i32(),
};
builder.add(Insn::Integer { value, dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), value);
}
}
#[test]
fn test_fuzz_control_flow() {
let mut rng = SimpleRng::new(11111);
for _ in 0..50 {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r_result = builder.alloc_register();
let value = rng.range(-100, 100);
builder.add(Insn::Integer { value, dest: r1 });
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let cmp_type = rng.range(0, 6);
let cmp_value = rng.range(-100, 100);
let r_cmp = builder.alloc_register();
builder.add(Insn::Integer {
value: cmp_value,
dest: r_cmp,
});
let jump_addr = match cmp_type {
0 => builder.add(Insn::Eq {
lhs: r1,
rhs: r_cmp,
target: 0,
}),
1 => builder.add(Insn::Ne {
lhs: r1,
rhs: r_cmp,
target: 0,
}),
2 => builder.add(Insn::Lt {
lhs: r1,
rhs: r_cmp,
target: 0,
}),
3 => builder.add(Insn::Le {
lhs: r1,
rhs: r_cmp,
target: 0,
}),
4 => builder.add(Insn::Gt {
lhs: r1,
rhs: r_cmp,
target: 0,
}),
_ => builder.add(Insn::Ge {
lhs: r1,
rhs: r_cmp,
target: 0,
}),
};
let skip_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(jump_addr);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.jump_here(skip_addr);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let result = program.step();
assert!(result.is_ok());
assert_eq!(result.unwrap(), StepResult::Row);
let expected = match cmp_type {
0 => {
if value == cmp_value {
1
} else {
0
}
}
1 => {
if value != cmp_value {
1
} else {
0
}
}
2 => {
if value < cmp_value {
1
} else {
0
}
}
3 => {
if value <= cmp_value {
1
} else {
0
}
}
4 => {
if value > cmp_value {
1
} else {
0
}
}
_ => {
if value >= cmp_value {
1
} else {
0
}
}
};
assert_eq!(program.column_int(0), expected);
}
}
#[test]
fn test_fuzz_long_programs() {
let mut rng = SimpleRng::new(99999);
for _ in 0..3 {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let num_regs = rng.range(5, 20) as usize;
let regs: Vec<i32> = (0..num_regs).map(|_| builder.alloc_register()).collect();
for (i, &r) in regs.iter().enumerate() {
builder.add(Insn::Integer {
value: (i * 10) as i32,
dest: r,
});
}
let num_ops = rng.range(5, 15);
for _ in 0..num_ops {
let src1 = regs[rng.range(0, num_regs as i32) as usize];
let src2 = regs[rng.range(0, num_regs as i32) as usize];
let dest = regs[rng.range(0, num_regs as i32) as usize];
match rng.range(0, 4) {
0 => builder.add(Insn::Add {
lhs: src1,
rhs: src2,
dest,
}),
1 => builder.add(Insn::Subtract {
lhs: src1,
rhs: src2,
dest,
}),
2 => builder.add(Insn::Multiply {
lhs: src1,
rhs: src2,
dest,
}),
_ => builder.add(Insn::SCopy { src: src1, dest }),
};
}
builder.add(Insn::ResultRow {
start: regs[0],
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let result = program.step();
assert!(result.is_ok());
}
}
#[test]
fn test_fuzz_nested_loops() {
let mut rng = SimpleRng::new(55555);
for _ in 0..10 {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_counter = builder.alloc_register();
let r_sum = builder.alloc_register();
let limit = rng.range(2, 10);
builder.add(Insn::Integer {
value: limit,
dest: r_counter,
});
builder.add(Insn::Integer {
value: 0,
dest: r_sum,
});
let loop_start = builder.current_addr();
builder.add(Insn::AddImm {
dest: r_sum,
value: 1,
});
builder.add(Insn::IfNotZero {
src: r_counter,
target: loop_start.raw(),
});
builder.add(Insn::ResultRow {
start: r_sum,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), limit + 1);
}
}
#[test]
fn test_many_result_rows() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_counter = builder.alloc_register();
let r_limit = builder.alloc_register();
let num_rows = 1000;
builder.add(Insn::Integer {
value: 0,
dest: r_counter,
});
builder.add(Insn::Integer {
value: num_rows,
dest: r_limit,
});
let loop_start = builder.current_addr();
builder.add(Insn::ResultRow {
start: r_counter,
count: 1,
});
builder.add(Insn::AddImm {
dest: r_counter,
value: 1,
});
builder.add(Insn::Lt {
lhs: r_counter,
rhs: r_limit,
target: loop_start.raw(),
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
let mut count = 0;
loop {
match program.step().unwrap() {
StepResult::Row => {
assert_eq!(program.column_int(0), count);
count += 1;
}
StepResult::Done => break,
}
}
assert_eq!(count, num_rows);
}
#[test]
fn test_program_reuse_many_times() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
for _ in 0..100 {
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
assert_eq!(program.step().unwrap(), StepResult::Done);
program.reset();
}
}
#[test]
fn test_single_instruction_program() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
builder.add(Insn::Halt);
let mut program = builder.finish(0).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Done);
}
#[test]
fn test_result_row_zero_columns() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 0,
}); builder.add(Insn::Halt);
let mut program = builder.finish(0).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_count(), 0);
}
#[test]
fn test_many_consecutive_jumps() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 });
let mut addrs = Vec::new();
for _ in 0..10 {
addrs.push(builder.add(Insn::Goto { target: 0 }));
builder.add(Insn::AddImm {
dest: r1,
value: 100,
}); }
for addr in addrs {
builder.jump_here(addr);
}
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_self_referential_computation() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 });
for _ in 0..5 {
builder.add(Insn::Add {
lhs: r1,
rhs: r1,
dest: r1,
});
}
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 32);
}
#[test]
fn test_fk_counter_opcode() {
use sqlite_vdbe::{Insn, P4, RawOpcode};
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Raw {
opcode: RawOpcode::FkCounter,
p1: 0, p2: 5, p3: 0,
p4: P4::None,
p5: 0,
});
builder.add(Insn::Raw {
opcode: RawOpcode::FkCounter,
p1: 0,
p2: -5, p3: 0,
p4: P4::None,
p5: 0,
});
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_fk_if_zero_opcode() {
use sqlite_vdbe::{Insn, P4, RawOpcode};
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_result = builder.alloc_register();
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let fk_check = builder.add(Insn::Raw {
opcode: RawOpcode::FkIfZero,
p1: 0, p2: 0, p3: 0,
p4: P4::None,
p5: 0,
});
builder.add(Insn::Integer {
value: 99,
dest: r_result,
});
builder.jump_here(fk_check);
builder.add(Insn::Integer {
value: 1,
dest: r_result,
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_and_opcode() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 });
builder.add(Insn::Integer { value: 1, dest: r2 });
builder.add(Insn::And {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_and_false_result() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 });
builder.add(Insn::Integer { value: 0, dest: r2 });
builder.add(Insn::And {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_or_opcode() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 });
builder.add(Insn::Integer { value: 1, dest: r2 });
builder.add(Insn::Or {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_or_both_false() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 });
builder.add(Insn::Integer { value: 0, dest: r2 });
builder.add(Insn::Or {
lhs: r1,
rhs: r2,
dest: r3,
});
builder.add(Insn::ResultRow {
start: r3,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_and_or_combined() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
let r3 = builder.alloc_register();
let r4 = builder.alloc_register();
let r5 = builder.alloc_register();
builder.add(Insn::Integer { value: 1, dest: r1 });
builder.add(Insn::Integer { value: 1, dest: r2 });
builder.add(Insn::Integer { value: 0, dest: r3 });
builder.add(Insn::And {
lhs: r1,
rhs: r2,
dest: r4,
});
builder.add(Insn::Or {
lhs: r4,
rhs: r3,
dest: r5,
});
builder.add(Insn::ResultRow {
start: r5,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_cast_to_integer() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Real {
value: 42.7,
dest: r1,
});
builder.add(Insn::Cast {
src: r1,
affinity: 'D' as i32,
}); builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_cast_to_real() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::Cast {
src: r1,
affinity: 'E' as i32,
}); builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!((program.column_double(0) - 42.0).abs() < 0.001);
}
#[test]
fn test_real_affinity() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 100,
dest: r1,
});
builder.add(Insn::RealAffinity { src: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert!((program.column_double(0) - 100.0).abs() < 0.001);
}
#[test]
fn test_is_true_with_true_value() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::IsTrue {
src: r1,
dest: r2,
null_value: 0,
});
builder.add(Insn::ResultRow {
start: r2,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 1);
}
#[test]
fn test_is_true_with_false_value() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Integer { value: 0, dest: r1 });
builder.add(Insn::IsTrue {
src: r1,
dest: r2,
null_value: 0,
});
builder.add(Insn::ResultRow {
start: r2,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_is_true_with_null() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Null { dest: r1, count: 1 });
builder.add(Insn::IsTrue {
src: r1,
dest: r2,
null_value: 2,
});
builder.add(Insn::ResultRow {
start: r2,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 2);
}
#[test]
fn test_soft_null() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::SoftNull { dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_type(0), ffi::SQLITE_NULL);
}
#[test]
fn test_zero_or_null_instruction_exists() {
let _ = Insn::ZeroOrNull {
src: 0,
dest: 1,
null_check: 0,
};
assert_eq!(
Insn::ZeroOrNull {
src: 0,
dest: 1,
null_check: 0
}
.name(),
"ZeroOrNull"
);
}
#[test]
fn test_begin_subrtn() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_result = builder.alloc_register();
let r_return = builder.alloc_register();
builder.add(Insn::Integer {
value: 0,
dest: r_result,
});
let gosub_addr = builder.add(Insn::Gosub {
return_reg: r_return,
target: 0,
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
let halt_addr = builder.add(Insn::Goto { target: 0 });
builder.jump_here(gosub_addr);
builder.add(Insn::BeginSubrtn {
return_reg: r_return,
target: 0,
});
builder.add(Insn::Integer {
value: 42,
dest: r_result,
});
builder.add(Insn::Return {
return_reg: r_return,
});
builder.jump_here(halt_addr);
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_read_cookie() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 0,
});
builder.add(Insn::ReadCookie {
db_num: 0,
dest: r1,
cookie: 0,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let value = program.column_int(0);
assert!(value >= 0); }
#[test]
fn test_set_and_read_cookie() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 0,
});
builder.add(Insn::ReadCookie {
db_num: 0,
dest: r1,
cookie: 0,
}); builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let cookie = program.column_int(0);
assert!(cookie >= 0);
let _ = Insn::SetCookie {
db_num: 0,
cookie: 1,
value: 0,
};
}
#[test]
fn test_pagecount() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 0,
});
builder.add(Insn::Pagecount {
db_num: 0,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let pages = program.column_int(0);
assert!(pages >= 0 && pages <= 1);
}
#[test]
fn test_transaction_read() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 0,
});
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_transaction_write() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 1,
});
builder.add(Insn::Integer {
value: 99,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 99);
}
#[test]
fn test_auto_commit() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Integer {
value: 123,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 123);
let _ = Insn::AutoCommit {
auto_commit: 1,
rollback: 0,
};
}
#[test]
fn test_open_ephemeral_and_sequence() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 2,
});
builder.add(Insn::Sequence { cursor, dest: r1 });
builder.add(Insn::Sequence { cursor, dest: r2 });
builder.add(Insn::ResultRow {
start: r1,
count: 2,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(2).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
assert_eq!(program.column_int(1), 1);
}
#[test]
fn test_open_pseudo() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_content = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::Integer {
value: 42,
dest: r_content,
});
builder.add(Insn::MakeRecord {
start: r_content,
count: 1,
dest: r_content,
});
builder.add(Insn::OpenPseudo {
cursor,
content: r_content,
num_columns: 1,
});
builder.add(Insn::Column {
cursor,
column: 0,
dest: r_result,
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_sorter_instructions_exist() {
let _ = Insn::SorterOpen {
cursor: 0,
num_columns: 1,
};
let _ = Insn::SorterSort {
cursor: 0,
target: 0,
};
let _ = Insn::Sort {
cursor: 0,
target: 0,
};
let _ = Insn::SorterNext {
cursor: 0,
target: 0,
};
let _ = Insn::SorterData { cursor: 0, dest: 0 };
let _ = Insn::SorterInsert { cursor: 0, key: 0 };
let _ = Insn::SorterCompare {
cursor: 0,
target: 0,
key: 0,
num_fields: 0,
};
let _ = Insn::ResetSorter { cursor: 0 };
assert_eq!(
Insn::SorterOpen {
cursor: 0,
num_columns: 1
}
.name(),
"SorterOpen"
);
assert_eq!(
Insn::SorterSort {
cursor: 0,
target: 0
}
.name(),
"SorterSort"
);
assert_eq!(Insn::ResetSorter { cursor: 0 }.name(), "ResetSorter");
}
#[test]
fn test_virtual_table_instructions_exist() {
let _ = Insn::VBegin;
let _ = Insn::VCreate {
db_num: 0,
name_reg: 1,
};
let _ = Insn::VDestroy { db_num: 0 };
let _ = Insn::VOpen { cursor: 0 };
let _ = Insn::VCheck {
schema: 0,
dest: 1,
arg: 0,
};
let _ = Insn::VInitIn {
cursor: 0,
dest: 1,
cache_reg: 2,
};
let _ = Insn::VFilter {
cursor: 0,
target: 10,
args_reg: 1,
};
let _ = Insn::VColumn {
cursor: 0,
column: 0,
dest: 1,
flags: 0,
};
let _ = Insn::VNext {
cursor: 0,
target: 5,
};
let _ = Insn::VRename { name_reg: 1 };
let _ = Insn::VUpdate {
update_rowid: 0,
argc: 3,
args_reg: 1,
on_error: 0,
};
assert_eq!(Insn::VBegin.name(), "VBegin");
assert_eq!(
Insn::VCreate {
db_num: 0,
name_reg: 1
}
.name(),
"VCreate"
);
assert_eq!(Insn::VDestroy { db_num: 0 }.name(), "VDestroy");
assert_eq!(Insn::VOpen { cursor: 0 }.name(), "VOpen");
assert_eq!(
Insn::VCheck {
schema: 0,
dest: 1,
arg: 0
}
.name(),
"VCheck"
);
assert_eq!(
Insn::VInitIn {
cursor: 0,
dest: 1,
cache_reg: 2
}
.name(),
"VInitIn"
);
assert_eq!(
Insn::VFilter {
cursor: 0,
target: 10,
args_reg: 1
}
.name(),
"VFilter"
);
assert_eq!(
Insn::VColumn {
cursor: 0,
column: 0,
dest: 1,
flags: 0
}
.name(),
"VColumn"
);
assert_eq!(
Insn::VNext {
cursor: 0,
target: 5
}
.name(),
"VNext"
);
assert_eq!(Insn::VRename { name_reg: 1 }.name(), "VRename");
assert_eq!(
Insn::VUpdate {
update_rowid: 0,
argc: 3,
args_reg: 1,
on_error: 0
}
.name(),
"VUpdate"
);
}
#[test]
fn test_virtual_table_raw_opcodes() {
use sqlite_vdbe::RawOpcode;
assert_eq!(Insn::VBegin.raw_opcode(), RawOpcode::VBegin as u8);
assert_eq!(
Insn::VCreate {
db_num: 0,
name_reg: 1
}
.raw_opcode(),
RawOpcode::VCreate as u8
);
assert_eq!(
Insn::VDestroy { db_num: 0 }.raw_opcode(),
RawOpcode::VDestroy as u8
);
assert_eq!(
Insn::VOpen { cursor: 0 }.raw_opcode(),
RawOpcode::VOpen as u8
);
assert_eq!(
Insn::VCheck {
schema: 0,
dest: 1,
arg: 0
}
.raw_opcode(),
RawOpcode::VCheck as u8
);
assert_eq!(
Insn::VInitIn {
cursor: 0,
dest: 1,
cache_reg: 2
}
.raw_opcode(),
RawOpcode::VInitIn as u8
);
assert_eq!(
Insn::VFilter {
cursor: 0,
target: 10,
args_reg: 1
}
.raw_opcode(),
RawOpcode::VFilter as u8
);
assert_eq!(
Insn::VColumn {
cursor: 0,
column: 0,
dest: 1,
flags: 0
}
.raw_opcode(),
RawOpcode::VColumn as u8
);
assert_eq!(
Insn::VNext {
cursor: 0,
target: 5
}
.raw_opcode(),
RawOpcode::VNext as u8
);
assert_eq!(
Insn::VRename { name_reg: 1 }.raw_opcode(),
RawOpcode::VRename as u8
);
assert_eq!(
Insn::VUpdate {
update_rowid: 0,
argc: 3,
args_reg: 1,
on_error: 0
}
.raw_opcode(),
RawOpcode::VUpdate as u8
);
}
#[test]
fn test_virtual_table_display() {
assert_eq!(format!("{}", Insn::VBegin), "VBegin");
assert_eq!(
format!(
"{}",
Insn::VCreate {
db_num: 0,
name_reg: 1
}
),
"VCreate"
);
assert_eq!(format!("{}", Insn::VDestroy { db_num: 0 }), "VDestroy");
assert_eq!(format!("{}", Insn::VOpen { cursor: 0 }), "VOpen");
assert_eq!(
format!(
"{}",
Insn::VCheck {
schema: 0,
dest: 1,
arg: 0
}
),
"VCheck"
);
assert_eq!(
format!(
"{}",
Insn::VInitIn {
cursor: 0,
dest: 1,
cache_reg: 2
}
),
"VInitIn"
);
assert_eq!(
format!(
"{}",
Insn::VFilter {
cursor: 0,
target: 10,
args_reg: 1
}
),
"VFilter"
);
assert_eq!(
format!(
"{}",
Insn::VColumn {
cursor: 0,
column: 0,
dest: 1,
flags: 0
}
),
"VColumn"
);
assert_eq!(
format!(
"{}",
Insn::VNext {
cursor: 0,
target: 5
}
),
"VNext"
);
assert_eq!(format!("{}", Insn::VRename { name_reg: 1 }), "VRename");
assert_eq!(
format!(
"{}",
Insn::VUpdate {
update_rowid: 0,
argc: 3,
args_reg: 1,
on_error: 0
}
),
"VUpdate"
);
}
#[test]
fn test_virtual_table_debug() {
let vbegin = Insn::VBegin;
let debug_str = format!("{:?}", vbegin);
assert!(debug_str.contains("VBegin"));
let vcreate = Insn::VCreate {
db_num: 1,
name_reg: 2,
};
let debug_str = format!("{:?}", vcreate);
assert!(debug_str.contains("VCreate"));
assert!(debug_str.contains("db_num: 1"));
assert!(debug_str.contains("name_reg: 2"));
let vcolumn = Insn::VColumn {
cursor: 1,
column: 2,
dest: 3,
flags: 4,
};
let debug_str = format!("{:?}", vcolumn);
assert!(debug_str.contains("VColumn"));
assert!(debug_str.contains("cursor: 1"));
assert!(debug_str.contains("column: 2"));
assert!(debug_str.contains("dest: 3"));
assert!(debug_str.contains("flags: 4"));
}
#[test]
fn test_virtual_table_clone() {
let vbegin = Insn::VBegin;
let vbegin_clone = vbegin.clone();
assert_eq!(vbegin.name(), vbegin_clone.name());
let vcreate = Insn::VCreate {
db_num: 1,
name_reg: 2,
};
let vcreate_clone = vcreate.clone();
assert_eq!(vcreate.raw_opcode(), vcreate_clone.raw_opcode());
let vupdate = Insn::VUpdate {
update_rowid: 1,
argc: 3,
args_reg: 2,
on_error: 5,
};
let vupdate_clone = vupdate.clone();
assert_eq!(vupdate.name(), vupdate_clone.name());
}
#[test]
fn test_vfilter_with_different_targets() {
let vfilter1 = Insn::VFilter {
cursor: 0,
target: 0,
args_reg: 1,
};
let vfilter2 = Insn::VFilter {
cursor: 0,
target: 100,
args_reg: 1,
};
let vfilter3 = Insn::VFilter {
cursor: 5,
target: 50,
args_reg: 10,
};
assert_eq!(vfilter1.name(), "VFilter");
assert_eq!(vfilter2.name(), "VFilter");
assert_eq!(vfilter3.name(), "VFilter");
assert_eq!(vfilter1.raw_opcode(), vfilter2.raw_opcode());
assert_eq!(vfilter2.raw_opcode(), vfilter3.raw_opcode());
}
#[test]
fn test_vnext_jump_behavior() {
let vnext1 = Insn::VNext {
cursor: 0,
target: 5,
};
let vnext2 = Insn::VNext {
cursor: 1,
target: 10,
};
let vnext3 = Insn::VNext {
cursor: 2,
target: 0,
};
assert_eq!(vnext1.name(), "VNext");
assert_eq!(vnext2.name(), "VNext");
assert_eq!(vnext3.name(), "VNext");
}
#[test]
fn test_vcolumn_flags() {
let vcol_no_flags = Insn::VColumn {
cursor: 0,
column: 0,
dest: 1,
flags: 0,
};
let vcol_with_flags = Insn::VColumn {
cursor: 0,
column: 0,
dest: 1,
flags: 0x10,
};
assert_eq!(vcol_no_flags.name(), "VColumn");
assert_eq!(vcol_with_flags.name(), "VColumn");
assert_eq!(vcol_no_flags.raw_opcode(), vcol_with_flags.raw_opcode());
}
#[test]
fn test_vupdate_error_actions() {
let vupdate_abort = Insn::VUpdate {
update_rowid: 0,
argc: 3,
args_reg: 1,
on_error: 0,
};
let vupdate_fail = Insn::VUpdate {
update_rowid: 0,
argc: 3,
args_reg: 1,
on_error: 1,
};
let vupdate_replace = Insn::VUpdate {
update_rowid: 1,
argc: 5,
args_reg: 2,
on_error: 5,
};
assert_eq!(vupdate_abort.name(), "VUpdate");
assert_eq!(vupdate_fail.name(), "VUpdate");
assert_eq!(vupdate_replace.name(), "VUpdate");
}
#[test]
fn test_function_instructions_exist() {
let _ = Insn::Function {
const_mask: 0,
args: 1,
dest: 2,
};
let _ = Insn::PureFunc {
const_mask: 0,
args: 1,
dest: 2,
};
let _ = Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 2,
num_args: 3,
};
let _ = Insn::AggValue {
num_args: 2,
dest: 3,
};
let _ = Insn::AggInverse {
args: 1,
accum: 2,
num_args: 3,
};
assert_eq!(
Insn::Function {
const_mask: 0,
args: 1,
dest: 2
}
.name(),
"Function"
);
assert_eq!(
Insn::PureFunc {
const_mask: 0,
args: 1,
dest: 2
}
.name(),
"PureFunc"
);
assert_eq!(
Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 2,
num_args: 3
}
.name(),
"AggStep1"
);
assert_eq!(
Insn::AggValue {
num_args: 2,
dest: 3
}
.name(),
"AggValue"
);
assert_eq!(
Insn::AggInverse {
args: 1,
accum: 2,
num_args: 3
}
.name(),
"AggInverse"
);
}
#[test]
fn test_function_raw_opcodes() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::Function {
const_mask: 0,
args: 1,
dest: 2
}
.raw_opcode(),
RawOpcode::Function as u8
);
assert_eq!(
Insn::PureFunc {
const_mask: 0,
args: 1,
dest: 2
}
.raw_opcode(),
RawOpcode::PureFunc as u8
);
assert_eq!(
Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 2,
num_args: 3
}
.raw_opcode(),
RawOpcode::AggStep1 as u8
);
assert_eq!(
Insn::AggValue {
num_args: 2,
dest: 3
}
.raw_opcode(),
RawOpcode::AggValue as u8
);
assert_eq!(
Insn::AggInverse {
args: 1,
accum: 2,
num_args: 3
}
.raw_opcode(),
RawOpcode::AggInverse as u8
);
}
#[test]
fn test_function_display() {
assert_eq!(
format!(
"{}",
Insn::Function {
const_mask: 0,
args: 1,
dest: 2
}
),
"Function"
);
assert_eq!(
format!(
"{}",
Insn::PureFunc {
const_mask: 0,
args: 1,
dest: 2
}
),
"PureFunc"
);
assert_eq!(
format!(
"{}",
Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 2,
num_args: 3
}
),
"AggStep1"
);
assert_eq!(
format!(
"{}",
Insn::AggValue {
num_args: 2,
dest: 3
}
),
"AggValue"
);
assert_eq!(
format!(
"{}",
Insn::AggInverse {
args: 1,
accum: 2,
num_args: 3
}
),
"AggInverse"
);
}
#[test]
fn test_function_debug() {
let func = Insn::Function {
const_mask: 7,
args: 1,
dest: 2,
};
let debug_str = format!("{:?}", func);
assert!(debug_str.contains("Function"));
assert!(debug_str.contains("const_mask: 7"));
assert!(debug_str.contains("args: 1"));
assert!(debug_str.contains("dest: 2"));
let aggstep = Insn::AggStep1 {
is_inverse: 1,
args: 2,
accum: 3,
num_args: 4,
};
let debug_str = format!("{:?}", aggstep);
assert!(debug_str.contains("AggStep1"));
assert!(debug_str.contains("is_inverse: 1"));
assert!(debug_str.contains("num_args: 4"));
}
#[test]
fn test_function_clone() {
let func = Insn::Function {
const_mask: 15,
args: 1,
dest: 2,
};
let func_clone = func.clone();
assert_eq!(func.name(), func_clone.name());
assert_eq!(func.raw_opcode(), func_clone.raw_opcode());
let pure = Insn::PureFunc {
const_mask: 3,
args: 4,
dest: 5,
};
let pure_clone = pure.clone();
assert_eq!(pure.name(), pure_clone.name());
}
#[test]
fn test_function_const_mask_variations() {
let func_no_const = Insn::Function {
const_mask: 0,
args: 1,
dest: 2,
};
let func_first_const = Insn::Function {
const_mask: 1,
args: 1,
dest: 2,
};
let func_all_const = Insn::Function {
const_mask: 0xFF,
args: 1,
dest: 2,
};
assert_eq!(func_no_const.name(), "Function");
assert_eq!(func_first_const.name(), "Function");
assert_eq!(func_all_const.name(), "Function");
}
#[test]
fn test_aggstep1_inverse_flag() {
let step = Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 2,
num_args: 3,
};
let inverse = Insn::AggStep1 {
is_inverse: 1,
args: 1,
accum: 2,
num_args: 3,
};
assert_eq!(step.name(), "AggStep1");
assert_eq!(inverse.name(), "AggStep1");
assert_eq!(step.raw_opcode(), inverse.raw_opcode());
}
#[test]
fn test_agg_operations_different_arg_counts() {
let agg1 = Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 10,
num_args: 1,
};
let agg2 = Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 10,
num_args: 5,
};
let agg3 = Insn::AggStep1 {
is_inverse: 0,
args: 1,
accum: 10,
num_args: 10,
};
assert_eq!(agg1.name(), "AggStep1");
assert_eq!(agg2.name(), "AggStep1");
assert_eq!(agg3.name(), "AggStep1");
let val1 = Insn::AggValue {
num_args: 0,
dest: 1,
};
let val2 = Insn::AggValue {
num_args: 5,
dest: 1,
};
assert_eq!(val1.name(), "AggValue");
assert_eq!(val2.name(), "AggValue");
}
#[test]
fn test_pure_func_vs_function() {
use sqlite_vdbe::RawOpcode;
let func = Insn::Function {
const_mask: 0,
args: 1,
dest: 2,
};
let pure = Insn::PureFunc {
const_mask: 0,
args: 1,
dest: 2,
};
assert_ne!(func.raw_opcode(), pure.raw_opcode());
assert_eq!(func.raw_opcode(), RawOpcode::Function as u8);
assert_eq!(pure.raw_opcode(), RawOpcode::PureFunc as u8);
}
#[test]
fn test_agg_inverse_vs_aggstep() {
use sqlite_vdbe::RawOpcode;
let step = Insn::AggStep {
func_def: 0,
args: 1,
accum: 2,
num_args: 3,
};
let inverse = Insn::AggInverse {
args: 1,
accum: 2,
num_args: 3,
};
assert_ne!(step.raw_opcode(), inverse.raw_opcode());
assert_eq!(step.raw_opcode(), RawOpcode::AggStep as u8);
assert_eq!(inverse.raw_opcode(), RawOpcode::AggInverse as u8);
}
#[test]
fn test_if_not_open_jumps_when_closed() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_result = builder.alloc_register();
let jump = builder.add(Insn::IfNotOpen { cursor, target: 0 });
builder.add(Insn::Integer {
value: 999,
dest: r_result,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(jump);
builder.add(Insn::Integer {
value: 42,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_if_not_open_falls_through_when_open() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_key = builder.alloc_register();
let r_data = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 1,
});
builder.add(Insn::Integer {
value: 1,
dest: r_data,
});
builder.add(Insn::MakeRecord {
start: r_data,
count: 1,
dest: r_data,
});
builder.add(Insn::NewRowid {
cursor,
dest: r_key,
prev_rowid: 0,
});
builder.add(Insn::Insert {
cursor,
data: r_data,
rowid: r_key,
});
let rewind_done = builder.add(Insn::Rewind { cursor, target: 0 });
let jump = builder.add(Insn::IfNotOpen { cursor, target: 0 });
builder.add(Insn::Integer {
value: 42,
dest: r_result,
});
let skip = builder.add(Insn::Goto { target: 0 });
builder.jump_here(jump);
builder.jump_here(rewind_done);
builder.add(Insn::Integer {
value: 999,
dest: r_result,
});
builder.jump_here(skip);
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_variable_instruction_exists() {
let _ = Insn::Variable { param: 1, dest: 0 };
assert_eq!(Insn::Variable { param: 1, dest: 0 }.name(), "Variable");
}
#[test]
fn test_fk_check() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::FkCheck);
builder.add(Insn::Integer {
value: 42,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_journal_mode() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 0,
});
builder.add(Insn::JournalMode {
db_num: 0,
target: 0,
dest: r1,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let mode = program.column_text(0);
assert!(mode.is_some());
}
#[test]
fn test_open_dup() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor1 = builder.alloc_cursor();
let cursor2 = builder.alloc_cursor();
let r_key = builder.alloc_register();
let r_data = builder.alloc_register();
let r_seq1 = builder.alloc_register();
let r_seq2 = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor: cursor1,
num_columns: 2,
});
builder.add(Insn::Integer {
value: 1,
dest: r_key,
});
builder.add(Insn::MakeRecord {
start: r_key,
count: 1,
dest: r_data,
});
builder.add(Insn::NewRowid {
cursor: cursor1,
dest: r_key,
prev_rowid: 0,
});
builder.add(Insn::Insert {
cursor: cursor1,
data: r_data,
rowid: r_key,
});
builder.add(Insn::OpenDup {
cursor: cursor2,
orig_cursor: cursor1,
});
builder.add(Insn::Sequence {
cursor: cursor1,
dest: r_seq1,
});
builder.add(Insn::Sequence {
cursor: cursor2,
dest: r_seq2,
});
builder.add(Insn::ResultRow {
start: r_seq1,
count: 2,
});
builder.add(Insn::Close { cursor: cursor1 });
builder.add(Insn::Close { cursor: cursor2 });
builder.add(Insn::Halt);
let mut program = builder.finish(2).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let seq1 = program.column_int(0);
let seq2 = program.column_int(1);
assert!(seq1 >= 0);
assert!(seq2 >= 0);
}
#[test]
fn test_create_btree() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r_root = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 1,
});
builder.add(Insn::CreateBtree {
db_num: 0,
dest: r_root,
flags: 1,
}); builder.add(Insn::ResultRow {
start: r_root,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let root = program.column_int(0);
assert!(root > 0);
}
#[test]
fn test_open_autoindex() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r1 = builder.alloc_register();
builder.add(Insn::OpenAutoindex {
cursor,
num_columns: 2,
});
builder.add(Insn::Sequence { cursor, dest: r1 });
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_seek_end() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_key = builder.alloc_register();
let r_data = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 1,
});
for i in 1..=3 {
builder.add(Insn::Integer {
value: i * 10,
dest: r_data,
});
builder.add(Insn::MakeRecord {
start: r_data,
count: 1,
dest: r_data,
});
builder.add(Insn::NewRowid {
cursor,
dest: r_key,
prev_rowid: 0,
});
builder.add(Insn::Insert {
cursor,
data: r_data,
rowid: r_key,
});
}
builder.add(Insn::SeekEnd { cursor });
builder.add(Insn::Integer {
value: 40,
dest: r_data,
});
builder.add(Insn::MakeRecord {
start: r_data,
count: 1,
dest: r_data,
});
builder.add(Insn::NewRowid {
cursor,
dest: r_key,
prev_rowid: 0,
});
builder.add(Insn::Insert {
cursor,
data: r_data,
rowid: r_key,
});
builder.add(Insn::SCopy {
src: r_key,
dest: r_result,
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 4);
}
#[test]
fn test_count_empty() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_count = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 1,
});
builder.add(Insn::Count {
cursor,
dest: r_count,
});
builder.add(Insn::ResultRow {
start: r_count,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 0);
}
#[test]
fn test_count_with_rows() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_key = builder.alloc_register();
let r_data = builder.alloc_register();
let r_count = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 1,
});
for i in 1..=5 {
builder.add(Insn::Integer {
value: i,
dest: r_data,
});
builder.add(Insn::MakeRecord {
start: r_data,
count: 1,
dest: r_data,
});
builder.add(Insn::NewRowid {
cursor,
dest: r_key,
prev_rowid: 0,
});
builder.add(Insn::Insert {
cursor,
data: r_data,
rowid: r_key,
});
}
builder.add(Insn::Count {
cursor,
dest: r_count,
});
builder.add(Insn::ResultRow {
start: r_count,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 5);
}
#[test]
fn test_row_data() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let pseudo = builder.alloc_cursor();
let r_key = builder.alloc_register();
let r_data = builder.alloc_register();
let r_row = builder.alloc_register();
let r_result = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 1,
});
builder.add(Insn::Integer {
value: 42,
dest: r_data,
});
builder.add(Insn::MakeRecord {
start: r_data,
count: 1,
dest: r_data,
});
builder.add(Insn::NewRowid {
cursor,
dest: r_key,
prev_rowid: 0,
});
builder.add(Insn::Insert {
cursor,
data: r_data,
rowid: r_key,
});
let rewind_end = builder.add(Insn::Rewind { cursor, target: 0 });
builder.add(Insn::RowData {
cursor,
dest: r_row,
});
builder.add(Insn::OpenPseudo {
cursor: pseudo,
content: r_row,
num_columns: 1,
});
builder.add(Insn::Column {
cursor: pseudo,
column: 0,
dest: r_result,
});
builder.add(Insn::Close { cursor: pseudo });
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.jump_here(rewind_end);
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_blob_via_makerecord() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
let r2 = builder.alloc_register();
builder.add(Insn::Integer {
value: 0x01020304,
dest: r1,
});
builder.add(Insn::MakeRecord {
start: r1,
count: 1,
dest: r2,
});
builder.add(Insn::ResultRow {
start: r2,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_type(0), ffi::SQLITE_BLOB);
}
#[test]
fn test_finish_seek() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let cursor = builder.alloc_cursor();
let r_result = builder.alloc_register();
builder.add(Insn::OpenEphemeral {
cursor,
num_columns: 1,
});
builder.add(Insn::FinishSeek { cursor });
builder.add(Insn::Integer {
value: 42,
dest: r_result,
});
builder.add(Insn::ResultRow {
start: r_result,
count: 1,
});
builder.add(Insn::Close { cursor });
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
assert_eq!(program.column_int(0), 42);
}
#[test]
fn test_max_pgcnt() {
let mut conn = Connection::open_in_memory().expect("Failed to open connection");
let mut builder = conn.new_program().expect("Failed to create program");
let r1 = builder.alloc_register();
builder.add(Insn::Transaction {
db_num: 0,
write: 0,
});
builder.add(Insn::MaxPgcnt {
db_num: 0,
dest: r1,
new_max: 0,
});
builder.add(Insn::ResultRow {
start: r1,
count: 1,
});
builder.add(Insn::Halt);
let mut program = builder.finish(1).expect("Failed to finish program");
assert_eq!(program.step().unwrap(), StepResult::Row);
let max = program.column_int64(0);
assert!(
max >= 0,
"Max page count should be non-negative, got {}",
max
);
}
#[test]
fn test_subtype_instructions_exist() {
let _ = Insn::ClrSubtype { src: 1 };
let _ = Insn::GetSubtype { src: 1, dest: 2 };
let _ = Insn::SetSubtype { src: 1, dest: 2 };
assert_eq!(Insn::ClrSubtype { src: 1 }.name(), "ClrSubtype");
assert_eq!(Insn::GetSubtype { src: 1, dest: 2 }.name(), "GetSubtype");
assert_eq!(Insn::SetSubtype { src: 1, dest: 2 }.name(), "SetSubtype");
}
#[test]
fn test_subtype_raw_opcodes() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::ClrSubtype { src: 1 }.raw_opcode(),
RawOpcode::ClrSubtype as u8
);
assert_eq!(
Insn::GetSubtype { src: 1, dest: 2 }.raw_opcode(),
RawOpcode::GetSubtype as u8
);
assert_eq!(
Insn::SetSubtype { src: 1, dest: 2 }.raw_opcode(),
RawOpcode::SetSubtype as u8
);
}
#[test]
fn test_subtype_display() {
assert_eq!(format!("{}", Insn::ClrSubtype { src: 1 }), "ClrSubtype");
assert_eq!(
format!("{}", Insn::GetSubtype { src: 1, dest: 2 }),
"GetSubtype"
);
assert_eq!(
format!("{}", Insn::SetSubtype { src: 1, dest: 2 }),
"SetSubtype"
);
}
#[test]
fn test_subtype_debug() {
let clr = Insn::ClrSubtype { src: 5 };
let debug_str = format!("{:?}", clr);
assert!(debug_str.contains("ClrSubtype"));
assert!(debug_str.contains("src: 5"));
let get = Insn::GetSubtype { src: 1, dest: 2 };
let debug_str = format!("{:?}", get);
assert!(debug_str.contains("GetSubtype"));
assert!(debug_str.contains("src: 1"));
assert!(debug_str.contains("dest: 2"));
}
#[test]
fn test_subtype_clone() {
let clr = Insn::ClrSubtype { src: 5 };
let cloned = clr.clone();
assert_eq!(clr.raw_opcode(), cloned.raw_opcode());
}
#[test]
fn test_cursor_lock_instructions_exist() {
let _ = Insn::CursorLock { cursor: 0 };
let _ = Insn::CursorUnlock { cursor: 0 };
assert_eq!(Insn::CursorLock { cursor: 0 }.name(), "CursorLock");
assert_eq!(Insn::CursorUnlock { cursor: 0 }.name(), "CursorUnlock");
}
#[test]
fn test_cursor_lock_raw_opcodes() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::CursorLock { cursor: 0 }.raw_opcode(),
RawOpcode::CursorLock as u8
);
assert_eq!(
Insn::CursorUnlock { cursor: 0 }.raw_opcode(),
RawOpcode::CursorUnlock as u8
);
}
#[test]
fn test_cursor_lock_display() {
assert_eq!(format!("{}", Insn::CursorLock { cursor: 0 }), "CursorLock");
assert_eq!(
format!("{}", Insn::CursorUnlock { cursor: 0 }),
"CursorUnlock"
);
}
#[test]
fn test_expire_instruction_exists() {
let _ = Insn::Expire {
current_only: 0,
deferred: 0,
};
let _ = Insn::Expire {
current_only: 1,
deferred: 1,
};
assert_eq!(
Insn::Expire {
current_only: 0,
deferred: 0
}
.name(),
"Expire"
);
}
#[test]
fn test_expire_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::Expire {
current_only: 0,
deferred: 0
}
.raw_opcode(),
RawOpcode::Expire as u8
);
}
#[test]
fn test_expire_display() {
assert_eq!(
format!(
"{}",
Insn::Expire {
current_only: 0,
deferred: 0
}
),
"Expire"
);
}
#[test]
fn test_reset_count_instruction_exists() {
let _ = Insn::ResetCount;
assert_eq!(Insn::ResetCount.name(), "ResetCount");
}
#[test]
fn test_reset_count_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(Insn::ResetCount.raw_opcode(), RawOpcode::ResetCount as u8);
}
#[test]
fn test_reset_count_display() {
assert_eq!(format!("{}", Insn::ResetCount), "ResetCount");
}
#[test]
fn test_incr_vacuum_instruction_exists() {
let _ = Insn::IncrVacuum {
db_num: 0,
target: 5,
};
assert_eq!(
Insn::IncrVacuum {
db_num: 0,
target: 5
}
.name(),
"IncrVacuum"
);
}
#[test]
fn test_incr_vacuum_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::IncrVacuum {
db_num: 0,
target: 5
}
.raw_opcode(),
RawOpcode::IncrVacuum as u8
);
}
#[test]
fn test_incr_vacuum_display() {
assert_eq!(
format!(
"{}",
Insn::IncrVacuum {
db_num: 0,
target: 5
}
),
"IncrVacuum"
);
}
#[test]
fn test_if_size_between_instruction_exists() {
let _ = Insn::IfSizeBetween {
cursor: 0,
target: 5,
lower: 10,
upper: 100,
};
assert_eq!(
Insn::IfSizeBetween {
cursor: 0,
target: 5,
lower: 10,
upper: 100
}
.name(),
"IfSizeBetween"
);
}
#[test]
fn test_if_size_between_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::IfSizeBetween {
cursor: 0,
target: 5,
lower: 10,
upper: 100
}
.raw_opcode(),
RawOpcode::IfSizeBetween as u8
);
}
#[test]
fn test_if_size_between_display() {
assert_eq!(
format!(
"{}",
Insn::IfSizeBetween {
cursor: 0,
target: 5,
lower: 10,
upper: 100
}
),
"IfSizeBetween"
);
}
#[test]
fn test_if_empty_instruction_exists() {
let _ = Insn::IfEmpty {
cursor: 0,
target: 5,
};
assert_eq!(
Insn::IfEmpty {
cursor: 0,
target: 5
}
.name(),
"IfEmpty"
);
}
#[test]
fn test_if_empty_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::IfEmpty {
cursor: 0,
target: 5
}
.raw_opcode(),
RawOpcode::IfEmpty as u8
);
}
#[test]
fn test_if_empty_display() {
assert_eq!(
format!(
"{}",
Insn::IfEmpty {
cursor: 0,
target: 5
}
),
"IfEmpty"
);
}
#[test]
fn test_abortable_instruction_exists() {
let _ = Insn::Abortable;
assert_eq!(Insn::Abortable.name(), "Abortable");
}
#[test]
fn test_abortable_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(Insn::Abortable.raw_opcode(), RawOpcode::Abortable as u8);
}
#[test]
fn test_trace_instruction_exists() {
let _ = Insn::Trace;
assert_eq!(Insn::Trace.name(), "Trace");
}
#[test]
fn test_trace_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(Insn::Trace.raw_opcode(), RawOpcode::Trace as u8);
}
#[test]
fn test_mem_max_instruction_exists() {
let _ = Insn::MemMax { accum: 1, value: 2 };
assert_eq!(Insn::MemMax { accum: 1, value: 2 }.name(), "MemMax");
}
#[test]
fn test_mem_max_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::MemMax { accum: 1, value: 2 }.raw_opcode(),
RawOpcode::MemMax as u8
);
}
#[test]
fn test_mem_max_display() {
assert_eq!(format!("{}", Insn::MemMax { accum: 1, value: 2 }), "MemMax");
}
#[test]
fn test_offset_limit_instruction_exists() {
let _ = Insn::OffsetLimit {
limit: 1,
dest: 2,
offset: 3,
};
assert_eq!(
Insn::OffsetLimit {
limit: 1,
dest: 2,
offset: 3
}
.name(),
"OffsetLimit"
);
}
#[test]
fn test_offset_limit_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::OffsetLimit {
limit: 1,
dest: 2,
offset: 3
}
.raw_opcode(),
RawOpcode::OffsetLimit as u8
);
}
#[test]
fn test_offset_limit_display() {
assert_eq!(
format!(
"{}",
Insn::OffsetLimit {
limit: 1,
dest: 2,
offset: 3
}
),
"OffsetLimit"
);
}
#[test]
fn test_release_reg_instruction_exists() {
let _ = Insn::ReleaseReg {
start: 1,
count: 5,
mask: 0,
flags: 0,
};
assert_eq!(
Insn::ReleaseReg {
start: 1,
count: 5,
mask: 0,
flags: 0
}
.name(),
"ReleaseReg"
);
}
#[test]
fn test_release_reg_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::ReleaseReg {
start: 1,
count: 5,
mask: 0,
flags: 0
}
.raw_opcode(),
RawOpcode::ReleaseReg as u8
);
}
#[test]
fn test_release_reg_display() {
assert_eq!(
format!(
"{}",
Insn::ReleaseReg {
start: 1,
count: 5,
mask: 0,
flags: 0
}
),
"ReleaseReg"
);
}
#[test]
fn test_rowset_instructions_exist() {
let _ = Insn::RowSetAdd {
rowset: 1,
value: 2,
};
let _ = Insn::RowSetRead {
rowset: 1,
target: 5,
dest: 3,
};
let _ = Insn::RowSetTest {
rowset: 1,
target: 5,
value: 3,
set_num: 0,
};
assert_eq!(
Insn::RowSetAdd {
rowset: 1,
value: 2
}
.name(),
"RowSetAdd"
);
assert_eq!(
Insn::RowSetRead {
rowset: 1,
target: 5,
dest: 3
}
.name(),
"RowSetRead"
);
assert_eq!(
Insn::RowSetTest {
rowset: 1,
target: 5,
value: 3,
set_num: 0
}
.name(),
"RowSetTest"
);
}
#[test]
fn test_rowset_raw_opcodes() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::RowSetAdd {
rowset: 1,
value: 2
}
.raw_opcode(),
RawOpcode::RowSetAdd as u8
);
assert_eq!(
Insn::RowSetRead {
rowset: 1,
target: 5,
dest: 3
}
.raw_opcode(),
RawOpcode::RowSetRead as u8
);
assert_eq!(
Insn::RowSetTest {
rowset: 1,
target: 5,
value: 3,
set_num: 0
}
.raw_opcode(),
RawOpcode::RowSetTest as u8
);
}
#[test]
fn test_rowset_display() {
assert_eq!(
format!(
"{}",
Insn::RowSetAdd {
rowset: 1,
value: 2
}
),
"RowSetAdd"
);
assert_eq!(
format!(
"{}",
Insn::RowSetRead {
rowset: 1,
target: 5,
dest: 3
}
),
"RowSetRead"
);
assert_eq!(
format!(
"{}",
Insn::RowSetTest {
rowset: 1,
target: 5,
value: 3,
set_num: 0
}
),
"RowSetTest"
);
}
#[test]
fn test_filter_instructions_exist() {
let _ = Insn::FilterAdd {
filter: 1,
key_start: 2,
key_count: 3,
};
let _ = Insn::Filter {
filter: 1,
target: 5,
key_start: 2,
key_count: 3,
};
assert_eq!(
Insn::FilterAdd {
filter: 1,
key_start: 2,
key_count: 3
}
.name(),
"FilterAdd"
);
assert_eq!(
Insn::Filter {
filter: 1,
target: 5,
key_start: 2,
key_count: 3
}
.name(),
"Filter"
);
}
#[test]
fn test_filter_raw_opcodes() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::FilterAdd {
filter: 1,
key_start: 2,
key_count: 3
}
.raw_opcode(),
RawOpcode::FilterAdd as u8
);
assert_eq!(
Insn::Filter {
filter: 1,
target: 5,
key_start: 2,
key_count: 3
}
.raw_opcode(),
RawOpcode::Filter as u8
);
}
#[test]
fn test_filter_display() {
assert_eq!(
format!(
"{}",
Insn::FilterAdd {
filter: 1,
key_start: 2,
key_count: 3
}
),
"FilterAdd"
);
assert_eq!(
format!(
"{}",
Insn::Filter {
filter: 1,
target: 5,
key_start: 2,
key_count: 3
}
),
"Filter"
);
}
#[test]
fn test_else_eq_instruction_exists() {
let _ = Insn::ElseEq { target: 5 };
assert_eq!(Insn::ElseEq { target: 5 }.name(), "ElseEq");
}
#[test]
fn test_else_eq_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::ElseEq { target: 5 }.raw_opcode(),
RawOpcode::ElseEq as u8
);
}
#[test]
fn test_else_eq_display() {
assert_eq!(format!("{}", Insn::ElseEq { target: 5 }), "ElseEq");
}
#[test]
fn test_permutation_instruction_exists() {
let _ = Insn::Permutation;
assert_eq!(Insn::Permutation.name(), "Permutation");
}
#[test]
fn test_permutation_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(Insn::Permutation.raw_opcode(), RawOpcode::Permutation as u8);
}
#[test]
fn test_permutation_display() {
assert_eq!(format!("{}", Insn::Permutation), "Permutation");
}
#[test]
fn test_compare_instruction_exists() {
let _ = Insn::Compare {
lhs: 1,
rhs: 5,
count: 3,
flags: 0,
};
assert_eq!(
Insn::Compare {
lhs: 1,
rhs: 5,
count: 3,
flags: 0
}
.name(),
"Compare"
);
}
#[test]
fn test_compare_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::Compare {
lhs: 1,
rhs: 5,
count: 3,
flags: 0
}
.raw_opcode(),
RawOpcode::Compare as u8
);
}
#[test]
fn test_compare_display() {
assert_eq!(
format!(
"{}",
Insn::Compare {
lhs: 1,
rhs: 5,
count: 3,
flags: 0
}
),
"Compare"
);
}
#[test]
fn test_compare_with_permute_flag() {
let compare_with_permute = Insn::Compare {
lhs: 1,
rhs: 5,
count: 3,
flags: 0x01,
};
assert_eq!(compare_with_permute.name(), "Compare");
}
#[test]
fn test_collseq_instruction_exists() {
let _ = Insn::CollSeq { dest: 0 };
let _ = Insn::CollSeq { dest: 5 };
assert_eq!(Insn::CollSeq { dest: 0 }.name(), "CollSeq");
}
#[test]
fn test_collseq_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::CollSeq { dest: 0 }.raw_opcode(),
RawOpcode::CollSeq as u8
);
}
#[test]
fn test_collseq_display() {
assert_eq!(format!("{}", Insn::CollSeq { dest: 0 }), "CollSeq");
}
#[test]
fn test_reopen_idx_instruction_exists() {
let _ = Insn::ReopenIdx {
cursor: 0,
root: 2,
db_num: 0,
flags: 0,
};
assert_eq!(
Insn::ReopenIdx {
cursor: 0,
root: 2,
db_num: 0,
flags: 0
}
.name(),
"ReopenIdx"
);
}
#[test]
fn test_reopen_idx_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::ReopenIdx {
cursor: 0,
root: 2,
db_num: 0,
flags: 0
}
.raw_opcode(),
RawOpcode::ReopenIdx as u8
);
}
#[test]
fn test_reopen_idx_display() {
assert_eq!(
format!(
"{}",
Insn::ReopenIdx {
cursor: 0,
root: 2,
db_num: 0,
flags: 0
}
),
"ReopenIdx"
);
}
#[test]
fn test_reopen_idx_with_seekeq_flag() {
let reopen = Insn::ReopenIdx {
cursor: 1,
root: 5,
db_num: 0,
flags: 0x02,
};
assert_eq!(reopen.name(), "ReopenIdx");
}
#[test]
fn test_cursor_hint_instruction_exists() {
let _ = Insn::CursorHint { cursor: 0 };
assert_eq!(Insn::CursorHint { cursor: 0 }.name(), "CursorHint");
}
#[test]
fn test_cursor_hint_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::CursorHint { cursor: 0 }.raw_opcode(),
RawOpcode::CursorHint as u8
);
}
#[test]
fn test_cursor_hint_display() {
assert_eq!(format!("{}", Insn::CursorHint { cursor: 0 }), "CursorHint");
}
#[test]
fn test_table_lock_instruction_exists() {
let _ = Insn::TableLock {
db_num: 0,
root: 2,
write: 0,
};
let _ = Insn::TableLock {
db_num: 0,
root: 2,
write: 1,
};
assert_eq!(
Insn::TableLock {
db_num: 0,
root: 2,
write: 0
}
.name(),
"TableLock"
);
}
#[test]
fn test_table_lock_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::TableLock {
db_num: 0,
root: 2,
write: 0
}
.raw_opcode(),
RawOpcode::TableLock as u8
);
}
#[test]
fn test_table_lock_display() {
assert_eq!(
format!(
"{}",
Insn::TableLock {
db_num: 0,
root: 2,
write: 0
}
),
"TableLock"
);
}
#[test]
fn test_table_lock_read_vs_write() {
let read_lock = Insn::TableLock {
db_num: 0,
root: 2,
write: 0,
};
let write_lock = Insn::TableLock {
db_num: 0,
root: 2,
write: 1,
};
assert_eq!(read_lock.raw_opcode(), write_lock.raw_opcode());
}
#[test]
fn test_integrity_ck_instruction_exists() {
let _ = Insn::IntegrityCk {
msg_reg: 1,
count: 5,
err_reg: 2,
db_num: 0,
};
assert_eq!(
Insn::IntegrityCk {
msg_reg: 1,
count: 5,
err_reg: 2,
db_num: 0
}
.name(),
"IntegrityCk"
);
}
#[test]
fn test_integrity_ck_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::IntegrityCk {
msg_reg: 1,
count: 5,
err_reg: 2,
db_num: 0
}
.raw_opcode(),
RawOpcode::IntegrityCk as u8
);
}
#[test]
fn test_integrity_ck_display() {
assert_eq!(
format!(
"{}",
Insn::IntegrityCk {
msg_reg: 1,
count: 5,
err_reg: 2,
db_num: 0
}
),
"IntegrityCk"
);
}
#[test]
fn test_program_instruction_exists() {
let _ = Insn::Program {
target: 10,
runtime_reg: 5,
flags: 0,
};
assert_eq!(
Insn::Program {
target: 10,
runtime_reg: 5,
flags: 0
}
.name(),
"Program"
);
}
#[test]
fn test_program_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::Program {
target: 10,
runtime_reg: 5,
flags: 0
}
.raw_opcode(),
RawOpcode::Program as u8
);
}
#[test]
fn test_program_display() {
assert_eq!(
format!(
"{}",
Insn::Program {
target: 10,
runtime_reg: 5,
flags: 0
}
),
"Program"
);
}
#[test]
fn test_param_instruction_exists() {
let _ = Insn::Param { index: 1, dest: 5 };
assert_eq!(Insn::Param { index: 1, dest: 5 }.name(), "Param");
}
#[test]
fn test_param_raw_opcode() {
use sqlite_vdbe::RawOpcode;
assert_eq!(
Insn::Param { index: 1, dest: 5 }.raw_opcode(),
RawOpcode::Param as u8
);
}
#[test]
fn test_param_display() {
assert_eq!(format!("{}", Insn::Param { index: 1, dest: 5 }), "Param");
}
#[test]
fn test_param_debug() {
let param = Insn::Param { index: 3, dest: 7 };
let debug_str = format!("{:?}", param);
assert!(debug_str.contains("Param"));
assert!(debug_str.contains("index: 3"));
assert!(debug_str.contains("dest: 7"));
}
#[test]
fn test_param_clone() {
let param = Insn::Param { index: 3, dest: 7 };
let cloned = param.clone();
assert_eq!(param.raw_opcode(), cloned.raw_opcode());
}