import unittest
import pexpect
from helper import Debugger
class VariablesTestCase(unittest.TestCase):
def setUp(self):
self.debugger = Debugger('./examples/target/debug/vars')
def test_read_scalar_variables(self):
self.debugger.cmd('break vars.rs:30', 'New breakpoint')
self.debugger.cmd('run', '30 let nop: Option<u8> = None;')
self.debugger.cmd(
'var locals',
'int8 = i8(1)',
'int16 = i16(-1)',
'int32 = i32(2)',
'int64 = i64(-2)',
'int128 = i128(3)',
'isize = isize(-3)',
'uint8 = u8(1)',
'uint16 = u16(2)',
'uint32 = u32(3)',
'uint64 = u64(4)',
'uint128 = u128(5)',
'usize = usize(6)',
'f32 = f32(1.1)',
'f64 = f64(1.2)',
'boolean_true = bool(true)',
'boolean_false = bool(false)',
'char_ascii = char(a)',
'char_non_ascii = char(😊)'.encode('utf-8'),
)
def test_read_scalar_variables_at_place(self):
self.debugger.cmd('break vars.rs:11', 'New breakpoint')
self.debugger.cmd('run', '11 let int128 = 3_i128;')
self.debugger.cmd(
'var locals',
'int8 = i8(1)',
'int16 = i16(-1)',
'int64 = i64(-2)',
)
with self.assertRaises(pexpect.exceptions.TIMEOUT):
self.debugger.expect_in_output('int128 = i128(3)', timeout=1)
def test_read_struct(self):
self.debugger.cmd('break vars.rs:53', 'New breakpoint')
self.debugger.cmd('run', '53 let nop: Option<u8> = None;')
self.debugger.cmd(
'var locals',
'tuple_0 = ()',
'tuple_1 = (f64, f64) {',
'0: f64(0)',
'1: f64(1.1)',
'}',
'tuple_2 = (u64, i64, char, bool) {',
'0: u64(1)',
'1: i64(-1)',
'2: char(a)',
'3: bool(false)',
'}',
'foo = Foo {',
'bar: i32(100)',
'baz: char(9)',
'}',
'foo2 = Foo2 {',
'foo: Foo {',
'bar: i32(100)',
'baz: char(9)',
'}',
'additional: bool(true)',
'}',
)
def test_read_array(self):
self.debugger.cmd('break vars.rs:61', 'New breakpoint')
self.debugger.cmd('run', '61 let nop: Option<u8> = None;')
self.debugger.cmd(
'var locals',
'arr_1 = [i32] {',
'0: 1',
'1: -1',
'2: 2',
'3: -2',
'4: 3',
'}',
'arr_2 = [[i32]] {',
'0: [i32] {',
'0: 1',
'1: -1',
'2: 2',
'3: -2',
'4: 3',
'}',
'1: [i32] {',
'0: 0',
'1: 1',
'2: 2',
'3: 3',
'4: 4',
'}',
'2: [i32] {',
'0: 0',
'1: -1',
'2: -2',
'3: -3',
'4: -4',
'}',
'}',
)
def test_read_enum(self):
self.debugger.cmd('break vars.rs:93', 'New breakpoint')
self.debugger.cmd('run', '93 let nop: Option<u8> = None;')
self.debugger.cmd(
'var locals',
'enum_1 = EnumA::B',
'enum_2 = EnumC::C {',
'0: char(b)',
'}',
'enum_3 = EnumC::D {',
'0: f64(1.1)',
'1: f32(1.2)',
'}',
'enum_4 = EnumC::E {',
'}',
'enum_5 = EnumF::F {',
'0: EnumC::C {',
'0: char(f)',
'}',
'}',
'enum_6 = EnumF::G {',
'0: Foo {',
'a: i32(1)',
'b: char(1)',
'}',
'}',
'enum_7 = EnumF::J {',
'0: EnumA::A',
'}',
)
def test_read_pointers(self):
self.debugger.cmd('break vars.rs:119', 'New breakpoint')
self.debugger.cmd('run', '119 let nop: Option<u8> = None;')
self.debugger.cmd_re(
'var locals',
r'a = i32\(2\)',
r'ref_a = &i32 \[0x[0-9A-F]{14}\]',
r'ptr_a = \*const i32 \[0x[0-9A-F]{14}\]',
r'ptr_ptr_a = \*const \*const i32 \[0x[0-9A-F]{14}\]',
r'b = i32\(2\)',
r'mut_ref_b = &mut i32 \[0x[0-9A-F]{14}\]',
r'c = i32\(2\)',
r'mut_ptr_c = \*mut i32 \[0x[0-9A-F]{14}\]',
r'box_d = alloc::boxed::Box<i32, alloc::alloc::Global> \[0x[0-9A-F]{14}\]',
r'f = Foo {',
r'bar: i32\(1\)',
r'baz: \[i32\] {',
r'0: 1',
r'1: 2',
r'}',
r'foo: &i32 \[0x[0-9A-F]{14}\]',
r'}',
r'ref_f = &vars::references::Foo \[0x[0-9A-F]{14}\]'
)
def test_deref_pointers(self):
self.debugger.cmd('break vars.rs:119', 'New breakpoint')
self.debugger.cmd('run', '119 let nop: Option<u8> = None;')
self.debugger.cmd('var *ref_a', 'i32(2)')
self.debugger.cmd('var *ptr_a', 'i32(2)')
self.debugger.cmd_re('var *ptr_ptr_a', r'\*const i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var **ptr_ptr_a', 'i32(2)')
self.debugger.cmd('var *mut_ref_b', 'i32(2)')
self.debugger.cmd('var *mut_ptr_c', 'i32(2)')
self.debugger.cmd('var *box_d', 'i32(2)')
self.debugger.cmd_re(
'var *ref_f',
r'Foo {',
r'baz: \[i32\] {',
r'0: 1',
r'1: 2',
r'}',
r'foo: &i32 \[0x[0-9A-F]{14}\]',
r'}',
)
def test_read_type_alias(self):
self.debugger.cmd('break vars.rs:126', 'New breakpoint')
self.debugger.cmd('run', '126 let nop: Option<u8> = None;')
self.debugger.cmd('var locals', 'a_alias = i32(1)')
def test_read_vec_and_slice(self):
self.debugger.cmd('break vars.rs:151', 'New breakpoint')
self.debugger.cmd('run', '151 let nop: Option<u8> = None;')
self.debugger.cmd_re(
'var locals',
r'vec1 = Vec<i32, alloc::alloc::Global> {',
r'buf: \[i32\] {',
r'0: 1',
r'1: 2',
r'2: 3',
r'}',
r'cap: usize\(3\)',
r'}',
r'vec2 = Vec<vars::vec_and_slice_types::Foo, alloc::alloc::Global> {',
r'buf: \[Foo\] {',
r'0: {',
r'foo: i32\(1\)',
r'}',
r'1: {',
r'foo: i32\(2\)',
r'}',
r'}',
r'cap: usize\(2\)',
r'}',
r'vec3 = Vec<alloc::vec::Vec<i32, alloc::alloc::Global>, alloc::alloc::Global> {',
r'buf: \[Vec<i32, alloc::alloc::Global>\] {',
r'0: {',
r'buf: \[i32\] {',
r'0: 1',
r'1: 2',
r'2: 3',
r'}',
r'cap: usize\(3\)',
r'}',
r'1: {',
r'buf: \[i32\] {',
r'0: 1',
r'1: 2',
r'2: 3',
r'}',
r'cap: usize\(3\)',
r'}',
r'}',
r'cap: usize\(2\)',
r'}',
r'slice1 = &\[i32; 3\] \[0x[0-9A-F]{14}\]',
r'slice2 = &\[&\[i32; 3\]; 2\] \[0x[0-9A-F]{14}\]',
)
self.debugger.cmd(
'var *slice1',
'[i32]',
'0: 1',
'1: 2',
'2: 3',
'}',
)
self.debugger.cmd_re(
'var *slice2',
r'\[&\[i32; 3\]\] {',
r'0: 0x[0-9A-F]{14}',
r'1: 0x[0-9A-F]{14}',
'}',
)
self.debugger.cmd(
'var *(*slice2)[0]',
'[i32] {',
'0: 1',
'1: 2',
'2: 3',
'}',
)
self.debugger.cmd(
'var *(*slice2)[1]',
'[i32] {',
'0: 1',
'1: 2',
'2: 3',
'}',
)
def test_read_strings(self):
self.debugger.cmd('break vars.rs:159', 'New breakpoint')
self.debugger.cmd('run', '159 let nop: Option<u8> = None;')
self.debugger.cmd(
'var locals',
's1 = String(hello world)',
's2 = &str(hello world)',
's3 = &str(hello world)',
)
def test_read_static_variables(self):
self.debugger.cmd('break vars.rs:168', 'New breakpoint')
self.debugger.cmd('run', '168 let nop: Option<u8> = None;')
self.debugger.cmd('var GLOB_1', 'vars::GLOB_1 = &str(glob_1)')
self.debugger.cmd('var GLOB_2', 'vars::GLOB_2 = i32(2)')
def test_read_static_variables_different_modules(self):
self.debugger.cmd('break vars.rs:179', 'New breakpoint')
self.debugger.cmd('run', '179 let nop: Option<u8> = None;')
self.debugger.cmd_re(
'var GLOB_3',
r'vars::(ns_1::)?GLOB_3',
r'vars::(ns_1::)?GLOB_3',
)
def test_read_tls_variables(self):
self.debugger.cmd('break vars.rs:194', 'New breakpoint')
self.debugger.cmd('run', '194 let nop: Option<u8> = None;')
self.debugger.cmd('var THREAD_LOCAL_VAR_1', '= Cell<i32>(2)')
self.debugger.cmd('var THREAD_LOCAL_VAR_2', '= Cell<&str>(2)')
self.debugger.cmd('break vars.rs:199', 'New breakpoint')
self.debugger.cmd('continue', '199 let nop: Option<u8> = None;')
self.debugger.cmd('var THREAD_LOCAL_VAR_1')
self.debugger.cmd('break vars.rs:203', 'New breakpoint')
self.debugger.cmd('continue', '203 let nop: Option<u8> = None;')
self.debugger.cmd('var THREAD_LOCAL_VAR_1', ' = Cell<i32>(1)')
def test_custom_select(self):
self.debugger.cmd('break vars.rs:61', 'New breakpoint')
self.debugger.cmd('run', '61 let nop: Option<u8> = None;')
self.debugger.cmd('var arr_2[0][2]', 'i32(2)')
self.debugger.cmd(
'var arr_1[2..4]',
'[i32] {',
'2: 2',
'3: -2',
'}',
)
self.debugger.cmd(
'var arr_1[..]',
'[i32] {',
'0: 1',
'1: -1',
'2: 2',
'3: -2',
'4: 3',
'}',
)
self.debugger.cmd(
'var arr_1[..2]',
'[i32] {',
'0: 1',
'1: -1',
'}',
)
self.debugger.cmd(
'var arr_1[3..]',
'[i32] {',
'3: -2',
'4: 3',
'}',
)
self.debugger.cmd(
'var arr_1[4..6]',
'[i32] {',
'4: 3',
'}',
)
self.debugger.cmd(
'var arr_1[2..4][1..]',
'[i32] {',
'3: -2',
'}',
)
self.debugger.cmd('break vars.rs:93', 'New breakpoint')
self.debugger.cmd('continue', '93 let nop: Option<u8> = None;')
self.debugger.cmd('var enum_6.__0.a', 'i32(1)')
self.debugger.cmd('break vars.rs:119', 'New breakpoint')
self.debugger.cmd('continue', '119 let nop: Option<u8> = None;')
self.debugger.cmd('var *((*ref_f).foo)', 'i32(2)')
self.debugger.cmd('break vars.rs:290', 'New breakpoint')
self.debugger.cmd('continue', '290 let nop: Option<u8> = None;')
self.debugger.cmd(
'var hm2.abc',
'Vec<i32, alloc::alloc::Global> {',
'buf: [i32] {',
'0: 1',
'1: 2',
'2: 3',
'}',
'cap: usize(3)',
'}',
)
self.debugger.cmd('var hm1[false]', 'i64(5)')
self.debugger.cmd('var hm2["abc"]', 'Vec<i32, alloc::alloc::Global> {')
self.debugger.cmd('var hm3[55]', 'i32(55)')
self.debugger.cmd('var hm4["1"][1]', 'i32(1)')
self.debugger.cmd('var a')
addr = self.debugger.search_in_output(r'a = &i32 \[(.*)\]')
self.debugger.cmd(f'var hm5[{addr}]', '&str(a)')
self.debugger.cmd('break vars.rs:307', 'New breakpoint')
self.debugger.cmd('continue', '307 let nop: Option<u8> = None;')
self.debugger.cmd('var hs1[1]', 'bool(true)')
self.debugger.cmd('var hs2[22]', 'bool(true)')
self.debugger.cmd('var hs2[222]', 'bool(false)')
self.debugger.cmd('var b')
addr = self.debugger.search_in_output(r'b = &i32 \[(.*)\]')
self.debugger.cmd(f'var hs4[{addr}]', 'bool(true)')
self.debugger.cmd('var hs4[0x000]', 'bool(false)')
self.debugger.cmd('break vars.rs:460', 'New breakpoint')
self.debugger.cmd('continue', '460 let nop: Option<u8> = None;')
self.debugger.cmd(
'var ptr[..4]',
'[i32] {',
'0: 1',
'1: 2',
'2: 3',
'3: 4',
'}',
)
def test_zst_types(self):
self.debugger.cmd('break vars.rs:496', 'New breakpoint')
self.debugger.cmd('run', '496 let nop: Option<u8> = None;')
self.debugger.cmd(
'var locals',
'ptr_zst = &()',
'array_zst = [()] {',
'0: ()',
'1: ()',
'}',
'vec_zst = Vec<(), alloc::alloc::Global> {',
'buf: [()] {',
'0: ()',
'1: ()',
'2: ()',
'}',
'cap: usize(0)',
'}',
'slice_zst = &[(); 4]',
'struct_zst = StructZst {',
'0: ()(())',
'}',
'enum_zst = Option<()>::Some {',
'0: ()(())',
'}',
'vecdeque_zst = VecDeque<(), alloc::alloc::Global> {',
'buf: [()] {',
'0: ()',
'1: ()',
'2: ()',
'3: ()',
'4: ()',
'}',
'cap: usize(0)',
'}',
'hash_map_zst_key = HashMap',
'()(()): i32(1)',
'}',
'hash_map_zst_val = HashMap',
'i32(1): ()(())',
'}',
'hash_map_zst = HashMap',
'()(()): ()(())',
'}',
'hash_set_zst = HashSet',
'()',
'}',
'btree_map_zst_key = BTreeMap<(), i32, alloc::alloc::Global> {',
'()(()): i32(1)',
'}',
'btree_map_zst_val = BTreeMap<i32, (), alloc::alloc::Global> {',
'i32(1): ()(())',
'2: ()',
'}',
'btree_map_zst = BTreeMap<(), (), alloc::alloc::Global> {',
'()(()): ()(())',
'}',
'btree_set_zst = BTreeSet<(), alloc::alloc::Global> {',
'()',
'}',
)
def test_read_arguments(self):
self.debugger.cmd('break vars.rs:232', 'New breakpoint')
self.debugger.cmd('run', 'let nop: Option<u8> = None;')
self.debugger.cmd('arg by_val', 'by_val = i32(1)')
self.debugger.cmd_re('arg by_ref', r'by_ref = &i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('arg vec', 'vec = Vec<u8, alloc::alloc::Global> {')
self.debugger.cmd('arg box_arr', 'box_arr = alloc::boxed::Box<[u8], alloc::alloc::Global> {')
self.debugger.cmd(
'arg all',
'by_val = i32(1)',
'by_ref = &i32',
'vec = Vec<u8, alloc::alloc::Global> {',
'box_arr = alloc::boxed::Box<[u8], alloc::alloc::Global> {',
)
def test_ptr_cast(self):
self.debugger.cmd('break vars.rs:119', 'New breakpoint')
self.debugger.cmd('run', 'let nop: Option<u8> = None;')
self.debugger.cmd('var ref_a')
addr = self.debugger.search_in_output(r'ref_a = &i32 \[0x(.*)\]')
addr = "0x" + addr[:14]
self.debugger.cmd(f'var *(*const i32){addr}', 'i32(2)')
def test_address(self):
self.debugger.cmd('break vars.rs:30', 'New breakpoint')
self.debugger.cmd('run', 'let nop: Option<u8> = None;')
self.debugger.cmd_re('var &int8', r'&i8 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var *&int8', 'i8(1)')
self.debugger.cmd('break vars.rs:53', 'New breakpoint')
self.debugger.cmd('continue', 'let nop: Option<u8> = None;')
self.debugger.cmd_re('var &tuple_1', r'&\(f64, f64\) \[0x[0-9A-F]{14}\]')
self.debugger.cmd(
'var *&tuple_1',
'(f64, f64) {',
'__0: f64(0)',
'__1: f64(1.1)',
'}',
)
self.debugger.cmd_re('var &tuple_1.__0', r'&f64 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var *&tuple_1.__0', 'f64(0)')
self.debugger.cmd_re('var &foo2.foo.bar', r'&i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var *&foo2.foo.bar', 'i32(100)')
self.debugger.cmd('break vars.rs:61', 'New breakpoint')
self.debugger.cmd('continue', 'let nop: Option<u8> = None;')
self.debugger.cmd_re('var &arr_1', r'&\[i32\] \[0x[0-9A-F]{14}\]')
self.debugger.cmd(
'var *&arr_1',
'[i32] {',
'0: 1',
'1: -1',
)
self.debugger.cmd_re('var &arr_1[3]', r'&i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var *&arr_1[3]', 'i32(-2)')
self.debugger.cmd('break vars.rs:119', 'New breakpoint')
self.debugger.cmd('continue', 'let nop: Option<u8> = None;')
self.debugger.cmd_re('var &ref_a', r'&&i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd_re('var *&ref_a', r'&i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var **&ref_a', 'i32(2)')
self.debugger.cmd('break vars.rs:168', 'New breakpoint')
self.debugger.cmd('continue', 'let nop: Option<u8> = None;')
self.debugger.cmd_re('var &GLOB_1', r'&&str \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var *&GLOB_1', '&str(glob_1)')
self.debugger.cmd('break vars.rs:290', 'New breakpoint')
self.debugger.cmd('continue', 'let nop: Option<u8> = None;')
self.debugger.cmd_re('var &hm6[{field_1: 1, field_2: *, field_3: *}]', r'&i32 \[0x[0-9A-F]{14}\]')
self.debugger.cmd('var *&hm6[{field_1: 1, field_2: *, field_3: *}]', 'i32(1)')
def test_read_time(self):
self.debugger.cmd('break vars.rs:529', 'New breakpoint')
self.debugger.cmd('run', 'let nop: Option<u8> = None;')
self.debugger.cmd('var system_time', 'system_time = SystemTime(1970-01-01 00:00:00)')
self.debugger.cmd_re('var instant', r'instant = Instant\(\d+ seconds from now\)')