%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%

-module(snmp_agent_conf_test).

%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------

%-include_lib("test_server/include/test_server.hrl").
%-include("snmp_test_lib.hrl").
-include_lib("common_test/include/ct.hrl").

-export([
    all/0,
    groups/0,
    init_per_suite/1,
    end_per_suite/1,

    check_agent/1,
    check_usm/1,
    check_vacm/1
    ]).


all() -> [
    check_agent,
    check_usm,
    check_vacm
    ].


groups() ->
    [].


init_per_suite(Config) ->
    PrivDir = ?config(priv_dir, Config),
    PrivSubdir = filename:join(PrivDir, "snmp_agent_conf_test"),
    ok = filelib:ensure_dir(filename:join(PrivSubdir, "dummy")),
    [{priv_subdir, PrivSubdir} | Config].

end_per_suite(_Config) ->
    ok.

%%======================================================================
%% Test data
%%======================================================================

engine_ids() -> [
    "plain eid",
    "here\"eid",
    "comes\neid",
    "trouble\0eid",
    binary_to_list(<<"中国引擎标识符"/utf8>>)
].

snmp_admin_strings() -> [
    "plain string",
    "heres\"eid",
    "trouble\neid",
    binary_to_list(<<"中国引擎标识符"/utf8>>)
].


%%======================================================================
%% Test functions
%%======================================================================


check_agent(Config) ->
    Dir = ?config(priv_subdir, Config),
    lists:foreach(
        fun(EngineId) -> check_agent_by_engineid(Dir, EngineId) end,
        engine_ids()
    ),
    ok.

check_agent_by_engineid(Dir, EngineId) ->
    WEntries = [
        snmpa_conf:agent_entry(intAgentIpAddress, {0,0,0,0}),
        snmpa_conf:agent_entry(intAgentUDPPort, 161),
        snmpa_conf:agent_entry(snmpEngineMaxMessageSize, 484),
        snmpa_conf:agent_entry(snmpEngineID, EngineId)
    ],

    ok = snmpa_conf:write_agent_config(Dir, WEntries),
    {ok, REntries} = snmpa_conf:read_agent_config(Dir),

    true = is_subset(WEntries, REntries),
    ok.

%%======================================================================

check_usm(Config) ->
    Dir = ?config(priv_subdir, Config),
    EngineId = hd(engine_ids()),
    UserName = hd(snmp_admin_strings()),
    SecName  = hd(snmp_admin_strings()),

    %% vary engine id
    lists:foreach(
        fun(EngineId_) -> check_usm_by_params(Dir, EngineId_, UserName, SecName) end,
        engine_ids()
    ),

    %% vary user name
    lists:foreach(
        fun(UserName_) -> check_usm_by_params(Dir, EngineId, UserName_, SecName) end,
        snmp_admin_strings()
    ),

    %% vary sec name
    lists:foreach(
        fun(SecName_) -> check_usm_by_params(Dir, EngineId, UserName, SecName_) end,
        snmp_admin_strings()
    ),

    ok.

check_usm_by_params(Dir, EngineId, UserName, SecName) ->
    WEntries = [
        snmpa_conf:usm_entry(
            EngineId,
            UserName,
            SecName,
            zeroDotZero,
            usmNoAuthProtocol, % authproto
            "", "",
            usmNoPrivProtocol, % privproto
            "", "", "",
            [], %AuthKey
            [])  %PrivKey
    ],

    ok = snmpa_conf:write_usm_config(Dir, WEntries),
    {ok, REntries} = snmpa_conf:read_usm_config(Dir),

    true = is_subset(WEntries, REntries),
    ok.

%%======================================================================

check_vacm(Config) ->
    Dir = ?config(priv_subdir, Config),

    %% vary sec name
    lists:foreach(
        fun(SecName_) -> check_vacm_by_params(Dir, SecName_) end,
        snmp_admin_strings()
    ),

    ok.


check_vacm_by_params(Dir, SecName) ->
    WEntries = [
        %%                      SecModel, SecName, GroupName
        snmpa_conf:vacm_s2g_entry(usm, SecName,  SecName),
        %%                     GroupName,Prefix,SecModel,SecLevel,Match,ReadView,WriteView,NotifyView
        snmpa_conf:vacm_acc_entry(SecName,  "", any, noAuthNoPriv, exact, "all", "all", "all")
    ],

    ok = snmpa_conf:write_vacm_config(Dir, WEntries),
    {ok, REntries} = snmpa_conf:read_vacm_config(Dir),

    true = is_subset(WEntries, REntries),
    ok.



%%======================================================================


%% additional tests needed:
% check_context()
% check_community()
% check_standard()
% check_target_addr()
% check_target_params()
% check_notify()


%%======================================================================
%% Local utility functions
%%======================================================================

is_subset(List1, List2) ->
    io:format("Check ~p is subset of ~p\n", [List1, List2]),
    sets:is_subset(
        sets:from_list(List1),
        sets:from_list(List2)
    ).
