aboutsummaryrefslogblamecommitdiffstats
path: root/lib/snmp/test/snmp_compiler_test.erl
blob: a28f925a221f466a9f8a4b0fd707d4080c02888a (plain) (tree)
1
2
3
4
5
6
7
8
9

                   
  
                                                        
  


                                                                   
  






                                                                           
  













                                                                        
                                           







                                                                        

                                                      
                                                 
                                           




                           
                              
                              
                              
                               
 

                     
                     
                      
                     
                     

                     




                                                                        
 


           
 











                                                                        































                                                                    
 
                                                       
           





                                                                        
         
     


                    


                         
                        
                          
                     
      

            
                  
                                                                     
                               

                                     
           

                                    
           

 










                                                                        
                                        


























                                                                     

                                                                        




                                              
                                        






                                                             

                                                                        





                                       

                                                                        





                                               

                                                                        





                                                  
                                          
                                                

                                        

                                                         
                                                                             





                                                                      
                                                                             


















                                                                      

                                                                        





                                                 



                                              

                                                         
                                                                               





                                                                        
                                                                               




                                                                        
                                     









                                          


       






                                                                        
                                            


                                              

                                  






                                                          
                              




                                                                        


                                        
                        

                                              
                                            

                                                   

                                                                    



                                                

                                                                        


                                        
                        

                                              
                                            























                                                                           

                                                                        


                                        
                        

                                              
                                            





                                                       
                            


       
                                                                        
 
















                                                                        


















                                                                        


                                         
                         



















                                                                        






























                                                                  















                                                                        


                                                                        







































                                                                        
























                                                                        
                    






























































































































                                                    
                                                


                      
                                          























                                                                            








                                                   

                           









                       


             




                                
                                                                  
 

                                       
%% 
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2003-2018. 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%
%% 

%%----------------------------------------------------------------------
%% Purpose: Test the snmp mib compiler
%% 
%% Run test: ts:run(snmp, snmp_compiler_test, [batch]).
%% 
%%----------------------------------------------------------------------
-module(snmp_compiler_test).

%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-include_lib("snmp/include/snmp_types.hrl").


%%----------------------------------------------------------------------
%% External exports
%%----------------------------------------------------------------------
-export([
	 all/0, 
	 groups/0, init_per_group/2, end_per_group/2, 
         init_per_testcase/2, end_per_testcase/2,
         init_per_suite/1, end_per_suite/1,

	 description/1,
	 oid_conflicts/1,
	 imports/1,
	 module_identity/1,
	 agent_capabilities/1,
	 module_compliance/1, 
	 warnings_as_errors/1,
	 augments_extra_info/1,

	 otp_6150/1,
	 otp_8574/1, 
	 otp_8595/1, 
	 otp_10799/1, 
	 otp_10808/1,
	 otp_14145/1,
         otp_13014/1,
         otp_14196/1
	]).

%%----------------------------------------------------------------------
%% Internal exports
%%----------------------------------------------------------------------

-export([
        ]).


%%----------------------------------------------------------------------
%% Macros
%%----------------------------------------------------------------------

%%----------------------------------------------------------------------
%% Records
%%----------------------------------------------------------------------

%%======================================================================
%% External functions
%%======================================================================

init_per_suite(Config0) when is_list(Config0) ->

    ?DBG("init_per_suite -> entry with"
	 "~n   Config0: ~p", [Config0]),

    Config1   = snmp_test_lib:init_suite_top_dir(?MODULE, Config0), 
    Config2   = snmp_test_lib:fix_data_dir(Config1),

    %% Mib-dirs
    %% data_dir is trashed by the test-server / common-test
    %% so there is no point in fixing it...
    MibDir    = snmp_test_lib:lookup(data_dir, Config2),
    StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),

    [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2].

end_per_suite(Config) when is_list(Config) ->

    ?DBG("end_per_suite -> entry with"
	 "~n   Config: ~p", [Config]),

    Config.


init_per_testcase(Case, Config) when is_list(Config) ->

    ?DBG("init_per_testcase -> entry with"
	 "~n   Config: ~p", [Config]),

    CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config), 

    [{case_top_dir, CaseTopDir} | Config].

end_per_testcase(_Case, Config) when is_list(Config) ->
    Config.


%%======================================================================
%% Test case definitions
%%======================================================================

all() -> 
    [
     description, 
     oid_conflicts, 
     imports, 
     module_identity, 
     agent_capabilities, 
     module_compliance, 
     warnings_as_errors,
     augments_extra_info, 
     {group, tickets}
    ].

groups() -> 
    [{tickets, [],
      [otp_6150, otp_8574, otp_8595, otp_10799, otp_10808, otp_14145,
       otp_13014, otp_14196]}].

init_per_group(_GroupName, Config) ->
    Config.

end_per_group(_GroupName, Config) ->
    Config.




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

description(suite) -> [];
description(Config) when is_list(Config) ->
    put(tname,desc),
    p("starting with Config: ~p~n", [Config]),

    Dir = ?config(case_top_dir, Config),
    Filename   = join(Dir,"test"),
    MibSrcName = Filename ++ ".mib",
    MibBinName = Filename ++ ".bin",
    Desctext   = "This is a test description",
    Oid = [1,3,6,1,2,1,15,1],
    write_mib(MibSrcName,Desctext),
    ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir,      Dir},
					      {group_check, false},
					      {warnings,    false},
					      {description, false}]),
    MIB1 = read_mib(MibBinName),
    %% io:format("description -> MIB1: ~n~p~n", [MIB1]),
    check_mib(MIB1#mib.mes, Oid,  undefined),
    ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir,      Dir},
					      {group_check, false},
					      {warnings,    false},
					      {description, true}]),
    MIB2 = read_mib(MibBinName),
    %% io:format("description -> MIB2: ~n~p~n", [MIB2]),
    check_mib(MIB2#mib.mes, Oid, Desctext),

    %% Cleanup
    file:delete(MibSrcName),
    file:delete(MibBinName),
    ok.


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

oid_conflicts(suite) -> [];
oid_conflicts(Config) when is_list(Config) ->
    put(tname,oid_conflicts),
    p("starting with Config: ~p~n", [Config]),

    Dir = ?config(case_top_dir, Config),
    Mib = join(Dir,"TESTv2.mib"),
    ?line ok = write_oid_conflict_mib(Mib),
    ?line {error,compilation_failed} = 
	snmpc:compile(Mib,[{outdir, Dir},{verbosity,trace}]),
    ok.


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

imports(suite) ->
    [];
imports(Config) when is_list(Config) ->
    ?SKIP(not_yet_implemented).


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

module_identity(suite) ->
    [];
module_identity(Config) when is_list(Config) ->
    ?SKIP(not_yet_implemented).


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

agent_capabilities(suite) ->
    [];
agent_capabilities(Config) when is_list(Config) ->
    put(tname,agent_capabilities),
    p("starting with Config: ~p~n", [Config]),

    SnmpPrivDir    = which_priv_dir(snmp),
    SnmpMibsDir    = join(SnmpPrivDir, "mibs"), 
    Dir   = ?config(mib_dir, Config),
    AcMib = join(Dir,"AC-TEST-MIB.mib"),
    ?line {ok, MibFile1} = snmpc:compile(AcMib, [options,
						 version,
						 {i,         [SnmpMibsDir]}, 
						 {outdir,    Dir}, 
						 {verbosity, trace}]),
    ?line {ok, Mib1} = snmp_misc:read_mib(MibFile1), 
    ?line {ok, MibFile2} = snmpc:compile(AcMib, [options,
						 version,
						 agent_capabilities,
						 {i,         [SnmpMibsDir]}, 
						 {outdir,    Dir}, 
						 {verbosity, trace}]),
    ?line {ok, Mib2} = snmp_misc:read_mib(MibFile2), 
    MEDiff = Mib2#mib.mes -- Mib1#mib.mes,
    %% This is a rather pathetic test, but it is somthing...
    io:format("agent_capabilities -> "
	      "~n   MEDiff: ~p"
	      "~n   Mib1:   ~p"
	      "~n   Mib2:   ~p"
	      "~n", [MEDiff, Mib1, Mib2]),
    case length(MEDiff) of
	2 ->
	    ok;
	_BadLen ->
	    exit({unexpected_mes, MEDiff})
    end,
    ok.


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

module_compliance(suite) ->
    [];
module_compliance(Config) when is_list(Config) ->
    put(tname,module_compliance),
    p("starting with Config: ~p~n", [Config]),

    SnmpPrivDir = which_priv_dir(snmp),
    SnmpMibsDir = join(SnmpPrivDir, "mibs"), 
    Dir         = ?config(mib_dir, Config),
    AcMib       = join(Dir,"MC-TEST-MIB.mib"),
    ?line {ok, MibFile1} = snmpc:compile(AcMib, [options,
						 version,
						 {i,           [SnmpMibsDir]}, 
						 {outdir,      Dir}, 
						 {verbosity,   trace}]),
    ?line {ok, Mib1} = snmp_misc:read_mib(MibFile1), 
    ?line {ok, MibFile2} = snmpc:compile(AcMib, [options,
						 version,
						 module_compliance,
						 {i,           [SnmpMibsDir]}, 
						 {outdir,      Dir}, 
						 {verbosity,   trace}]),
    ?line {ok, Mib2} = snmp_misc:read_mib(MibFile2), 
    MEDiff = Mib2#mib.mes -- Mib1#mib.mes,
    %% This is a rather pathetic test, but it is somthing...
    io:format("module_compliance -> "
	      "~n   MEDiff: ~p"
	      "~n   Mib1:   ~p"
	      "~n   Mib2:   ~p"
	      "~n", [MEDiff, Mib1, Mib2]),
    case length(MEDiff) of
	1 ->
	    ok;
	_BadLen ->
	    exit({unexpected_mes, MEDiff})
    end,
    ok.


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

warnings_as_errors(suite) ->
    ["OTP-9437"];
warnings_as_errors(Config) when is_list(Config) ->
    put(tname,warnings_as_errors),
    p("starting with Config: ~p~n", [Config]),
    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,  Config),
    MibFile = join(MibDir, "OTP8574-MIB.mib"),
    OutFile = join(Dir, "OTP8574-MIB.bin"),
    Opts =  [{group_check, false},
	     {outdir,      Dir},
	     {verbosity,   trace},
	     relaxed_row_name_assign_check],
    {error, compilation_failed} =
	snmpc:compile(MibFile, [warnings_as_errors|Opts]),
    false = filelib:is_regular(OutFile),
    {ok, _} = snmpc:compile(MibFile, Opts),
    true = filelib:is_regular(OutFile),
    ok = file:delete(OutFile),
    ok.


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

otp_6150(suite) ->
    [];
otp_6150(Config) when is_list(Config) ->
    put(tname, otp6150),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,  Config),
    MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"),
    ?line {ok, Mib} = 
	snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
    io:format("otp_6150 -> Mib: ~n~p~n", [Mib]),
    ok.


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

otp_8574(suite) ->
    [];
otp_8574(Config) when is_list(Config) ->
    put(tname, otp8574),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,  Config),
    MibFile = join(MibDir, "OTP8574-MIB.mib"),
    
    p("ensure compile fail without relaxed assign check"),
    case snmpc:compile(MibFile, [{group_check, false}, {outdir, Dir}]) of
	{error, compilation_failed} ->
	    p("with relaxed assign check MIB compiles with warning"),
	    case snmpc:compile(MibFile, [{group_check, false}, 
					 {outdir, Dir}, 
					 relaxed_row_name_assign_check]) of
		{ok, _Mib} ->
		    ok;
		{error, Reason} ->
		    p("unexpected compile failure: "
		      "~n   Reason: ~p", [Reason]),
		    exit({unexpected_compile_failure, Reason})
	    end;

	{ok, _} ->
	    p("unexpected compile success"),
	    exit(unexpected_compile_success)
    end.


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

otp_8595(suite) ->
    [];
otp_8595(Config) when is_list(Config) ->
    put(tname, otp8595),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,  Config),
    MibFile = join(MibDir, "OTP8595-MIB.mib"),
    ?line {ok, Mib} = 
	snmpc:compile(MibFile, [{outdir,      Dir}, 
				{verbosity,   trace}, 
				{group_check, false}]),
    p("Mib: ~n~p~n", [Mib]),
    ok.


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

otp_10799(suite) ->
    [];
otp_10799(Config) when is_list(Config) ->
    put(tname, otp10799),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,      Config),
    MibFile = join(MibDir, "OTP10799-MIB.mib"),
    ?line {ok, Mib} = 
	snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
    p("Mib: ~n~p~n", [Mib]),
    ok.


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

otp_10808(suite) ->
    [];
otp_10808(Config) when is_list(Config) ->
    put(tname, otp10808),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,      Config),
    MibFile = join(MibDir, "OTP10808-MIB.mib"),
    ?line {ok, Mib} = 
	snmpc:compile(MibFile, [{outdir,      Dir}, 
				{verbosity,   trace}, 
				{group_check, false}]),
    p("Mib: ~n~p~n", [Mib]),
    ok.


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

otp_14145(suite) ->
    [];
otp_14145(Config) when is_list(Config) ->
    put(tname, otp14145),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,      Config),
    MibName = "OTP14145-MIB",
    MibFile = join(MibDir, MibName++".mib"),
    ?line {ok, MibBin} =
	snmpc:compile(MibFile, [{outdir, Dir},
				{verbosity, trace},
				{group_check, false},
				module_compliance]),
    p("Mib: ~n~p~n", [MibBin]),
    MIB = read_mib(MibBin),
    Oid = [1,3,6,1,2,1,67,4],
    check_mib(MIB#mib.mes, Oid, undefined),
    ok.


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

otp_13014(suite) ->
    [];
otp_13014(Config) when is_list(Config) ->
    put(tname, otp13014),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,      Config),
    MibName = "Test-LLDP-MIB",
    MibFile = join(MibDir, MibName++".mib"),
    ?line {ok, MibBin} =
	snmpc:compile(MibFile, [{outdir, Dir},
				{verbosity, log},
				{group_check, false},
				module_compliance]),
    p("Mib: ~n~p~n", [MibBin]),
    #mib{mes = MEs} = read_mib(MibBin),
    Oid = [1,0,8802,1,1,2,1,1,7],
    #me{
       entrytype = table,
       aliasname = lldpConfigManAddrTable,
       assocList = [{table_info,TableInfo}]} =
        lists:keyfind(Oid, #me.oid, MEs),
    #table_info{
       nbr_of_cols = 1,
       first_accessible = 1,
       not_accessible = [],
       index_types = {augments,{lldpLocManAddrEntry,undefined}}} =
        TableInfo,
    ok.

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

otp_14196(suite) ->
    [];
otp_14196(Config) when is_list(Config) ->
    put(tname, otp14196),
    p("starting with Config: ~p~n", [Config]),

    Dir     = ?config(case_top_dir, Config),
    MibDir  = ?config(mib_dir,      Config),
    MibFile = join(MibDir, "OTP14196-MIB.mib"),
    ?line {ok, Mib} =
	snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
    p("Mib: ~n~p~n", [Mib]),
    ok.


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

augments_extra_info(suite) ->
    [];
augments_extra_info(Config) when is_list(Config) ->
    put(tname, augments_extra_info),
    p("starting with Config: ~p~n", [Config]),

    Dir       = ?config(case_top_dir, Config),
    MibDir    = ?config(mib_dir,      Config),
    Test2File = join(MibDir, "Test2.mib"),
    Test3File = join(MibDir, "Test3.mib"),
    ?line {ok, Test2BinFile} = 
	snmpc:compile(Test2File, [{outdir,      Dir}, 
				  {verbosity,   silence}, 
				  {group_check, false}]),
    io:format("Test2BinFile: ~n~p~n", [Test2BinFile]),
    ?line {ok, Test3BinFile} = 
	snmpc:compile(Test3File, [{i,           [MibDir]}, 
				  {outdir,      Dir}, 
				  {verbosity,   silence}, 
				  {group_check, true}]),
    io:format("Test3BinFile: ~n~p~n", [Test3BinFile]),
    {ok, Test3Mib} = snmp_misc:read_mib(Test3BinFile), 
    io:format("Test3Mib: ~n~p~n", [Test3Mib]),
    %% There is only one table in this mib
    #mib{table_infos = [{TableName, TI}]} = Test3Mib, 
    io:format("TableName: ~p"
	      "~n   Table Info: ~p"
	      "~n", [TableName, TI]), 
    #table_info{nbr_of_cols      = 4, 
		defvals          = DefVals, 
		not_accessible   = [2,4], 
		index_types      = {augments, {tEntry, undefined}},
		first_accessible = 1} = TI,
    io:format("Table info:   ~p"
	      "~n   DefVals: ~p"
	      "~n", [TableName, DefVals]), 
    ok.


%%======================================================================
%% Internal functions
%%======================================================================

write_oid_conflict_mib(Filename) ->
    MibText = "TESTv2 DEFINITIONS ::= BEGIN

IMPORTS
	MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,
    Integer32, snmpModules ,experimental
        FROM SNMPv2-SMI
	MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP
        FROM SNMPv2-CONF
	DisplayString 
        FROM SNMPv2-TC
	RowStatus
        FROM STANDARD-MIB;


exampleModule MODULE-IDENTITY
LAST-UPDATED \"0005290000Z\"
        ORGANIZATION \"Erlang\"
        CONTACT-INFO \" test mib
                        Ericsson Utvecklings AB
Open System
Box 1505
SE-125 25 ÄLVSJÖ\"

DESCRIPTION 
\" Objects for management \"
        REVISION   \"0005290000Z\"
        DESCRIPTION 
\"The initial version\"
        ::= { snmpModules 1 }

example1 OBJECT IDENTIFIER ::= { experimental 7}
-- example2 OBJECT IDENTIFIER ::= { experimental 7}


myName OBJECT-TYPE
SYNTAX      DisplayString
MAX-ACCESS  read-write
STATUS  current
DESCRIPTION
\"My own name\"
              ::= { example1 1 }

myNotification NOTIFICATION-TYPE
STATUS      current 
DESCRIPTION 
\"test trap.\" 
              ::= { example1 1 }

friendsTable OBJECT-TYPE
SYNTAX  SEQUENCE OF FriendsEntry
MAX-ACCESS  not-accessible
STATUS   current
DESCRIPTION
\"A list of friends.\"
              ::= { example1 4 }

friendsEntry OBJECT-TYPE
SYNTAX  FriendsEntry
MAX-ACCESS  not-accessible
STATUS  current
DESCRIPTION
\"\"
              INDEX   { fIndex }
::= { friendsTable 1 }

FriendsEntry ::= SEQUENCE {
		   fIndex   INTEGER,
		   fName    DisplayString,
		   fAddress DisplayString,
		   fStatus  RowStatus
		  }

fIndex OBJECT-TYPE
SYNTAX      INTEGER
MAX-ACCESS  read-only
STATUS      current
DESCRIPTION
\"number of friend\"
              ::= { friendsEntry 1 }

fName OBJECT-TYPE
SYNTAX      DisplayString (SIZE (0..255))
MAX-ACCESS  read-write
STATUS      current
DESCRIPTION
\"Name of  a friend\"
              ::= { friendsEntry 2 }

fAddress OBJECT-TYPE
SYNTAX      DisplayString (SIZE (0..255))
MAX-ACCESS  read-write
STATUS      current
DESCRIPTION
\"Address of a friend\"
              ::= { friendsEntry 3 }

fStatus OBJECT-TYPE
SYNTAX      RowStatus
MAX-ACCESS  read-write
STATUS      current
DESCRIPTION
\"The status of this conceptual row.\"
              ::= { friendsEntry 4 }

-- myName2 OBJECT IDENTIFIER ::= { example1 1 }

friendGroup OBJECT-GROUP
OBJECTS { myName, fIndex, fName,fAddress, fStatus } 
STATUS current
DESCRIPTION \" A object group\"
        ::= { example1 2 }

myNotificationGroup NOTIFICATION-GROUP 
NOTIFICATIONS { myNotification } 
STATUS     current 
DESCRIPTION 
\"Test notification group\" 
      ::= { example1 3 }
END",

    file:write_file(Filename, MibText).


write_mib(Filename,Desc) ->
    Binary = "Test DEFINITIONS ::= BEGIN

IMPORTS
	MODULE-IDENTITY, OBJECT-TYPE, 
    snmpModules, mib-2
        FROM SNMPv2-SMI ;

snmpMIB MODULE-IDENTITY
LAST-UPDATED \"9511090000Z\"
    ORGANIZATION \"\" 
    CONTACT-INFO \"\"
    DESCRIPTION
::= { snmpModules 1 }


test   OBJECT IDENTIFIER ::= { mib-2 15 }

bits1 OBJECT-TYPE
SYNTAX      BITS { b0(0), b1(1), b2(2) }
MAX-ACCESS  read-write
STATUS      current
DESCRIPTION	\"" ++ Desc ++ "\"
    ::= { test 1 }

END",
    Message = file:write_file(Filename, Binary),
case Message of
    ok -> ok;
    {error, Reason} ->
	exit({failed_writing_mib, Reason})
end.


read_mib(Filename) ->
    case file:read_file(Filename) of
        {ok,Bin} -> 
	    binary_to_term(Bin);     
        {error,Reason} ->
            exit({failed_reading_mib,Filename,Reason})
    end.

check_mib([],_,_) ->
    not_found;
check_mib([#me{oid = Oid, description = Description}| _T], Oid, Testdata) ->
    check_desc(Description, Testdata);
check_mib([_H|T], Oid, Testdata ) ->
    check_mib(T, Oid, Testdata ).

check_desc(Desc, Desc) ->
    ok;
check_desc(Desc1, Desc2) ->
    exit({'description not equal', Desc1, Desc2}).


which_priv_dir(App) ->
    case code:priv_dir(App) of
        Dir when is_list(Dir) ->
            Dir;
        {error, Reason} ->
            exit({App, priv_dir_not_found, Reason})
    end.
    

%% join(Comp) ->
%%     filename:join(Comp).

join(A,B) ->
    filename:join(A,B).


%% ------

%% p(F) ->
%%     p(F, []).

p(F) ->
    p(F, []).

p(F, A) ->
    p(get(tname), F, A).

p(TName, F, A) ->
    io:format("*** [~w][~s] ***"
              "~n" ++ F ++ "~n", [TName, formated_timestamp()|A]).

formated_timestamp() ->
    snmp_test_lib:formated_timestamp().