<commit_before>%% -*- erlang-indent-level: 4;indent-tabs-mode: nil; fill-column: 92 -*-
%% ex: ts=4 sw=4 et
%%
%% @author <NAME> <<EMAIL>>
%%
%% @copyright 2012 Opscode Inc.
%% @end

%%
%% @doc simple FSM for tracking node heartbeats and thus up/down status
%%
-module(pushy_node_state_tests).

-define(NODE, {<<"org">>, <<"thenode">>}).
-define(ADDR, <<"AAAAAAA">>).
-define(NS, pushy_node_state).
-define(GPROC_NAME, {heartbeat,<<"org">>,<<"thenode">>}).

-define(HB_INTERVAL, 100).
-define(DECAY_WINDOW, 4). %% 4 is friendly to base 2 float arith
-define(DOWN_THRESHOLD, 0.25).

-include_lib("eunit/include/eunit.hrl").

-define(ASSERT_AVAILABLE(Node), ?assertMatch({online, {available, _}}, ?NS:status(Node)) ).
-define(ASSERT_UNAVAILABLE(Node), ?assertMatch({online, {unavailable, _}}, ?NS:status(Node)) ).
-define(ASSERT_OFFLINE(Node), ?assertMatch({offline, {unavailable, _}}, ?NS:status(Node)) ).

basic_setup() ->
    test_util:start_apps(),

    meck:new(pushy_command_switch, []),
    meck:expect(pushy_command_switch, send_raw,
                fun(_Message) -> ok end),
    application:set_env(pushy, heartbeat_interval, ?HB_INTERVAL),
    application:set_env(pushy, decay_window, ?DECAY_WINDOW),
    application:set_env(pushy, down_threshold, ?DOWN_THRESHOLD),

    pushy_key_manager:init(),
    pushy_node_stats:init(),
    ok.


basic_cleanup() ->
    pushy_key_manager:stop(),
    pushy_node_stats:stop(),
    meck:unload(pushy_command_switch).

init_test_() ->
    {foreach,
     fun basic_setup/0,
     fun(_) ->
             basic_cleanup(),
             ok
     end,
     [fun(_) -><commit_msg>eunit: Add test code for message receive and decode<commit_after>%% -*- erlang-indent-level: 4;indent-tabs-mode: nil; fill-column: 92 -*-
%% ex: ts=4 sw=4 et
%%
%% @author <NAME> <<EMAIL>>
%%
%% @copyright 2012 Opscode Inc.
%% @end

%%
%% @doc simple FSM for tracking node heartbeats and thus up/down status
%%
-module(pushy_node_state_tests).

-define(NODE, {<<"org">>, <<"thenode">>}).
-define(ADDR, <<"AAAAAAA">>).
-define(NS, pushy_node_state).
-define(GPROC_NAME, {heartbeat,<<"org">>,<<"thenode">>}).

-define(HB_INTERVAL, 100).
-define(DECAY_WINDOW, 4). %% 4 is friendly to base 2 float arith
-define(DOWN_THRESHOLD, 0.25).

-include_lib("eunit/include/eunit.hrl").

-define(ASSERT_AVAILABLE(Node), ?assertMatch({online, {available, _}}, ?NS:status(Node)) ).
-define(ASSERT_UNAVAILABLE(Node), ?assertMatch({online, {unavailable, _}}, ?NS:status(Node)) ).
-define(ASSERT_OFFLINE(Node), ?assertMatch({offline, {unavailable, _}}, ?NS:status(Node)) ).

basic_setup() ->
    test_util:start_apps(),

    meck:new(pushy_command_switch, []),
    meck:expect(pushy_command_switch, send_raw,
                fun(_Message) -> ok end),
    meck:new(pushy_object, []),
    meck:expect(pushy_object, fetch_org_id,
                fun(X) -> X end),
    application:set_env(pushy, heartbeat_interval, ?HB_INTERVAL),
    application:set_env(pushy, decay_window, ?DECAY_WINDOW),
    application:set_env(pushy, down_threshold, ?DOWN_THRESHOLD),

    pushy_key_manager:init(),
    pushy_node_stats:init(),
    ok.


basic_cleanup() ->
    pushy_key_manager:stop(),
    pushy_node_stats:stop(),
    meck:unload(pushy_object),
    meck:unload(pushy_command_switch).

mk_message_body({Org,Node}, Type) ->
    EJson =
        {[{<<"node">>, Node},
          {<<"client">>, <<"private-chef.opscode.piab">>},
          {<<"org">>, Org},
          {<<"type">>,  atom_to_binary(Type, utf8)},
          {<<"timestamp">>, <<"Thu, 29 Nov 2012 00:26:17 GMT">>},
          {<<"incarnation_id">>, <<"5b8061c8-cb44-4ad9-a85f-82e87b8c87fb">>},
          {<<"job_state">>, <<"idle">>},
          {<<"job_id">>, <<"null">>},
          {<<"sequence">>, 2} ]},
    jiffy:encode(EJson).

send_message(Node, Type) ->
    {hmac_sha256, Key} = pushy_key_manager:get_key(Node),
    Body = mk_message_body(Node, Type),
    Header = pushy_messaging:make_header(proto_v2, hmac_sha256, Key, Body),
    Message = [?ADDR, Header, Body],
    pushy_node_state:recv_msg(Message).

message_test_() ->
    {foreach,
     fun() ->
             basic_setup(),
             {ok, Pid} = ?NS:start_link(?NODE, ?ADDR),
             erlang:unlink(Pid),
             {Pid}
     end,
     fun({Pid}) ->
             basic_cleanup(),
             erlang:exit(Pid, kill),
             ok
     end,
     [fun(_) ->
              {"Send heartbeats to a node",
               fun() ->
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, heartbeat),
                       timer:sleep(?HB_INTERVAL),
                       send_message(?NODE, aborted),
                       timer:sleep(?HB_INTERVAL),
                       ?ASSERT_AVAILABLE(?NODE)
               end
              }
      end
     ]}.


init_test_() ->
    {foreach,
     fun basic_setup/0,
     fun(_) ->
             basic_cleanup(),
             ok
     end,
     [fun(_) ->
{'fraction_non_alphanumeric': 0.16948856694012918, 'fraction_numerical': 0.013614941525571652, 'mean_word_length': 2.6543367346938775, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, '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': '965233', 'n_tokens_mistral': 2056, 'n_tokens_neox': 1947, 'n_words': 316}