renderdag: add tests showing how orders affect rendering

Summary:
I wrote it to understand how renderdag draws the same graph with different
orders. It seems useful for future optimization that tries to reduce the number
of columns. So let's check it in.

Reviewed By: xavierd

Differential Revision: D19440713

fbshipit-source-id: 8bc580799f6b24c87886d5ac306020f50bb694e5
This commit is contained in:
Jun Wu 2020-01-23 20:49:07 -08:00 committed by Facebook Github Bot
parent 09618791bd
commit 52af332c28
3 changed files with 198 additions and 2 deletions

View File

@ -291,7 +291,7 @@ where
mod tests {
use crate::render::GraphRowRenderer;
use crate::test_fixtures::{self, TestFixture};
use crate::test_utils::render_string;
use crate::test_utils::{render_string, render_string_with_order};
fn render(fixture: &TestFixture) -> String {
let mut renderer = GraphRowRenderer::new().output().build_box_drawing();
@ -525,4 +525,137 @@ mod tests {
long message 3"#
);
}
#[test]
fn different_orders() {
let order = |order: &str| {
let order = order.matches(|_: char| true).collect::<Vec<_>>();
let mut renderer = GraphRowRenderer::new().output().build_box_drawing();
render_string_with_order(&test_fixtures::ORDERS1, &mut renderer, Some(&order))
};
assert_eq!(
order("KJIHGFEDCBZA"),
r#"
o K
o J
o I
o H
o G
o F
o E
o D
o C
o B
o Z
o A"#
);
assert_eq!(
order("KJIHGZBCDEFA"),
r#"
o K
o J
o I
o H
o G
o Z
o B
o C
o D
o E
o F
o A"#
);
// Keeping the p1 branch the longest path (KFEDCBA) is a reasonable
// optimization for a cleaner graph (less columns, more text space).
assert_eq!(
render(&test_fixtures::ORDERS2),
r#"
o K
o J
o F
o I
o E
o H
o D
o G
o C
o Z
o B
o A"#
);
// Try to use the ORDERS2 order. However, the parent ordering in the
// graph is different, which makes the rendering different.
//
// Note: it's KJFIEHDGCZBA in the ORDERS2 graph. To map it to ORDERS1,
// follow:
//
// ORDERS1: KFJEIDHCGBZA
// ORDERS2: KJFIEHDGCBZA
//
// And we get KFJEIDHCGZBA.
assert_eq!(
order("KFJEIDHCGZBA"),
r#"
o K
o F
o J
o E
o I
o D
o H
o C
o G
o Z
o B
o A"#
);
}
}

View File

@ -127,3 +127,50 @@ pub(crate) const LONG_MESSAGES: TestFixture = TestFixture {
ancestors: &[],
missing: &["Y", "Z"],
};
pub(crate) const ORDERS1: TestFixture = TestFixture {
dag: r#"
K
/|
F J
/ /|
| E I
|/ /|
| D H
|/ /|
| C G
|/ /|
| B Z
|/
A
"#,
messages: &[],
heads: &["K"],
reserve: &[],
ancestors: &[],
missing: &[],
};
// Unlike ORDERS1, the first-parent branch (KFEDCBA) is the longest path.
pub(crate) const ORDERS2: TestFixture = TestFixture {
dag: r#"
K
/|
J F
/ /|
| I E
|/ /|
| H D
|/ /|
| G C
|/ /|
| B Z
|/
A
"#,
messages: &[],
heads: &["K"],
reserve: &[],
ancestors: &[],
missing: &[],
};

View File

@ -18,6 +18,14 @@ use crate::test_fixtures::TestFixture;
pub(crate) fn render_string(
fixture: &TestFixture,
renderer: &mut dyn Renderer<Id, Output = String>,
) -> String {
render_string_with_order(fixture, renderer, None)
}
pub(crate) fn render_string_with_order(
fixture: &TestFixture,
renderer: &mut dyn Renderer<Id, Output = String>,
order: Option<&[&str]>,
) -> String {
let TestFixture {
dag,
@ -71,8 +79,16 @@ pub(crate) fn render_string(
let parents_by_id = id_map.build_get_parents_by_id(&parents_by_name);
let messages: HashMap<_, _> = messages.iter().cloned().collect();
let iter = match order {
None => (0..=last_head).rev().collect::<Vec<_>>(),
Some(order) => order
.iter()
.map(|name| id_map.find_id_by_name(name.as_bytes()).unwrap().unwrap().0)
.collect(),
};
let mut out = String::new();
for id in (0..=last_head).rev() {
for id in iter {
let node = Id(id);
if missing.contains(&node) {
continue;