Skip to content

Commit d0df00d

Browse files
committed
Rework view memory layout tests to use expect_test and to_strings.
1 parent add9056 commit d0df00d

File tree

1 file changed

+133
-97
lines changed

1 file changed

+133
-97
lines changed

crates/ide/src/view_memory_layout.rs

+133-97
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt;
2+
13
use hir::{Field, HirDisplay, Layout, Semantics, Type};
24
use ide_db::{
35
defs::Definition,
@@ -23,6 +25,36 @@ pub struct RecursiveMemoryLayout {
2325
pub nodes: Vec<MemoryLayoutNode>,
2426
}
2527

28+
// NOTE: this is currently strictly for testing and so isn't super useful as a visualization tool, however it could be adapted to become one?
29+
impl fmt::Display for RecursiveMemoryLayout {
30+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
31+
fn process(
32+
fmt: &mut fmt::Formatter<'_>,
33+
nodes: &Vec<MemoryLayoutNode>,
34+
idx: usize,
35+
depth: usize,
36+
) -> fmt::Result {
37+
let mut out = "\t".repeat(depth);
38+
let node = &nodes[idx];
39+
out += &format!(
40+
"{}: {} (size: {}, align: {}, field offset: {})\n",
41+
node.item_name, node.typename, node.size, node.alignment, node.offset
42+
);
43+
write!(fmt, "{}", out)?;
44+
if node.children_start != -1 {
45+
for j in nodes[idx].children_start
46+
..(nodes[idx].children_start + nodes[idx].children_len as i64)
47+
{
48+
process(fmt, nodes, j as usize, depth + 1)?;
49+
}
50+
}
51+
Ok(())
52+
}
53+
54+
process(fmt, &self.nodes, 0, 0)
55+
}
56+
}
57+
2658
enum FieldOrTupleIdx {
2759
Field(Field),
2860
TupleIdx(usize),
@@ -191,22 +223,14 @@ mod tests {
191223
use super::*;
192224

193225
use crate::fixture;
226+
use expect_test::expect;
194227

195228
fn make_memory_layout(ra_fixture: &str) -> Option<RecursiveMemoryLayout> {
196229
let (analysis, position, _) = fixture::annotations(ra_fixture);
197230

198231
view_memory_layout(&analysis.db, position)
199232
}
200233

201-
fn check_item_info<T>(node: &MemoryLayoutNode, item_name: &str, check_typename: bool) {
202-
assert_eq!(node.item_name, item_name);
203-
assert_eq!(node.size, core::mem::size_of::<T>() as u64);
204-
assert_eq!(node.alignment, core::mem::align_of::<T>() as u64);
205-
if check_typename {
206-
assert_eq!(node.typename, std::any::type_name::<T>());
207-
}
208-
}
209-
210234
#[test]
211235
fn view_memory_layout_none() {
212236
assert!(make_memory_layout(r#"$0"#).is_none());
@@ -215,123 +239,143 @@ mod tests {
215239

216240
#[test]
217241
fn view_memory_layout_primitive() {
218-
let ml = make_memory_layout(
219-
r#"
242+
expect![[r#"
243+
foo: i32 (size: 4, align: 4, field offset: 0)
244+
"#]]
245+
.assert_eq(
246+
&make_memory_layout(
247+
r#"
220248
fn main() {
221249
let foo$0 = 109; // default i32
222250
}
223251
"#,
224-
)
225-
.unwrap();
226-
227-
assert_eq!(ml.nodes.len(), 1);
228-
assert_eq!(ml.nodes[0].parent_idx, -1);
229-
assert_eq!(ml.nodes[0].children_start, -1);
230-
check_item_info::<i32>(&ml.nodes[0], "foo", true);
231-
assert_eq!(ml.nodes[0].offset, 0);
252+
)
253+
.unwrap()
254+
.to_string(),
255+
);
232256
}
233257

234258
#[test]
235259
fn view_memory_layout_constant() {
236-
let ml = make_memory_layout(
237-
r#"
260+
expect![[r#"
261+
BLAH: bool (size: 1, align: 1, field offset: 0)
262+
"#]]
263+
.assert_eq(
264+
&make_memory_layout(
265+
r#"
238266
const BLAH$0: bool = 0;
239267
"#,
240-
)
241-
.unwrap();
242-
243-
assert_eq!(ml.nodes.len(), 1);
244-
assert_eq!(ml.nodes[0].parent_idx, -1);
245-
assert_eq!(ml.nodes[0].children_start, -1);
246-
check_item_info::<bool>(&ml.nodes[0], "BLAH", true);
247-
assert_eq!(ml.nodes[0].offset, 0);
268+
)
269+
.unwrap()
270+
.to_string(),
271+
);
248272
}
249273

250274
#[test]
251275
fn view_memory_layout_static() {
252-
let ml = make_memory_layout(
253-
r#"
276+
expect![[r#"
277+
BLAH: bool (size: 1, align: 1, field offset: 0)
278+
"#]]
279+
.assert_eq(
280+
&make_memory_layout(
281+
r#"
254282
static BLAH$0: bool = 0;
255283
"#,
256-
)
257-
.unwrap();
258-
259-
assert_eq!(ml.nodes.len(), 1);
260-
assert_eq!(ml.nodes[0].parent_idx, -1);
261-
assert_eq!(ml.nodes[0].children_start, -1);
262-
check_item_info::<bool>(&ml.nodes[0], "BLAH", true);
263-
assert_eq!(ml.nodes[0].offset, 0);
284+
)
285+
.unwrap()
286+
.to_string(),
287+
);
264288
}
265289

266290
#[test]
267291
fn view_memory_layout_tuple() {
268-
let ml = make_memory_layout(
269-
r#"
292+
expect![[r#"
293+
x: (f64, u8, i64) (size: 24, align: 8, field offset: 0)
294+
.0: f64 (size: 8, align: 8, field offset: 0)
295+
.1: u8 (size: 1, align: 1, field offset: 8)
296+
.2: i64 (size: 8, align: 8, field offset: 16)
297+
"#]]
298+
.assert_eq(
299+
&make_memory_layout(
300+
r#"
270301
fn main() {
271302
let x$0 = (101.0, 111u8, 119i64);
272303
}
273-
"#,
274-
)
275-
.unwrap();
276-
277-
assert_eq!(ml.nodes.len(), 4);
278-
assert_eq!(ml.nodes[0].children_start, 1);
279-
assert_eq!(ml.nodes[0].children_len, 3);
280-
check_item_info::<(f64, u8, i64)>(&ml.nodes[0], "x", true);
304+
"#,
305+
)
306+
.unwrap()
307+
.to_string(),
308+
);
281309
}
282310

283311
#[test]
284-
fn view_memory_layout_struct() {
285-
let ml = make_memory_layout(
286-
r#"
312+
fn view_memory_layout_c_struct() {
313+
expect![[r#"
314+
[ROOT]: Blah (size: 16, align: 4, field offset: 0)
315+
a: u32 (size: 4, align: 4, field offset: 0)
316+
b: (i32, u8) (size: 8, align: 4, field offset: 4)
317+
.0: i32 (size: 4, align: 4, field offset: 0)
318+
.1: u8 (size: 1, align: 1, field offset: 4)
319+
c: i8 (size: 1, align: 1, field offset: 12)
320+
"#]]
321+
.assert_eq(
322+
&make_memory_layout(
323+
r#"
287324
#[repr(C)]
288325
struct Blah$0 {
289326
a: u32,
290327
b: (i32, u8),
291328
c: i8,
292329
}
293330
"#,
294-
)
295-
.unwrap();
296-
297-
#[repr(C)] // repr C makes this testable, rustc doesn't enforce a layout otherwise ;-;
298-
struct Blah {
299-
a: u32,
300-
b: (i32, u8),
301-
c: i8,
302-
}
303-
304-
assert_eq!(ml.nodes.len(), 6);
305-
check_item_info::<Blah>(&ml.nodes[0], "[ROOT]", false);
306-
assert_eq!(ml.nodes[0].offset, 0);
307-
308-
check_item_info::<u32>(&ml.nodes[1], "a", true);
309-
assert_eq!(ml.nodes[1].offset, 0);
310-
311-
check_item_info::<(i32, u8)>(&ml.nodes[2], "b", true);
312-
assert_eq!(ml.nodes[2].offset, 4);
331+
)
332+
.unwrap()
333+
.to_string(),
334+
);
335+
}
313336

314-
check_item_info::<i8>(&ml.nodes[3], "c", true);
315-
assert_eq!(ml.nodes[3].offset, 12);
337+
#[test]
338+
fn view_memory_layout_struct() {
339+
expect![[r#"
340+
[ROOT]: Blah (size: 16, align: 4, field offset: 0)
341+
b: (i32, u8) (size: 8, align: 4, field offset: 0)
342+
.0: i32 (size: 4, align: 4, field offset: 0)
343+
.1: u8 (size: 1, align: 1, field offset: 4)
344+
a: u32 (size: 4, align: 4, field offset: 8)
345+
c: i8 (size: 1, align: 1, field offset: 12)
346+
"#]]
347+
.assert_eq(
348+
&make_memory_layout(
349+
r#"
350+
struct Blah$0 {
351+
a: u32,
352+
b: (i32, u8),
353+
c: i8,
354+
}
355+
"#,
356+
)
357+
.unwrap()
358+
.to_string(),
359+
);
316360
}
317361

318362
#[test]
319363
fn view_memory_layout_member() {
320-
let ml = make_memory_layout(
321-
r#"
364+
expect![[r#"
365+
a: bool (size: 1, align: 1, field offset: 0)
366+
"#]]
367+
.assert_eq(
368+
&make_memory_layout(
369+
r#"
370+
#[repr(C)]
322371
struct Oof {
323-
a$0: bool
372+
a$0: bool,
324373
}
325374
"#,
326-
)
327-
.unwrap();
328-
329-
assert_eq!(ml.nodes.len(), 1);
330-
assert_eq!(ml.nodes[0].parent_idx, -1);
331-
assert_eq!(ml.nodes[0].children_start, -1);
332-
check_item_info::<bool>(&ml.nodes[0], "a", true);
333-
// NOTE: this should not give the memory layout relative to the parent structure, but the type referred to by the member variable alone.
334-
assert_eq!(ml.nodes[0].offset, 0);
375+
)
376+
.unwrap()
377+
.to_string(),
378+
);
335379
}
336380

337381
#[test]
@@ -345,29 +389,21 @@ struct X {
345389
}
346390
347391
type Foo$0 = X;
348-
"#,
392+
"#,
349393
)
350394
.unwrap();
395+
351396
let ml_b = make_memory_layout(
352397
r#"
353398
struct X$0 {
354399
a: u32,
355400
b: i8,
356401
c: (f32, f32),
357402
}
358-
"#,
403+
"#,
359404
)
360405
.unwrap();
361406

362-
ml_a.nodes.iter().zip(ml_b.nodes.iter()).for_each(|(a, b)| {
363-
assert_eq!(a.item_name, b.item_name);
364-
assert_eq!(a.typename, b.typename);
365-
assert_eq!(a.size, b.size);
366-
assert_eq!(a.alignment, b.alignment);
367-
assert_eq!(a.offset, b.offset);
368-
assert_eq!(a.parent_idx, b.parent_idx);
369-
assert_eq!(a.children_start, b.children_start);
370-
assert_eq!(a.children_len, b.children_len);
371-
})
407+
assert_eq!(ml_a.to_string(), ml_b.to_string());
372408
}
373409
}

0 commit comments

Comments
 (0)