%%% This is an excerpt from a test module that exhibits 
%%% the same dialyzer behavior as the original.
-module(dialyzer_test).

-export([test/1]).

%% Simulates all test functions in the original module. These are 
%% all invocations of create_files/2 in the original code. For better 
%% context, each test function in the original module looks like:
%%
%% test_up_to_date({Path, Options}) ->
%%     Results = create_files(Path, {erl, "f", up_to_date}),
%%     ?assert({up_to_date, Results}, xmake:all(Options)),
%%     ok
test(Path) ->
    create_files(Path, {erl, "f", up_to_date}),
    create_files(Path, {erl, "f", rebuilt_no_exist}),
    create_files(Path, {erl, "f", rebuilt_mod_time}),
    create_files(Path, {yrl, "f", rebuilt_mod_time}),
    create_files(Path, {erl, "f", error}),
    create_files(filename:join(Path, "b1"), {erl, "b1", up_to_date}),
    create_files(filename:join(Path, "b2"), {erl, "b2", up_to_date}),
    create_files(Path, {erl, "f1", up_to_date}),
    create_files(Path, {erl, "f2", error}),
    create_files(Path, {erl, "f3", up_to_date}),
    create_files(Path, erls),
    create_files(Path, erls),
    ok.

%% Utility function that creates various sets of source files for the tests.
create_files(Path, {erl, Prefix, Type})
  when Type == up_to_date; Type == rebuilt_no_exist; Type == rebuilt_mod_time; Type == error ->
    [HrlName, ErlName, BeamName] = [filename:join(Path, Prefix ++ Each) || Each <- [".hrl", ".erl", ".beam"]],
    MakeName = filename:join(Path, "Xmakefile"),
    EmptyContent = "",
    ErlContent = "-module(" ++ Prefix ++ ").
                  -include(\"" ++ Prefix ++ ".hrl\").",
    MakeContent = "{erl, \"*.erl\", []}.",
    {Date, _Time} = erlang:localtime(),
    case Type of
	up_to_date ->
	    SourceTime = {0, 0, 1},
	    TargetTime = {0, 0, 2};
	_ ->
	    SourceTime = {0, 0, 2},
	    TargetTime = {0, 0, 1}
    end,
    case Type of
	error ->
	    ok;
	_ ->
	    create_file(HrlName, EmptyContent, {Date, SourceTime})
    end,
    create_file(ErlName, ErlContent, {Date, SourceTime}),
    case Type of
	rebuilt_no_exist ->
	    ok;
	_ ->
	    create_file(BeamName, EmptyContent, {Date, TargetTime})
    end,
    create_file(MakeName, MakeContent, leave),
    case Type of
	up_to_date ->
	    [{BeamName, up_to_date}, {ErlName, up_to_date}, {HrlName, up_to_date}];
	error ->
	    [{ErlName, up_to_date}, {Prefix ++ ".hrl", {error, target_not_exist}}];
	_ ->
	    [{BeamName, rebuilt}, {ErlName, up_to_date}, {HrlName, up_to_date}]
    end;
create_files(Path, {yrl, Prefix, Type}) when Type == up_to_date; Type == rebuilt_no_exist; Type == rebuilt_mod_time ->
    [YrlName, ErlName] = [filename:join(Path, Prefix ++ Each) || Each <- [".yrl", ".erl"]],
    MakeName = filename:join(Path, "Xmakefile"),
    EmptyContent = "",
    MakeContent = "{yrl, \"*.yrl\", []}.",
    {Date, _Time} = erlang:localtime(),
    case Type of
	up_to_date ->
	    SourceTime = {0, 0, 1},
	    TargetTime = {0, 0, 2};
	_ ->
	    SourceTime = {0, 0, 2},
	    TargetTime = {0, 0, 1}
    end,
    create_file(YrlName, EmptyContent, {Date, SourceTime}),
    case Type of
	rebuilt_no_exist ->
	    ok;
	_ ->
	    create_file(ErlName, EmptyContent, {Date, TargetTime})
    end,
    create_file(MakeName, MakeContent, leave),
    case Type of
	up_to_date ->
	    [{filename:join(Path, Prefix ++ ".beam"), rebuilt}, {ErlName, up_to_date}, {YrlName, up_to_date}];
	_ ->
	    [{filename:join(Path, Prefix ++ ".beam"), rebuilt}, {ErlName, rebuilt}, {YrlName, up_to_date}]
    end;
create_files(Path, erls) ->
    [F1Name, F2Name, MakeName] =
	[filename:join(Path, Each) || Each <- ["f1.erl", "f2.erl", "Xmakefile"]],
    F1Content = "-module(f1).
                  -include(\"f.hrl\").",
    F2Content = "-module(f2).
                  -include(\"f.hrl\").",
    MakeContent = "{erl, \"*.erl\", []}.",
    create_file(F1Name, F1Content, leave),
    create_file(F2Name, F2Content, leave),
    create_file(MakeName, MakeContent, leave),
    ["f.hrl", F1Name, F2Name].

create_file(Name, Content, ModTime) ->
    ok = filelib:ensure_dir(Name),
    ok = file:write_file(Name, list_to_binary(Content)),
    case ModTime of
	leave ->
	    ok;
	_ ->
	    ok = file:change_time(Name, ModTime)
    end.
