Skip to main content

Command Palette

Search for a command to run...

callGraph测试模块

Published
•1 min read•View as Markdown
  1. 初始化一个新的 CallGraph 实例。

  2. 填充预定义的函数到 call_graph.defined_fns。

  3. 创建一个模拟调用关系的 calls 向量。

  4. 创建一个表示每个函数的调用者的 callers 哈希映射。

  5. 遍历 calls 向量,并使用 add_call 方法将它们添加到 call_graph。

  6. 创建预期的闭包(transitive closure)哈希映射 closure。

  7. 调用 call_graph.compute_closure() 计算闭包。

  8. 使用断言检查 call_graph 的闭包与预期闭包是否匹配,以及 call_graph 的调用者与预期调用者是否匹配。

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn call_graph_test() {
        let mut call_graph = CallGraph::new();
        call_graph.defined_fns.extend(
            vec!["::e", "::f", "::g"]
                .into_iter()
                .map(|f| (Name::from(f), Name::from(f))),
        );

        let calls = vec![
            ("::f", "::g"),
            ("::g", "::h"),
            ("::i", "::h"),
            ("::g", "::j"),
            ("::e", "::j"),
            ("::j", "::e"),
            ("::g", "::g"),
        ]
        .into_iter()
        .map(|(f, g)| (Name::from(f), Name::from(g)))
        .collect::<Vec<(Name, Name)>>();

        let callers = vec![
            ("::e", vec!["::j"]),
            ("::f", vec![]),
            ("::g", vec!["::f", "::g"]),
            ("::i", vec![]),
            ("::h", vec!["::g", "::i"]),
            ("::j", vec!["::e", "::g"]),
        ]
        .into_iter()
        .map(|(f, gs)| {
            (
                Name::from(f),
                gs.into_iter().map(|g| Name::from(g)).collect(),
            )
        })
        .collect::<HashMap<Name, HashSet<Name>>>();

        for (f, g) in calls.into_iter() {
            call_graph.add_call(f, g, false);
        }

        let closure: HashMap<Name, HashSet<Name>> = vec![
            ("::f", vec!["::g", "::h", "::j", "::e"]),
            ("::g", vec!["::g", "::h", "::j", "::e"]),
            ("::h", vec![]),
            ("::i", vec!["::h"]),
            ("::e", vec!["::j", "::e"]),
            ("::j", vec!["::j", "::e"]),
        ]
        .into_iter()
        .map(|(f, gs)| {
            (
                Name::from(f),
                gs.into_iter()
                    .map(|g| Name::from(g))
                    .collect::<HashSet<Name>>(),
            )
        })
        .collect();

        call_graph.compute_closure();

        assert_eq!(call_graph.closure().unwrap(), &closure);
        assert_eq!(call_graph.callers(), &callers);
    }
}

More from this blog

c_void到u8 - laertes-2023

为什么把c_void重命名为u8? 类型大小: u8通常代表一个单字节(8位)的无符号整数。c_void作为一个“空”类型,通常也被当作一个单字节进行处理(尽管这取决于具体的实现)。因此,这两者在大小上是匹配的。 类型转换简便: u8是一个非常基础的类型,与之进行类型转换通常比较方便。 操作简单: u8类型上可用的操作相对简单,可能更容易进行后续的代码分析或转换。 为什么不把其他东西重命名为u8? 类型语义: 其他类型可能具有其自己的语义和操作,这些可能不适用或不等价于u8。 数据...

Sep 5, 20231 min read

Retriever's blog

48 posts