@@ -334,8 +334,9 @@ impl<'a> VirtualMachine<'a> {
334334
335335#[ cfg( test) ]
336336mod tests {
337- use super :: { compile_expression, execute_program, Instruction } ;
338- use crate :: { create_context, parse_expression, Value } ;
337+ use super :: { compile_expression, execute_program, Instruction , Program , VirtualMachine } ;
338+ use crate :: { create_context, error:: Error , parse_expression, Value } ;
339+ use std:: sync:: Arc ;
339340 fn run_ast ( expr : & str ) -> crate :: Result < Value > {
340341 let ast = parse_expression ( expr) ?;
341342 let mut ctx = create_context ! (
@@ -355,6 +356,55 @@ mod tests {
355356 execute_program ( & program, & mut ctx)
356357 }
357358
359+ #[ test]
360+ fn test_vm_stack_reserves_when_full ( ) {
361+ let program = Program {
362+ instructions : Vec :: new ( ) ,
363+ constants : vec ! [ Value :: Bool ( true ) ] ,
364+ } ;
365+ let mut vm = VirtualMachine :: new ( & program) ;
366+ let initial_capacity = vm. stack . capacity ( ) ;
367+
368+ for _ in 0 ..( initial_capacity + 5 ) {
369+ vm. push ( Value :: Bool ( true ) ) ;
370+ }
371+
372+ assert ! ( vm. stack. capacity( ) > initial_capacity) ;
373+ assert_eq ! ( vm. stack_top, initial_capacity + 5 ) ;
374+ }
375+
376+ #[ test]
377+ fn test_program_validate_rejects_oob_jump ( ) {
378+ let program = Program {
379+ instructions : vec ! [ Instruction :: Jump ( 5 ) ] ,
380+ constants : vec ! [ ] ,
381+ } ;
382+
383+ assert ! ( matches!( program. validate( ) , Err ( Error :: UnexpectedToken ( ) ) ) ) ;
384+ }
385+
386+ #[ test]
387+ fn test_jump_if_false_with_non_bool_errors ( ) {
388+ let program = Program {
389+ instructions : vec ! [ Instruction :: PushConst ( 0 ) , Instruction :: JumpIfFalse ( 2 ) ] ,
390+ constants : vec ! [ Value :: from( "not_bool" ) ] ,
391+ } ;
392+
393+ let err = execute_program ( & program, & mut create_context ! ( ) ) . unwrap_err ( ) ;
394+ assert ! ( matches!( err, Error :: ShouldBeBool ( ) ) ) ;
395+ }
396+
397+ #[ test]
398+ fn test_pop_without_value_errors ( ) {
399+ let program = Program {
400+ instructions : vec ! [ Instruction :: Pop ] ,
401+ constants : vec ! [ ] ,
402+ } ;
403+
404+ let err = execute_program ( & program, & mut create_context ! ( ) ) . unwrap_err ( ) ;
405+ assert ! ( matches!( err, Error :: UnexpectedToken ( ) ) ) ;
406+ }
407+
358408 #[ test]
359409 fn test_compile_ternary_has_jumps ( ) {
360410 let ast = parse_expression ( "true ? 1 : 2" ) . unwrap ( ) ;
0 commit comments