Current section
Files
Jump to
Current section
Files
lib/examples/e_analysis.ex
defmodule Examples.EAnalysis do
@moduledoc """
I am examples for GtBridge.Analysis, the static analysis module.
"""
use ExExample
import ExUnit.Assertions
alias GtBridge.Analysis
def rerun?(_), do: true
############################################################
# Module Graph Examples #
############################################################
@spec module_graph() :: [Analysis.edge()]
example module_graph do
edges = Analysis.module_graph(:gt_bridge)
assert length(edges) > 0
assert Enum.all?(edges, fn {from, to} -> is_atom(from) and is_atom(to) end)
# Eval calls ObjectRegistry
assert {GtBridge.Eval, GtBridge.ObjectRegistry} in edges
edges
end
@spec callees_of_eval() :: [module()]
example callees_of_eval do
mods = Analysis.callees(GtBridge.Eval, :gt_bridge)
assert GtBridge.ObjectRegistry in mods
assert GtBridge.Eval not in mods
mods
end
@spec callers_of_serializer() :: [module()]
example callers_of_serializer do
mods = Analysis.callers(GtBridge.Serializer, :gt_bridge)
assert length(mods) > 0
mods
end
############################################################
# Supervision Tree Examples #
############################################################
@spec supervision_tree() :: map()
example supervision_tree do
pid = Process.whereis(GtBridge.Supervisor)
tree = GtBridge.Supervision.tree(pid)
assert tree.name == "GtBridge.Supervisor"
assert tree.supervisor == true
assert length(tree.children) > 0
tree
end
############################################################
# System-Wide Examples #
############################################################
@spec system_stats() :: map()
example system_stats do
stats = Analysis.system_stats()
assert stats.apps > 0
assert stats.modules > 0
assert stats.with_docs >= 0
stats
end
@spec system_doc_coverage() :: [map()]
example system_doc_coverage do
coverage = Analysis.system_doc_coverage()
assert length(coverage) > 0
assert Enum.all?(coverage, fn c -> is_binary(c.app) end)
gt = Enum.find(coverage, fn c -> c.app == "gt_bridge" end)
assert gt != nil
assert length(gt.modules) > 0
coverage
end
############################################################
# New Function Examples #
############################################################
@spec system_info() :: map()
example system_info do
info = Analysis.system_info()
assert is_binary(info.node)
assert is_binary(info.elixir)
assert info.schedulers > 0
assert info.memory_mb > 0
info
end
@spec module_details() :: [map()]
example module_details do
details = Analysis.module_details(:gt_bridge)
assert length(details) > 0
eval = Enum.find(details, fn d -> d.name == "GtBridge.Eval" end)
assert eval != nil
assert eval.has_doc == true
assert eval.functions > 0
details
end
@spec root_apps() :: [atom()]
example root_apps do
roots = GtBridge.DepGraph.root_apps()
assert length(roots) > 0
assert is_atom(hd(roots))
roots
end
@spec exported_functions() :: [map()]
example exported_functions do
fns = Analysis.exported_functions(GtBridge.Eval)
assert length(fns) > 0
assert Enum.any?(fns, fn f -> f.name == "eval" end)
fns
end
@spec exported_functions_erlang() :: [map()]
example exported_functions_erlang do
fns = Analysis.exported_functions(:erlang)
assert length(fns) > 0
assert Enum.any?(fns, fn f -> f.name == "node" end)
fns
end
@spec example_deps() :: [{String.t(), [String.t()]}]
example example_deps do
deps = Analysis.example_deps(Examples.EEval)
assert length(deps) > 0
{name, _} = hd(deps)
assert is_binary(name)
deps
end
@spec app_dep_tree() :: map()
example app_dep_tree do
tree = GtBridge.DepGraph.app_dep_tree(:gt_bridge)
assert tree.name == "gt_bridge"
assert length(tree.children) > 0
tree
end
@spec app_reverse_dep_tree() :: map()
example app_reverse_dep_tree do
tree = GtBridge.DepGraph.app_reverse_dep_tree(:gt_bridge)
assert tree.name == "gt_bridge"
tree
end
@spec mnesia_tables() :: [map()]
example mnesia_tables do
tables =
try do
GtBridge.Mnesia.tables()
rescue
_ -> []
end
assert is_list(tables)
tables
end
############################################################
# Implementors Examples #
############################################################
@spec implementors_of_start_link() :: [map()]
example implementors_of_start_link do
results = Analysis.implementors(:start_link)
assert length(results) > 0
assert Enum.all?(results, &Map.has_key?(&1, :module))
assert Enum.all?(results, &(&1.name == "start_link"))
results
end
@spec implementors_with_arity() :: [map()]
example implementors_with_arity do
results = Analysis.implementors(:start_link, 1)
assert length(results) > 0
assert Enum.all?(results, &(&1.arity == 1))
results
end
@spec implementors_required_keys() :: [map()]
example implementors_required_keys do
required = [:name, :arity, :module, :kind, :start, :end_line, :sig, :source]
results = Analysis.implementors(:new, nil)
assert length(results) > 0
for entry <- results, key <- required do
assert Map.has_key?(entry, key), "missing #{inspect(key)} in #{inspect(entry)}"
end
results
end
############################################################
# Function References Examples #
############################################################
@spec references_to_source_file() :: [map()]
example references_to_source_file do
results = Analysis.function_references(GtBridge.Resolve, :source_file, 1)
assert length(results) > 0
assert Enum.all?(results, &Map.has_key?(&1, :module))
results
end
############################################################
# Call Site Examples #
############################################################
@spec call_sites_simple() :: [map()]
example call_sites_simple do
source = ~s'''
defmodule Example do
def run do
Enum.map([1, 2], &inspect/1)
String.trim(" hello ")
end
end
'''
sites = Analysis.call_sites(source)
modules = Enum.map(sites, & &1.target_module)
assert "Enum" in modules
assert "String" in modules
assert Enum.all?(sites, &Map.has_key?(&1, :line))
sites
end
@spec modules_loaded_batch_query() :: %{String.t() => boolean()}
example modules_loaded_batch_query do
result =
Analysis.modules_loaded?(["GtBridge.Eval", "Enum", "TotallyNotAModuleXYZ"])
assert result["GtBridge.Eval"] == true
assert result["Enum"] == true
assert result["TotallyNotAModuleXYZ"] == false
result
end
@spec call_sites_with_aliases() :: [map()]
example call_sites_with_aliases do
source = ~s'''
defmodule Example do
alias GtBridge.Analysis
def run, do: Analysis.module_graph(:gt_bridge)
end
'''
sites = Analysis.call_sites(source)
assert Enum.any?(sites, &(&1.target_module == "GtBridge.Analysis"))
sites
end
end