ProfinetConnector/profinet_stack/p-net/test/test_snmp.cpp

264 lines
9.3 KiB
C++

/*********************************************************************
* _ _ _
* _ __ | |_ _ | | __ _ | |__ ___
* | '__|| __|(_)| | / _` || '_ \ / __|
* | | | |_ _ | || (_| || |_) |\__ \
* |_| \__|(_)|_| \__,_||_.__/ |___/
*
* www.rt-labs.com
* Copyright 2020 rt-labs AB, Sweden.
*
* This software is dual-licensed under GPLv3 and a commercial
* license. See the file LICENSE.md distributed with this software for
* full license information.
********************************************************************/
/**
* @file
* @brief Unit test for SNMP helper functions in pf_snmp.h.
*
*/
#include "utils_for_testing.h"
#include "mocks.h"
#include "pf_includes.h"
#include <gtest/gtest.h>
#define LOCAL_PORT 1
class SnmpTest : public PnetIntegrationTest
{
};
/* See https://tools.ietf.org/html/rfc2578#section-7.7 clause 3,
* for encoding of OCTET STRING field ManAddress.
*/
TEST_F (SnmpTest, SnmpGetManagementAddress)
{
pf_snmp_management_address_t address;
memset (&address, 0xff, sizeof (address));
mock_lldp_data.management_address.subtype = 1;
mock_lldp_data.management_address.value[0] = 192;
mock_lldp_data.management_address.value[1] = 168;
mock_lldp_data.management_address.value[2] = 1;
mock_lldp_data.management_address.value[3] = 100;
mock_lldp_data.management_address.len = 4;
pf_snmp_get_management_address (net, &address);
EXPECT_EQ (address.subtype, 1);
EXPECT_EQ (address.value[0], 4); /* len */
EXPECT_EQ (address.value[1], 192);
EXPECT_EQ (address.value[2], 168);
EXPECT_EQ (address.value[3], 1);
EXPECT_EQ (address.value[4], 100);
EXPECT_EQ (address.len, 5u);
}
TEST_F (SnmpTest, SnmpGetPeerManagementAddress)
{
pf_snmp_management_address_t address;
int error;
memset (&address, 0xff, sizeof (address));
mock_lldp_data.peer_management_address.subtype = 1;
mock_lldp_data.peer_management_address.value[0] = 192;
mock_lldp_data.peer_management_address.value[1] = 168;
mock_lldp_data.peer_management_address.value[2] = 1;
mock_lldp_data.peer_management_address.value[3] = 101;
mock_lldp_data.peer_management_address.len = 4;
mock_lldp_data.error = 0;
error = pf_snmp_get_peer_management_address (net, LOCAL_PORT, &address);
EXPECT_EQ (error, 0);
EXPECT_EQ (address.subtype, 1);
EXPECT_EQ (address.value[0], 4); /* len */
EXPECT_EQ (address.value[1], 192);
EXPECT_EQ (address.value[2], 168);
EXPECT_EQ (address.value[3], 1);
EXPECT_EQ (address.value[4], 101);
EXPECT_EQ (address.len, 5u);
mock_lldp_data.error = -1;
error = pf_snmp_get_peer_management_address (net, LOCAL_PORT, &address);
EXPECT_EQ (error, -1);
}
/* See https://tools.ietf.org/html/rfc1906 for encoding of
* BITS field AutoNegAdvertisedCap.
* See https://tools.ietf.org/html/rfc2579 for encoding of
* TruthValue fields AutoNegSupported and AutoNegEnabled.
*/
TEST_F (SnmpTest, SnmpGetLinkStatus)
{
pf_snmp_link_status_t status;
memset (&status, 0xff, sizeof (status));
mock_lldp_data.link_status.is_autonegotiation_supported = true;
mock_lldp_data.link_status.is_autonegotiation_enabled = true;
mock_lldp_data.link_status.autonegotiation_advertised_capabilities = 0xF00F;
mock_lldp_data.link_status.operational_mau_type =
PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX;
pf_snmp_get_link_status (net, LOCAL_PORT, &status);
EXPECT_EQ (status.auto_neg_supported, 1); /* true */
EXPECT_EQ (status.auto_neg_enabled, 1); /* true */
EXPECT_EQ (status.auto_neg_advertised_cap[0], 0xF0);
EXPECT_EQ (status.auto_neg_advertised_cap[1], 0x0F);
EXPECT_EQ (status.oper_mau_type, PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX);
memset (&status, 0xff, sizeof (status));
mock_lldp_data.link_status.is_autonegotiation_supported = true;
mock_lldp_data.link_status.is_autonegotiation_enabled = false;
mock_lldp_data.link_status.autonegotiation_advertised_capabilities =
BIT (5 + 0) | BIT (3 + 0) | BIT (6 + 8) | BIT (0 + 8);
mock_lldp_data.link_status.operational_mau_type =
PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX;
pf_snmp_get_link_status (net, LOCAL_PORT, &status);
EXPECT_EQ (status.auto_neg_supported, 1); /* true */
EXPECT_EQ (status.auto_neg_enabled, 2); /* false */
EXPECT_EQ (status.auto_neg_advertised_cap[0], BIT (2) | BIT (4));
EXPECT_EQ (status.auto_neg_advertised_cap[1], BIT (1) | BIT (7));
EXPECT_EQ (status.oper_mau_type, PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX);
}
TEST_F (SnmpTest, SnmpGetPeerLinkStatus)
{
pf_snmp_link_status_t status;
int error;
memset (&status, 0xff, sizeof (status));
mock_lldp_data.peer_link_status.is_autonegotiation_supported = true;
mock_lldp_data.peer_link_status.is_autonegotiation_enabled = true;
mock_lldp_data.peer_link_status.autonegotiation_advertised_capabilities =
0xF00F;
mock_lldp_data.peer_link_status.operational_mau_type =
PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX;
mock_lldp_data.error = 0;
error = pf_snmp_get_peer_link_status (net, LOCAL_PORT, &status);
EXPECT_EQ (error, 0);
EXPECT_EQ (status.auto_neg_supported, 1); /* true */
EXPECT_EQ (status.auto_neg_enabled, 1); /* true */
EXPECT_EQ (status.auto_neg_advertised_cap[0], 0xF0);
EXPECT_EQ (status.auto_neg_advertised_cap[1], 0x0F);
EXPECT_EQ (status.oper_mau_type, PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX);
memset (&status, 0xff, sizeof (status));
mock_lldp_data.peer_link_status.is_autonegotiation_supported = true;
mock_lldp_data.peer_link_status.is_autonegotiation_enabled = false;
mock_lldp_data.peer_link_status.autonegotiation_advertised_capabilities =
BIT (5 + 0) | BIT (3 + 0) | BIT (6 + 8) | BIT (0 + 8);
mock_lldp_data.peer_link_status.operational_mau_type =
PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX;
mock_lldp_data.error = 0;
error = pf_snmp_get_peer_link_status (net, LOCAL_PORT, &status);
EXPECT_EQ (error, 0);
EXPECT_EQ (status.auto_neg_supported, 1); /* true */
EXPECT_EQ (status.auto_neg_enabled, 2); /* false */
EXPECT_EQ (status.auto_neg_advertised_cap[0], BIT (2) | BIT (4));
EXPECT_EQ (status.auto_neg_advertised_cap[1], BIT (1) | BIT (7));
EXPECT_EQ (status.oper_mau_type, PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX);
mock_lldp_data.error = -1;
error = pf_snmp_get_peer_link_status (net, LOCAL_PORT, &status);
EXPECT_EQ (error, -1);
}
TEST_F (SnmpTest, SnmpGetLocationGivenLargeString)
{
const pf_snmp_system_location_t stored = {"1234567890123456789012 large"};
const char * expected = stored.string;
pf_snmp_system_location_t actual;
memset (&actual, 0xff, sizeof (actual));
mock_pf_file_save (NULL, PF_FILENAME_SNMP_SYSLOCATION, &stored, sizeof (stored));
pf_snmp_data_init (net);
pf_snmp_get_system_location (net, &actual);
EXPECT_STREQ (actual.string, expected);
}
TEST_F (SnmpTest, SnmpGetLocationGivenSmallString)
{
const pf_snmp_system_location_t stored = {"small"};
const char * expected = stored.string;
pf_snmp_system_location_t actual;
memset (&actual, 0xcd, sizeof (actual));
mock_pf_file_save (NULL, PF_FILENAME_SNMP_SYSLOCATION, &stored, sizeof (stored));
pf_snmp_data_init (net);
pf_snmp_get_system_location (net, &actual);
EXPECT_STREQ (actual.string, expected);
}
/* Note that the 22 bytes device location in I&M1 will be used if loading of
* sysLocation file fails (e.g. if does not exit).
*/
TEST_F (SnmpTest, SnmpGetLocationGivenError)
{
const char expected[] = "IM_Tag_Location in I&M";
pf_snmp_system_location_t actual;
mock_file_data.is_load_failing = true;
memset (&actual, 0xff, sizeof (actual));
mock_pf_fspm_save_im_location (net, expected);
pf_snmp_data_init (net);
pf_snmp_get_system_location (net, &actual);
EXPECT_STREQ (actual.string, expected);
EXPECT_EQ (strlen (actual.string), 22u);
}
/* Note that the first 22 bytes is also written to device location in I&M1 */
TEST_F (SnmpTest, SnmpSetLocationGivenLargeString)
{
const pf_snmp_system_location_t written = {"1234567890123456789012345"};
int error;
error = pf_snmp_set_system_location (net, &written);
EXPECT_EQ (error, 0);
EXPECT_STREQ (mock_file_data.filename, PF_FILENAME_SNMP_SYSLOCATION);
EXPECT_EQ (mock_file_data.size, sizeof (written));
EXPECT_EQ (memcmp (mock_file_data.object, &written, sizeof (written)), 0);
EXPECT_STREQ (mock_fspm_data.im_location, "1234567890123456789012");
}
/* Note that the first 22 bytes is also written to device location in I&M1 */
TEST_F (SnmpTest, SnmpSetLocationGivenSmallString)
{
const pf_snmp_system_location_t written = {"small"};
int error;
error = pf_snmp_set_system_location (net, &written);
EXPECT_EQ (error, 0);
EXPECT_STREQ (mock_file_data.filename, PF_FILENAME_SNMP_SYSLOCATION);
EXPECT_EQ (mock_file_data.size, sizeof (written));
EXPECT_EQ (memcmp (mock_file_data.object, &written, sizeof (written)), 0);
EXPECT_STREQ (mock_fspm_data.im_location, "small ");
}
/* Note that the first 22 bytes is also written to device location in I&M1 */
TEST_F (SnmpTest, SnmpSetLocationGivenError)
{
const pf_snmp_system_location_t written = {"1234567890123456789012345"};
int error;
mock_file_data.is_save_failing = true;
error = pf_snmp_set_system_location (net, &written);
EXPECT_EQ (error, -1);
EXPECT_STREQ (mock_fspm_data.im_location, "1234567890123456789012");
}