<commit_before>%% vim: ts=4 sw=4 et
-module(wf_test_srv).
-include("wf.hrl").
-behaviour(gen_server).
-export([main/0]).

-define(TIMEOUT, 15000).

%% API
-export([
    start/1,
    start/2,
    passed/1,
    failed/1,
    next_test_path/0,
    get_summary/0,
    stop/0
]).

%% gen_server callbacks
-export([
    init/1,
    handle_call/3,
    handle_cast/2,
    handle_info/2,
    terminate/2,
    code_change/3
]).

-record(state, {trigger, test_paths=[], current_test, passed=0, failed=0}).

main() ->
    Trigger = wf:to_integer(wf:q(id)),
    case is_trigger_valid(Trigger) of
        false ->
            "Invalid Test Launch Path";
        true ->
            FirstTestPath = next_test_path(),
            wf:redirect(FirstTestPath)
    end.

start(TestPaths) ->
    start(undefined, TestPaths).

start(BrowserExec, TestPaths) ->
    Trigger = crypto:rand_uniform(1, 1000000000),
    LaunchUrl = wf:f("http://127.0.0.1:8000/wf_test_srv?id=~p", [Trigger]),
    wf_test:log("Starting Nitrogen Test Server...~nOpen your browser to:~n        ~s~n", [LaunchUrl]),
    {ok, Pid} = gen_server:start({local, ?MODULE}, ?MODULE, [Trigger, TestPaths], []),
    maybe_launch_browser(BrowserExec, LaunchUrl),
    Pid.

maybe_launch_browser(undefined, _) ->
    ok;
maybe_launch_browser(BrowserExec, LaunchUrl) ->
    os:cmd(BrowserExec ++ " " ++ LaunchUrl ++ " &"),
    ok.

is_trigger_valid(Trigger) ->
    try gen_server:call(?MODULE, {is_trigger_valid, Trigger})
    catch exit:{noproc,_} -> false
    end.

passed(Num) ->
    gen_server:cast(?MODULE, {passed, Num}).

failed(Num) ->
    gen_server:cast(?MODULE, {failed, Num}).

next_test_path() ->
    case gen_server:call(?MODULE, next_test_path) of
        {ok, Next} ->
            Next;
        undefined ->
            print_summary_and_close(),
            done
    end.

print_summary_and_close() ->
    {ok, Summary} = get_summary(),
    Passed = proplists:get_value(passed, Summary),
    Failed = proplists:get_value(failed, Summary),
    wf_test:log("SUMMARY: Tests Finished. ~p Passed. ~p Failed.", [Passed, Failed]),
    stop().

get_summary() ->
    gen_server:call(?MODULE, summary).

stop() ->
    gen_server:cast(?MODULE, stop).

init([Trigger, TestPaths]) ->
    {ok, #state{trigger=Trigger, test_paths=TestPaths}, ?TIMEOUT}.

handle_call({is_trigger_valid, ProvidedTrigger}, _From, State=#state{trigger=Trigger}) ->
    Reply = ProvidedTrigger == Trigger,
    {reply, Reply, State, ?TIMEOUT};
handle_call(next_test_path, _From, State=#state{test_paths=[Next | Rest]}) ->
    Reply = {ok, Next},
    {reply, Reply, State#state{test_paths=Rest, current_test=Next}, ?TIMEOUT};
handle_call(next_test_path, _From, State=#state{test_paths=[]}) ->
    Reply = undefined,
    {reply, Reply, State#state{current_test=undefined}, ?TIMEOUT};
handle_call(summary, _From, State=#state{passed=Passed, failed=Failed}) ->
    Reply = {ok, [{passed, Passed}, {failed, Failed}]},
    {reply, Reply, State, ?TIMEOUT}.

handle_cast({passed, Num}, State=#state{passed=Cur}) ->
    {noreply, State#state{passed=Cur+Num}, ?TIMEOUT};
handle_cast({failed, Num}, State=#state{failed=Cur}) ->
    {noreply, State#state{failed=Cur+Num}, ?TIMEOUT};
handle_cast(stop, State) ->
    {stop, normal, State}.

handle_info(timeout, State=#state{test_paths=TestPaths, current_test=Cur}) ->
    Remaining = length(TestPaths),
    wf_test:log("ERROR: Tests Timed Out. Test '~s' never finished. ~p remaining tests!", [Cur, Remaining]),
    {stop, State}.

terminate(_Reason, _State) -><commit_msg>Fix `stop` bug in wf_test (found with dialyzer, yo)<commit_after>%% vim: ts=4 sw=4 et
-module(wf_test_srv).
-include("wf.hrl").
-behaviour(gen_server).
-export([main/0]).

-define(TIMEOUT, 15000).

%% API
-export([
    start/1,
    start/2,
    passed/1,
    failed/1,
    next_test_path/0,
    get_summary/0,
    stop/0
]).

%% gen_server callbacks
-export([
    init/1,
    handle_call/3,
    handle_cast/2,
    handle_info/2,
    terminate/2,
    code_change/3
]).

-record(state, {trigger, test_paths=[], current_test, passed=0, failed=0}).

main() ->
    Trigger = wf:to_integer(wf:q(id)),
    case is_trigger_valid(Trigger) of
        false ->
            "Invalid Test Launch Path";
        true ->
            FirstTestPath = next_test_path(),
            wf:redirect(FirstTestPath)
    end.

start(TestPaths) ->
    start(undefined, TestPaths).

start(BrowserExec, TestPaths) ->
    Trigger = crypto:rand_uniform(1, 1000000000),
    LaunchUrl = wf:f("http://127.0.0.1:8000/wf_test_srv?id=~p", [Trigger]),
    wf_test:log("Starting Nitrogen Test Server...~nOpen your browser to:~n        ~s~n", [LaunchUrl]),
    {ok, Pid} = gen_server:start({local, ?MODULE}, ?MODULE, [Trigger, TestPaths], []),
    maybe_launch_browser(BrowserExec, LaunchUrl),
    Pid.

maybe_launch_browser(undefined, _) ->
    ok;
maybe_launch_browser(BrowserExec, LaunchUrl) ->
    os:cmd(BrowserExec ++ " " ++ LaunchUrl ++ " &"),
    ok.

is_trigger_valid(Trigger) ->
    try gen_server:call(?MODULE, {is_trigger_valid, Trigger})
    catch exit:{noproc,_} -> false
    end.

passed(Num) ->
    gen_server:cast(?MODULE, {passed, Num}).

failed(Num) ->
    gen_server:cast(?MODULE, {failed, Num}).

next_test_path() ->
    case gen_server:call(?MODULE, next_test_path) of
        {ok, Next} ->
            Next;
        undefined ->
            print_summary_and_close(),
            done
    end.

print_summary_and_close() ->
    {ok, Summary} = get_summary(),
    Passed = proplists:get_value(passed, Summary),
    Failed = proplists:get_value(failed, Summary),
    wf_test:log("SUMMARY: Tests Finished. ~p Passed. ~p Failed.", [Passed, Failed]),
    stop().

get_summary() ->
    gen_server:call(?MODULE, summary).

stop() ->
    gen_server:cast(?MODULE, stop).

init([Trigger, TestPaths]) ->
    {ok, #state{trigger=Trigger, test_paths=TestPaths}, ?TIMEOUT}.

handle_call({is_trigger_valid, ProvidedTrigger}, _From, State=#state{trigger=Trigger}) ->
    Reply = ProvidedTrigger == Trigger,
    {reply, Reply, State, ?TIMEOUT};
handle_call(next_test_path, _From, State=#state{test_paths=[Next | Rest]}) ->
    Reply = {ok, Next},
    {reply, Reply, State#state{test_paths=Rest, current_test=Next}, ?TIMEOUT};
handle_call(next_test_path, _From, State=#state{test_paths=[]}) ->
    Reply = undefined,
    {reply, Reply, State#state{current_test=undefined}, ?TIMEOUT};
handle_call(summary, _From, State=#state{passed=Passed, failed=Failed}) ->
    Reply = {ok, [{passed, Passed}, {failed, Failed}]},
    {reply, Reply, State, ?TIMEOUT}.

handle_cast({passed, Num}, State=#state{passed=Cur}) ->
    {noreply, State#state{passed=Cur+Num}, ?TIMEOUT};
handle_cast({failed, Num}, State=#state{failed=Cur}) ->
    {noreply, State#state{failed=Cur+Num}, ?TIMEOUT};
handle_cast(stop, State) ->
    {stop, normal, State}.

handle_info(timeout, State=#state{test_paths=TestPaths, current_test=Cur}) ->
    Remaining = length(TestPaths),
    wf_test:log("ERROR: Tests Timed Out. Test '~s' never finished. ~p remaining tests!", [Cur, Remaining]),
    {stop, timeout, State}.

terminate(_Reason, _State) ->
{'fraction_non_alphanumeric': 0.16847443301873502, 'fraction_numerical': 0.012396112128468799, 'mean_word_length': 3.856361149110807, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6779765', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2455, 'n_words': 477}