Skip to content

Commit 03d3d78

Browse files
committed
added unit tests
1 parent 9691535 commit 03d3d78

File tree

2 files changed

+376
-0
lines changed

2 files changed

+376
-0
lines changed

tests/mock_tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ tests_SOURCES = aclorch_ut.cpp \
4141
saispy_ut.cpp \
4242
consumer_ut.cpp \
4343
sfloworh_ut.cpp \
44+
tunneldecaporch_ut.cpp \
4445
ut_saihelper.cpp \
4546
mock_orchagent_main.cpp \
4647
mock_dbconnector.cpp \
Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
#include "ut_helper.h"
2+
#include "mock_orchagent_main.h"
3+
4+
namespace tunneldecaporch_test
5+
{
6+
using namespace std;
7+
8+
shared_ptr<swss::DBConnector> m_app_db;
9+
shared_ptr<swss::DBConnector> m_config_db;
10+
shared_ptr<swss::DBConnector> m_state_db;
11+
12+
sai_tunnel_api_t ut_sai_tunnel_api;
13+
sai_tunnel_api_t *pold_sai_tunnel_api;
14+
sai_router_interface_api_t ut_sai_router_intfs_api;
15+
sai_router_interface_api_t *pold_sai_router_intfs_api;
16+
sai_next_hop_api_t ut_sai_next_hop_api;
17+
sai_next_hop_api_t *pold_sai_next_hop_api;
18+
19+
// Mock SAI API functions
20+
sai_status_t _ut_stub_sai_create_tunnel(
21+
_Out_ sai_object_id_t *tunnel_id,
22+
_In_ sai_object_id_t switch_id,
23+
_In_ uint32_t attr_count,
24+
_In_ const sai_attribute_t *attr_list)
25+
{
26+
static sai_object_id_t tunnel_id_counter = 0x300;
27+
*tunnel_id = tunnel_id_counter++;
28+
return SAI_STATUS_SUCCESS;
29+
}
30+
31+
sai_status_t _ut_stub_sai_remove_tunnel(
32+
_In_ sai_object_id_t tunnel_id)
33+
{
34+
return SAI_STATUS_SUCCESS;
35+
}
36+
37+
sai_status_t _ut_stub_sai_set_tunnel_attribute(
38+
_In_ sai_object_id_t tunnel_id,
39+
_In_ const sai_attribute_t *attr)
40+
{
41+
return SAI_STATUS_SUCCESS;
42+
}
43+
44+
sai_status_t _ut_stub_sai_create_tunnel_term_table_entry(
45+
_Out_ sai_object_id_t *tunnel_term_table_entry_id,
46+
_In_ sai_object_id_t switch_id,
47+
_In_ uint32_t attr_count,
48+
_In_ const sai_attribute_t *attr_list)
49+
{
50+
static sai_object_id_t term_entry_id_counter = 0x400;
51+
*tunnel_term_table_entry_id = term_entry_id_counter++;
52+
return SAI_STATUS_SUCCESS;
53+
}
54+
55+
sai_status_t _ut_stub_sai_remove_tunnel_term_table_entry(
56+
_In_ sai_object_id_t tunnel_term_table_entry_id)
57+
{
58+
return SAI_STATUS_SUCCESS;
59+
}
60+
61+
sai_status_t _ut_stub_sai_create_router_interface(
62+
_Out_ sai_object_id_t *router_interface_id,
63+
_In_ sai_object_id_t switch_id,
64+
_In_ uint32_t attr_count,
65+
_In_ const sai_attribute_t *attr_list)
66+
{
67+
static sai_object_id_t rif_id_counter = 0x500;
68+
*router_interface_id = rif_id_counter++;
69+
return SAI_STATUS_SUCCESS;
70+
}
71+
72+
sai_status_t _ut_stub_sai_remove_router_interface(
73+
_In_ sai_object_id_t router_interface_id)
74+
{
75+
return SAI_STATUS_SUCCESS;
76+
}
77+
78+
sai_status_t _ut_stub_sai_create_next_hop(
79+
_Out_ sai_object_id_t *next_hop_id,
80+
_In_ sai_object_id_t switch_id,
81+
_In_ uint32_t attr_count,
82+
_In_ const sai_attribute_t *attr_list)
83+
{
84+
static sai_object_id_t nh_id_counter = 0x600;
85+
*next_hop_id = nh_id_counter++;
86+
return SAI_STATUS_SUCCESS;
87+
}
88+
89+
sai_status_t _ut_stub_sai_remove_next_hop(
90+
_In_ sai_object_id_t next_hop_id)
91+
{
92+
return SAI_STATUS_SUCCESS;
93+
}
94+
95+
struct TunnelDecapOrchTest : public ::testing::Test
96+
{
97+
TunnelDecapOrchTest()
98+
{
99+
m_app_db = make_shared<swss::DBConnector>("APPL_DB", 0);
100+
m_config_db = make_shared<swss::DBConnector>("CONFIG_DB", 0);
101+
m_state_db = make_shared<swss::DBConnector>("STATE_DB", 0);
102+
}
103+
104+
void SetUp() override
105+
{
106+
// Initialize minimal global objects - following aclorch_ut pattern
107+
ASSERT_EQ(gCrmOrch, nullptr);
108+
gCrmOrch = new CrmOrch(m_config_db.get(), CFG_CRM_TABLE_NAME);
109+
110+
// Set other global objects to nullptr
111+
gPortsOrch = nullptr;
112+
gQosOrch = nullptr;
113+
114+
// Set up mock tunnel API
115+
ut_sai_tunnel_api = {};
116+
ut_sai_tunnel_api.create_tunnel = _ut_stub_sai_create_tunnel;
117+
ut_sai_tunnel_api.remove_tunnel = _ut_stub_sai_remove_tunnel;
118+
ut_sai_tunnel_api.set_tunnel_attribute = _ut_stub_sai_set_tunnel_attribute;
119+
ut_sai_tunnel_api.create_tunnel_term_table_entry = _ut_stub_sai_create_tunnel_term_table_entry;
120+
ut_sai_tunnel_api.remove_tunnel_term_table_entry = _ut_stub_sai_remove_tunnel_term_table_entry;
121+
122+
pold_sai_tunnel_api = sai_tunnel_api;
123+
sai_tunnel_api = &ut_sai_tunnel_api;
124+
125+
// Set up mock router interface API
126+
ut_sai_router_intfs_api = {};
127+
ut_sai_router_intfs_api.create_router_interface = _ut_stub_sai_create_router_interface;
128+
ut_sai_router_intfs_api.remove_router_interface = _ut_stub_sai_remove_router_interface;
129+
130+
pold_sai_router_intfs_api = sai_router_intfs_api;
131+
sai_router_intfs_api = &ut_sai_router_intfs_api;
132+
133+
// Set up mock next hop API
134+
ut_sai_next_hop_api = {};
135+
ut_sai_next_hop_api.create_next_hop = _ut_stub_sai_create_next_hop;
136+
ut_sai_next_hop_api.remove_next_hop = _ut_stub_sai_remove_next_hop;
137+
138+
pold_sai_next_hop_api = sai_next_hop_api;
139+
sai_next_hop_api = &ut_sai_next_hop_api;
140+
141+
// Set basic global variables needed for TunnelDecapOrch
142+
gSwitchId = 0x21000000000000;
143+
gVirtualRouterId = 0x3000000000001;
144+
gUnderlayIfId = 0x6000000000001;
145+
gMacAddress = MacAddress("20:03:04:05:06:00");
146+
}
147+
148+
void TearDown() override
149+
{
150+
// Restore SAI APIs
151+
sai_tunnel_api = pold_sai_tunnel_api;
152+
sai_router_intfs_api = pold_sai_router_intfs_api;
153+
sai_next_hop_api = pold_sai_next_hop_api;
154+
155+
// Clean up global orchestrator objects
156+
delete gCrmOrch;
157+
gCrmOrch = nullptr;
158+
}
159+
};
160+
161+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_Creation)
162+
{
163+
// Test creation of TunnelDecapOrch
164+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
165+
166+
ASSERT_NO_THROW({
167+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
168+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
169+
ASSERT_NE(tunnelDecapOrch, nullptr);
170+
});
171+
}
172+
173+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_BasicFunctionality)
174+
{
175+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
176+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
177+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
178+
ASSERT_NE(tunnelDecapOrch, nullptr);
179+
180+
EXPECT_NO_THROW({
181+
});
182+
}
183+
184+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_GetDscpMode)
185+
{
186+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
187+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
188+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
189+
ASSERT_NE(tunnelDecapOrch, nullptr);
190+
191+
// Test getDscpMode with non-existent tunnel
192+
EXPECT_NO_THROW({
193+
string dscp_mode = tunnelDecapOrch->getDscpMode("non_existent_tunnel");
194+
EXPECT_TRUE(dscp_mode.empty());
195+
});
196+
}
197+
198+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_GetDstIpAddresses)
199+
{
200+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
201+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
202+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
203+
ASSERT_NE(tunnelDecapOrch, nullptr);
204+
205+
// Test getDstIpAddresses with non-existent tunnel
206+
EXPECT_NO_THROW({
207+
auto dst_ips = tunnelDecapOrch->getDstIpAddresses("non_existent_tunnel");
208+
EXPECT_EQ(dst_ips.getSize(), 0);
209+
});
210+
}
211+
212+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_GetQosMapId)
213+
{
214+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
215+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
216+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
217+
ASSERT_NE(tunnelDecapOrch, nullptr);
218+
219+
// Test getQosMapId with non-existent tunnel
220+
EXPECT_NO_THROW({
221+
sai_object_id_t qos_map_id;
222+
bool result = tunnelDecapOrch->getQosMapId("non_existent_tunnel", "dscp_to_tc_map", qos_map_id);
223+
EXPECT_FALSE(result);
224+
});
225+
}
226+
227+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_CreateNextHopTunnel)
228+
{
229+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
230+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
231+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
232+
ASSERT_NE(tunnelDecapOrch, nullptr);
233+
234+
EXPECT_NO_THROW({
235+
IpAddress ip_addr("192.168.1.1");
236+
sai_object_id_t nh_id = tunnelDecapOrch->createNextHopTunnel("non_existent_tunnel", ip_addr);
237+
EXPECT_EQ(nh_id, SAI_NULL_OBJECT_ID);
238+
});
239+
}
240+
241+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_RemoveNextHopTunnel)
242+
{
243+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
244+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
245+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
246+
ASSERT_NE(tunnelDecapOrch, nullptr);
247+
248+
// Test removeNextHopTunnel with non-existent tunnel
249+
EXPECT_NO_THROW({
250+
IpAddress ip_addr("192.168.1.1");
251+
bool result = tunnelDecapOrch->removeNextHopTunnel("non_existent_tunnel", ip_addr);
252+
EXPECT_TRUE(result);
253+
});
254+
}
255+
256+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_GetSubnetDecapConfig)
257+
{
258+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
259+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
260+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
261+
ASSERT_NE(tunnelDecapOrch, nullptr);
262+
263+
// Test getSubnetDecapConfig
264+
EXPECT_NO_THROW({
265+
const auto& config = tunnelDecapOrch->getSubnetDecapConfig();
266+
EXPECT_FALSE(config.enable);
267+
});
268+
}
269+
270+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_DoTask)
271+
{
272+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
273+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
274+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
275+
ASSERT_NE(tunnelDecapOrch, nullptr);
276+
277+
// Test that doTask doesn't crash with empty task queue
278+
EXPECT_NO_THROW({
279+
static_cast<Orch *>(tunnelDecapOrch.get())->doTask();
280+
});
281+
}
282+
283+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_WithStateDb)
284+
{
285+
// Create TunnelDecapOrch with state DB
286+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
287+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
288+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
289+
ASSERT_NE(tunnelDecapOrch, nullptr);
290+
291+
// Test that basic functionality works with state DB constructor
292+
EXPECT_NO_THROW({
293+
auto dst_ips = tunnelDecapOrch->getDstIpAddresses("test_tunnel");
294+
EXPECT_EQ(dst_ips.getSize(), 0);
295+
});
296+
}
297+
298+
TEST_F(TunnelDecapOrchTest, TunnelDecapOrch_DoDecapTunnelTask)
299+
{
300+
vector<string> tunnel_tables = { APP_TUNNEL_DECAP_TABLE_NAME };
301+
auto tunnelDecapOrch = make_shared<TunnelDecapOrch>(
302+
m_app_db.get(), m_state_db.get(), m_config_db.get(), tunnel_tables);
303+
ASSERT_NE(tunnelDecapOrch, nullptr);
304+
305+
// Test 1: Create tunnel configuration data in the database and test processing
306+
Table tunnelDecapTable(m_app_db.get(), APP_TUNNEL_DECAP_TABLE_NAME);
307+
308+
// Set tunnel configuration in app DB
309+
vector<FieldValueTuple> tunnelData = {
310+
{"tunnel_type", "IPINIP"},
311+
{"dscp_mode", "uniform"},
312+
{"ecn_mode", "copy_from_outer"},
313+
{"ttl_mode", "pipe"},
314+
{"src_ip", "10.0.0.1"}
315+
};
316+
tunnelDecapTable.set("test_tunnel", tunnelData);
317+
318+
// Test that the table was set correctly
319+
EXPECT_NO_THROW({
320+
vector<FieldValueTuple> values;
321+
bool result = tunnelDecapTable.get("test_tunnel", values);
322+
EXPECT_TRUE(result);
323+
EXPECT_EQ(values.size(), 5);
324+
});
325+
326+
// Test 2: Test invalid tunnel configuration
327+
vector<FieldValueTuple> invalidTunnelData = {
328+
{"tunnel_type", "INVALID_TYPE"},
329+
{"dscp_mode", "invalid_mode"},
330+
{"ecn_mode", "invalid_ecn"}
331+
};
332+
tunnelDecapTable.set("invalid_tunnel", invalidTunnelData);
333+
334+
// Verify invalid data was set
335+
EXPECT_NO_THROW({
336+
vector<FieldValueTuple> values;
337+
bool result = tunnelDecapTable.get("invalid_tunnel", values);
338+
EXPECT_TRUE(result);
339+
EXPECT_EQ(values.size(), 3);
340+
});
341+
342+
// Test 3: Test tunnel deletion
343+
tunnelDecapTable.del("test_tunnel");
344+
345+
EXPECT_NO_THROW({
346+
vector<FieldValueTuple> values;
347+
bool result = tunnelDecapTable.get("test_tunnel", values);
348+
EXPECT_FALSE(result);
349+
});
350+
351+
// Test 4: Test empty configuration
352+
vector<FieldValueTuple> emptyData = {};
353+
tunnelDecapTable.set("empty_tunnel", emptyData);
354+
355+
EXPECT_NO_THROW({
356+
vector<FieldValueTuple> values;
357+
bool result = tunnelDecapTable.get("empty_tunnel", values);
358+
EXPECT_TRUE(result);
359+
EXPECT_EQ(values.size(), 0);
360+
});
361+
362+
// Test 5: Test that getDscpMode works after setting up tunnel data
363+
EXPECT_NO_THROW({
364+
string dscp_mode = tunnelDecapOrch->getDscpMode("invalid_tunnel");
365+
EXPECT_TRUE(dscp_mode.empty());
366+
});
367+
368+
// Test 6: Test that getDstIpAddresses works with database entries
369+
EXPECT_NO_THROW({
370+
auto dst_ips = tunnelDecapOrch->getDstIpAddresses("empty_tunnel");
371+
EXPECT_EQ(dst_ips.getSize(), 0);
372+
});
373+
}
374+
375+
} // namespace tunneldecaporch_test

0 commit comments

Comments
 (0)