Current section

Files

Jump to
muzak lib mutation_testing_experiment.ex
Raw

lib/mutation_testing_experiment.ex

defmodule Test do
def modify(num) do
if num in [2, 5, 9, 10, 12, 31] do
num
else
num + 1
end
end
def add_to_num(num) do
if num > 10 do
num + 10
else
num + 1
end
end
end
#defmodule MutationTestingExperiment do
#def mutate() do
#{_mod, mod_binary, _filename} = :code.get_object_code(Test)
#{:ok, {_, [{:abstract_code, {:raw_abstract_v1, [file, _module | rest] = abstract}}]}} =
#:beam_lib.chunks(mod_binary, [:abstract_code])
#Agent.start(fn -> abstract end, name: TestAgent)
#renamed_forms = [file, {:attribute, 1, :module, TestSavedVersion} | rest]
#altered_forms = Enum.map(abstract, &mutate/1)
#compile_and_load(renamed_forms)
#compile_and_load(altered_forms)
#end
#def unmutate() do
#abstract = Agent.get(TestAgent, & &1)
#:code.purge(Test)
#:code.delete(Test)
#compile_and_load(abstract)
#:code.purge(Test.Saved.Version)
#:code.delete(Test.Saved.Version)
#end
#defp compile_and_load(abstract) do
#case :compile.forms(abstract, [:return_errors]) do
#{:ok, module_name, binary} -> :code.load_binary(module_name, '', binary)
#{:ok, module_name, binary, _} -> :code.load_binary(module_name, '', binary)
#_ -> :error
#end
#end
#defp mutate({:attribute, _, _, _} = form) do
#form
#end
#defp mutate({:function, 2, :pure_fun, 1, body}) do
#[{:clause, 2, [{:var, 2, :_num@1}], [], clause}] = body
#new_clause = Enum.map(clause, &mutate/1)
#{:function, 2, :pure_fun, 1, [{:clause, 2, [{:var, 2, :_num@1}], [], new_clause}]}
#end
#defp mutate({:case, 3, condition, clauses}) do
#{:op, 3, :>, {:var, 3, :_num@1}, {:integer, 0, 10}} = condition
#new_condition_1 = {:op, 3, :<, {:var, 3, :_num@1}, {:integer, 0, 10}}
#new_condition_2 = {:op, 3, :>, {:var, 3, :_num@1}, {:integer, 0, 0}}
#[clause1, clause2] = clauses
#{:clause, [generated: true, location: 3], [{:atom, 0, false}], [],
#[{:op, 6, :+, {:var, 6, :_num@1}, {:integer, 0, 1}}]} = clause1
#new_clause1_1 =
#{:clause, [generated: true, location: 3], [{:atom, 0, false}], [],
#[{:op, 6, :-, {:var, 6, :_num@1}, {:integer, 0, 1}}]}
#new_clause1_2 =
#{:clause, [generated: true, location: 3], [{:atom, 0, false}], [],
#[{:op, 6, :+, {:var, 6, :_num@1}, {:integer, 0, 0}}]}
#new_clause1_3 =
#{:clause, [generated: true, location: 3], [{:atom, 0, true}], [],
#[{:op, 6, :+, {:var, 6, :_num@1}, {:integer, 0, 1}}]}
#{:clause, [generated: true, location: 3], [{:atom, 0, true}], [],
#[{:op, 4, :+, {:var, 4, :_num@1}, {:integer, 0, 10}}]} = clause2
#new_clause2_1 =
#{:clause, [generated: true, location: 3], [{:atom, 0, true}], [],
#[{:op, 4, :-, {:var, 4, :_num@1}, {:integer, 0, 10}}]}
#new_clause2_2 =
#{:clause, [generated: true, location: 3], [{:atom, 0, true}], [],
#[{:op, 4, :+, {:var, 4, :_num@1}, {:integer, 0, 0}}]}
#new_clause2_3 =
#{:clause, [generated: true, location: 3], [{:atom, 0, false}], [],
#[{:op, 4, :+, {:var, 4, :_num@1}, {:integer, 0, 10}}]}
#case Enum.random(0..7) do
#0 -> {:case, 3, new_condition_1, [clause1, clause2]}
#1 -> {:case, 3, new_condition_2, [clause1, clause2]}
#2 -> {:case, 3, condition, [new_clause1_1, clause2]}
#3 -> {:case, 3, condition, [new_clause1_2, clause2]}
#4 -> {:case, 3, condition, [new_clause1_3, clause2]}
#5 -> {:case, 3, condition, [clause1, new_clause2_1]}
#6 -> {:case, 3, condition, [clause1, new_clause2_2]}
#_ -> {:case, 3, condition, [clause1, new_clause2_3]}
#end
#end
#defp mutate(form) do
#form
#end
#end